78#ifndef DISABLE_QDATABASE
80#if defined(ENABLE_MYSQL) || defined( _DOXYGEN_SKIP)
85#define Q_MYSQL_OPT_RECONNECT (1)
86#define Q_MYSQL_OPT_CONNECT_TIMEOUT (10)
87#define Q_MYSQL_OPT_READ_TIMEOUT (30)
88#define Q_MYSQL_OPT_WRITE_TIMEOUT (30)
97#include "extensions/qdatabase.h"
104static bool open_(qdb_t *db);
105static bool close_(qdb_t *db);
109static qdbresult_t *
execute_query(qdb_t *db,
const char *query);
110static qdbresult_t *
execute_queryf(qdb_t *db,
const char *format, ...);
113static bool commit(qdb_t *db);
118static bool ping(qdb_t *db);
119static const char *
get_error(qdb_t *db,
unsigned int *errorno);
120static void free_(qdb_t *db);
123static const char *
_resultGetStr(qdbresult_t *result,
const char *field);
125static int _resultGetInt(qdbresult_t *result,
const char *field);
160qdb_t *
qdb(
const char *dbtype,
const char *addr,
int port,
const char *username,
161 const char *password,
const char *database,
bool autocommit) {
164 if (strcmp(dbtype,
"MYSQL"))
return NULL;
172 || database == NULL) {
178 if ((db = (qdb_t *)malloc(
sizeof(qdb_t))) == NULL)
return NULL;
179 memset((
void *)db, 0,
sizeof(qdb_t));
180 db->connected =
false;
183 db->info.dbtype = strdup(dbtype);
184 db->info.addr = strdup(addr);
185 db->info.port = port;
186 db->info.username = strdup(username);
187 db->info.password = strdup(password);
188 db->info.database = strdup(database);
189 db->info.autocommit = autocommit;
190 db->info.fetchtype =
false;
217 Q_MUTEX_NEW(db->qmutex,
true);
230 if (db == NULL)
return false;
233 if (db->connected ==
true) {
238 Q_MUTEX_ENTER(db->qmutex);
241 if (db->mysql != NULL)
close_(db);
243 if (mysql_library_init(0, NULL, NULL) != 0) {
244 Q_MUTEX_LEAVE(db->qmutex);
248 if ((db->mysql = mysql_init(NULL)) == NULL) {
249 Q_MUTEX_LEAVE(db->qmutex);
254 my_bool reconnect = Q_MYSQL_OPT_RECONNECT;
255 unsigned int connect_timeout = Q_MYSQL_OPT_CONNECT_TIMEOUT;
256 unsigned int read_timeout = Q_MYSQL_OPT_READ_TIMEOUT;
257 unsigned int write_timeout = Q_MYSQL_OPT_WRITE_TIMEOUT;
259 if (reconnect !=
false) {
260 mysql_options(db->mysql,
264 if (connect_timeout > 0) {
265 mysql_options(db->mysql,
266 MYSQL_OPT_CONNECT_TIMEOUT,
267 (
char *)&connect_timeout);
269 if (read_timeout > 0) {
270 mysql_options(db->mysql,
271 MYSQL_OPT_READ_TIMEOUT,
272 (
char *)&read_timeout);
274 if (write_timeout > 0) {
275 mysql_options(db->mysql,
276 MYSQL_OPT_WRITE_TIMEOUT,
277 (
char *)&write_timeout);
281 if (mysql_real_connect(db->mysql,
286 db->info.port, NULL, 0) == NULL) {
288 Q_MUTEX_LEAVE(db->qmutex);
293 if (mysql_autocommit(db->mysql, db->info.autocommit) != 0) {
295 Q_MUTEX_LEAVE(db->qmutex);
300 db->connected =
true;
301 Q_MUTEX_LEAVE(db->qmutex);
320 if (db == NULL)
return false;
323 Q_MUTEX_ENTER(db->qmutex);
325 if (db->mysql != NULL) {
326 mysql_close(db->mysql);
330 db->connected =
false;
332 Q_MUTEX_LEAVE(db->qmutex);
348 if (db == NULL || db->connected ==
false)
return -1;
351 Q_MUTEX_ENTER(db->qmutex);
357 if (mysql_query(db->mysql, query) == 0) {
359 if ((affected = mysql_affected_rows(db->mysql)) < 0) affected = -1;
362 Q_MUTEX_LEAVE(db->qmutex);
379 DYNAMIC_VSPRINTF(query, format);
380 if (query == NULL)
return -1;
397 if (db == NULL || db->connected ==
false)
return NULL;
402 if (mysql_query(db->mysql, query))
return NULL;
405 qdbresult_t *result = (qdbresult_t *)malloc(
sizeof(qdbresult_t));
406 if (result == NULL)
return NULL;
408 result->fetchtype = db->info.fetchtype;
409 if (result->fetchtype ==
false) {
410 result->rs = mysql_store_result(db->mysql);
412 result->rs = mysql_use_result(db->mysql);
414 if (result->rs == NULL) {
420 result->fields = NULL;
422 result->cols = mysql_num_fields(result->rs);
454 DYNAMIC_VSPRINTF(query, format);
455 if (query == NULL)
return NULL;
457 qdbresult_t *ret = db->execute_query(db, query);
476 if (db == NULL)
return false;
479 Q_MUTEX_ENTER(db->qmutex);
480 if (db->qmutex.count != 1) {
481 Q_MUTEX_LEAVE(db->qmutex);
486 result = db->execute_query(db,
"START TRANSACTION");
487 if (result == NULL) {
488 Q_MUTEX_LEAVE(db->qmutex);
491 result->free(result);
506 if (db == NULL)
return false;
510 if (mysql_commit(db->mysql) == 0) {
514 if (db->qmutex.count > 0) {
515 Q_MUTEX_LEAVE(db->qmutex);
531 if (db == NULL)
return false;
535 if (mysql_rollback(db->mysql) == 0) {
539 if (db->qmutex.count > 0) {
540 Q_MUTEX_LEAVE(db->qmutex);
566 if (db == NULL)
return false;
567 db->info.fetchtype = fromdb;
582 if (db == NULL)
return false;
584 return db->connected;
599 if (db == NULL)
return false;
602 if (db->connected ==
true && mysql_ping(db->mysql) == 0) {
605 if (
open_(db) ==
true) {
606 DEBUG(
"Connection recovered.");
628static const char *
get_error(qdb_t *db,
unsigned int *errorno) {
629 if (db == NULL || db->connected ==
false)
return "(no opened db)";
631 unsigned int eno = 0;
634 eno = mysql_errno(db->mysql);
635 if (eno == 0) emsg =
"(no error)";
636 else emsg = mysql_error(db->mysql);
638 emsg =
"(not implemented)";
641 if (errorno != NULL) *errorno = eno;
651 if (db == NULL)
return;
653 Q_MUTEX_ENTER(db->qmutex);
657 free(db->info.dbtype);
659 free(db->info.username);
660 free(db->info.password);
661 free(db->info.database);
664 Q_MUTEX_LEAVE(db->qmutex);
665 Q_MUTEX_DESTROY(db->qmutex);
683 if (result == NULL || result->rs == NULL || result->cols <= 0)
return NULL;
685 if (result->fields == NULL) result->fields = mysql_fetch_fields(result->rs);
688 for (i = 0; i < result->cols; i++) {
689 if (!strcasecmp(result->fields[i].name, field)) {
690 return result->get_str_at(result, i + 1);
711 || result->rs == NULL
712 || result->cursor == 0
714 || idx > result->cols ) {
717 return result->row[idx-1];
732 const char *val = result->get_str(result, field);
733 if (val == NULL)
return 0;
746 const char *val = result->get_str_at(result, idx);
747 if (val == NULL)
return 0;
760 if (result == NULL || result->rs == NULL)
return false;
762 if ((result->row = mysql_fetch_row(result->rs)) == NULL)
return false;
780 if (result == NULL || result->rs == NULL)
return 0;
796 if (result == NULL || result->rs == NULL)
return 0;
797 return mysql_num_rows(result->rs);
815 if (result == NULL || result->rs == NULL)
return 0;
816 return result->cursor;
829 if (result == NULL)
return;
830 if (result->rs != NULL) {
831 if (result->fetchtype ==
true) {
832 while (mysql_fetch_row(result->rs) != NULL);
834 mysql_free_result(result->rs);
static void free_(qaconf_t *qaconf)
qaconf_t->free(): Release resources.
static bool get_conn_status(qdb_t *db)
qdb->get_conn_status(): Get last connection status
static qdbresult_t * execute_query(qdb_t *db, const char *query)
qdb->execute_query(): Execute a query.
static int result_get_rows(qdbresult_t *result)
qdbresult->get_rows(): Get the number of rows in the result set
static bool begin_tran(qdb_t *db)
qdb->begin_tran(): Start transaction
static bool commit(qdb_t *db)
qdb->commit(): Commit transaction
static qdbresult_t * execute_queryf(qdb_t *db, const char *format,...)
qdb->execute_queryf(): Execute a formatted query.
static int result_get_row(qdbresult_t *result)
qdbresult->get_row(): Get the current row number
static int execute_update(qdb_t *db, const char *query)
qdb->execute_update(): Executes the update DML
static void result_free(qdbresult_t *result)
qdbresult->free(): Free the result
static const char * _resultGetStr(qdbresult_t *result, const char *field)
qdbresult->get_str(): Get the result as a string by field name.
qdb_t * qdb(const char *dbtype, const char *addr, int port, const char *username, const char *password, const char *database, bool autocommit)
Initialize the internal database connector structure.
static const char * _resultGetStrAt(qdbresult_t *result, int idx)
qdbresult->get_str_at(): Get the result as a string by column number.
static bool set_fetchtype(qdb_t *db, bool fromdb)
qdb->set_fetchtype(): Set result fetching type
static int _resultGetIntAt(qdbresult_t *result, int idx)
qdbresult->get_int_at(): Get the result as an integer by column number.
static bool rollback(qdb_t *db)
qdb->rellback(): Roll-back and abort transaction
static bool close_(qdb_t *db)
qdb->close(): Disconnect from database server
static int result_get_cols(qdbresult_t *result)
qdbresult->get_cols(): Get the number of columns in the result set
static bool ping(qdb_t *db)
qdb->ping(): Checks whether the connection to the server is working.
static int execute_updatef(qdb_t *db, const char *format,...)
qdb->execute_updatef(): Executes the formatted update DML
static int _resultGetInt(qdbresult_t *result, const char *field)
qdbresult->get_int(): Get the result as an integer by field name.
static bool open_(qdb_t *db)
qdb->open(): Connect to database server
static bool _resultGetNext(qdbresult_t *result)
qdbresult->get_next(): Retrieves the next row of a result set
static void free_(qdb_t *db)
qdb->free(): Free qdb_t structure
static const char * get_error(qdb_t *db, unsigned int *errorno)
qdb->get_error(): Get error number and message
static bool open_(qhttpclient_t *client)
qhttpclient->open(): Opens a connection to the remote host.