qLibc
qdatabase.c
Go to the documentation of this file.
1/******************************************************************************
2 * qLibc
3 *
4 * Copyright (c) 2010-2015 Seungyoung Kim.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright notice,
13 * this list of conditions and the following disclaimer in the documentation
14 * and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 *****************************************************************************/
28
29/**
30 * @file qdatabase.c Database wrapper.
31 *
32 * Database header files should be included prior to qlibcext.h in your source
33 * codes like below.
34 *
35 * @code
36 * #include "mysql.h"
37 * #include "qlibcext.h"
38 * @endcode
39 *
40 * @code
41 * qdb_t *db = NULL;
42 * qdbresult_t *result = NULL;
43 *
44 * db = qdb("MYSQL", "dbhost.qdecoder.org", 3306,
45 * "test", "secret", "sampledb", true);
46 * if (db == NULL) {
47 * printf("ERROR: Not supported database type.\n");
48 * return -1;
49 * }
50 *
51 * // try to connect
52 * if (db->open(db) == false) {
53 * printf("WARNING: Can't connect to database.\n");
54 * return -1;
55 * }
56 *
57 * // get results
58 * result = db->execute_query(db, "SELECT name, population FROM City");
59 * if (result != NULL) {
60 * printf("COLS : %d , ROWS : %d\n",
61 * result->get_cols(result), result->get_rows(result));
62 * while (result->get_next(result) == true) {
63 * char *pszName = result->get_str(result, "name");
64 * int nPopulation = result->get_int(result, "population");
65 * printf("Country : %s , Population : %d\n", pszName, nPopulation);
66 * }
67 * result->free(result);
68 * }
69 *
70 * // close connection
71 * db->close(db);
72 *
73 * // free db object
74 * db->free(db);
75 * @endcode
76 */
77
78#ifndef DISABLE_QDATABASE
79
80#if defined(ENABLE_MYSQL) || defined( _DOXYGEN_SKIP)
81
82#ifdef ENABLE_MYSQL
83#include "mysql.h"
84/* mysql specific connector options */
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)
89#endif
90
91#include <stdio.h>
92#include <stdlib.h>
93#include <stdbool.h>
94#include <stdarg.h>
95#include <string.h>
96#include "qinternal.h"
97#include "extensions/qdatabase.h"
98
99/*
100 * Member method protos
101 */
102#ifndef _DOXYGEN_SKIP
103// qdb_t object
104static bool open_(qdb_t *db);
105static bool close_(qdb_t *db);
106
107static int execute_update(qdb_t *db, const char *query);
108static int execute_updatef(qdb_t *db, const char *format, ...);
109static qdbresult_t *execute_query(qdb_t *db, const char *query);
110static qdbresult_t *execute_queryf(qdb_t *db, const char *format, ...);
111
112static bool begin_tran(qdb_t *db);
113static bool commit(qdb_t *db);
114static bool rollback(qdb_t *db);
115
116static bool set_fetchtype(qdb_t *db, bool use);
117static bool get_conn_status(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);
121
122// qdbresult_t object
123static const char *_resultGetStr(qdbresult_t *result, const char *field);
124static const char *_resultGetStrAt(qdbresult_t *result, int idx);
125static int _resultGetInt(qdbresult_t *result, const char *field);
126static int _resultGetIntAt(qdbresult_t *result, int idx);
127static bool _resultGetNext(qdbresult_t *result);
128
129static int result_get_cols(qdbresult_t *result);
130static int result_get_rows(qdbresult_t *result);
131static int result_get_row(qdbresult_t *result);
132
133static void result_free(qdbresult_t *result);
134
135#endif
136
137/**
138 * Initialize internal connector structure
139 *
140 * @param dbtype database server type. currently "MYSQL" is only supported
141 * @param addr ip or fqdn address.
142 * @param port port number
143 * @param username database username
144 * @param password database password
145 * @param database database server type. currently "MYSQL" is only supported
146 * @param autocommit sets autocommit mode on if autocommit is true, off if
147 * autocommit is false
148 *
149 * @return a pointer of qdb_t object in case of successful,
150 * otherwise returns NULL.
151 *
152 * @code
153 * qdb_t *db = qdb("MYSQL",
154 * "dbhost.qdecoder.org", 3306, "test", "secret",
155 * "sampledb", true);
156 * if (db == NULL) {
157 * printf("ERROR: Not supported database type.\n");
158 * return -1;
159 * }
160 * @endcode
161 */
162qdb_t *qdb(const char *dbtype, const char *addr, int port, const char *username,
163 const char *password, const char *database, bool autocommit)
164{
165 // check db type
166#ifdef Q_ENABLE_MYSQL
167 if (strcmp(dbtype, "MYSQL")) return NULL;
168#else
169 return NULL;
170#endif
171 if (dbtype == NULL
172 || addr == NULL
173 || username == NULL
174 || password == NULL
175 || database == NULL) {
176 return NULL;
177 }
178
179 // initialize
180 qdb_t *db;
181 if ((db = (qdb_t *)malloc(sizeof(qdb_t))) == NULL) return NULL;
182 memset((void *)db, 0, sizeof(qdb_t));
183 db->connected = false;
184
185 // set common structure
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;// store mode
194
195 // set db handler
196#ifdef Q_ENABLE_MYSQL
197 db->mysql = NULL;
198#endif
199
200 // assign methods
201 db->open = open_;
202 db->close = close_;
203
204 db->execute_update = execute_update;
205 db->execute_updatef = execute_updatef;
206 db->execute_query = execute_query;
207 db->execute_queryf = execute_queryf;
208
209 db->begin_tran = begin_tran;
210 db->commit = commit;
211 db->rollback = rollback;
212
213 db->set_fetchtype = set_fetchtype;
214 db->get_conn_status = get_conn_status;
215 db->ping = ping;
216 db->get_error = get_error;
217 db->free = free_;
218
219 // initialize recrusive mutex
220 Q_MUTEX_NEW(db->qmutex, true);
221
222 return db;
223}
224
225/**
226 * qdb->open(): Connect to database server
227 *
228 * @param db a pointer of qdb_t object
229 *
230 * @return true if successful, otherwise returns false.
231 */
232static bool open_(qdb_t *db)
233{
234 if (db == NULL) return false;
235
236 // if connected, close first
237 if (db->connected == true) {
238 close_(db);
239 }
240
241#ifdef Q_ENABLE_MYSQL
242 Q_MUTEX_ENTER(db->qmutex);
243
244 // initialize handler
245 if (db->mysql != NULL) close_(db);
246
247 if (mysql_library_init(0, NULL, NULL) != 0) {
248 Q_MUTEX_LEAVE(db->qmutex);
249 return false;
250 }
251
252 if ((db->mysql = mysql_init(NULL)) == NULL) {
253 Q_MUTEX_LEAVE(db->qmutex);
254 return false;
255 }
256
257 // set options
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;
262
263 if (reconnect != false) {
264 mysql_options(db->mysql,
265 MYSQL_OPT_RECONNECT,
266 (char *)&reconnect);
267 }
268 if (connect_timeout > 0) {
269 mysql_options(db->mysql,
270 MYSQL_OPT_CONNECT_TIMEOUT,
271 (char *)&connect_timeout);
272 }
273 if (read_timeout > 0) {
274 mysql_options(db->mysql,
275 MYSQL_OPT_READ_TIMEOUT,
276 (char *)&read_timeout);
277 }
278 if (write_timeout > 0) {
279 mysql_options(db->mysql,
280 MYSQL_OPT_WRITE_TIMEOUT,
281 (char *)&write_timeout);
282 }
283
284 // try to connect
285 if (mysql_real_connect(db->mysql,
286 db->info.addr,
287 db->info.username,
288 db->info.password,
289 db->info.database,
290 db->info.port, NULL, 0) == NULL) {
291 close_(db); // free mysql handler
292 Q_MUTEX_LEAVE(db->qmutex);
293 return false;
294 }
295
296 // set auto-commit
297 if (mysql_autocommit(db->mysql, db->info.autocommit) != 0) {
298 close_(db); // free mysql handler
299 Q_MUTEX_LEAVE(db->qmutex);
300 return false;
301 }
302
303 // set flag
304 db->connected = true;
305 Q_MUTEX_LEAVE(db->qmutex);
306 return true;
307#else
308 return false;
309#endif
310}
311
312/**
313 * qdb->close(): Disconnect from database server
314 *
315 * @param db a pointer of qdb_t object
316 *
317 * @return true if successful, otherwise returns false.
318 *
319 * @note
320 * Unless you call qdb->free(), qdb_t object will keep the database
321 * information. So you can re-connect to database using qdb->open().
322 */
323static bool close_(qdb_t *db)
324{
325 if (db == NULL) return false;
326
327#ifdef Q_ENABLE_MYSQL
328 Q_MUTEX_ENTER(db->qmutex);
329
330 if (db->mysql != NULL) {
331 mysql_close(db->mysql);
332 db->mysql = NULL;
333 mysql_library_end();
334 }
335 db->connected = false;
336
337 Q_MUTEX_LEAVE(db->qmutex);
338 return true;
339#else
340 return false;
341#endif
342}
343
344/**
345 * qdb->execute_update(): Executes the update DML
346 *
347 * @param db a pointer of qdb_t object
348 * @param query query string
349 *
350 * @return a number of affected rows
351 */
352static int execute_update(qdb_t *db, const char *query)
353{
354 if (db == NULL || db->connected == false) return -1;
355
356#ifdef Q_ENABLE_MYSQL
357 Q_MUTEX_ENTER(db->qmutex);
358
359 int affected = -1;
360
361 // query
362 DEBUG("%s", query);
363 if (mysql_query(db->mysql, query) == 0) {
364 /* get affected rows */
365 if ((affected = mysql_affected_rows(db->mysql)) < 0) affected = -1;
366 }
367
368 Q_MUTEX_LEAVE(db->qmutex);
369 return affected;
370#else
371 return -1;
372#endif
373}
374
375/**
376 * qdb->execute_updatef(): Executes the formatted update DML
377 *
378 * @param db a pointer of qdb_t object
379 * @param format query string format
380 *
381 * @return a number of affected rows, otherwise returns -1
382 */
383static int execute_updatef(qdb_t *db, const char *format, ...)
384{
385 char *query;
386 DYNAMIC_VSPRINTF(query, format);
387 if (query == NULL) return -1;
388
389 int affected = execute_update(db, query);
390 free(query);
391
392 return affected;
393}
394
395/**
396 * qdb->execute_query(): Executes the query
397 *
398 * @param db a pointer of qdb_t object
399 * @param query query string
400 *
401 * @return a pointer of qdbresult_t if successful, otherwise returns NULL
402 */
403static qdbresult_t *execute_query(qdb_t *db, const char *query)
404{
405 if (db == NULL || db->connected == false) return NULL;
406
407#ifdef Q_ENABLE_MYSQL
408 // query
409 DEBUG("%s", query);
410 if (mysql_query(db->mysql, query)) return NULL;
411
412 // store
413 qdbresult_t *result = (qdbresult_t *)malloc(sizeof(qdbresult_t));
414 if (result == NULL) return NULL;
415
416 result->fetchtype = db->info.fetchtype;
417 if (result->fetchtype == false) {
418 result->rs = mysql_store_result(db->mysql);
419 } else {
420 result->rs = mysql_use_result(db->mysql);
421 }
422 if (result->rs == NULL) {
423 free(result);
424 return NULL;
425 }
426
427 /* get meta data */
428 result->fields = NULL;
429 result->row = NULL;
430 result->cols = mysql_num_fields(result->rs);
431 result->cursor = 0;
432
433 /* assign methods */
434 result->get_str = _resultGetStr;
435 result->get_str_at = _resultGetStrAt;
436 result->get_int = _resultGetInt;
437 result->get_int_at = _resultGetIntAt;
438 result->get_next = _resultGetNext;
439
440 result->get_cols = result_get_cols;
441 result->get_rows = result_get_rows;
442 result->get_row = result_get_row;
443
444 result->free = result_free;
445
446 return result;
447#else
448 return NULL;
449#endif
450}
451
452/**
453 * qdb->execute_queryf(): Executes the formatted query
454 *
455 * @param db a pointer of qdb_t object
456 * @param format query string format
457 *
458 * @return a pointer of qdbresult_t if successful, otherwise returns NULL
459 */
460static qdbresult_t *execute_queryf(qdb_t *db, const char *format, ...)
461{
462 char *query;
463 DYNAMIC_VSPRINTF(query, format);
464 if (query == NULL) return NULL;
465
466 qdbresult_t *ret = db->execute_query(db, query);
467 free(query);
468 return ret;
469}
470
471/**
472 * qdb->begin_tran(): Start transaction
473 *
474 * @param db a pointer of qdb_t object
475 *
476 * @return true if successful, otherwise returns false
477 *
478 * @code
479 * db->begin_tran(db);
480 * (... insert/update/delete ...)
481 * db->commit(db);
482 * @endcode
483 */
484static bool begin_tran(qdb_t *db)
485{
486 if (db == NULL) return false;
487
488#ifdef Q_ENABLE_MYSQL
489 Q_MUTEX_ENTER(db->qmutex);
490 if (db->qmutex.count != 1) {
491 Q_MUTEX_LEAVE(db->qmutex);
492 return false;
493 }
494
495 qdbresult_t *result;
496 result = db->execute_query(db, "START TRANSACTION");
497 if (result == NULL) {
498 Q_MUTEX_LEAVE(db->qmutex);
499 return false;
500 }
501 result->free(result);
502 return true;
503#else
504 return false;
505#endif
506}
507
508/**
509 * qdb->commit(): Commit transaction
510 *
511 * @param db a pointer of qdb_t object
512 *
513 * @return true if successful, otherwise returns false
514 */
515static bool commit(qdb_t *db)
516{
517 if (db == NULL) return false;
518
519#ifdef Q_ENABLE_MYSQL
520 bool ret = false;
521 if (mysql_commit(db->mysql) == 0) {
522 ret = true;
523 }
524
525 if (db->qmutex.count > 0) {
526 Q_MUTEX_LEAVE(db->qmutex);
527 }
528 return ret;
529#else
530 return false;
531#endif
532}
533
534/**
535 * qdb->rellback(): Roll-back and abort transaction
536 *
537 * @param db a pointer of qdb_t object
538 *
539 * @return true if successful, otherwise returns false
540 */
541static bool rollback(qdb_t *db)
542{
543 if (db == NULL) return false;
544
545#ifdef Q_ENABLE_MYSQL
546 bool ret = false;
547 if (mysql_rollback(db->mysql) == 0) {
548 ret = true;
549 }
550
551 if (db->qmutex.count > 0) {
552 Q_MUTEX_LEAVE(db->qmutex);
553 }
554 return ret;
555#else
556 return 0;
557#endif
558}
559
560/**
561 * qdb->set_fetchtype(): Set result fetching type
562 *
563 * @param db a pointer of qdb_t object
564 * @param fromdb false for storing the results to client (default mode),
565 * true for fetching directly from server,
566 *
567 * @return true if successful otherwise returns false
568 *
569 * @note
570 * If qdb->set_fetchtype(db, true) is called, the results does not
571 * actually read into the client. Instead, each row must be retrieved
572 * individually by making calls to qdbresult->get_next().
573 * This reads the result of a query directly from the server without storing
574 * it in local buffer, which is somewhat faster and uses much less memory than
575 * default behavior qdb->set_fetchtype(db, false).
576 */
577static bool set_fetchtype(qdb_t *db, bool fromdb)
578{
579 if (db == NULL) return false;
580 db->info.fetchtype = fromdb;
581 return true;
582}
583
584/**
585 * qdb->get_conn_status(): Get last connection status
586 *
587 * @param db a pointer of qdb_t object
588 *
589 * @return true if the connection flag is set to alive, otherwise returns false
590 *
591 * @note
592 * This function just returns the the connection status flag.
593 */
594static bool get_conn_status(qdb_t *db)
595{
596 if (db == NULL) return false;
597
598 return db->connected;
599}
600
601/**
602 * qdb->ping(): Checks whether the connection to the server is working.
603 *
604 * @param db a pointer of qdb_t object
605 *
606 * @return true if connection is alive, false if connection is not available
607 * and failed to reconnect
608 *
609 * @note
610 * If the connection has gone down, an attempt to reconnect.
611 */
612static bool ping(qdb_t *db)
613{
614 if (db == NULL) return false;
615
616#ifdef Q_ENABLE_MYSQL
617 if (db->connected == true && mysql_ping(db->mysql) == 0) {
618 return true;
619 } else { // ping test failed
620 if (open_(db) == true) { // try re-connect
621 DEBUG("Connection recovered.");
622 return true;
623 }
624 }
625
626 return false;
627#else
628 return false;
629#endif
630}
631
632/**
633 * qdb->get_error(): Get error number and message
634 *
635 * @param db a pointer of qdb_t object
636 * @param errorno if not NULL, error number will be stored
637 *
638 * @return a pointer of error message string
639 *
640 * @note
641 * Do not free returned error message
642 */
643static const char *get_error(qdb_t *db, unsigned int *errorno)
644{
645 if (db == NULL || db->connected == false) return "(no opened db)";
646
647 unsigned int eno = 0;
648 const char *emsg;
649#ifdef Q_ENABLE_MYSQL
650 eno = mysql_errno(db->mysql);
651 if (eno == 0) emsg = "(no error)";
652 else emsg = mysql_error(db->mysql);
653#else
654 emsg = "(not implemented)";
655#endif
656
657 if (errorno != NULL) *errorno = eno;
658 return emsg;
659}
660
661/**
662 * qdb->free(): De-allocate qdb_t structure
663 *
664 * @param db a pointer of qdb_t object
665 */
666static void free_(qdb_t *db)
667{
668 if (db == NULL) return;
669
670 Q_MUTEX_ENTER(db->qmutex);
671
672 close_(db);
673
674 free(db->info.dbtype);
675 free(db->info.addr);
676 free(db->info.username);
677 free(db->info.password);
678 free(db->info.database);
679 free(db);
680
681 Q_MUTEX_LEAVE(db->qmutex);
682 Q_MUTEX_DESTROY(db->qmutex);
683
684 return;
685}
686
687/**
688 * qdbresult->get_str(): Get the result as string by field name
689 *
690 * @param result a pointer of qdbresult_t
691 * @param field column name
692 *
693 * @return a string pointer if successful, otherwise returns NULL.
694 *
695 * @note
696 * Do not free returned string.
697 */
698static const char *_resultGetStr(qdbresult_t *result, const char *field)
699{
700#ifdef Q_ENABLE_MYSQL
701 if (result == NULL || result->rs == NULL || result->cols <= 0) return NULL;
702
703 if (result->fields == NULL) result->fields = mysql_fetch_fields(result->rs);
704
705 int i;
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);
709 }
710 }
711
712 return NULL;
713#else
714 return NULL;
715#endif
716}
717
718/**
719 * qdbresult->get_str_at(): Get the result as string by column number
720 *
721 * @param result a pointer of qdbresult_t
722 * @param idx column number (first column is 1)
723 *
724 * @return a string pointer if successful, otherwise returns NULL.
725 */
726static const char *_resultGetStrAt(qdbresult_t *result, int idx)
727{
728#ifdef Q_ENABLE_MYSQL
729 if (result == NULL
730 || result->rs == NULL
731 || result->cursor == 0
732 || idx <= 0
733 || idx > result->cols ) {
734 return NULL;
735 }
736 return result->row[idx-1];
737#else
738 return NULL;
739#endif
740}
741
742/**
743 * qdbresult->get_int(): Get the result as integer by field name
744 *
745 * @param result a pointer of qdbresult_t
746 * @param field column name
747 *
748 * @return a integer converted value
749 */
750static int _resultGetInt(qdbresult_t *result, const char *field)
751{
752 const char *val = result->get_str(result, field);
753 if (val == NULL) return 0;
754 return atoi(val);
755}
756
757/**
758 * qdbresult->get_int_at(): Get the result as integer by column number
759 *
760 * @param result a pointer of qdbresult_t
761 * @param idx column number (first column is 1)
762 *
763 * @return a integer converted value
764 */
765static int _resultGetIntAt(qdbresult_t *result, int idx)
766{
767 const char *val = result->get_str_at(result, idx);
768 if (val == NULL) return 0;
769 return atoi(val);
770}
771
772/**
773 * qdbresult->get_next(): Retrieves the next row of a result set
774 *
775 * @param result a pointer of qdbresult_t
776 *
777 * @return true if successful, false if no more rows are left
778 */
779static bool _resultGetNext(qdbresult_t *result)
780{
781#ifdef Q_ENABLE_MYSQL
782 if (result == NULL || result->rs == NULL) return false;
783
784 if ((result->row = mysql_fetch_row(result->rs)) == NULL) return false;
785 result->cursor++;
786
787 return true;
788#else
789 return false;
790#endif
791}
792
793/**
794 * qdbresult->get_cols(): Get the number of columns in the result set
795 *
796 * @param result a pointer of qdbresult_t
797 *
798 * @return the number of columns in the result set
799 */
800static int result_get_cols(qdbresult_t *result)
801{
802#ifdef Q_ENABLE_MYSQL
803 if (result == NULL || result->rs == NULL) return 0;
804 return result->cols;
805#else
806 return 0;
807#endif
808}
809
810/**
811 * qdbresult->get_rows(): Get the number of rows in the result set
812 *
813 * @param result a pointer of qdbresult_t
814 *
815 * @return the number of rows in the result set
816 */
817static int result_get_rows(qdbresult_t *result)
818{
819#ifdef Q_ENABLE_MYSQL
820 if (result == NULL || result->rs == NULL) return 0;
821 return mysql_num_rows(result->rs);
822#else
823 return 0;
824#endif
825}
826
827/**
828 * qdbresult->get_row(): Get the current row number
829 *
830 * @param result a pointer of qdbresult_t
831 *
832 * @return current fetching row number of the result set
833 *
834 * @note
835 * This number is sequencial counter which is started from 1.
836 */
837static int result_get_row(qdbresult_t *result)
838{
839#ifdef Q_ENABLE_MYSQL
840 if (result == NULL || result->rs == NULL) return 0;
841 return result->cursor;
842#else
843 return 0;
844#endif
845}
846
847/**
848 * qdbresult->free(): De-allocate the result
849 *
850 * @param result a pointer of qdbresult_t
851 */
852static void result_free(qdbresult_t *result)
853{
854#ifdef Q_ENABLE_MYSQL
855 if (result == NULL) return;
856 if (result->rs != NULL) {
857 if (result->fetchtype == true) {
858 while (mysql_fetch_row(result->rs) != NULL);
859 }
860 mysql_free_result(result->rs);
861 result->rs = NULL;
862 }
863 free(result);
864 return;
865#else
866 return;
867#endif
868}
869
870#endif
871
872#endif /* DISABLE_QDATABASE */
static bool get_conn_status(qdb_t *db)
qdb->get_conn_status(): Get last connection status
Definition qdatabase.c:594
static qdbresult_t * execute_query(qdb_t *db, const char *query)
qdb->execute_query(): Executes the query
Definition qdatabase.c:403
static int result_get_rows(qdbresult_t *result)
qdbresult->get_rows(): Get the number of rows in the result set
Definition qdatabase.c:817
static bool begin_tran(qdb_t *db)
qdb->begin_tran(): Start transaction
Definition qdatabase.c:484
static bool commit(qdb_t *db)
qdb->commit(): Commit transaction
Definition qdatabase.c:515
static qdbresult_t * execute_queryf(qdb_t *db, const char *format,...)
qdb->execute_queryf(): Executes the formatted query
Definition qdatabase.c:460
static int result_get_row(qdbresult_t *result)
qdbresult->get_row(): Get the current row number
Definition qdatabase.c:837
static int execute_update(qdb_t *db, const char *query)
qdb->execute_update(): Executes the update DML
Definition qdatabase.c:352
static void result_free(qdbresult_t *result)
qdbresult->free(): De-allocate the result
Definition qdatabase.c:852
static const char * _resultGetStr(qdbresult_t *result, const char *field)
qdbresult->get_str(): Get the result as string by field name
Definition qdatabase.c:698
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.
Definition qdatabase.c:162
static const char * _resultGetStrAt(qdbresult_t *result, int idx)
qdbresult->get_str_at(): Get the result as string by column number
Definition qdatabase.c:726
static bool set_fetchtype(qdb_t *db, bool fromdb)
qdb->set_fetchtype(): Set result fetching type
Definition qdatabase.c:577
static int _resultGetIntAt(qdbresult_t *result, int idx)
qdbresult->get_int_at(): Get the result as integer by column number
Definition qdatabase.c:765
static bool rollback(qdb_t *db)
qdb->rellback(): Roll-back and abort transaction
Definition qdatabase.c:541
static bool close_(qdb_t *db)
qdb->close(): Disconnect from database server
Definition qdatabase.c:323
static int result_get_cols(qdbresult_t *result)
qdbresult->get_cols(): Get the number of columns in the result set
Definition qdatabase.c:800
static bool ping(qdb_t *db)
qdb->ping(): Checks whether the connection to the server is working.
Definition qdatabase.c:612
static int execute_updatef(qdb_t *db, const char *format,...)
qdb->execute_updatef(): Executes the formatted update DML
Definition qdatabase.c:383
static int _resultGetInt(qdbresult_t *result, const char *field)
qdbresult->get_int(): Get the result as integer by field name
Definition qdatabase.c:750
static bool open_(qdb_t *db)
qdb->open(): Connect to database server
Definition qdatabase.c:232
static bool _resultGetNext(qdbresult_t *result)
qdbresult->get_next(): Retrieves the next row of a result set
Definition qdatabase.c:779
static void free_(qdb_t *db)
qdb->free(): De-allocate qdb_t structure
Definition qdatabase.c:666
static const char * get_error(qdb_t *db, unsigned int *errorno)
qdb->get_error(): Get error number and message
Definition qdatabase.c:643