summaryrefslogtreecommitdiff
path: root/modules/database/db_sql.cpp
diff options
context:
space:
mode:
authorAdam <Adam@anope.org>2011-09-25 04:19:15 -0400
committerAdam <Adam@anope.org>2011-09-25 04:19:15 -0400
commit1f2399de364c09adcce4193895cd362d80ffdfc5 (patch)
tree5f40fc531f22c174b6e10bb7bc12842a4a21d30b /modules/database/db_sql.cpp
parent43201ead9575a74e350710bc191f4ac67366aca7 (diff)
Added a new database format and sqlite support. Also moved db-convert to a module.
Diffstat (limited to 'modules/database/db_sql.cpp')
-rw-r--r--modules/database/db_sql.cpp169
1 files changed, 169 insertions, 0 deletions
diff --git a/modules/database/db_sql.cpp b/modules/database/db_sql.cpp
new file mode 100644
index 000000000..43e7cfe6d
--- /dev/null
+++ b/modules/database/db_sql.cpp
@@ -0,0 +1,169 @@
+/*
+ * (C) 2003-2011 Anope Team
+ * Contact us at team@anope.org
+ *
+ * Please read COPYING and README for further details.
+ *
+ * Based on the original code of Epona by Lara.
+ * Based on the original code of Services by Andy Church.
+ */
+
+#include "module.h"
+#include "../extra/sql.h"
+
+class SQLSQLInterface : public SQLInterface
+{
+ public:
+ SQLSQLInterface(Module *o) : SQLInterface(o) { }
+
+ void OnResult(const SQLResult &r)
+ {
+ Log(LOG_DEBUG) << "SQL successfully executed query: " << r.finished_query;
+ }
+
+ void OnError(const SQLResult &r)
+ {
+ if (!r.GetQuery().query.empty())
+ Log(LOG_DEBUG) << "Error executing query " << r.finished_query << ": " << r.GetError();
+ else
+ Log(LOG_DEBUG) << "Error executing query: " << r.GetError();
+ }
+};
+
+class DBSQL : public Module
+{
+ service_reference<SQLProvider, Base> sql;
+ SQLSQLInterface sqlinterface;
+
+ void RunBackground(const SQLQuery &q)
+ {
+ if (!quitting)
+ this->sql->Run(&sqlinterface, q);
+ else
+ this->sql->RunQuery(q);
+ }
+
+ void DropTable(const Anope::string &table)
+ {
+ SQLQuery query("DROP TABLE `" + table + "`");
+ this->RunBackground(query);
+ }
+
+ void AlterTable(const Anope::string &table, const SerializableBase::serialized_data &oldd, const SerializableBase::serialized_data &newd)
+ {
+ for (SerializableBase::serialized_data::const_iterator it = newd.begin(), it_end = newd.end(); it != it_end; ++it)
+ {
+ if (oldd.count(it->first) > 0)
+ continue;
+
+ Anope::string query_text = "ALTER TABLE `" + table + "` ADD `" + it->first + "` ";
+ if (it->second.getType() == Serialize::DT_INT)
+ query_text += "int(11)";
+ else if (it->second.getMax() > 0)
+ query_text += "varchar(" + stringify(it->second.getMax()) + ")";
+ else
+ query_text += "text";
+
+ this->RunBackground(SQLQuery(query_text));
+ }
+ }
+
+ void Insert(const Anope::string &table, const SerializableBase::serialized_data &data)
+ {
+ Anope::string query_text = "INSERT INTO `" + table + "` (";
+ for (SerializableBase::serialized_data::const_iterator it = data.begin(), it_end = data.end(); it != it_end; ++it)
+ query_text += "`" + it->first + "`,";
+ query_text.erase(query_text.end() - 1);
+ query_text += ") VALUES (";
+ for (SerializableBase::serialized_data::const_iterator it = data.begin(), it_end = data.end(); it != it_end; ++it)
+ query_text += "@" + it->first + "@,";
+ query_text.erase(query_text.end() - 1);
+ query_text += ")";
+
+ SQLQuery query(query_text);
+ for (SerializableBase::serialized_data::const_iterator it = data.begin(), it_end = data.end(); it != it_end; ++it)
+ query.setValue(it->first, it->second.astr());
+
+ this->RunBackground(query);
+ }
+
+ public:
+ DBSQL(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, DATABASE), sql(""), sqlinterface(this)
+ {
+ this->SetAuthor("Anope");
+
+ Implementation i[] = { I_OnReload, I_OnSaveDatabase, I_OnLoadDatabase };
+ ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation));
+
+ this->OnReload();
+ }
+
+ void OnReload()
+ {
+ ConfigReader config;
+ Anope::string engine = config.ReadValue("db_sql", "engine", "", 0);
+ this->sql = engine;
+ }
+
+ EventReturn OnSaveDatabase()
+ {
+ if (!this->sql)
+ {
+ Log() << "db_sql: Unable to save databases, is SQL configured correctly?";
+ return EVENT_CONTINUE;
+ }
+
+ std::map<Anope::string, SerializableBase::serialized_data> table_layout;
+ for (std::list<SerializableBase *>::iterator it = serialized_items.begin(), it_end = serialized_items.end(); it != it_end; ++it)
+ {
+ SerializableBase *base = *it;
+ SerializableBase::serialized_data data = base->serialize();
+
+ if (data.empty())
+ continue;
+
+ if (table_layout.count(base->serialize_name()) == 0)
+ {
+ this->DropTable(base->serialize_name());
+ this->RunBackground(this->sql->CreateTable(base->serialize_name(), data));
+ }
+ else
+ this->AlterTable(base->serialize_name(), table_layout[base->serialize_name()], data);
+ table_layout[base->serialize_name()] = data;
+
+ this->Insert(base->serialize_name(), data);
+ }
+ return EVENT_CONTINUE;
+ }
+
+ EventReturn OnLoadDatabase()
+ {
+ if (!this->sql)
+ {
+ Log() << "db_sql: Unable to load databases, is SQL configured correctly?";
+ return EVENT_CONTINUE;
+ }
+
+ for (std::vector<SerializableBase *>::iterator it = serialized_types.begin(), it_end = serialized_types.end(); it != it_end; ++it)
+ {
+ SerializableBase *sb = *it;
+
+ SQLQuery query("SELECT * FROM `" + sb->serialize_name() + "`");
+ SQLResult res = this->sql->RunQuery(query);
+ for (int i = 0; i < res.Rows(); ++i)
+ {
+ SerializableBase::serialized_data data;
+ const std::map<Anope::string, Anope::string> &row = res.Row(i);
+ for (std::map<Anope::string, Anope::string>::const_iterator rit = row.begin(), rit_end = row.end(); rit != rit_end; ++rit)
+ data[rit->first] << rit->second;
+
+ sb->alloc(data);
+ }
+ }
+
+ return EVENT_CONTINUE;
+ }
+};
+
+MODULE_INIT(DBSQL)
+