Planeshift
dal.h
Go to the documentation of this file.
1 //
2 // Database Abstraction Layer
3 // Keith Fulton <keith@paqrat.com>
4 // 02/14/02
5 //
6 
7 #ifndef __DAL_H__
8 #define __DAL_H__
9 
10 #include <idal.h>
11 
12 #include <csutil/scf.h>
13 #include <csutil/scf_implementation.h>
14 #include <csutil/threading/thread.h>
15 
16 #include "iutil/comp.h"
17 
18 #include "net/netbase.h" // Make sure that winsock is included.
19 
20 #include <mysql.h>
21 
22 #include <csutil/csstring.h>
23 #include "util/stringarray.h"
24 #include "util/dbprofile.h"
25 
26 using namespace CS::Threading;
27 
28 struct iObjectRegistry;
29 
31 {
32  #ifdef USE_DELAY_QUERY
33  #define THREADED_BUFFER_SIZE 300
34  class DelayedQueryManager : public CS::Threading::Runnable
35  {
36  public:
37  DelayedQueryManager(const char *host, unsigned int port, const char *database,
38  const char *user, const char *pwd);
39 
40  virtual void Run ();
41  void Push(csString query);
42  void Stop();
43  private:
44  MYSQL* m_conn;
45  csString arr[THREADED_BUFFER_SIZE];
46  size_t start, end;
47  CS::Threading::Mutex mutex;
48  CS::Threading::RecursiveMutex mutexArray;
49  CS::Threading::Condition datacondition;
50  bool m_Close;
51  psDBProfiles profs;
52  csString m_host;
53  unsigned int m_port;
54  csString m_db;
55  csString m_user;
56  csString m_pwd;
57  };
58  #endif
59 
60  class psMysqlConnection : public scfImplementation2<psMysqlConnection, iComponent, iDataConnection>
61  {
62  protected:
63  MYSQL mydb; // Mysql connection
64  MYSQL *conn; // Points to mydb after a successfull connection to the db
65  csString lastquery;
66  iObjectRegistry *objectReg;
67  psDBProfiles profs;
68  csString profileDump;
69  LogCSV* logcsv;
70 
71  public:
72  psMysqlConnection(iBase *iParent);
73  virtual ~psMysqlConnection();
74 
75  bool Initialize (iObjectRegistry *objectreg);
76  bool Initialize(const char *host, unsigned int port, const char *database,
77  const char *user, const char *pwd, LogCSV* logcsv);
78  virtual bool Close();
79 
80  int IsValid(void);
81 
86  void Escape(csString& to, const char *from);
87 
88  iResultSet *Select(const char *sql,...);
89  int SelectSingleNumber(const char *sql, ...);
90  unsigned long Command(const char *sql,...);
91  unsigned long CommandPump(const char *sql,...);
92 
93  uint64 GenericInsertWithID(const char *table,const char **fieldnames,psStringArray& fieldvalues);
94  bool GenericUpdateWithID(const char *table,const char *idfield,const char *id,const char **fieldnames,psStringArray& fieldvalues);
95  bool GenericUpdateWithID(const char *table,const char *idfield,const char *id,psStringArray& fields);
96 
97  const char *GetLastError(void);
98  const char *GetLastQuery(void)
99  {
100  return lastquery;
101  };
102  uint64 GetLastInsertID();
103 
104  const char *uint64tostring(uint64 value,csString& recv);
105 
106  virtual const char* DumpProfile();
107  virtual void ResetProfile();
108 
109  iRecord* NewUpdatePreparedStatement(const char* table, const char* idfield, unsigned int count, const char* file, unsigned int line);
110  iRecord* NewInsertPreparedStatement(const char* table, unsigned int count, const char* file, unsigned int line);
111 
112  #ifdef USE_DELAY_QUERY
113  csRef<DelayedQueryManager> dqm;
114  csRef<Thread> dqmThread;
115  #endif
116  };
117 
118 
119  class psResultRow : public iResultRow
120  {
121  protected:
122  MYSQL_ROW rr;
123  MYSQL_RES *rs;
124  int max;
125  int last_index;
126 
127  public:
128  psResultRow()
129  {
130  rr = NULL;
131  rs = NULL;
132  last_index=0;
133  };
134 
135  void SetMaxFields(int fields) { max = fields; };
136  void SetResultSet(void* resultsettoken);
137 
138  int Fetch(int row);
139 
140  const char *operator[](int whichfield);
141  const char *operator[](const char *fieldname);
142 
143  const char* GetString(int whichfield);
144  const char* GetString(const char *fieldname);
145 
146  int GetInt(int whichfield);
147  int GetInt(const char *fieldname);
148 
149  unsigned long GetUInt32(int whichfield);
150  unsigned long GetUInt32(const char *fieldname);
151 
152  float GetFloat(int whichfield);
153  float GetFloat(const char *fieldname);
154 
155  uint64 GetUInt64(int whichfield);
156  uint64 GetUInt64(const char *fieldname);
157 
158  uint64 stringtouint64(const char *stringbuf);
159  const char *uint64tostring(uint64 value,char *stringbuf,int buflen);
160  };
161 
162  class psResultSet : public iResultSet
163  {
164  protected:
165  MYSQL_RES *rs;
166  unsigned long rows, fields, current;
167  psResultRow row;
168 
169  public:
170  psResultSet(MYSQL *conn);
171  virtual ~psResultSet();
172 
173  void Release(void) { delete this; };
174 
175  iResultRow& operator[](unsigned long whichrow);
176 
177  unsigned long Count(void) { return rows; };
178  };
179 
180  class dbRecord : public iRecord
181  {
182  protected:
183  const char* table;
184  const char* idfield;
185 
186  MYSQL* conn;
187 
188  psStringArray command;
189  bool prepared;
190 
191  MYSQL_BIND* bind;
192  MYSQL_STMT* stmt;
193 
194  unsigned int index;
195  unsigned int count;
196 
197  // Useful for debugging
198  LogCSV* logcsv;
199  const char* file;
200  unsigned int line;
201 
202  // This is a holding structure to ensure the data is available as long as the binding needs it.
203  typedef struct{
204  int iValue;
205  // On *nix and Windows, uint32 is equivalent to unsigned int
206  // this is important for SQL
207  unsigned int uiValue;
208  unsigned short usValue;
209  float fValue;
210  csString string;
211  unsigned long length;
212  } dataType;
213 
214  dataType* temp;
215 
216  virtual void AddToStatement(const char* fname) = 0;
217 
218  virtual void SetID(uint32 uid) = 0;
219 
220  public:
221  dbRecord(MYSQL* db, const char* Table, const char* Idfield, unsigned int count, LogCSV* logcsv, const char* file, unsigned int line)
222  {
223  conn = db;
224  table = Table;
225  idfield = Idfield;
226  bind = new MYSQL_BIND[count];
227  memset(bind, 0, sizeof(MYSQL_BIND) * count);
228  temp = new dataType[count];
229  index = 0;
230  this->count = count;
231  this->logcsv = logcsv;
232  this->file = file;
233  this->line = line;
234 
235  stmt = (MYSQL_STMT*) mysql_stmt_init(conn);
236  prepared = false;
237  }
238 
239  virtual ~dbRecord()
240  {
241  mysql_stmt_close(stmt);
242  delete[] bind;
243  delete[] temp;
244  }
245 
246  void Reset()
247  {
248  index = 0;
249  memset(bind, 0, sizeof(MYSQL_BIND) * count);
250  command.Empty(); //clears the command array to avoid restarting from a wrong position.
251  }
252 
253 
254  void AddField(const char* fname, float fValue);
255 
256  void AddField(const char* fname, int iValue);
257 
258  void AddField(const char* fname, unsigned int uiValue);
259 
260  void AddField(const char* fname, unsigned short usValue);
261 
262  void AddField(const char* fname, const char* sValue);
263 
264  void AddFieldNull(const char* fname);
265 
266  virtual bool Prepare() = 0;
267 
268  virtual bool Execute(uint32 uid);
269  };
270 
271  class dbInsert : public dbRecord
272  {
273  virtual void AddToStatement(const char* fname)
274  {
275  if(!prepared)
276  command.Push(fname);
277  }
278 
279  virtual void SetID(uint32 /*uid*/) { };
280 
281  public:
282  dbInsert(MYSQL* db, const char* Table, unsigned int count, LogCSV* logcsv, const char* file, unsigned int line)
283  : dbRecord(db, Table, "", count, logcsv, file, line) { }
284 
285  virtual bool Prepare();
286  };
287 
288  class dbUpdate : public dbRecord
289  {
290  virtual void AddToStatement(const char* fname)
291  {
292  if(!prepared)
293  command.FormatPush("%s = ?", fname);
294  }
295 
296  virtual void SetID(uint32 uid)
297  {
298  temp[index].uiValue = uid;
299  bind[index].buffer_type = MYSQL_TYPE_LONG;
300  bind[index].buffer = &(temp[index].uiValue);
301  bind[index].is_unsigned = true;
302  index++;
303  }
304  public:
305  dbUpdate(MYSQL* db, const char* Table, const char* Idfield, unsigned int count, LogCSV* logcsv, const char* file, unsigned int line)
306  : dbRecord(db, Table, Idfield, count, logcsv, file, line) { }
307 
308  virtual bool Prepare();
309 
310  };
311 }
312 CS_PLUGIN_NAMESPACE_END(dbmysql)
313 #endif
314 
Definition: log.h:306
iDataConnection * db
Global connection to the Database. Set from the psDatabase class.
CS_PLUGIN_NAMESPACE_BEGIN(dbmysql)
Definition: dal.h:30
Statistics of time consumed by SQL statements.
Definition: dbprofile.h:33
void void Initialize(iObjectRegistry *object_reg)
#define max(x, y)
Definition: xdelta3.h:314
A slightly improved version of csStringArray, sporting the handy FormatPush method.
Definition: stringarray.h:33