Merge ktlim@zizzer:/bk/newmem
[gem5.git] / src / base / mysql.hh
1 /*
2 * Copyright (c) 2004-2005 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Authors: Nathan Binkert
29 */
30
31 #ifndef __BASE_MYSQL_HH__
32 #define __BASE_MYSQL_HH__
33
34 #define TO_BE_INCLUDED_LATER 0
35
36 #include <cassert>
37 #include <iosfwd>
38 #include <mysql_version.h>
39 #include <mysql.h>
40 #include <string>
41 #include <sstream>
42
43 namespace MySQL {
44
45 class Error
46 {
47 protected:
48 const char *error;
49
50 public:
51 Error() : error(NULL) {}
52
53 Error &clear() { error = NULL; return *this; }
54 Error &set(const char *err) { error = err; return *this; }
55
56 const char *string() const { return error; }
57
58 operator bool() const { return error != NULL; }
59 bool operator!() const { return error == NULL; }
60 };
61
62 std::ostream &operator<<(std::ostream &stream, const Error &error);
63
64 class Result
65 {
66 private:
67 MYSQL_RES *result;
68 int *refcount;
69
70 void
71 decref()
72 {
73 if (!refcount)
74 return;
75
76 *refcount -= 1;
77 if (*refcount == 0) {
78 mysql_free_result(result);
79 delete refcount;
80 }
81
82 refcount = NULL;
83 }
84
85 public:
86 Result()
87 : result(0), refcount(NULL)
88 { }
89
90 Result(MYSQL_RES *res)
91 : result(res)
92 {
93 if (result)
94 refcount = new int(1);
95 else
96 refcount = NULL;
97 }
98
99 Result(const Result &result)
100 : result(result.result), refcount(result.refcount)
101 {
102 if (result)
103 *refcount += 1;
104 }
105
106 ~Result()
107 {
108 decref();
109 }
110
111 const Result &
112 operator=(MYSQL_RES *res)
113 {
114 decref();
115 result = res;
116 if (result)
117 refcount = new int(1);
118
119 return *this;
120 }
121
122 const Result &
123 operator=(const Result &res)
124 {
125 decref();
126 result = res.result;
127 refcount = res.refcount;
128 if (result)
129 *refcount += 1;
130
131 return *this;
132 }
133
134 operator bool() const { return result != NULL; }
135 bool operator!() const { return result == NULL; }
136
137 unsigned
138 num_fields()
139 {
140 assert(result);
141 return mysql_num_fields(result);
142 }
143
144 MYSQL_ROW
145 fetch_row()
146 {
147 return mysql_fetch_row(result);
148 }
149
150 unsigned long *
151 fetch_lengths()
152 {
153 return mysql_fetch_lengths(result);
154 }
155 };
156
157 typedef MYSQL_ROW Row;
158
159 class Connection
160 {
161 protected:
162 MYSQL mysql;
163 bool valid;
164
165 protected:
166 std::string _host;
167 std::string _user;
168 std::string _passwd;
169 std::string _database;
170
171 public:
172 Connection();
173 virtual ~Connection();
174
175 bool connected() const { return valid; }
176 bool connect(const std::string &host, const std::string &user,
177 const std::string &passwd, const std::string &database);
178 void close();
179
180 public:
181 Error error;
182 operator MYSQL *() { return &mysql; }
183
184 public:
185 bool query(const std::string &sql);
186
187 bool
188 query(const std::stringstream &sql)
189 {
190 return query(sql.str());
191 }
192
193 bool
194 autocommit(bool mode)
195 {
196 return mysql_autocommit(&mysql, mode);
197 }
198
199 bool
200 commit()
201 {
202 return mysql_commit(&mysql);
203 }
204
205 bool
206 rollback()
207 {
208 return mysql_rollback(&mysql);
209 }
210
211 unsigned
212 field_count()
213 {
214 return mysql_field_count(&mysql);
215 }
216
217 unsigned
218 affected_rows()
219 {
220 return mysql_affected_rows(&mysql);
221 }
222
223 unsigned
224 insert_id()
225 {
226 return mysql_insert_id(&mysql);
227 }
228
229
230 Result
231 store_result()
232 {
233 error.clear();
234 Result result = mysql_store_result(&mysql);
235 if (!result)
236 error.set(mysql_error(&mysql));
237
238 return result;
239 }
240 };
241
242 #if 0
243 class BindProxy
244 {
245 MYSQL_BIND *bind;
246 BindProxy(MYSQL_BIND *b) : bind(b) {}
247
248 void operator=(bool &buffer)
249 {
250 bind->buffer_type = MYSQL_TYPE_TINY;
251 bind->buffer = (char *)&buffer;
252 }
253
254 void operator=(int8_t &buffer)
255 {
256 bind->buffer_type = MYSQL_TYPE_TINY;
257 bind->buffer = (char *)&buffer;
258 }
259
260 void operator=(int16_t &buffer)
261 {
262 bind->buffer_type = MYSQL_TYPE_SHORT;
263 bind->buffer = (char *)&buffer;
264 }
265
266 void operator=(int32_t &buffer)
267 {
268 bind->buffer_type = MYSQL_TYPE_LONG;
269 bind->buffer = (char *)&buffer;
270 }
271
272 void operator=(int64_t &buffer)
273 {
274 bind->buffer_type = MYSQL_TYPE_LONGLONG;
275 bind->buffer = (char *)&buffer;
276 }
277
278 void operator=(uint8_t &buffer)
279 {
280 bind->buffer_type = MYSQL_TYPE_TINY;
281 bind->buffer = (char *)&buffer;
282 }
283
284 void operator=(uint16_t &buffer)
285 {
286 bind->buffer_type = MYSQL_TYPE_SHORT;
287 bind->buffer = (char *)&buffer;
288 }
289
290 void operator=(uint32_t &buffer)
291 {
292 bind->buffer_type = MYSQL_TYPE_LONG;
293 bind->buffer = (char *)&buffer;
294 }
295
296 void operator=(uint64_t &buffer)
297 {
298 bind->buffer_type = MYSQL_TYPE_LONGLONG;
299 bind->buffer = (char *)&buffer;
300 }
301
302 void operator=(float &buffer)
303 {
304 bind->buffer_type = MYSQL_TYPE_FLOAT;
305 bind->buffer = (char *)&buffer;
306 }
307
308 void operator=(double &buffer)
309 {
310 bind->buffer_type = MYSQL_TYPE_DOUBLE;
311 bind->buffer = (char *)&buffer;
312 }
313
314 void operator=(Time &buffer)
315 {
316 bind->buffer_type = MYSQL_TYPE_DATE;
317 bind->buffer = (char *)&buffer;
318 }
319
320 void operator=(const char *buffer)
321 {
322 bind->buffer_type = MYSQL_TYPE_VAR_STRING;
323 bind->buffer = buffer;
324 }
325
326 void operator=(const std::string &buffer)
327 {
328 bind->buffer_type = MYSQL_TYPE_VAR_STRING;
329 bind->buffer = (char *)&buffer;
330 bind->length = buffer.length;
331 }
332
333 bool
334 set_null(bool null)
335 {
336 bind->is_null = null;
337 }
338 };
339
340 class Statement
341 {
342 protected:
343 Error &error;
344 MYSQL_STMT *stmt;
345 MYSQL_BIND *bind;
346 int size;
347
348 public:
349 Statement(Connection &mysql)
350 : error(mysql.error), bind(NULL), size(0)
351 {
352 stmt = mysql_stmt_init(mysql);
353 assert(valid() && "mysql_stmt_init(), out of memory\n");
354 }
355
356 ~Statement()
357 {
358 assert(valid());
359 error.clear();
360 if (mysql_stmt_close(stmt))
361 error.set(mysql_stmt_error(stmt));
362
363 if (bind)
364 delete [] bind;
365 }
366
367 bool valid()
368 {
369 return stmt != NULL;
370 }
371
372 void prepare(const std::string &query)
373 {
374 assert(valid());
375 mysql.error.clear();
376 if (mysql_stmt_prepare(mysql, query, strlen(query)))
377 mysql.error.set(mysql_stmt_error(stmt));
378
379 int size = count();
380 bind = new MYSQL_BIND[size];
381 }
382
383 unsigned count()
384 {
385 assert(valid());
386 return mysql_stmt_param_count(stmt);
387 }
388
389 unsigned affected()
390 {
391 assert(valid());
392 return mysql_stmt_affected_rows(stmt);
393 }
394
395 void bind(MYSQL_BIND *bind)
396 {
397 mysql.error.clear();
398 if (mysql_stmt_bind_param(stmt, bind))
399 mysql.error.set(mysql_stmt_error(stmt));
400 }
401
402 BindProxy operator[](int index)
403 {
404 assert(index > 0 && index < N);
405 return &bind[N];
406 }
407
408 operator MYSQL_BIND *()
409 {
410 return bind;
411 }
412
413 void operator()()
414 {
415 assert(valid());
416 error.clear();
417 if (mysql_stmt_execute(stmt))
418 error.set(mysql_stmt_error(stmt));
419 }
420 }
421 #endif
422
423 /* namespace MySQL */ }
424
425 #endif // __BASE_MYSQL_HH__