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