Planeshift

dal.h

Go to the documentation of this file.
00001 /*
00002  * dal.h by Stefano Angeleri
00003  * Database Abstraction Layer (sqlite3)
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 <sqlite3.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(dbsqlite3)
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         sqlite3* m_conn;
00058         csString arr[THREADED_BUFFER_SIZE];
00059         size_t start, end;
00060         CS::Threading::Mutex mutex;
00061         CS::Threading::RecursiveMutex mutexArray;
00062         CS::Threading::Condition datacondition;
00063         bool m_Close;
00064         psDBProfiles profs;
00065         csString m_host;
00066         unsigned int m_port;
00067         csString m_db;
00068         csString m_user;
00069         csString m_pwd;
00070     };
00071     #endif
00072 
00073     class psMysqlConnection : public scfImplementation2<psMysqlConnection, iComponent, iDataConnection>
00074     {
00075     protected:
00076         sqlite3 *conn;  //Points to mydb after a successfull connection to the db
00077         csString lastquery;
00078         iObjectRegistry *objectReg;
00079         psDBProfiles profs;
00080         csString profileDump;
00081         LogCSV* logcsv;
00082 
00083     public:
00084         psMysqlConnection(iBase *iParent);
00085         virtual ~psMysqlConnection();
00086 
00087         bool Initialize (iObjectRegistry *objectreg);
00088         bool Initialize(const char *host, unsigned int port, const char *database, 
00089                         const char *user, const char *pwd, LogCSV* logcsv);
00090         virtual bool Close();
00091 
00092         int IsValid(void);
00093 
00098         void Escape(csString& to, const char *from);
00099         
00100         iResultSet *Select(const char *sql,...);
00101         int SelectSingleNumber(const char *sql, ...);
00102         unsigned long Command(const char *sql,...);
00103         unsigned long CommandPump(const char *sql,...);
00104 
00105         uint64 GenericInsertWithID(const char *table,const char **fieldnames,psStringArray& fieldvalues);
00106         bool GenericUpdateWithID(const char *table,const char *idfield,const char *id,const char **fieldnames,psStringArray& fieldvalues);
00107         bool GenericUpdateWithID(const char *table,const char *idfield,const char *id,psStringArray& fields);
00108 
00109         const char *GetLastError(void);
00110         const char *GetLastQuery(void)
00111         {
00112             return lastquery;
00113         };
00114         uint64 GetLastInsertID();
00115         
00116         const char *uint64tostring(uint64 value,csString& recv);
00117 
00118         virtual const char* DumpProfile();
00119         virtual void ResetProfile();
00120         
00121         iRecord* NewUpdatePreparedStatement(const char* table, const char* idfield, unsigned int count, const char* file, unsigned int line);
00122         iRecord* NewInsertPreparedStatement(const char* table, unsigned int count, const char* file, unsigned int line);
00123 
00124     #ifdef USE_DELAY_QUERY    
00125         csRef<DelayedQueryManager> dqm;
00126         csRef<Thread> dqmThread;
00127     #endif    
00128     };
00129 
00130 
00131     class psResultRow : public iResultRow
00132     {
00133     protected:
00134         int rowNum;
00135         char **rs;
00136         int max;
00137 
00138     public:
00139         psResultRow()
00140         {
00141             rowNum = 0;
00142             rs = NULL;
00143         };
00144 
00145         void SetMaxFields(int fields)  {    max = fields;   };
00146         void SetResultSet(void* resultsettoken);
00147 
00148         int Fetch(int row);
00149 
00150         const char *operator[](int whichfield);
00151         const char *operator[](const char *fieldname);
00152 
00153         const char* GetString(int whichfield);
00154         const char* GetString(const char *fieldname);
00155 
00156         int GetInt(int whichfield);
00157         int GetInt(const char *fieldname);
00158 
00159         unsigned long GetUInt32(int whichfield);
00160         unsigned long GetUInt32(const char *fieldname);
00161 
00162         float GetFloat(int whichfield);
00163         float GetFloat(const char *fieldname);
00164 
00165         uint64 GetUInt64(int whichfield);
00166         uint64 GetUInt64(const char *fieldname);
00167 
00168         uint64 stringtouint64(const char *stringbuf);
00169         const char *uint64tostring(uint64 value,char *stringbuf,int buflen);
00170     };
00171 
00172     class psResultSet : public iResultSet
00173     {
00174     protected:
00175         char **rs;
00176         unsigned long rows, fields, current;
00177         psResultRow  row;
00178 
00179     public:
00180         psResultSet(char **result, int rows, int columns);
00181         virtual ~psResultSet();
00182 
00183         void Release(void) { delete this; };
00184 
00185         iResultRow& operator[](unsigned long whichrow);
00186 
00187         unsigned long Count(void) { return rows; };
00188     };
00189 
00190     class dbRecord : public iRecord
00191     {
00192     protected:
00193         enum FIELDTYPE { SQL_TYPE_FLOAT, SQL_TYPE_INT, SQL_TYPE_STRING, SQL_TYPE_NULL };
00194 
00195         typedef struct
00196         {
00197             float fValue;
00198             int iValue;
00199             csString sValue;
00200             FIELDTYPE type;
00201         } StatField;
00202         const char* table;
00203         const char* idfield;
00204         
00205         sqlite3* conn;
00206         
00207         psStringArray command;
00208         bool prepared;
00209         
00210         sqlite3_stmt* stmt;
00211         
00212         unsigned int index;
00213         unsigned int count;
00214         
00215         // Useful for debugging
00216         LogCSV* logcsv;
00217         const char* file;
00218         unsigned int line;
00219         
00220         StatField* temp;
00221         
00222         virtual void AddToStatement(const char* fname) = 0;
00223         
00224         virtual void SetID(uint32 uid) = 0;
00225         
00226     public:
00227         dbRecord(sqlite3* db, const char* Table, const char* Idfield, unsigned int count, LogCSV* logcsv, const char* file, unsigned int line)
00228         {
00229             conn = db;
00230             table = Table;
00231             idfield = Idfield;
00232             temp = new StatField[count];
00233             index = 0;
00234             this->count = count;
00235             this->logcsv = logcsv;
00236             this->file = file;
00237             this->line = line;
00238             
00239             stmt = NULL;
00240             prepared = false;
00241         }
00242         
00243         virtual ~dbRecord()
00244         {
00245             sqlite3_finalize(stmt);
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             if(stmt)
00254                 sqlite3_reset(stmt);        
00255         }
00256 
00257         
00258         void AddField(const char* fname, float fValue);
00259         
00260         void AddField(const char* fname, int iValue);
00261         
00262         void AddField(const char* fname, unsigned int uiValue);
00263         
00264         void AddField(const char* fname, unsigned short usValue);
00265 
00266         void AddField(const char* fname, const char* sValue);
00267 
00268         void AddFieldNull(const char* fname);
00269         
00270         virtual bool Prepare() = 0;
00271 
00272         virtual bool Execute(uint32 uid);
00273     };
00274 
00275     class dbInsert : public dbRecord
00276     {
00277         virtual void AddToStatement(const char* fname)
00278         {
00279             if(!prepared)
00280                 command.Push(fname);
00281         }
00282         
00283         virtual void SetID(uint32 /*uid*/)  {  };
00284         
00285     public:
00286         dbInsert(sqlite3* db, const char* Table, unsigned int count, LogCSV* logcsv, const char* file, unsigned int line)
00287         : dbRecord(db, Table, "", count, logcsv, file, line) { }
00288         
00289         virtual bool Prepare();
00290     };
00291 
00292     class dbUpdate : public dbRecord
00293     {
00294         virtual void AddToStatement(const char* fname)
00295         {
00296             if(!prepared)
00297                 command.FormatPush("%s = ?", fname);
00298         }
00299         
00300         virtual void SetID(uint32 uid) 
00301         {
00302             temp[index].iValue = uid;
00303             temp[index].type = SQL_TYPE_INT;
00304             index++;
00305         }
00306     public:
00307         dbUpdate(sqlite3* db, const char* Table, const char* Idfield, unsigned int count, LogCSV* logcsv, const char* file, unsigned int line)
00308         : dbRecord(db, Table, Idfield, count, logcsv, file, line) { }
00309         virtual bool Prepare();
00310 
00311     };
00312 } CS_PLUGIN_NAMESPACE_END(dbsqlite3)   
00313 #endif
00314