diff options
Diffstat (limited to 'include/modules/sql.h')
-rw-r--r-- | include/modules/sql.h | 183 |
1 files changed, 93 insertions, 90 deletions
diff --git a/include/modules/sql.h b/include/modules/sql.h index 471d18d07..bf1ebc3ee 100644 --- a/include/modules/sql.h +++ b/include/modules/sql.h @@ -1,80 +1,24 @@ /* + * Anope IRC Services * - * (C) 2003-2017 Anope Team - * Contact us at team@anope.org + * Copyright (C) 2010-2017 Anope Team <team@anope.org> * - * Please read COPYING and README for further details. + * This file is part of Anope. Anope is free software; you can + * redistribute it and/or modify it under the terms of the GNU + * General Public License as published by the Free Software + * Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see see <http://www.gnu.org/licenses/>. */ namespace SQL { - - class Data : public Serialize::Data - { - public: - typedef std::map<Anope::string, std::stringstream *> Map; - Map data; - std::map<Anope::string, Type> types; - - ~Data() - { - Clear(); - } - - std::iostream& operator[](const Anope::string &key) anope_override - { - std::stringstream *&ss = data[key]; - if (!ss) - ss = new std::stringstream(); - return *ss; - } - - std::set<Anope::string> KeySet() const anope_override - { - std::set<Anope::string> keys; - for (Map::const_iterator it = this->data.begin(), it_end = this->data.end(); it != it_end; ++it) - keys.insert(it->first); - return keys; - } - - size_t Hash() const anope_override - { - size_t hash = 0; - for (Map::const_iterator it = this->data.begin(), it_end = this->data.end(); it != it_end; ++it) - if (!it->second->str().empty()) - hash ^= Anope::hash_cs()(it->second->str()); - return hash; - } - - std::map<Anope::string, std::iostream *> GetData() const - { - std::map<Anope::string, std::iostream *> d; - for (Map::const_iterator it = this->data.begin(), it_end = this->data.end(); it != it_end; ++it) - d[it->first] = it->second; - return d; - } - - void Clear() - { - for (Map::const_iterator it = this->data.begin(), it_end = this->data.end(); it != it_end; ++it) - delete it->second; - this->data.clear(); - } - - void SetType(const Anope::string &key, Type t) anope_override - { - this->types[key] = t; - } - - Type GetType(const Anope::string &key) const anope_override - { - std::map<Anope::string, Type>::const_iterator it = this->types.find(key); - if (it != this->types.end()) - return it->second; - return DT_TEXT; - } - }; - /** A SQL exception, can be thrown at various points */ class Exception : public ModuleException @@ -92,6 +36,7 @@ namespace SQL { Anope::string data; bool escape; + bool null; }; struct Query @@ -129,15 +74,41 @@ namespace SQL } catch (const ConvertException &ex) { } } + + void SetNull(const Anope::string &key) + { + QueryData &qd = this->parameters[key]; + + qd.data = ""; + qd.escape = false; + qd.null = true; + } + + Anope::string Unsafe() const + { + Anope::string q = query; + for (auto it = parameters.begin(); it != parameters.end(); ++it) + q = q.replace_all_cs("@" + it->first + "@", it->second.data); + return q; + } }; /** A result from a SQL query */ class Result { + public: + struct Value + { + bool null = false; + Anope::string value; + }; + protected: - /* Rows, column, item */ - std::vector<std::map<Anope::string, Anope::string> > entries; + std::vector<Anope::string> columns; + // row, column + std::vector<std::vector<Value>> values; + Query query; Anope::string error; public: @@ -149,17 +120,20 @@ namespace SQL inline operator bool() const { return this->error.empty(); } - inline const unsigned int GetID() const { return this->id; } + inline unsigned int GetID() const { return this->id; } inline const Query &GetQuery() const { return this->query; } inline const Anope::string &GetError() const { return this->error; } - int Rows() const { return this->entries.size(); } + int Rows() const + { + return this->values.size(); + } - const std::map<Anope::string, Anope::string> &Row(size_t index) const + const std::vector<Value> &Row(size_t index) const { try { - return this->entries.at(index); + return this->values.at(index); } catch (const std::out_of_range &) { @@ -167,15 +141,35 @@ namespace SQL } } - const Anope::string Get(size_t index, const Anope::string &col) const + const Value &GetValue(size_t index, const Anope::string &col) const { - const std::map<Anope::string, Anope::string> rows = this->Row(index); + const std::vector<Value> &v = this->Row(index); - std::map<Anope::string, Anope::string>::const_iterator it = rows.find(col); - if (it == rows.end()) + auto it = std::find(this->columns.begin(), this->columns.end(), col); + if (it == this->columns.end()) throw Exception("Unknown column name in SQLResult: " + col); + unsigned int col_idx = it - this->columns.begin(); - return it->second; + try + { + return v[col_idx]; + } + catch (const std::out_of_range &) + { + throw Exception("Out of bounds access to SQLResult"); + } + } + + const Anope::string &Get(size_t index, const Anope::string &col) const + { + const Value &value = GetValue(index, col); + return value.value; + } + + bool IsNull(size_t index, const Anope::string &col) const + { + const Value &value = GetValue(index, col); + return value.null; } }; @@ -189,8 +183,8 @@ namespace SQL Interface(Module *m) : owner(m) { } virtual ~Interface() { } - virtual void OnResult(const Result &r) = 0; - virtual void OnError(const Result &r) = 0; + virtual void OnResult(const Result &r) anope_abstract; + virtual void OnError(const Result &r) anope_abstract; }; /** Class providing the SQL service, modules call this to execute queries @@ -198,19 +192,28 @@ namespace SQL class Provider : public Service { public: - Provider(Module *c, const Anope::string &n) : Service(c, "SQL::Provider", n) { } + static constexpr const char *NAME = "sql"; + + Provider(Module *c, const Anope::string &n) : Service(c, NAME, n) { } - virtual void Run(Interface *i, const Query &query) = 0; + virtual void Run(Interface *i, const Query &query) anope_abstract; - virtual Result RunQuery(const Query &query) = 0; + virtual Result RunQuery(const Query &query) anope_abstract; - virtual std::vector<Query> CreateTable(const Anope::string &table, const Data &data) = 0; + virtual std::vector<Query> InitSchema(const Anope::string &prefix) anope_abstract; + virtual std::vector<Query> Replace(const Anope::string &table, const Query &, const std::set<Anope::string> &) anope_abstract; + virtual std::vector<Query> CreateTable(const Anope::string &prefix, Serialize::TypeBase *) anope_abstract; + virtual std::vector<Query> AlterTable(const Anope::string &, Serialize::TypeBase *, Serialize::FieldBase *) anope_abstract; + virtual std::vector<Query> CreateIndex(const Anope::string &table, const Anope::string &field) anope_abstract; + virtual Query SelectFind(const Anope::string &table, const Anope::string &field) anope_abstract; - virtual Query BuildInsert(const Anope::string &table, unsigned int id, Data &data) = 0; + virtual Query BeginTransaction() anope_abstract; + virtual Query Commit() anope_abstract; - virtual Query GetTables(const Anope::string &prefix) = 0; + virtual Serialize::ID GetID(const Anope::string &prefix, const Anope::string &type) anope_abstract; - virtual Anope::string FromUnixtime(time_t) = 0; + virtual Query GetTables(const Anope::string &prefix) anope_abstract; }; } + |