00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00077 #ifdef ENABLE_MYSQL
00078 #include "mysql.h"
00079 #endif
00080
00081 #include <stdio.h>
00082 #include <stdlib.h>
00083 #include <stdbool.h>
00084 #include <stdarg.h>
00085 #include <string.h>
00086 #include "qDecoder.h"
00087 #include "qInternal.h"
00088
00111 Q_DB *qDbInit(const char *dbtype, const char *addr, int port, const char *username, const char *password, const char *database, bool autocommit) {
00112
00113 #ifdef _Q_ENABLE_MYSQL
00114 if (strcmp(dbtype, "MYSQL")) return NULL;
00115 #else
00116 return NULL;
00117 #endif
00118 if(dbtype == NULL || addr == NULL || username == NULL || password == NULL || database == NULL) return NULL;
00119
00120
00121 Q_DB *db;
00122 if ((db = (Q_DB *)malloc(sizeof(Q_DB))) == NULL) return NULL;
00123 memset((void *)db, 0, sizeof(Q_DB));
00124 db->connected = false;
00125
00126
00127 db->info.dbtype = strdup(dbtype);
00128 db->info.addr = strdup(addr);
00129 db->info.port = port;
00130 db->info.username = strdup(username);
00131 db->info.password = strdup(password);
00132 db->info.database = strdup(database);
00133 db->info.autocommit = autocommit;
00134 db->info.fetchtype = false;
00135
00136
00137 #ifdef _Q_ENABLE_MYSQL
00138 db->mysql = NULL;
00139 #endif
00140
00141 return db;
00142 }
00143
00151 bool qDbOpen(Q_DB *db) {
00152 if (db == NULL) return false;
00153
00154
00155 if (db->connected == true) {
00156 qDbClose(db);
00157 }
00158
00159 #ifdef _Q_ENABLE_MYSQL
00160
00161 if(db->mysql != NULL) qDbClose(db);
00162
00163 db->mysql = mysql_init(NULL);
00164 if(db->mysql == NULL) return false;
00165
00166
00167 my_bool reconnect = _Q_MYSQL_OPT_RECONNECT;
00168 unsigned int connect_timeout = _Q_MYSQL_OPT_CONNECT_TIMEOUT;
00169 unsigned int read_timeout = _Q_MYSQL_OPT_READ_TIMEOUT;
00170 unsigned int write_timeout = _Q_MYSQL_OPT_WRITE_TIMEOUT;
00171
00172 if(reconnect != false) mysql_options(db->mysql, MYSQL_OPT_RECONNECT, (char *)&reconnect);
00173 if(connect_timeout > 0) mysql_options(db->mysql, MYSQL_OPT_CONNECT_TIMEOUT, (char *)&connect_timeout);
00174 if(read_timeout > 0) mysql_options(db->mysql, MYSQL_OPT_READ_TIMEOUT, (char *)&read_timeout);
00175 if(write_timeout > 0) mysql_options(db->mysql, MYSQL_OPT_WRITE_TIMEOUT, (char *)&write_timeout);
00176
00177
00178 if(mysql_real_connect(db->mysql, db->info.addr, db->info.username, db->info.password, db->info.database, db->info.port, NULL, 0) == NULL) {
00179 qDbClose(db);
00180 return false;
00181 }
00182
00183
00184 if (mysql_autocommit(db->mysql, db->info.autocommit) != 0) {
00185 qDbClose(db);
00186 return false;
00187 }
00188
00189
00190 db->connected = true;
00191
00192 return true;
00193 #else
00194 return false;
00195 #endif
00196 }
00197
00209 bool qDbClose(Q_DB *db) {
00210 if (db == NULL) return false;
00211
00212 #ifdef _Q_ENABLE_MYSQL
00213 if(db->mysql != NULL) {
00214 mysql_close(db->mysql);
00215 db->mysql = NULL;
00216 }
00217 db->connected = false;
00218 return true;
00219 #else
00220 return false;
00221 #endif
00222 }
00223
00231 bool qDbFree(Q_DB *db) {
00232 if (db == NULL) return false;
00233 qDbClose(db);
00234
00235 free(db->info.dbtype);
00236 free(db->info.addr);
00237 free(db->info.username);
00238 free(db->info.password);
00239 free(db->info.database);
00240 free(db);
00241
00242 return true;
00243 }
00244
00256 const char *qDbGetError(Q_DB *db, unsigned int *errorno) {
00257 if (db == NULL || db->connected == false) return "(no opened db)";
00258
00259 unsigned int eno = 0;
00260 const char *emsg;
00261 #ifdef _Q_ENABLE_MYSQL
00262 eno = mysql_errno(db->mysql);
00263 if(eno == 0) emsg = "(no error)";
00264 else emsg = mysql_error(db->mysql);
00265 #else
00266 emsg = "(not implemented)";
00267 #endif
00268
00269 if(errorno != NULL) *errorno = eno;
00270 return emsg;
00271 }
00272
00283 bool qDbPing(Q_DB *db) {
00284 if (db == NULL) return false;
00285
00286 #ifdef _Q_ENABLE_MYSQL
00287 if (db->connected == true && mysql_ping(db->mysql) == 0) {
00288 return true;
00289 } else {
00290 if (db->connected == true) {
00291 qDbClose(db);
00292 }
00293
00294 if (qDbOpen(db) == true) {
00295 DEBUG("Connection recovered.");
00296 return true;
00297 }
00298 }
00299
00300 return false;
00301 #else
00302 return false;
00303 #endif
00304 }
00305
00316 bool qDbGetLastConnStatus(Q_DB *db) {
00317 if (db == NULL) return false;
00318
00319 return db->connected;
00320 }
00321
00336 bool qDbSetFetchType(Q_DB *db, bool use) {
00337 if (db == NULL) return false;
00338 db->info.fetchtype = use;
00339 return true;
00340 }
00341
00343
00345
00354 int qDbExecuteUpdate(Q_DB *db, const char *query) {
00355 if (db == NULL || db->connected == false) return -1;
00356
00357 #ifdef _Q_ENABLE_MYSQL
00358 int affected = -1;
00359
00360
00361 DEBUG("%s", query);
00362 if (mysql_query(db->mysql, query)) return -1;
00363
00364
00365 if ((affected = mysql_affected_rows(db->mysql)) < 0) return -1;
00366
00367 return affected;
00368 #else
00369 return -1;
00370 #endif
00371 }
00372
00381 int qDbExecuteUpdatef(Q_DB *db, const char *format, ...) {
00382 char query[1024];
00383 va_list arglist;
00384
00385 va_start(arglist, format);
00386 vsnprintf(query, sizeof(query), format, arglist);
00387 va_end(arglist);
00388
00389 return qDbExecuteUpdate(db, query);
00390 }
00391
00400 Q_DBRESULT *qDbExecuteQuery(Q_DB *db, const char *query) {
00401 if (db == NULL || db->connected == false) return NULL;
00402
00403 #ifdef _Q_ENABLE_MYSQL
00404
00405 DEBUG("%s", query);
00406 if (mysql_query(db->mysql, query)) return NULL;
00407
00408
00409 Q_DBRESULT *result = (Q_DBRESULT *)malloc(sizeof(Q_DBRESULT));
00410 if (result == NULL) return NULL;
00411
00412 result->fetchtype = db->info.fetchtype;
00413 if(result->fetchtype == false) {
00414 result->rs = mysql_store_result(db->mysql);
00415 } else {
00416 result->rs = mysql_use_result(db->mysql);
00417 }
00418 if (result->rs == NULL) {
00419 free(result);
00420 return NULL;
00421 }
00422
00423
00424 result->fields = NULL;
00425 result->row = NULL;
00426 result->cols = mysql_num_fields(result->rs);
00427 result->cursor = 0;
00428
00429 return result;
00430 #else
00431 return NULL;
00432 #endif
00433 }
00434
00443 Q_DBRESULT *qDbExecuteQueryf(Q_DB *db, const char *format, ...) {
00444 char query[1024];
00445 va_list arglist;
00446
00447 va_start(arglist, format);
00448 vsnprintf(query, sizeof(query), format, arglist);
00449 va_end(arglist);
00450
00451 return qDbExecuteQuery(db, query);
00452 }
00453
00461 bool qDbResultNext(Q_DBRESULT *result) {
00462 #ifdef _Q_ENABLE_MYSQL
00463 if (result == NULL || result->rs == NULL) return false;
00464
00465 if ((result->row = mysql_fetch_row(result->rs)) == NULL) return false;
00466 result->cursor++;
00467
00468 return true;
00469 #else
00470 return false;
00471 #endif
00472 }
00473
00481 bool qDbResultFree(Q_DBRESULT *result) {
00482 #ifdef _Q_ENABLE_MYSQL
00483 if (result == NULL) return false;
00484 if (result->rs != NULL) {
00485 if(result->fetchtype == true) {
00486 while(mysql_fetch_row(result->rs) != NULL);
00487 }
00488 mysql_free_result(result->rs);
00489 result->rs = NULL;
00490 }
00491 free(result);
00492 return true;
00493 #else
00494 return false;
00495 #endif
00496 }
00497
00505 int qDbGetCols(Q_DBRESULT *result) {
00506 #ifdef _Q_ENABLE_MYSQL
00507 if (result == NULL || result->rs == NULL) return 0;
00508 return result->cols;
00509 #else
00510 return 0;
00511 #endif
00512 }
00513
00521 int qDbGetRows(Q_DBRESULT *result) {
00522 #ifdef _Q_ENABLE_MYSQL
00523 if (result == NULL || result->rs == NULL) return 0;
00524 return mysql_num_rows(result->rs);
00525 #else
00526 return 0;
00527 #endif
00528 }
00529
00540 int qDbGetRow(Q_DBRESULT *result) {
00541 #ifdef _Q_ENABLE_MYSQL
00542 if (result == NULL || result->rs == NULL) return 0;
00543 return result->cursor;
00544 #else
00545 return 0;
00546 #endif
00547 }
00548
00560 const char *qDbGetStr(Q_DBRESULT *result, const char *field) {
00561 #ifdef _Q_ENABLE_MYSQL
00562 if (result == NULL || result->rs == NULL || result->cols <= 0) return NULL;
00563
00564 if (result->fields == NULL) result->fields = mysql_fetch_fields(result->rs);
00565
00566 int i;
00567 for (i = 0; i < result->cols; i++) {
00568 if (!strcasecmp(result->fields[i].name, field)) return qDbGetStrAt(result, i + 1);
00569 }
00570
00571 return NULL;
00572 #else
00573 return NULL;
00574 #endif
00575 }
00576
00585 const char *qDbGetStrAt(Q_DBRESULT *result, int idx) {
00586 #ifdef _Q_ENABLE_MYSQL
00587 if (result == NULL || result->rs == NULL || result->cursor == 0 || idx <= 0 || idx > result->cols ) return NULL;
00588 return result->row[idx-1];
00589 #else
00590 return NULL;
00591 #endif
00592 }
00593
00602 int qDbGetInt(Q_DBRESULT *result, const char *field) {
00603 const char *val = qDbGetStr(result, field);
00604 if(val == NULL) return 0;
00605 return atoi(val);
00606 }
00607
00616 int qDbGetIntAt(Q_DBRESULT *result, int idx) {
00617 const char *val = qDbGetStrAt(result, idx);
00618 if(val == NULL) return 0;
00619 return atoi(val);
00620 }
00621
00629 bool qDbBeginTran(Q_DB *db) {
00630 if (db == NULL) return false;
00631
00632 #ifdef _Q_ENABLE_MYSQL
00633 Q_DBRESULT *result;
00634 result = qDbExecuteQuery(db, "START TRANSACTION");
00635 if(result == NULL) return false;
00636 qDbResultFree(result);
00637 return true;
00638 #else
00639 return false;
00640 #endif
00641 }
00642
00651 bool qDbEndTran(Q_DB *db, bool commit) {
00652 if (db == NULL) return false;
00653
00654 if (commit == false) return qDbRollback(db);
00655 return qDbCommit(db);
00656 }
00657
00665 bool qDbCommit(Q_DB *db) {
00666 if (db == NULL) return false;
00667
00668 #ifdef _Q_ENABLE_MYSQL
00669 if (mysql_commit(db->mysql) != 0) return false;
00670 return true;
00671 #else
00672 return false;
00673 #endif
00674 }
00675
00683 bool qDbRollback(Q_DB *db) {
00684 if (db == NULL) return false;
00685
00686 #ifdef _Q_ENABLE_MYSQL
00687 if (mysql_rollback(db->mysql) != 0) {
00688 return false;
00689 }
00690 return true;
00691 #else
00692 return 0;
00693 #endif
00694 }