The InspIRCd Project
Home | Developers | Wiki | Forums | Bug Tracker | SVN | Download
Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

m_sqlv2.h

Go to the documentation of this file.
00001 /*       +------------------------------------+
00002  *       | Inspire Internet Relay Chat Daemon |
00003  *       +------------------------------------+
00004  *
00005  *  InspIRCd: (C) 2002-2008 InspIRCd Development Team
00006  * See: http://www.inspircd.org/wiki/index.php/Credits
00007  *
00008  * This program is free but copyrighted software; see
00009  *          the file COPYING for details.
00010  *
00011  * ---------------------------------------------------
00012  */
00013 
00014 #ifndef INSPIRCD_SQLAPI_2
00015 #define INSPIRCD_SQLAPI_2
00016 
00017 #include <string>
00018 #include <deque>
00019 #include <map>
00020 #include "modules.h"
00021 
00024 #define SQLREQID "SQLv2 Request"
00025 #define SQLRESID "SQLv2 Result"
00026 #define SQLSUCCESS "You shouldn't be reading this (success)"
00027 
00030 enum SQLerrorNum { SQL_NO_ERROR, SQL_BAD_DBID, SQL_BAD_CONN, SQL_QSEND_FAIL, SQL_QREPLY_FAIL };
00031 
00034 typedef std::deque<std::string> ParamL;
00035 
00038 class SQLexception : public ModuleException
00039 {
00040  public:
00041         SQLexception(const std::string &reason) : ModuleException(reason)
00042         {
00043         }
00044 
00045         SQLexception() : ModuleException("SQLv2: Undefined exception")
00046         {
00047         }
00048 };
00049 
00052 class SQLbadColName : public SQLexception
00053 {
00054 public:
00055         SQLbadColName() : SQLexception("SQLv2: Bad column name")
00056         {
00057         }
00058 };
00059 
00064 class SQLerror : public classbase
00065 {
00068         SQLerrorNum id;
00071         std::string str;
00072 public:
00077         SQLerror(SQLerrorNum i = SQL_NO_ERROR, const std::string &s = "")
00078         : id(i), str(s)
00079         {
00080         }
00081 
00084         SQLerrorNum Id()
00085         {
00086                 return id;
00087         }
00088 
00093         SQLerrorNum Id(SQLerrorNum i)
00094         {
00095                 id = i;
00096                 return id;
00097         }
00098 
00102         void Str(const std::string &s)
00103         {
00104                 str = s;
00105         }
00106 
00109         const char* Str()
00110         {
00111                 if(str.length())
00112                         return str.c_str();
00113 
00114                 switch(id)
00115                 {
00116                         case SQL_NO_ERROR:
00117                                 return "No error";
00118                         case SQL_BAD_DBID:
00119                                 return "Invalid database ID";
00120                         case SQL_BAD_CONN:
00121                                 return "Invalid connection";
00122                         case SQL_QSEND_FAIL:
00123                                 return "Sending query failed";
00124                         case SQL_QREPLY_FAIL:
00125                                 return "Getting query result failed";
00126                         default:
00127                                 return "Unknown error";
00128                 }
00129         }
00130 };
00131 
00152 class SQLquery : public classbase
00153 {
00154 public:
00157         std::string q;
00162         ParamL p;
00163 
00166         SQLquery(const std::string &query)
00167         : q(query)
00168         {
00169         }
00170 
00175         SQLquery(const std::string &query, const ParamL &params)
00176         : q(query), p(params)
00177         {
00178         }
00179 
00182         template<typename T> SQLquery& operator,(const T &foo)
00183         {
00184                 p.push_back(ConvToStr(foo));
00185                 return *this;
00186         }
00187 
00191         template<typename T> SQLquery& operator%(const T &foo)
00192         {
00193                 p.push_back(ConvToStr(foo));
00194                 return *this;
00195         }
00196 };
00197 
00203 class SQLrequest : public Request
00204 {
00205 public:
00209         SQLquery query;
00212         std::string dbid;
00216         bool pri;
00222         unsigned long id;
00225         SQLerror error;
00226 
00238         SQLrequest(Module* s, Module* d, const std::string &databaseid, const SQLquery &q)
00239         : Request(s, d, SQLREQID), query(q), dbid(databaseid), pri(false), id(0)
00240         {
00241         }
00242 
00245         void Priority(bool p = true)
00246         {
00247                 pri = p;
00248         }
00249 
00252         void SetSource(Module* mod)
00253         {
00254                 source = mod;
00255         }
00256 };
00257 
00262 class SQLfield
00263 {
00264 public:
00268         std::string d;
00269 
00273         bool null;
00274 
00277         SQLfield(const std::string &data = "", bool n = false)
00278         : d(data), null(n)
00279         {
00280 
00281         }
00282 };
00283 
00287 typedef std::vector<SQLfield> SQLfieldList;
00291 typedef std::map<std::string, SQLfield> SQLfieldMap;
00292 
00301 class SQLresult : public Request
00302 {
00303 public:
00306         std::string query;
00309         std::string dbid;
00315         SQLerror error;
00320         unsigned long id;
00321 
00324         SQLresult(Module* s, Module* d, unsigned long i)
00325         : Request(s, d, SQLRESID), id(i)
00326         {
00327         }
00328 
00339         virtual int Rows() = 0;
00340 
00348         virtual int Cols() = 0;
00349 
00355         virtual std::string ColName(int column) = 0;
00356 
00364         virtual int ColNum(const std::string &column) = 0;
00365 
00371         virtual SQLfield GetValue(int row, int column) = 0;
00372 
00385         virtual SQLfieldList& GetRow() = 0;
00386 
00392         virtual SQLfieldMap& GetRowMap() = 0;
00393 
00401         virtual SQLfieldList* GetRowPtr() = 0;
00402 
00408         virtual SQLfieldMap* GetRowMapPtr() = 0;
00409 
00415         virtual void Free(SQLfieldMap* fm) = 0;
00416 
00422         virtual void Free(SQLfieldList* fl) = 0;
00423 };
00424 
00425 
00430 class SQLhost
00431 {
00432  public:
00433         std::string             id;             /* Database handle id */
00434         std::string             host;   /* Database server hostname */
00435         std::string             ip;             /* resolved IP, needed for at least pgsql.so */
00436         unsigned int    port;   /* Database server port */
00437         std::string             name;   /* Database name */
00438         std::string             user;   /* Database username */
00439         std::string             pass;   /* Database password */
00440         bool                    ssl;    /* If we should require SSL */
00441 
00442         SQLhost()
00443         : id(""), host(""), ip(""), port(0), name(""), user(""), pass(""), ssl(0)
00444         {
00445         }
00446 
00447         SQLhost(const std::string& i, const std::string& h, unsigned int p, const std::string& n, const std::string& u, const std::string& pa, bool s)
00448         : id(i), host(h), ip(""), port(p), name(n), user(u), pass(pa), ssl(s)
00449         {
00450         }
00451 
00455         std::string GetDSN();
00456 };
00457 
00460 bool operator== (const SQLhost& l, const SQLhost& r)
00461 {
00462         return (l.id == r.id && l.host == r.host && l.port == r.port && l.name == r.name && l.user == r.user && l.pass == r.pass && l.ssl == r.ssl);
00463 }
00466 bool operator!= (const SQLhost& l, const SQLhost& r)
00467 {
00468         return (l.id != r.id || l.host != r.host || l.port != r.port || l.name != r.name || l.user != r.user || l.pass != r.pass || l.ssl != r.ssl);
00469 }
00470 
00471 
00497 class QueryQueue : public classbase
00498 {
00499 private:
00500         typedef std::deque<SQLrequest> ReqDeque;
00501 
00502         ReqDeque priority;      /* The priority queue */
00503         ReqDeque normal;        /* The 'normal' queue */
00504         enum { PRI, NOR, NON } which;   /* Which queue the currently active element is at the front of */
00505 
00506 public:
00507         QueryQueue()
00508         : which(NON)
00509         {
00510         }
00511 
00512         void push(const SQLrequest &q)
00513         {
00514                 if(q.pri)
00515                         priority.push_back(q);
00516                 else
00517                         normal.push_back(q);
00518         }
00519 
00520         void pop()
00521         {
00522                 if((which == PRI) && priority.size())
00523                 {
00524                         priority.pop_front();
00525                 }
00526                 else if((which == NOR) && normal.size())
00527                 {
00528                         normal.pop_front();
00529                 }
00530 
00531                 /* Reset this */
00532                 which = NON;
00533 
00534                 /* Silently do nothing if there was no element to pop() */
00535         }
00536 
00537         SQLrequest& front()
00538         {
00539                 switch(which)
00540                 {
00541                         case PRI:
00542                                 return priority.front();
00543                         case NOR:
00544                                 return normal.front();
00545                         default:
00546                                 if(priority.size())
00547                                 {
00548                                         which = PRI;
00549                                         return priority.front();
00550                                 }
00551 
00552                                 if(normal.size())
00553                                 {
00554                                         which = NOR;
00555                                         return normal.front();
00556                                 }
00557 
00558                                 /* This will probably result in a segfault,
00559                                  * but the caller should have checked totalsize()
00560                                  * first so..meh - moron :p
00561                                  */
00562 
00563                                 return priority.front();
00564                 }
00565         }
00566 
00567         std::pair<int, int> size()
00568         {
00569                 return std::make_pair(priority.size(), normal.size());
00570         }
00571 
00572         int totalsize()
00573         {
00574                 return priority.size() + normal.size();
00575         }
00576 
00577         void PurgeModule(Module* mod)
00578         {
00579                 DoPurgeModule(mod, priority);
00580                 DoPurgeModule(mod, normal);
00581         }
00582 
00583 private:
00584         void DoPurgeModule(Module* mod, ReqDeque& q)
00585         {
00586                 for(ReqDeque::iterator iter = q.begin(); iter != q.end(); iter++)
00587                 {
00588                         if(iter->GetSource() == mod)
00589                         {
00590                                 if(iter->id == front().id)
00591                                 {
00592                                         /* It's the currently active query.. :x */
00593                                         iter->SetSource(NULL);
00594                                 }
00595                                 else
00596                                 {
00597                                         /* It hasn't been executed yet..just remove it */
00598                                         iter = q.erase(iter);
00599                                 }
00600                         }
00601                 }
00602         }
00603 };
00604 
00605 
00606 #endif