sql.h

Go to the documentation of this file.
00001 /*
00002  * (C) 2003-2013 Anope Team
00003  * Contact us at team@anope.org
00004  *
00005  * Please read COPYING and README for further details.
00006  */
00007 
00008 namespace SQL
00009 {
00010 
00011         class Data : public Serialize::Data
00012         {
00013          public:
00014                 typedef std::map<Anope::string, std::stringstream *> Map;
00015                 Map data;
00016                 std::map<Anope::string, Type> types;
00017 
00018                 ~Data()
00019                 {
00020                         Clear();
00021                 }
00022 
00023                 std::iostream& operator[](const Anope::string &key) anope_override
00024                 {
00025                         std::stringstream *&ss = data[key];
00026                         if (!ss)
00027                                 ss = new std::stringstream();
00028                         return *ss;
00029                 }
00030 
00031                 std::set<Anope::string> KeySet() const anope_override
00032                 {
00033                         std::set<Anope::string> keys;
00034                         for (Map::const_iterator it = this->data.begin(), it_end = this->data.end(); it != it_end; ++it)
00035                                 keys.insert(it->first);
00036                         return keys;
00037                 }
00038 
00039                 size_t Hash() const anope_override
00040                 {
00041                         size_t hash = 0;
00042                         for (Map::const_iterator it = this->data.begin(), it_end = this->data.end(); it != it_end; ++it)
00043                                 if (!it->second->str().empty())
00044                                         hash ^= Anope::hash_cs()(it->second->str());
00045                         return hash;
00046                 }
00047 
00048                 std::map<Anope::string, std::iostream *> GetData() const
00049                 {
00050                         std::map<Anope::string, std::iostream *> d;
00051                         for (Map::const_iterator it = this->data.begin(), it_end = this->data.end(); it != it_end; ++it)
00052                                 d[it->first] = it->second;
00053                         return d;
00054                 }
00055 
00056                 void Clear()
00057                 {
00058                         for (Map::const_iterator it = this->data.begin(), it_end = this->data.end(); it != it_end; ++it)
00059                                 delete it->second;
00060                         this->data.clear();
00061                 }
00062 
00063                 void SetType(const Anope::string &key, Type t) anope_override
00064                 {
00065                         this->types[key] = t;
00066                 }
00067 
00068                 Type GetType(const Anope::string &key) const anope_override
00069                 {
00070                         std::map<Anope::string, Type>::const_iterator it = this->types.find(key);
00071                         if (it != this->types.end())
00072                                 return it->second;
00073                         return DT_TEXT;
00074                 }
00075         };
00076 
00079         class Exception : public ModuleException
00080         {
00081          public:
00082                 Exception(const Anope::string &reason) : ModuleException(reason) { }
00083 
00084                 virtual ~Exception() throw() { }
00085         };
00086 
00090         struct QueryData
00091         {
00092                 Anope::string data;
00093                 bool escape;
00094         };
00095 
00096         struct Query
00097         {
00098                 Anope::string query;
00099                 std::map<Anope::string, QueryData> parameters;
00100 
00101                 Query() { }
00102                 Query(const Anope::string &q) : query(q) { }
00103 
00104                 Query& operator=(const Anope::string &q)
00105                 {
00106                         this->query = q;
00107                         this->parameters.clear();
00108                         return *this;
00109                 }
00110 
00111                 bool operator==(const Query &other) const
00112                 {
00113                         return this->query == other.query;
00114                 }
00115 
00116                 inline bool operator!=(const Query &other) const
00117                 {
00118                         return !(*this == other);
00119                 }
00120 
00121                 template<typename T> void SetValue(const Anope::string &key, const T& value, bool escape = true)
00122                 {
00123                         try
00124                         {
00125                                 Anope::string string_value = stringify(value);
00126                                 this->parameters[key].data = string_value;
00127                                 this->parameters[key].escape = escape;
00128                         }
00129                         catch (const ConvertException &ex) { }
00130                 }
00131         };
00132 
00135         class Result
00136         {
00137          protected:
00138                 /* Rows, column, item */
00139                 std::vector<std::map<Anope::string, Anope::string> > entries;
00140                 Query query;
00141                 Anope::string error;
00142          public:
00143                 unsigned int id;
00144                 Anope::string finished_query;
00145 
00146                 Result() : id(0) { }
00147                 Result(unsigned int i, const Query &q, const Anope::string &fq, const Anope::string &err = "") : query(q), error(err), id(i), finished_query(fq) { }
00148 
00149                 inline operator bool() const { return this->error.empty(); }
00150 
00151                 inline const unsigned int GetID() const { return this->id; }
00152                 inline const Query &GetQuery() const { return this->query; }
00153                 inline const Anope::string &GetError() const { return this->error; }
00154 
00155                 int Rows() const { return this->entries.size(); }
00156 
00157                 const std::map<Anope::string, Anope::string> &Row(size_t index) const
00158                 {
00159                         try
00160                         {
00161                                 return this->entries.at(index);
00162                         }
00163                         catch (const std::out_of_range &)
00164                         {
00165                                 throw Exception("Out of bounds access to SQLResult");
00166                         }
00167                 }
00168 
00169                 const Anope::string Get(size_t index, const Anope::string &col) const
00170                 {
00171                         const std::map<Anope::string, Anope::string> rows = this->Row(index);
00172 
00173                         std::map<Anope::string, Anope::string>::const_iterator it = rows.find(col);
00174                         if (it == rows.end())
00175                                 throw Exception("Unknown column name in SQLResult: " + col);
00176 
00177                         return it->second;
00178                 }
00179         };
00180 
00181         /* An interface used by modules to retrieve the results
00182          */
00183         class Interface
00184         {
00185          public:
00186                 Module *owner;
00187 
00188                 Interface(Module *m) : owner(m) { }
00189                 virtual ~Interface() { }
00190 
00191                 virtual void OnResult(const Result &r) = 0;
00192                 virtual void OnError(const Result &r) = 0;
00193         };
00194 
00197         class Provider : public Service
00198         {
00199          public:
00200                 Provider(Module *c, const Anope::string &n) : Service(c, "SQL::Provider", n) { }
00201 
00202                 virtual void Run(Interface *i, const Query &query) = 0;
00203 
00204                 virtual Result RunQuery(const Query &query) = 0;
00205 
00206                 virtual std::vector<Query> CreateTable(const Anope::string &table, const Data &data) = 0;
00207 
00208                 virtual Query BuildInsert(const Anope::string &table, unsigned int id, Data &data) = 0;
00209 
00210                 virtual Query GetTables(const Anope::string &prefix) = 0;
00211 
00212                 virtual Anope::string FromUnixtime(time_t) = 0;
00213         };
00214 
00215 }
00216