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
104 static bool open_(qdb_t *db);
105 static bool close_(qdb_t *db);
106 
107 static int execute_update(qdb_t *db, const char *query);
108 static int execute_updatef(qdb_t *db, const char *format, ...);
109 static qdbresult_t *execute_query(qdb_t *db, const char *query);
110 static qdbresult_t *execute_queryf(qdb_t *db, const char *format, ...);
111 
112 static bool begin_tran(qdb_t *db);
113 static bool commit(qdb_t *db);
114 static bool rollback(qdb_t *db);
115 
116 static bool set_fetchtype(qdb_t *db, bool use);
117 static bool get_conn_status(qdb_t *db);
118 static bool ping(qdb_t *db);
119 static const char *get_error(qdb_t *db, unsigned int *errorno);
120 static void free_(qdb_t *db);
121 
122 // qdbresult_t object
123 static const char *_resultGetStr(qdbresult_t *result, const char *field);
124 static const char *_resultGetStrAt(qdbresult_t *result, int idx);
125 static int _resultGetInt(qdbresult_t *result, const char *field);
126 static int _resultGetIntAt(qdbresult_t *result, int idx);
127 static bool _resultGetNext(qdbresult_t *result);
128 
129 static int result_get_cols(qdbresult_t *result);
130 static int result_get_rows(qdbresult_t *result);
131 static int result_get_row(qdbresult_t *result);
132 
133 static 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  */
162 qdb_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  */
232 static 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  */
323 static 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  */
352 static 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  */
383 static 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  */
403 static 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  */
460 static 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  */
484 static 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  */
515 static 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  */
541 static 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  */
577 static 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  */
594 static 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  */
612 static 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  */
643 static 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  */
666 static 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  */
698 static 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  */
726 static 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  */
750 static 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  */
765 static 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  */
779 static 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  */
800 static 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  */
817 static 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  */
837 static 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  */
852 static 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 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 get_conn_status(qdb_t *db)
qdb->get_conn_status(): Get last connection status
Definition: qdatabase.c:594
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 int execute_update(qdb_t *db, const char *query)
qdb->execute_update(): Executes the update DML
Definition: qdatabase.c:352
static int execute_updatef(qdb_t *db, const char *format,...)
qdb->execute_updatef(): Executes the formatted update DML
Definition: qdatabase.c:383
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
static int result_get_row(qdbresult_t *result)
qdbresult->get_row(): Get the current row number
Definition: qdatabase.c:837
static bool open_(qdb_t *db)
qdb->open(): Connect to database server
Definition: qdatabase.c:232
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 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 ping(qdb_t *db)
qdb->ping(): Checks whether the connection to the server is working.
Definition: qdatabase.c:612
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 _resultGetNext(qdbresult_t *result)
qdbresult->get_next(): Retrieves the next row of a result set
Definition: qdatabase.c:779
static qdbresult_t * execute_query(qdb_t *db, const char *query)
qdb->execute_query(): Executes the query
Definition: qdatabase.c:403
static const char * get_error(qdb_t *db, unsigned int *errorno)
qdb->get_error(): Get error number and message
Definition: qdatabase.c:643
static void result_free(qdbresult_t *result)
qdbresult->free(): De-allocate the result
Definition: qdatabase.c:852
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 close_(qdb_t *db)
qdb->close(): Disconnect from database server
Definition: qdatabase.c:323
static bool begin_tran(qdb_t *db)
qdb->begin_tran(): Start transaction
Definition: qdatabase.c:484
static qdbresult_t * execute_queryf(qdb_t *db, const char *format,...)
qdb->execute_queryf(): Executes the formatted query
Definition: qdatabase.c:460
static void free_(qdb_t *db)
qdb->free(): De-allocate qdb_t structure
Definition: qdatabase.c:666
static bool set_fetchtype(qdb_t *db, bool fromdb)
qdb->set_fetchtype(): Set result fetching type
Definition: qdatabase.c:577
static bool commit(qdb_t *db)
qdb->commit(): Commit transaction
Definition: qdatabase.c:515
static bool rollback(qdb_t *db)
qdb->rellback(): Roll-back and abort transaction
Definition: qdatabase.c:541