Planeshift
|
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