summaryrefslogtreecommitdiff
path: root/modules/extra/m_sqlite.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'modules/extra/m_sqlite.cpp')
-rw-r--r--modules/extra/m_sqlite.cpp334
1 files changed, 0 insertions, 334 deletions
diff --git a/modules/extra/m_sqlite.cpp b/modules/extra/m_sqlite.cpp
deleted file mode 100644
index b444c1a6c..000000000
--- a/modules/extra/m_sqlite.cpp
+++ /dev/null
@@ -1,334 +0,0 @@
-/*
- *
- * (C) 2011-2017 Anope Team
- * Contact us at team@anope.org
- *
- * Please read COPYING and README for further details.
- */
-
-/* RequiredLibraries: sqlite3 */
-/* RequiredWindowsLibraries: sqlite3 */
-
-#include "module.h"
-#include "modules/sql.h"
-#include <sqlite3.h>
-
-using namespace SQL;
-
-/* SQLite3 API, based from InspiRCd */
-
-/** A SQLite result
- */
-class SQLiteResult : public Result
-{
- public:
- SQLiteResult(unsigned int i, const Query &q, const Anope::string &fq) : Result(i, q, fq)
- {
- }
-
- SQLiteResult(const Query &q, const Anope::string &fq, const Anope::string &err) : Result(0, q, fq, err)
- {
- }
-
- void AddRow(const std::map<Anope::string, Anope::string> &data)
- {
- this->entries.push_back(data);
- }
-};
-
-/** A SQLite database, there can be multiple
- */
-class SQLiteService : public Provider
-{
- std::map<Anope::string, std::set<Anope::string> > active_schema;
-
- Anope::string database;
-
- sqlite3 *sql;
-
- Anope::string Escape(const Anope::string &query);
-
- public:
- SQLiteService(Module *o, const Anope::string &n, const Anope::string &d);
-
- ~SQLiteService();
-
- void Run(Interface *i, const Query &query) anope_override;
-
- Result RunQuery(const Query &query);
-
- std::vector<Query> CreateTable(const Anope::string &table, const Data &data) anope_override;
-
- Query BuildInsert(const Anope::string &table, unsigned int id, Data &data);
-
- Query GetTables(const Anope::string &prefix);
-
- Anope::string BuildQuery(const Query &q);
-
- Anope::string FromUnixtime(time_t);
-};
-
-class ModuleSQLite : public Module
-{
- /* SQL connections */
- std::map<Anope::string, SQLiteService *> SQLiteServices;
- public:
- ModuleSQLite(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, EXTRA | VENDOR)
- {
- }
-
- ~ModuleSQLite()
- {
- for (std::map<Anope::string, SQLiteService *>::iterator it = this->SQLiteServices.begin(); it != this->SQLiteServices.end(); ++it)
- delete it->second;
- SQLiteServices.clear();
- }
-
- void OnReload(Configuration::Conf *conf) anope_override
- {
- Configuration::Block *config = conf->GetModule(this);
-
- for (std::map<Anope::string, SQLiteService *>::iterator it = this->SQLiteServices.begin(); it != this->SQLiteServices.end();)
- {
- const Anope::string &cname = it->first;
- SQLiteService *s = it->second;
- int i, num;
- ++it;
-
- for (i = 0, num = config->CountBlock("sqlite"); i < num; ++i)
- if (config->GetBlock("sqlite", i)->Get<const Anope::string>("name", "sqlite/main") == cname)
- break;
-
- if (i == num)
- {
- Log(LOG_NORMAL, "sqlite") << "SQLite: Removing server connection " << cname;
-
- delete s;
- this->SQLiteServices.erase(cname);
- }
- }
-
- for (int i = 0; i < config->CountBlock("sqlite"); ++i)
- {
- Configuration::Block *block = config->GetBlock("sqlite", i);
- Anope::string connname = block->Get<const Anope::string>("name", "sqlite/main");
-
- if (this->SQLiteServices.find(connname) == this->SQLiteServices.end())
- {
- Anope::string database = Anope::DataDir + "/" + block->Get<const Anope::string>("database", "anope");
-
- try
- {
- SQLiteService *ss = new SQLiteService(this, connname, database);
- this->SQLiteServices[connname] = ss;
-
- Log(LOG_NORMAL, "sqlite") << "SQLite: Successfully added database " << database;
- }
- catch (const SQL::Exception &ex)
- {
- Log(LOG_NORMAL, "sqlite") << "SQLite: " << ex.GetReason();
- }
- }
- }
- }
-};
-
-SQLiteService::SQLiteService(Module *o, const Anope::string &n, const Anope::string &d)
-: Provider(o, n), database(d), sql(NULL)
-{
- int db = sqlite3_open_v2(database.c_str(), &this->sql, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, 0);
- if (db != SQLITE_OK)
- {
- Anope::string exstr = "Unable to open SQLite database " + database;
- if (this->sql)
- {
- exstr += ": ";
- exstr += sqlite3_errmsg(this->sql);
- sqlite3_close(this->sql);
- }
- throw SQL::Exception(exstr);
- }
-}
-
-SQLiteService::~SQLiteService()
-{
- sqlite3_interrupt(this->sql);
- sqlite3_close(this->sql);
-}
-
-void SQLiteService::Run(Interface *i, const Query &query)
-{
- Result res = this->RunQuery(query);
- if (!res.GetError().empty())
- i->OnError(res);
- else
- i->OnResult(res);
-}
-
-Result SQLiteService::RunQuery(const Query &query)
-{
- Anope::string real_query = this->BuildQuery(query);
- sqlite3_stmt *stmt;
- int err = sqlite3_prepare_v2(this->sql, real_query.c_str(), real_query.length(), &stmt, NULL);
- if (err != SQLITE_OK)
- return SQLiteResult(query, real_query, sqlite3_errmsg(this->sql));
-
- std::vector<Anope::string> columns;
- int cols = sqlite3_column_count(stmt);
- columns.resize(cols);
- for (int i = 0; i < cols; ++i)
- columns[i] = sqlite3_column_name(stmt, i);
-
- SQLiteResult result(0, query, real_query);
-
- while ((err = sqlite3_step(stmt)) == SQLITE_ROW)
- {
- std::map<Anope::string, Anope::string> items;
- for (int i = 0; i < cols; ++i)
- {
- const char *data = reinterpret_cast<const char *>(sqlite3_column_text(stmt, i));
- if (data && *data)
- items[columns[i]] = data;
- }
- result.AddRow(items);
- }
-
- result.id = sqlite3_last_insert_rowid(this->sql);
-
- sqlite3_finalize(stmt);
-
- if (err != SQLITE_DONE)
- return SQLiteResult(query, real_query, sqlite3_errmsg(this->sql));
-
- return result;
-}
-
-std::vector<Query> SQLiteService::CreateTable(const Anope::string &table, const Data &data)
-{
- std::vector<Query> queries;
- std::set<Anope::string> &known_cols = this->active_schema[table];
-
- if (known_cols.empty())
- {
- Log(LOG_DEBUG) << "m_sqlite: Fetching columns for " << table;
-
- Result columns = this->RunQuery("PRAGMA table_info(" + table + ")");
- for (int i = 0; i < columns.Rows(); ++i)
- {
- const Anope::string &column = columns.Get(i, "name");
-
- Log(LOG_DEBUG) << "m_sqlite: Column #" << i << " for " << table << ": " << column;
- known_cols.insert(column);
- }
- }
-
- if (known_cols.empty())
- {
- Anope::string query_text = "CREATE TABLE `" + table + "` (`id` INTEGER PRIMARY KEY, `timestamp` timestamp DEFAULT CURRENT_TIMESTAMP";
-
- for (Data::Map::const_iterator it = data.data.begin(), it_end = data.data.end(); it != it_end; ++it)
- {
- known_cols.insert(it->first);
-
- query_text += ", `" + it->first + "` ";
- if (data.GetType(it->first) == Serialize::Data::DT_INT)
- query_text += "int(11)";
- else
- query_text += "text";
- }
-
- query_text += ")";
-
- queries.push_back(query_text);
-
- query_text = "CREATE UNIQUE INDEX `" + table + "_id_idx` ON `" + table + "` (`id`)";
- queries.push_back(query_text);
-
- query_text = "CREATE INDEX `" + table + "_timestamp_idx` ON `" + table + "` (`timestamp`)";
- queries.push_back(query_text);
-
- query_text = "CREATE TRIGGER `" + table + "_trigger` AFTER UPDATE ON `" + table + "` FOR EACH ROW BEGIN UPDATE `" + table + "` SET `timestamp` = CURRENT_TIMESTAMP WHERE `id` = `old.id`; end;";
- queries.push_back(query_text);
- }
- else
- for (Data::Map::const_iterator it = data.data.begin(), it_end = data.data.end(); it != it_end; ++it)
- {
- if (known_cols.count(it->first) > 0)
- continue;
-
- known_cols.insert(it->first);
-
- Anope::string query_text = "ALTER TABLE `" + table + "` ADD `" + it->first + "` ";
- if (data.GetType(it->first) == Serialize::Data::DT_INT)
- query_text += "int(11)";
- else
- query_text += "text";
-
- queries.push_back(query_text);
- }
-
- return queries;
-}
-
-Query SQLiteService::BuildInsert(const Anope::string &table, unsigned int id, Data &data)
-{
- /* Empty columns not present in the data set */
- const std::set<Anope::string> &known_cols = this->active_schema[table];
- for (std::set<Anope::string>::iterator it = known_cols.begin(), it_end = known_cols.end(); it != it_end; ++it)
- if (*it != "id" && *it != "timestamp" && data.data.count(*it) == 0)
- data[*it] << "";
-
- Anope::string query_text = "REPLACE INTO `" + table + "` (";
- if (id > 0)
- query_text += "`id`,";
- for (Data::Map::const_iterator it = data.data.begin(), it_end = data.data.end(); it != it_end; ++it)
- query_text += "`" + it->first + "`,";
- query_text.erase(query_text.length() - 1);
- query_text += ") VALUES (";
- if (id > 0)
- query_text += stringify(id) + ",";
- for (Data::Map::const_iterator it = data.data.begin(), it_end = data.data.end(); it != it_end; ++it)
- query_text += "@" + it->first + "@,";
- query_text.erase(query_text.length() - 1);
- query_text += ")";
-
- Query query(query_text);
- for (Data::Map::const_iterator it = data.data.begin(), it_end = data.data.end(); it != it_end; ++it)
- {
- Anope::string buf;
- *it->second >> buf;
- query.SetValue(it->first, buf);
- }
-
- return query;
-}
-
-Query SQLiteService::GetTables(const Anope::string &prefix)
-{
- return Query("SELECT name FROM sqlite_master WHERE type='table' AND name LIKE '" + prefix + "%';");
-}
-
-Anope::string SQLiteService::Escape(const Anope::string &query)
-{
- char *e = sqlite3_mprintf("%q", query.c_str());
- Anope::string buffer = e;
- sqlite3_free(e);
- return buffer;
-}
-
-Anope::string SQLiteService::BuildQuery(const Query &q)
-{
- Anope::string real_query = q.query;
-
- for (std::map<Anope::string, QueryData>::const_iterator it = q.parameters.begin(), it_end = q.parameters.end(); it != it_end; ++it)
- real_query = real_query.replace_all_cs("@" + it->first + "@", (it->second.escape ? ("'" + this->Escape(it->second.data) + "'") : it->second.data));
-
- return real_query;
-}
-
-Anope::string SQLiteService::FromUnixtime(time_t t)
-{
- return "datetime('" + stringify(t) + "', 'unixepoch')";
-}
-
-MODULE_INIT(ModuleSQLite)