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);
162qdb_t *
qdb(
const char *dbtype,
const char *addr,
int port,
const char *username,
163 const char *password,
const char *database,
bool autocommit)
167 if (strcmp(dbtype,
"MYSQL"))
return NULL;
175 || database == NULL) {
181 if ((db = (qdb_t *)malloc(
sizeof(qdb_t))) == NULL)
return NULL;
182 memset((
void *)db, 0,
sizeof(qdb_t));
183 db->connected =
false;
186 db->info.dbtype = strdup(dbtype);
187 db->info.addr = strdup(addr);
188 db->info.port = port;
189 db->info.username = strdup(username);
190 db->info.password = strdup(password);
191 db->info.database = strdup(database);
192 db->info.autocommit = autocommit;
193 db->info.fetchtype =
false;
220 Q_MUTEX_NEW(db->qmutex,
true);
234 if (db == NULL)
return false;
237 if (db->connected ==
true) {
242 Q_MUTEX_ENTER(db->qmutex);
245 if (db->mysql != NULL)
close_(db);
247 if (mysql_library_init(0, NULL, NULL) != 0) {
248 Q_MUTEX_LEAVE(db->qmutex);
252 if ((db->mysql = mysql_init(NULL)) == NULL) {
253 Q_MUTEX_LEAVE(db->qmutex);
258 my_bool reconnect = Q_MYSQL_OPT_RECONNECT;
259 unsigned int connect_timeout = Q_MYSQL_OPT_CONNECT_TIMEOUT;
260 unsigned int read_timeout = Q_MYSQL_OPT_READ_TIMEOUT;
261 unsigned int write_timeout = Q_MYSQL_OPT_WRITE_TIMEOUT;
263 if (reconnect !=
false) {
264 mysql_options(db->mysql,
268 if (connect_timeout > 0) {
269 mysql_options(db->mysql,
270 MYSQL_OPT_CONNECT_TIMEOUT,
271 (
char *)&connect_timeout);
273 if (read_timeout > 0) {
274 mysql_options(db->mysql,
275 MYSQL_OPT_READ_TIMEOUT,
276 (
char *)&read_timeout);
278 if (write_timeout > 0) {
279 mysql_options(db->mysql,
280 MYSQL_OPT_WRITE_TIMEOUT,
281 (
char *)&write_timeout);
285 if (mysql_real_connect(db->mysql,
290 db->info.port, NULL, 0) == NULL) {
292 Q_MUTEX_LEAVE(db->qmutex);
297 if (mysql_autocommit(db->mysql, db->info.autocommit) != 0) {
299 Q_MUTEX_LEAVE(db->qmutex);
304 db->connected =
true;
305 Q_MUTEX_LEAVE(db->qmutex);
325 if (db == NULL)
return false;
328 Q_MUTEX_ENTER(db->qmutex);
330 if (db->mysql != NULL) {
331 mysql_close(db->mysql);
335 db->connected =
false;
337 Q_MUTEX_LEAVE(db->qmutex);
354 if (db == NULL || db->connected ==
false)
return -1;
357 Q_MUTEX_ENTER(db->qmutex);
363 if (mysql_query(db->mysql, query) == 0) {
365 if ((affected = mysql_affected_rows(db->mysql)) < 0) affected = -1;
368 Q_MUTEX_LEAVE(db->qmutex);
386 DYNAMIC_VSPRINTF(query, format);
387 if (query == NULL)
return -1;
405 if (db == NULL || db->connected ==
false)
return NULL;
410 if (mysql_query(db->mysql, query))
return NULL;
413 qdbresult_t *result = (qdbresult_t *)malloc(
sizeof(qdbresult_t));
414 if (result == NULL)
return NULL;
416 result->fetchtype = db->info.fetchtype;
417 if (result->fetchtype ==
false) {
418 result->rs = mysql_store_result(db->mysql);
420 result->rs = mysql_use_result(db->mysql);
422 if (result->rs == NULL) {
428 result->fields = NULL;
430 result->cols = mysql_num_fields(result->rs);
463 DYNAMIC_VSPRINTF(query, format);
464 if (query == NULL)
return NULL;
466 qdbresult_t *ret = db->execute_query(db, query);
486 if (db == NULL)
return false;
489 Q_MUTEX_ENTER(db->qmutex);
490 if (db->qmutex.count != 1) {
491 Q_MUTEX_LEAVE(db->qmutex);
496 result = db->execute_query(db,
"START TRANSACTION");
497 if (result == NULL) {
498 Q_MUTEX_LEAVE(db->qmutex);
501 result->free(result);
517 if (db == NULL)
return false;
521 if (mysql_commit(db->mysql) == 0) {
525 if (db->qmutex.count > 0) {
526 Q_MUTEX_LEAVE(db->qmutex);
543 if (db == NULL)
return false;
547 if (mysql_rollback(db->mysql) == 0) {
551 if (db->qmutex.count > 0) {
552 Q_MUTEX_LEAVE(db->qmutex);
579 if (db == NULL)
return false;
580 db->info.fetchtype = fromdb;
596 if (db == NULL)
return false;
598 return db->connected;
614 if (db == NULL)
return false;
617 if (db->connected ==
true && mysql_ping(db->mysql) == 0) {
620 if (
open_(db) ==
true) {
621 DEBUG(
"Connection recovered.");
643static const char *
get_error(qdb_t *db,
unsigned int *errorno)
645 if (db == NULL || db->connected ==
false)
return "(no opened db)";
647 unsigned int eno = 0;
650 eno = mysql_errno(db->mysql);
651 if (eno == 0) emsg =
"(no error)";
652 else emsg = mysql_error(db->mysql);
654 emsg =
"(not implemented)";
657 if (errorno != NULL) *errorno = eno;
668 if (db == NULL)
return;
670 Q_MUTEX_ENTER(db->qmutex);
674 free(db->info.dbtype);
676 free(db->info.username);
677 free(db->info.password);
678 free(db->info.database);
681 Q_MUTEX_LEAVE(db->qmutex);
682 Q_MUTEX_DESTROY(db->qmutex);
701 if (result == NULL || result->rs == NULL || result->cols <= 0)
return NULL;
703 if (result->fields == NULL) result->fields = mysql_fetch_fields(result->rs);
706 for (i = 0; i < result->cols; i++) {
707 if (!strcasecmp(result->fields[i].name, field)) {
708 return result->get_str_at(result, i + 1);
730 || result->rs == NULL
731 || result->cursor == 0
733 || idx > result->cols ) {
736 return result->row[idx-1];
752 const char *val = result->get_str(result, field);
753 if (val == NULL)
return 0;
767 const char *val = result->get_str_at(result, idx);
768 if (val == NULL)
return 0;
782 if (result == NULL || result->rs == NULL)
return false;
784 if ((result->row = mysql_fetch_row(result->rs)) == NULL)
return false;
803 if (result == NULL || result->rs == NULL)
return 0;
820 if (result == NULL || result->rs == NULL)
return 0;
821 return mysql_num_rows(result->rs);
840 if (result == NULL || result->rs == NULL)
return 0;
841 return result->cursor;
855 if (result == NULL)
return;
856 if (result->rs != NULL) {
857 if (result->fetchtype ==
true) {
858 while (mysql_fetch_row(result->rs) != NULL);
860 mysql_free_result(result->rs);
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(): Executes the 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(): Executes the 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(): De-allocate the result
static const char * _resultGetStr(qdbresult_t *result, const char *field)
qdbresult->get_str(): Get the result as 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 internal connector structure.
static const char * _resultGetStrAt(qdbresult_t *result, int idx)
qdbresult->get_str_at(): Get the result as 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 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 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(): De-allocate qdb_t structure
static const char * get_error(qdb_t *db, unsigned int *errorno)
qdb->get_error(): Get error number and message