Planeshift

dal.h

Go to the documentation of this file.
00001 /*
00002  * dal.h by Stefano Angeleri
00003  * Database Abstraction Layer (postgresql)
00004  *
00005  * Copyright (C) 2010 Atomic Blue ([email protected], http://www.atomicblue.org)
00006  *
00007  *
00008  * This program is free software; you can redistribute it and/or
00009  * modify it under the terms of the GNU General Public License
00010  * as published by the Free Software Foundation (version 2 of the License)
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program; if not, write to the Free Software
00017  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00018  */
00019 
00020 #ifndef __DAL_H__
00021 #define __DAL_H__
00022 
00023 #include <idal.h>
00024 
00025 #include <csutil/scf.h>
00026 #include <csutil/scf_implementation.h>
00027 #include <csutil/threading/thread.h>
00028 
00029 #include "iutil/comp.h"
00030 
00031 #include "net/netbase.h"  // Make sure that winsock is included.
00032 
00033 #include <libpq-fe.h>
00034 
00035 #include <csutil/csstring.h>
00036 #include "util/stringarray.h"
00037 #include "util/dbprofile.h"
00038 
00039 using namespace CS::Threading;
00040 
00041 struct iObjectRegistry;
00042 
00043 CS_PLUGIN_NAMESPACE_BEGIN(dbpostgresql)
00044 {
00045     #ifdef USE_DELAY_QUERY
00046     #define THREADED_BUFFER_SIZE 300
00047     class DelayedQueryManager : public CS::Threading::Runnable
00048     {
00049     public:
00050         DelayedQueryManager(const char *host, unsigned int port, const char *database,
00051                                   const char *user, const char *pwd);
00052 
00053         virtual void Run ();
00054         void Push(csString query);
00055         void Stop();
00056     private:
00057         csString arr[THREADED_BUFFER_SIZE];
00058         size_t start, end;
00059         CS::Threading::Mutex mutex;
00060         CS::Threading::RecursiveMutex mutexArray;
00061         CS::Threading::Condition datacondition;
00062         bool m_Close;
00063         psDBProfiles profs;
00064         csString m_host;
00065         unsigned int m_port;
00066         csString m_db;
00067         csString m_user;
00068         csString m_pwd;
00069     };
00070     #endif
00071 
00072     class psMysqlConnection : public scfImplementation2<psMysqlConnection, iComponent, iDataConnection>
00073     {
00074     protected:
00075         PGconn* conn; //Points to mydb after a successfull connection to the db
00076         uint64 lastRow;
00077         csString lastquery;
00078         int stmtNum;
00079         iObjectRegistry *objectReg;
00080         psDBProfiles profs;
00081         csString profileDump;
00082         LogCSV* logcsv;
00083 
00084     public:
00085         psMysqlConnection(iBase *iParent);
00086         virtual ~psMysqlConnection();
00087 
00088         bool Initialize (iObjectRegistry *objectreg);
00089         bool Initialize(const char *host, unsigned int port, const char *database, 
00090                         const char *user, const char *pwd, LogCSV* logcsv);
00091         virtual bool Close();
00092 
00093         int IsValid(void);
00094 
00099         void Escape(csString& to, const char *from);
00100         
00101         iResultSet *Select(const char *sql,...);
00102         int SelectSingleNumber(const char *sql, ...);
00103         unsigned long Command(const char *sql,...);
00104         unsigned long CommandPump(const char *sql,...);
00105 
00106         uint64 GenericInsertWithID(const char *table,const char **fieldnames,psStringArray& fieldvalues);
00107         bool GenericUpdateWithID(const char *table,const char *idfield,const char *id,const char **fieldnames,psStringArray& fieldvalues);
00108         bool GenericUpdateWithID(const char *table,const char *idfield,const char *id,psStringArray& fields);
00109 
00110         const char *GetLastError(void);
00111         const char *GetLastQuery(void)
00112         {
00113             return lastquery;
00114         };
00115         uint64 GetLastInsertID();
00116         
00117         const char *uint64tostring(uint64 value,csString& recv);
00118 
00119         virtual const char* DumpProfile();
00120         virtual void ResetProfile();
00121         
00122         iRecord* NewUpdatePreparedStatement(const char* table, const char* idfield, unsigned int count, const char* file, unsigned int line);
00123         iRecord* NewInsertPreparedStatement(const char* table, unsigned int count, const char* file, unsigned int line);
00124 
00125     #ifdef USE_DELAY_QUERY    
00126         csRef<DelayedQueryManager> dqm;
00127         csRef<Thread> dqmThread;
00128     #endif    
00129     };
00130 
00131 
00132     class psResultRow : public iResultRow
00133     {
00134     protected:
00135         int rowNum;
00136         PGresult *rs;
00137         int max;
00138 
00139     public:
00140         psResultRow()
00141         {
00142             rowNum = 0;
00143             rs = NULL;
00144         };
00145 
00146         void SetMaxFields(int fields)  {    max = fields;   };
00147         void SetResultSet(void* resultsettoken);
00148 
00149         int Fetch(int row);
00150 
00151         const char *operator[](int whichfield);
00152         const char *operator[](const char *fieldname);
00153 
00154         const char* GetString(int whichfield);
00155         const char* GetString(const char *fieldname);
00156 
00157         int GetInt(int whichfield);
00158         int GetInt(const char *fieldname);
00159 
00160         unsigned long GetUInt32(int whichfield);
00161         unsigned long GetUInt32(const char *fieldname);
00162 
00163         float GetFloat(int whichfield);
00164         float GetFloat(const char *fieldname);
00165 
00166         uint64 GetUInt64(int whichfield);
00167         uint64 GetUInt64(const char *fieldname);
00168 
00169         uint64 stringtouint64(const char *stringbuf);
00170         const char *uint64tostring(uint64 value,char *stringbuf,int buflen);
00171     };
00172 
00173     class psResultSet : public iResultSet
00174     {
00175     protected:
00176         PGresult *rs;
00177         unsigned long rows, fields, current;
00178         psResultRow  row;
00179 
00180     public:
00181         psResultSet(PGresult *res);
00182         virtual ~psResultSet();
00183 
00184         void Release(void) { delete this; };
00185 
00186         iResultRow& operator[](unsigned long whichrow);
00187 
00188         unsigned long Count(void) { return rows; };
00189     };
00190 
00191     class dbRecord : public iRecord
00192     {
00193     protected:
00194         enum FIELDTYPE { SQL_TYPE_FLOAT, SQL_TYPE_INT, SQL_TYPE_STRING, SQL_TYPE_NULL };
00195 
00196         typedef struct
00197         {
00198             float fValue;
00199             int iValue;
00200             csString sValue;
00201             FIELDTYPE type;
00202         } StatField;
00203         const char* table;
00204         const char* idfield;
00205         
00206         PGconn *conn;
00207         int *stmtNum;
00208         
00209         psStringArray command;
00210         bool prepared;
00211         
00212         csString stmt;
00213         
00214         unsigned int index;
00215         unsigned int count;
00216         
00217         // Useful for debugging
00218         LogCSV* logcsv;
00219         const char* file;
00220         unsigned int line;
00221         
00222         StatField* temp;
00223         
00224         virtual void AddToStatement(const char* fname) = 0;
00225         
00226         virtual void SetID(uint32 uid) = 0;
00227         
00228     public:
00229         dbRecord(PGconn* db, int *StmtNum, const char* Table, const char* Idfield, unsigned int count, LogCSV* logcsv, const char* file, unsigned int line)
00230         {
00231             conn = db;
00232             table = Table;
00233             idfield = Idfield;
00234             temp = new StatField[count];
00235             index = 0;
00236             this->count = count;
00237             this->logcsv = logcsv;
00238             this->file = file;
00239             this->line = line;
00240             stmtNum = StmtNum;
00241             prepared = false;
00242         }
00243         
00244         virtual ~dbRecord()
00245         {
00246             delete[] temp;
00247         }
00248         
00249         void Reset()
00250         {
00251             index = 0;
00252             command.Empty(); //clears the command array to avoid restarting from a wrong position.
00253         }
00254         
00255         void AddField(const char* fname, float fValue);
00256         
00257         void AddField(const char* fname, int iValue);
00258         
00259         void AddField(const char* fname, unsigned int uiValue);
00260         
00261         void AddField(const char* fname, unsigned short usValue);
00262 
00263         void AddField(const char* fname, const char* sValue);
00264 
00265         void AddFieldNull(const char* fname);
00266         
00267         virtual bool Prepare() = 0;
00268 
00269         virtual bool Execute(uint32 uid);
00270     };
00271 
00272     class dbInsert : public dbRecord
00273     {
00274         virtual void AddToStatement(const char* fname)
00275         {
00276             if(!prepared)
00277                 command.Push(fname);
00278         }
00279         
00280         virtual void SetID(uint32 /*uid*/) {};
00281         
00282     public:
00283         dbInsert(PGconn* db, int *StmtNum, const char* Table, unsigned int count, LogCSV* logcsv, const char* file, unsigned int line)
00284         : dbRecord(db, StmtNum, Table, "", count, logcsv, file, line) { }
00285         
00286         virtual bool Prepare();
00287     };
00288 
00289     class dbUpdate : public dbRecord
00290     {
00291         virtual void AddToStatement(const char* fname)
00292         {
00293             if(!prepared)
00294                 command.FormatPush("%s = $", fname);
00295         }
00296         
00297         virtual void SetID(uint32 uid) 
00298         {
00299             temp[index].iValue = uid;
00300             temp[index].type = SQL_TYPE_INT;
00301             index++;
00302         }
00303     public:
00304         dbUpdate(PGconn* db, int *StmtNum, const char* Table, const char* Idfield, unsigned int count, LogCSV* logcsv, const char* file, unsigned int line)
00305         : dbRecord(db, StmtNum, Table, Idfield, count, logcsv, file, line) { }
00306         virtual bool Prepare();
00307 
00308     };
00309 }
00310 CS_PLUGIN_NAMESPACE_END(dbpostgresql)
00311     
00312 #endif