OpenDNSSEC-enforcer  2.0.3
db_backend_mysql.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014 Jerry Lundström <lundstrom.jerry@gmail.com>
3  * Copyright (c) 2014 .SE (The Internet Infrastructure Foundation).
4  * Copyright (c) 2014 OpenDNSSEC AB (svb)
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
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  * notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditions and the following disclaimer in the
14  * documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
20  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
22  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
24  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  *
28  */
29 
30 #include "db_backend_mysql.h"
31 #include "db_error.h"
32 
33 #include "log.h"
34 
35 #include <mysql/mysql.h>
36 #include <stdlib.h>
37 #include <stdio.h>
38 #include <unistd.h>
39 #include <string.h>
40 #include <time.h>
41 #include <pthread.h>
42 #include <errno.h>
43 
44 static int db_backend_mysql_transaction_rollback(void*);
45 
49 static int __mysql_initialized = 0;
50 
54 typedef struct db_backend_mysql {
55  MYSQL* db;
57  unsigned int timeout;
59 
60 
61 
68  MYSQL_BIND* bind;
69  unsigned long length;
70  my_bool error;
72 };
73 
74 
75 
81  MYSQL_STMT* statement;
82  MYSQL_BIND* mysql_bind_input;
85  MYSQL_BIND* mysql_bind_output;
89  int fields;
90  int bound;
92 
93 
94 
100 static inline void __db_backend_mysql_finish(db_backend_mysql_statement_t* statement) {
102 
103  if (!statement) {
104  return;
105  }
106 
107  if (statement->statement) {
108  mysql_stmt_close(statement->statement);
109  }
110  if (statement->mysql_bind_input) {
111  free(statement->mysql_bind_input);
112  }
113  while (statement->bind_input) {
114  bind = statement->bind_input;
115  statement->bind_input = bind->next;
116  free(bind);
117  }
118  while (statement->bind_output) {
119  bind = statement->bind_output;
120  statement->bind_output = bind->next;
121  if (bind->bind && bind->bind->buffer) {
122  free(bind->bind->buffer);
123  }
124  free(bind);
125  }
126  if (statement->mysql_bind_output) {
127  free(statement->mysql_bind_output);
128  }
129  if (statement->object_field_list) {
131  }
132 
133  free(statement);
134 }
135 
142 static inline int __db_backend_mysql_prepare(db_backend_mysql_t* backend_mysql, db_backend_mysql_statement_t** statement, const char* sql, size_t size, const db_object_field_list_t* object_field_list) {
143  unsigned long i, params;
145  const db_object_field_t* object_field;
146  MYSQL_BIND* mysql_bind;
147  MYSQL_RES* result_metadata = NULL;
148  MYSQL_FIELD* field;
149 
150  if (!backend_mysql) {
151  return DB_ERROR_UNKNOWN;
152  }
153  if (!backend_mysql->db) {
154  return DB_ERROR_UNKNOWN;
155  }
156  if (!statement) {
157  return DB_ERROR_UNKNOWN;
158  }
159  if (*statement) {
160  return DB_ERROR_UNKNOWN;
161  }
162  if (!sql) {
163  return DB_ERROR_UNKNOWN;
164  }
165 
166  /*
167  * Prepare the statement.
168  */
169  ods_log_debug("%s", sql);
170  if (!(*statement = calloc(1, sizeof(db_backend_mysql_statement_t)))
171  || !((*statement)->statement = mysql_stmt_init(backend_mysql->db))
172  || mysql_stmt_prepare((*statement)->statement, sql, size))
173  {
174  if ((*statement)->statement) {
175  ods_log_info("DB prepare SQL %s", sql);
176  ods_log_info("DB prepare Err %d: %s", mysql_stmt_errno((*statement)->statement), mysql_stmt_error((*statement)->statement));
177  }
178  __db_backend_mysql_finish(*statement);
179  *statement = NULL;
180  return DB_ERROR_UNKNOWN;
181  }
182 
183  (*statement)->backend_mysql = backend_mysql;
184 
185  /*
186  * Create the input binding based on the number of parameters in the SQL
187  * statement.
188  */
189  if ((params = mysql_stmt_param_count((*statement)->statement)) > 0) {
190  if (!((*statement)->mysql_bind_input = calloc(params, sizeof(MYSQL_BIND)))) {
191  __db_backend_mysql_finish(*statement);
192  *statement = NULL;
193  return DB_ERROR_UNKNOWN;
194  }
195 
196  for (i = 0; i < params; i++) {
197  if (!(bind = calloc(1, sizeof(db_backend_mysql_bind_t)))) {
198  __db_backend_mysql_finish(*statement);
199  *statement = NULL;
200  return DB_ERROR_UNKNOWN;
201  }
202 
203  bind->bind = &((*statement)->mysql_bind_input[i]);
204  if (!(*statement)->bind_input) {
205  (*statement)->bind_input = bind;
206  }
207  if ((*statement)->bind_input_end) {
208  (*statement)->bind_input_end->next = bind;
209  }
210  (*statement)->bind_input_end = bind;
211  }
212  }
213 
214  /*
215  * Create the output binding based on the object field list given.
216  */
217  if (object_field_list
218  && (params = db_object_field_list_size(object_field_list)) > 0
219  && (result_metadata = mysql_stmt_result_metadata((*statement)->statement)))
220  {
221  if (!((*statement)->object_field_list = db_object_field_list_new_copy(object_field_list))
222  || !((*statement)->mysql_bind_output = calloc(params, sizeof(MYSQL_BIND))))
223  {
224  mysql_free_result(result_metadata);
225  __db_backend_mysql_finish(*statement);
226  *statement = NULL;
227  return DB_ERROR_UNKNOWN;
228  }
229 
230  (*statement)->fields = params;
231  field = mysql_fetch_field(result_metadata);
232  object_field = db_object_field_list_begin(object_field_list);
233  for (i = 0; i < params; i++) {
234  if (!field
235  || !object_field
236  || !(bind = calloc(1, sizeof(db_backend_mysql_bind_t))))
237  {
238  mysql_free_result(result_metadata);
239  __db_backend_mysql_finish(*statement);
240  *statement = NULL;
241  return DB_ERROR_UNKNOWN;
242  }
243 
244  bind->bind = (mysql_bind = &((*statement)->mysql_bind_output[i]));
245  mysql_bind->is_null = (my_bool*)0;
246  mysql_bind->error = &bind->error;
247  mysql_bind->length = &bind->length;
248 
249  switch (db_object_field_type(object_field)) {
250  case DB_TYPE_PRIMARY_KEY:
251  switch (field->type) {
252  case MYSQL_TYPE_TINY:
253  case MYSQL_TYPE_SHORT:
254  case MYSQL_TYPE_LONG:
255  case MYSQL_TYPE_INT24:
256  mysql_bind->buffer_type = MYSQL_TYPE_LONG;
257  if (!(mysql_bind->buffer = calloc(1, sizeof(db_type_uint32_t)))) {
258  mysql_free_result(result_metadata);
259  __db_backend_mysql_finish(*statement);
260  *statement = NULL;
261  return DB_ERROR_UNKNOWN;
262  }
263  mysql_bind->buffer_length = sizeof(db_type_uint32_t);
264  bind->length = mysql_bind->buffer_length;
265  mysql_bind->is_unsigned = 1;
266  break;
267 
268  case MYSQL_TYPE_LONGLONG:
269  mysql_bind->buffer_type = MYSQL_TYPE_LONGLONG;
270  if (!(mysql_bind->buffer = calloc(1, sizeof(db_type_uint64_t)))) {
271  mysql_free_result(result_metadata);
272  __db_backend_mysql_finish(*statement);
273  *statement = NULL;
274  return DB_ERROR_UNKNOWN;
275  }
276  mysql_bind->buffer_length = sizeof(db_type_uint64_t);
277  bind->length = mysql_bind->buffer_length;
278  mysql_bind->is_unsigned = 1;
279  break;
280 
281  case MYSQL_TYPE_STRING:
282  case MYSQL_TYPE_VAR_STRING:
283  mysql_bind->buffer_type = MYSQL_TYPE_STRING;
284  /*
285  * field->length does not include ending NULL character so
286  * we increase it by one.
287  */
288  bind->length = field->length + 1;
291  }
292  if (!(mysql_bind->buffer = calloc(1, bind->length))) {
293  mysql_free_result(result_metadata);
294  __db_backend_mysql_finish(*statement);
295  *statement = NULL;
296  return DB_ERROR_UNKNOWN;
297  }
298  mysql_bind->buffer_length = bind->length;
299  mysql_bind->is_unsigned = 0;
300  break;
301 
302  default:
303  mysql_free_result(result_metadata);
304  __db_backend_mysql_finish(*statement);
305  *statement = NULL;
306  return DB_ERROR_UNKNOWN;
307  }
308  break;
309 
310  case DB_TYPE_ENUM:
311  /*
312  * Enum needs to be handled elsewhere since we don't know the
313  * enum_set_t here.
314  *
315  * TODO: can something be done here?
316  */
317  case DB_TYPE_INT32:
318  mysql_bind->buffer_type = MYSQL_TYPE_LONG;
319  if (!(mysql_bind->buffer = calloc(1, sizeof(db_type_int32_t)))) {
320  mysql_free_result(result_metadata);
321  __db_backend_mysql_finish(*statement);
322  *statement = NULL;
323  return DB_ERROR_UNKNOWN;
324  }
325  mysql_bind->buffer_length = sizeof(db_type_int32_t);
326  bind->length = mysql_bind->buffer_length;
327  mysql_bind->is_unsigned = 0;
328  break;
329 
330  case DB_TYPE_UINT32:
331  mysql_bind->buffer_type = MYSQL_TYPE_LONG;
332  if (!(mysql_bind->buffer = calloc(1, sizeof(db_type_uint32_t)))) {
333  mysql_free_result(result_metadata);
334  __db_backend_mysql_finish(*statement);
335  *statement = NULL;
336  return DB_ERROR_UNKNOWN;
337  }
338  mysql_bind->buffer_length = sizeof(db_type_uint32_t);
339  bind->length = mysql_bind->buffer_length;
340  mysql_bind->is_unsigned = 1;
341  break;
342 
343  case DB_TYPE_INT64:
344  mysql_bind->buffer_type = MYSQL_TYPE_LONGLONG;
345  if (!(mysql_bind->buffer = calloc(1, sizeof(db_type_int64_t)))) {
346  mysql_free_result(result_metadata);
347  __db_backend_mysql_finish(*statement);
348  *statement = NULL;
349  return DB_ERROR_UNKNOWN;
350  }
351  mysql_bind->buffer_length = sizeof(db_type_int64_t);
352  bind->length = mysql_bind->buffer_length;
353  mysql_bind->is_unsigned = 0;
354  break;
355 
356  case DB_TYPE_UINT64:
357  mysql_bind->buffer_type = MYSQL_TYPE_LONGLONG;
358  if (!(mysql_bind->buffer = calloc(1, sizeof(db_type_uint64_t)))) {
359  mysql_free_result(result_metadata);
360  __db_backend_mysql_finish(*statement);
361  *statement = NULL;
362  return DB_ERROR_UNKNOWN;
363  }
364  mysql_bind->buffer_length = sizeof(db_type_uint64_t);
365  bind->length = mysql_bind->buffer_length;
366  mysql_bind->is_unsigned = 1;
367  break;
368 
369  case DB_TYPE_TEXT:
370  mysql_bind->buffer_type = MYSQL_TYPE_STRING;
371  /*
372  * field->length does not include ending NULL character so
373  * we increase it by one.
374  */
375  bind->length = field->length + 1;
378  }
379  if (!(mysql_bind->buffer = calloc(1, bind->length))) {
380  mysql_free_result(result_metadata);
381  __db_backend_mysql_finish(*statement);
382  *statement = NULL;
383  return DB_ERROR_UNKNOWN;
384  }
385  mysql_bind->buffer_length = bind->length;
386  mysql_bind->is_unsigned = 0;
387  break;
388 
389  case DB_TYPE_ANY:
390  case DB_TYPE_REVISION:
391  switch (field->type) {
392  case MYSQL_TYPE_TINY:
393  case MYSQL_TYPE_SHORT:
394  case MYSQL_TYPE_LONG:
395  case MYSQL_TYPE_INT24:
396  mysql_bind->buffer_type = MYSQL_TYPE_LONG;
397  if (field->flags & UNSIGNED_FLAG) {
398  if (!(mysql_bind->buffer = calloc(1, sizeof(db_type_uint32_t)))) {
399  mysql_free_result(result_metadata);
400  __db_backend_mysql_finish(*statement);
401  *statement = NULL;
402  return DB_ERROR_UNKNOWN;
403  }
404  mysql_bind->buffer_length = sizeof(db_type_uint32_t);
405  mysql_bind->is_unsigned = 1;
406  }
407  else {
408  if (!(mysql_bind->buffer = calloc(1, sizeof(db_type_int32_t)))) {
409  mysql_free_result(result_metadata);
410  __db_backend_mysql_finish(*statement);
411  *statement = NULL;
412  return DB_ERROR_UNKNOWN;
413  }
414  mysql_bind->buffer_length = sizeof(db_type_int32_t);
415  mysql_bind->is_unsigned = 0;
416  }
417  bind->length = mysql_bind->buffer_length;
418  break;
419 
420  case MYSQL_TYPE_LONGLONG:
421  mysql_bind->buffer_type = MYSQL_TYPE_LONGLONG;
422  if (field->flags & UNSIGNED_FLAG) {
423  if (!(mysql_bind->buffer = calloc(1, sizeof(db_type_uint64_t)))) {
424  mysql_free_result(result_metadata);
425  __db_backend_mysql_finish(*statement);
426  *statement = NULL;
427  return DB_ERROR_UNKNOWN;
428  }
429  mysql_bind->buffer_length = sizeof(db_type_uint64_t);
430  mysql_bind->is_unsigned = 1;
431  }
432  else {
433  if (!(mysql_bind->buffer = calloc(1, sizeof(db_type_int64_t)))) {
434  mysql_free_result(result_metadata);
435  __db_backend_mysql_finish(*statement);
436  *statement = NULL;
437  return DB_ERROR_UNKNOWN;
438  }
439  mysql_bind->buffer_length = sizeof(db_type_int64_t);
440  mysql_bind->is_unsigned = 0;
441  }
442  bind->length = mysql_bind->buffer_length;
443  break;
444 
445  case MYSQL_TYPE_STRING:
446  case MYSQL_TYPE_VAR_STRING:
447  mysql_bind->buffer_type = MYSQL_TYPE_STRING;
448  /*
449  * field->length does not include ending NULL character so
450  * we increase it by one.
451  */
452  bind->length = field->length + 1;
455  }
456  if (!(mysql_bind->buffer = calloc(1, bind->length))) {
457  mysql_free_result(result_metadata);
458  __db_backend_mysql_finish(*statement);
459  *statement = NULL;
460  return DB_ERROR_UNKNOWN;
461  }
462  mysql_bind->buffer_length = bind->length;
463  mysql_bind->is_unsigned = 0;
464  break;
465 
466  default:
467  mysql_free_result(result_metadata);
468  __db_backend_mysql_finish(*statement);
469  *statement = NULL;
470  return DB_ERROR_UNKNOWN;
471  }
472  break;
473 
474  default:
475  return DB_ERROR_UNKNOWN;
476  }
477 
478  if (!(*statement)->bind_output) {
479  (*statement)->bind_output = bind;
480  }
481  if ((*statement)->bind_output_end) {
482  (*statement)->bind_output_end->next = bind;
483  }
484  (*statement)->bind_output_end = bind;
485  object_field = db_object_field_next(object_field);
486  field = mysql_fetch_field(result_metadata);
487  }
488  /*
489  * If we still have an object field or a MySQL field then the number of
490  * fields in both is mismatching and we should return an error.
491  */
492  if (object_field || field) {
493  mysql_free_result(result_metadata);
494  __db_backend_mysql_finish(*statement);
495  *statement = NULL;
496  return DB_ERROR_UNKNOWN;
497  }
498  }
499  if (result_metadata) {
500  mysql_free_result(result_metadata);
501  }
502 
503  return DB_OK;
504 }
505 
511 static inline int __db_backend_mysql_fetch(db_backend_mysql_statement_t* statement) {
512  int ret;
513 
514  if (!statement) {
515  return DB_ERROR_UNKNOWN;
516  }
517  if (!statement->statement) {
518  return DB_ERROR_UNKNOWN;
519  }
520 
521  /*
522  * Handle output binding if not already done.
523  */
524  if (!statement->bound) {
525  if (statement->mysql_bind_output
526  && mysql_stmt_bind_result(statement->statement, statement->mysql_bind_output))
527  {
528  ods_log_info("DB bind result Err %d: %s", mysql_stmt_errno(statement->statement), mysql_stmt_error(statement->statement));
529  return DB_ERROR_UNKNOWN;
530  }
531  statement->bound = 1;
532  }
533 
534  /*
535  * Fetch the next row.
536  */
537  ret = mysql_stmt_fetch(statement->statement);
538  if (ret == 1) {
539  ods_log_info("DB fetch Err %d: %s", mysql_stmt_errno(statement->statement), mysql_stmt_error(statement->statement));
540  return DB_ERROR_UNKNOWN;
541  }
542  else if (ret == MYSQL_DATA_TRUNCATED) {
543  int i;
545 
546  /*
547  * Scan through all of the output binds and check where the data was
548  * truncated and reallocate the buffer and try again. MySQL should have
549  * updated bind->length with the required buffer size.
550  *
551  * We can really only retry fetch on string columns, if another type had
552  * a too small buffer its more a programmable error in the prepare
553  * function.
554  */
555  for (i = 0, bind = statement->bind_output; bind; i++, bind = bind->next) {
556  if (bind->error) {
557  if (statement->mysql_bind_output[i].buffer_type != MYSQL_TYPE_STRING
558  || bind->length <= statement->mysql_bind_output[i].buffer_length)
559  {
560  ods_log_info("DB fetch Err data truncated");
561  return DB_ERROR_UNKNOWN;
562  }
563 
564  free(statement->mysql_bind_output[i].buffer);
565  statement->mysql_bind_output[i].buffer = NULL;
566  if (!(statement->mysql_bind_output[i].buffer = calloc(1, bind->length))) {
567  ods_log_info("DB fetch Err data truncated");
568  return DB_ERROR_UNKNOWN;
569  }
570  statement->mysql_bind_output[i].buffer_length = bind->length;
571  bind->error = 0;
572  if (mysql_stmt_fetch_column(statement->statement, &(statement->mysql_bind_output[i]), i, 0)
573  || bind->error)
574  {
575  ods_log_info("DB fetch Err data truncated");
576  return DB_ERROR_UNKNOWN;
577  }
578  }
579  }
580  }
581  else if (ret == MYSQL_NO_DATA) {
582  /*
583  * Not really an error but we need to indicate that there is no more
584  * data some how.
585  */
586  return DB_ERROR_UNKNOWN;
587  }
588  else if (ret) {
589  ods_log_info("DB fetch UNKNOWN %d Err %d: %s", ret, mysql_stmt_errno(statement->statement), mysql_stmt_error(statement->statement));
590  return DB_ERROR_UNKNOWN;
591  }
592 
593  return DB_OK;
594 }
595 
601 static inline int __db_backend_mysql_execute(db_backend_mysql_statement_t* statement) {
602  if (!statement) {
603  return DB_ERROR_UNKNOWN;
604  }
605  if (!statement->statement) {
606  return DB_ERROR_UNKNOWN;
607  }
608 
609  /*
610  * Bind the input parameters.
611  */
612  if (statement->mysql_bind_input
613  && mysql_stmt_bind_param(statement->statement, statement->mysql_bind_input))
614  {
615  ods_log_info("DB bind param Err %d: %s", mysql_stmt_errno(statement->statement), mysql_stmt_error(statement->statement));
616  return DB_ERROR_UNKNOWN;
617  }
618 
619  /*
620  * Execute the statement.
621  */
622  if (mysql_stmt_execute(statement->statement)) {
623  ods_log_info("DB execute Err %d: %s", mysql_stmt_errno(statement->statement), mysql_stmt_error(statement->statement));
624  return DB_ERROR_UNKNOWN;
625  }
626 
627  return DB_OK;
628 }
629 
630 static int db_backend_mysql_initialize(void* data) {
631  db_backend_mysql_t* backend_mysql = (db_backend_mysql_t*)data;
632 
633  if (!backend_mysql) {
634  return DB_ERROR_UNKNOWN;
635  }
636 
637  if (!__mysql_initialized) {
638  if (mysql_library_init(0, NULL, NULL)) {
639  return DB_ERROR_UNKNOWN;
640  }
641  __mysql_initialized = 1;
642  }
643  return DB_OK;
644 }
645 
646 static int db_backend_mysql_shutdown(void* data) {
647  db_backend_mysql_t* backend_mysql = (db_backend_mysql_t*)data;
648 
649  if (!backend_mysql) {
650  return DB_ERROR_UNKNOWN;
651  }
652 
653  if (__mysql_initialized) {
654  mysql_library_end();
655  __mysql_initialized = 0;
656  }
657  return DB_OK;
658 }
659 
660 static int db_backend_mysql_connect(void* data, const db_configuration_list_t* configuration_list) {
661  db_backend_mysql_t* backend_mysql = (db_backend_mysql_t*)data;
662  const db_configuration_t* host;
663  const db_configuration_t* user;
664  const db_configuration_t* pass;
665  const db_configuration_t* db;
666  const db_configuration_t* port_configuration;
667  const db_configuration_t* timeout_configuration;
668  int timeout;
669  unsigned int port = 0;
670 
671  if (!__mysql_initialized) {
672  return DB_ERROR_UNKNOWN;
673  }
674  if (!backend_mysql) {
675  return DB_ERROR_UNKNOWN;
676  }
677  if (backend_mysql->db) {
678  return DB_ERROR_UNKNOWN;
679  }
680  if (!configuration_list) {
681  return DB_ERROR_UNKNOWN;
682  }
683 
684  host = db_configuration_list_find(configuration_list, "host");
685  user = db_configuration_list_find(configuration_list, "user");
686  pass = db_configuration_list_find(configuration_list, "pass");
687  db = db_configuration_list_find(configuration_list, "db");
688  port_configuration = db_configuration_list_find(configuration_list, "port");
689  if (port_configuration) {
690  port = atoi(db_configuration_value(port_configuration));
691  }
692 
693  backend_mysql->timeout = DB_BACKEND_MYSQL_DEFAULT_TIMEOUT;
694  if ((timeout_configuration = db_configuration_list_find(configuration_list, "timeout"))) {
695  timeout = atoi(db_configuration_value(timeout_configuration));
696  if (timeout < 1) {
697  backend_mysql->timeout = DB_BACKEND_MYSQL_DEFAULT_TIMEOUT;
698  }
699  else {
700  backend_mysql->timeout = (unsigned int)timeout;
701  }
702  }
703 
704  if (!(backend_mysql->db = mysql_init(NULL))
705  || mysql_options(backend_mysql->db, MYSQL_OPT_CONNECT_TIMEOUT, &backend_mysql->timeout)
706  || !mysql_real_connect(backend_mysql->db,
707  (host ? db_configuration_value(host) : NULL),
708  (user ? db_configuration_value(user) : NULL),
709  (pass ? db_configuration_value(pass) : NULL),
710  (db ? db_configuration_value(db) : NULL),
711  port,
712  NULL,
713  0)
714  || mysql_autocommit(backend_mysql->db, 1))
715  {
716  if (backend_mysql->db) {
717  ods_log_error("db_backend_mysql: connect failed %d: %s", mysql_errno(backend_mysql->db), mysql_error(backend_mysql->db));
718  mysql_close(backend_mysql->db);
719  backend_mysql->db = NULL;
720  }
721  return DB_ERROR_UNKNOWN;
722  }
723 
724  return DB_OK;
725 }
726 
727 static int db_backend_mysql_disconnect(void* data) {
728  db_backend_mysql_t* backend_mysql = (db_backend_mysql_t*)data;
729 
730  if (!__mysql_initialized) {
731  return DB_ERROR_UNKNOWN;
732  }
733  if (!backend_mysql) {
734  return DB_ERROR_UNKNOWN;
735  }
736  if (!backend_mysql->db) {
737  return DB_ERROR_UNKNOWN;
738  }
739 
740  if (backend_mysql->transaction) {
741  db_backend_mysql_transaction_rollback(backend_mysql);
742  }
743 
744  mysql_close(backend_mysql->db);
745  backend_mysql->db = NULL;
746 
747  return DB_OK;
748 }
749 
759 static int __db_backend_mysql_build_clause(const db_object_t* object, const db_clause_list_t* clause_list, char** sqlp, int* left) {
760  const db_clause_t* clause;
761  int first, ret;
762 
763  if (!clause_list) {
764  return DB_ERROR_UNKNOWN;
765  }
766  if (!sqlp) {
767  return DB_ERROR_UNKNOWN;
768  }
769  if (!*sqlp) {
770  return DB_ERROR_UNKNOWN;
771  }
772  if (!left) {
773  return DB_ERROR_UNKNOWN;
774  }
775  if (*left < 1) {
776  return DB_ERROR_UNKNOWN;
777  }
778 
779  clause = db_clause_list_begin(clause_list);
780  first = 1;
781  while (clause) {
782  if (first) {
783  first = 0;
784  }
785  else {
786  switch (db_clause_operator(clause)) {
788  if ((ret = snprintf(*sqlp, *left, " AND")) >= *left) {
789  return DB_ERROR_UNKNOWN;
790  }
791  break;
792 
794  if ((ret = snprintf(*sqlp, *left, " OR")) >= *left) {
795  return DB_ERROR_UNKNOWN;
796  }
797  break;
798 
799  default:
800  return DB_ERROR_UNKNOWN;
801  }
802  *sqlp += ret;
803  *left -= ret;
804  }
805 
806  switch (db_clause_type(clause)) {
807  case DB_CLAUSE_EQUAL:
808  if ((ret = snprintf(*sqlp, *left, " %s.%s = ?",
809  db_object_table(object),
810  db_clause_field(clause))) >= *left)
811  {
812  return DB_ERROR_UNKNOWN;
813  }
814  break;
815 
816  case DB_CLAUSE_NOT_EQUAL:
817  if ((ret = snprintf(*sqlp, *left, " %s.%s != ?",
818  db_object_table(object),
819  db_clause_field(clause))) >= *left)
820  {
821  return DB_ERROR_UNKNOWN;
822  }
823  break;
824 
825  case DB_CLAUSE_LESS_THEN:
826  if ((ret = snprintf(*sqlp, *left, " %s.%s < ?",
827  db_object_table(object),
828  db_clause_field(clause))) >= *left)
829  {
830  return DB_ERROR_UNKNOWN;
831  }
832  break;
833 
835  if ((ret = snprintf(*sqlp, *left, " %s.%s <= ?",
836  db_object_table(object),
837  db_clause_field(clause))) >= *left)
838  {
839  return DB_ERROR_UNKNOWN;
840  }
841  break;
842 
844  if ((ret = snprintf(*sqlp, *left, " %s.%s >= ?",
845  db_object_table(object),
846  db_clause_field(clause))) >= *left)
847  {
848  return DB_ERROR_UNKNOWN;
849  }
850  break;
851 
853  if ((ret = snprintf(*sqlp, *left, " %s.%s > ?",
854  db_object_table(object),
855  db_clause_field(clause))) >= *left)
856  {
857  return DB_ERROR_UNKNOWN;
858  }
859  break;
860 
861  case DB_CLAUSE_IS_NULL:
862  if ((ret = snprintf(*sqlp, *left, " %s.%s IS NULL",
863  db_object_table(object),
864  db_clause_field(clause))) >= *left)
865  {
866  return DB_ERROR_UNKNOWN;
867  }
868  break;
869 
871  if ((ret = snprintf(*sqlp, *left, " %s.%s IS NOT NULL",
872  db_object_table(object),
873  db_clause_field(clause))) >= *left)
874  {
875  return DB_ERROR_UNKNOWN;
876  }
877  break;
878 
879  case DB_CLAUSE_NESTED:
880  if ((ret = snprintf(*sqlp, *left, " (")) >= *left) {
881  return DB_ERROR_UNKNOWN;
882  }
883  *sqlp += ret;
884  *left -= ret;
885  if (__db_backend_mysql_build_clause(object, db_clause_list(clause), sqlp, left)) {
886  return DB_ERROR_UNKNOWN;
887  }
888  if ((ret = snprintf(*sqlp, *left, " )")) >= *left) {
889  return DB_ERROR_UNKNOWN;
890  }
891  break;
892 
893  default:
894  return DB_ERROR_UNKNOWN;
895  }
896  *sqlp += ret;
897  *left -= ret;
898 
899  clause = db_clause_next(clause);
900  }
901  return DB_OK;
902 }
903 
909 static int __db_backend_mysql_bind_clause(db_backend_mysql_bind_t** bind, const db_clause_list_t* clause_list) {
910  const db_clause_t* clause;
911  const db_type_int32_t* int32;
912  const db_type_uint32_t* uint32;
913  const db_type_int64_t* int64;
914  const db_type_uint64_t* uint64;
915  const char* text;
916 
917  if (!bind) {
918  return DB_ERROR_UNKNOWN;
919  }
920  if (!*bind) {
921  return DB_ERROR_UNKNOWN;
922  }
923  if (!clause_list) {
924  return DB_ERROR_UNKNOWN;
925  }
926 
927  clause = db_clause_list_begin(clause_list);
928  while (clause) {
929  if (!*bind) {
930  return DB_ERROR_UNKNOWN;
931  }
932 
933  (*bind)->bind->length = &((*bind)->bind->buffer_length);
934  (*bind)->bind->is_null = (my_bool*)0;
935 
936  switch (db_clause_type(clause)) {
937  case DB_CLAUSE_EQUAL:
938  case DB_CLAUSE_NOT_EQUAL:
939  case DB_CLAUSE_LESS_THEN:
943  switch (db_value_type(db_clause_value(clause))) {
944  case DB_TYPE_PRIMARY_KEY:
945  case DB_TYPE_INT32:
946  if (!(int32 = db_value_int32(db_clause_value(clause)))) {
947  return DB_ERROR_UNKNOWN;
948  }
949  (*bind)->bind->buffer_type = MYSQL_TYPE_LONG;
950  (*bind)->bind->buffer = (void*)int32;
951  (*bind)->bind->buffer_length = sizeof(db_type_int32_t);
952  (*bind)->bind->is_unsigned = 0;
953  break;
954 
955  case DB_TYPE_UINT32:
956  if (!(uint32 = db_value_uint32(db_clause_value(clause)))) {
957  return DB_ERROR_UNKNOWN;
958  }
959  (*bind)->bind->buffer_type = MYSQL_TYPE_LONG;
960  (*bind)->bind->buffer = (void*)uint32;
961  (*bind)->bind->buffer_length = sizeof(db_type_uint32_t);
962  (*bind)->bind->is_unsigned = 1;
963  break;
964 
965  case DB_TYPE_INT64:
966  if (!(int64 = db_value_int64(db_clause_value(clause)))) {
967  return DB_ERROR_UNKNOWN;
968  }
969  (*bind)->bind->buffer_type = MYSQL_TYPE_LONGLONG;
970  (*bind)->bind->buffer = (void*)int64;
971  (*bind)->bind->buffer_length = sizeof(db_type_int64_t);
972  (*bind)->bind->is_unsigned = 0;
973  break;
974 
975  case DB_TYPE_UINT64:
976  if (!(uint64 = db_value_uint64(db_clause_value(clause)))) {
977  return DB_ERROR_UNKNOWN;
978  }
979  (*bind)->bind->buffer_type = MYSQL_TYPE_LONGLONG;
980  (*bind)->bind->buffer = (void*)uint64;
981  (*bind)->bind->buffer_length = sizeof(db_type_uint64_t);
982  (*bind)->bind->is_unsigned = 1;
983  break;
984 
985  case DB_TYPE_TEXT:
986  if (!(text = db_value_text(db_clause_value(clause)))) {
987  return DB_ERROR_UNKNOWN;
988  }
989  (*bind)->bind->buffer_type = MYSQL_TYPE_STRING;
990  (*bind)->bind->buffer = (void*)text;
991  (*bind)->bind->buffer_length = strlen(text);
992  (*bind)->bind->is_unsigned = 0;
993  break;
994 
995  case DB_TYPE_ENUM:
996  if (db_value_enum_value(db_clause_value(clause), &((*bind)->value_enum))) {
997  return DB_ERROR_UNKNOWN;
998  }
999  (*bind)->bind->buffer_type = MYSQL_TYPE_LONG;
1000  (*bind)->bind->buffer = (void*)&((*bind)->value_enum);
1001  (*bind)->bind->buffer_length = sizeof(int);
1002  (*bind)->bind->is_unsigned = 0;
1003  break;
1004 
1005  default:
1006  return DB_ERROR_UNKNOWN;
1007  }
1008  break;
1009 
1010  case DB_CLAUSE_IS_NULL:
1011  /* TODO: is null */
1012  break;
1013 
1014  case DB_CLAUSE_IS_NOT_NULL:
1015  /* TODO: is not null */
1016  break;
1017 
1018  case DB_CLAUSE_NESTED:
1019  *bind = (*bind)->next;
1020  if (__db_backend_mysql_bind_clause(bind, db_clause_list(clause))) {
1021  return DB_ERROR_UNKNOWN;
1022  }
1023  clause = db_clause_next(clause);
1024  continue;
1025 
1026  default:
1027  return DB_ERROR_UNKNOWN;
1028  }
1029 
1030  *bind = (*bind)->next;
1031  clause = db_clause_next(clause);
1032  }
1033  return DB_OK;
1034 }
1035 
1036 static int __db_backend_mysql_bind_value(db_backend_mysql_bind_t* bind, const db_value_t* value) {
1037  const db_type_int32_t* int32;
1038  const db_type_uint32_t* uint32;
1039  const db_type_int64_t* int64;
1040  const db_type_uint64_t* uint64;
1041  const char* text;
1042 
1043  if (!bind) {
1044  return DB_ERROR_UNKNOWN;
1045  }
1046  if (!bind->bind) {
1047  return DB_ERROR_UNKNOWN;
1048  }
1049  if (!value) {
1050  return DB_ERROR_UNKNOWN;
1051  }
1052 
1053  bind->bind->length = &(bind->bind->buffer_length);
1054  bind->bind->is_null = (my_bool*)0;
1055 
1056  switch (db_value_type(value)) {
1057  case DB_TYPE_PRIMARY_KEY:
1058  case DB_TYPE_INT32:
1059  if (!(int32 = db_value_int32(value))) {
1060  return DB_ERROR_UNKNOWN;
1061  }
1062  bind->bind->buffer_type = MYSQL_TYPE_LONG;
1063  bind->bind->buffer = (void*)int32;
1064  bind->bind->buffer_length = sizeof(db_type_int32_t);
1065  bind->bind->is_unsigned = 0;
1066  break;
1067 
1068  case DB_TYPE_UINT32:
1069  if (!(uint32 = db_value_uint32(value))) {
1070  return DB_ERROR_UNKNOWN;
1071  }
1072  bind->bind->buffer_type = MYSQL_TYPE_LONG;
1073  bind->bind->buffer = (void*)uint32;
1074  bind->bind->buffer_length = sizeof(db_type_uint32_t);
1075  bind->bind->is_unsigned = 1;
1076  break;
1077 
1078  case DB_TYPE_INT64:
1079  if (!(int64 = db_value_int64(value))) {
1080  return DB_ERROR_UNKNOWN;
1081  }
1082  bind->bind->buffer_type = MYSQL_TYPE_LONGLONG;
1083  bind->bind->buffer = (void*)int64;
1084  bind->bind->buffer_length = sizeof(db_type_int64_t);
1085  bind->bind->is_unsigned = 0;
1086  break;
1087 
1088  case DB_TYPE_UINT64:
1089  if (!(uint64 = db_value_uint64(value))) {
1090  return DB_ERROR_UNKNOWN;
1091  }
1092  bind->bind->buffer_type = MYSQL_TYPE_LONGLONG;
1093  bind->bind->buffer = (void*)uint64;
1094  bind->bind->buffer_length = sizeof(db_type_uint64_t);
1095  bind->bind->is_unsigned = 1;
1096  break;
1097 
1098  case DB_TYPE_TEXT:
1099  if (!(text = db_value_text(value))) {
1100  return DB_ERROR_UNKNOWN;
1101  }
1102  bind->bind->buffer_type = MYSQL_TYPE_STRING;
1103  bind->bind->buffer = (void*)text;
1104  bind->bind->buffer_length = strlen(text);
1105  bind->bind->is_unsigned = 0;
1106  break;
1107 
1108  case DB_TYPE_ENUM:
1109  if (db_value_enum_value(value, &(bind->value_enum))) {
1110  return DB_ERROR_UNKNOWN;
1111  }
1112  bind->bind->buffer_type = MYSQL_TYPE_LONG;
1113  bind->bind->buffer = (void*)&(bind->value_enum);
1114  bind->bind->buffer_length = sizeof(int);
1115  bind->bind->is_unsigned = 0;
1116  break;
1117 
1118  default:
1119  return DB_ERROR_UNKNOWN;
1120  }
1121 
1122  return DB_OK;
1123 }
1124 
1125 static int __db_backend_mysql_bind_value_set(db_backend_mysql_bind_t** bind, const db_value_set_t* value_set) {
1126  size_t i;
1127 
1128  if (!bind) {
1129  return DB_ERROR_UNKNOWN;
1130  }
1131  if (!*bind) {
1132  return DB_ERROR_UNKNOWN;
1133  }
1134  if (!value_set) {
1135  return DB_ERROR_UNKNOWN;
1136  }
1137 
1138  for (i = 0; i < db_value_set_size(value_set); i++, *bind = (*bind)->next) {
1139  if (!*bind) {
1140  return DB_ERROR_UNKNOWN;
1141  }
1142 
1143  if (__db_backend_mysql_bind_value(*bind, db_value_set_at(value_set, i))) {
1144  return DB_ERROR_UNKNOWN;
1145  }
1146  }
1147  return DB_OK;
1148 }
1149 
1150 static db_result_t* db_backend_mysql_next(void* data, int finish) {
1152  db_result_t* result = NULL;
1153  db_value_set_t* value_set = NULL;
1154  const db_object_field_t* object_field;
1156  int value;
1157 
1158  if (!statement) {
1159  return NULL;
1160  }
1161  if (!statement->object_field_list) {
1162  return NULL;
1163  }
1164  if (!statement->statement) {
1165  return NULL;
1166  }
1167 
1168  if (finish) {
1169  __db_backend_mysql_finish(statement);
1170  return NULL;
1171  }
1172 
1173  if (__db_backend_mysql_fetch(statement)) {
1174  return NULL;
1175  }
1176 
1177  if (!(result = db_result_new())
1178  || !(value_set = db_value_set_new(statement->fields))
1179  || db_result_set_value_set(result, value_set))
1180  {
1181  db_result_free(result);
1182  db_value_set_free(value_set);
1183  return NULL;
1184  }
1185  object_field = db_object_field_list_begin(statement->object_field_list);
1186  bind = statement->bind_output;
1187  value = 0;
1188  while (object_field) {
1189  if (!bind || !bind->bind || !bind->bind->buffer) {
1190  db_result_free(result);
1191  return NULL;
1192  }
1193 
1194  switch (db_object_field_type(object_field)) {
1195  case DB_TYPE_PRIMARY_KEY:
1196  case DB_TYPE_ANY:
1197  case DB_TYPE_REVISION:
1198  switch (bind->bind->buffer_type) {
1199  case MYSQL_TYPE_LONG:
1200  if ((bind->bind->is_unsigned
1201  && db_value_from_uint32(db_value_set_get(value_set, value), *((db_type_uint32_t*)bind->bind->buffer)))
1202  || (!bind->bind->is_unsigned
1203  && db_value_from_int32(db_value_set_get(value_set, value), *((db_type_int32_t*)bind->bind->buffer))))
1204  {
1205  db_result_free(result);
1206  return NULL;
1207  }
1208  break;
1209 
1210  case MYSQL_TYPE_LONGLONG:
1211  if ((bind->bind->is_unsigned
1212  && db_value_from_uint64(db_value_set_get(value_set, value), *((db_type_uint64_t*)bind->bind->buffer)))
1213  || (!bind->bind->is_unsigned
1214  && db_value_from_int64(db_value_set_get(value_set, value), *((db_type_int64_t*)bind->bind->buffer))))
1215  {
1216  db_result_free(result);
1217  return NULL;
1218  }
1219  break;
1220 
1221  case MYSQL_TYPE_STRING:
1222  if ((!bind->length
1223  && db_value_from_text(db_value_set_get(value_set, value), ""))
1224  || (bind->length
1225  && db_value_from_text2(db_value_set_get(value_set, value), (char*)bind->bind->buffer, bind->length)))
1226  {
1227  db_result_free(result);
1228  return NULL;
1229  }
1230  break;
1231 
1232  default:
1233  db_result_free(result);
1234  return NULL;
1235  }
1236  if (db_object_field_type(object_field) == DB_TYPE_PRIMARY_KEY
1237  && db_value_set_primary_key(db_value_set_get(value_set, value)))
1238  {
1239  db_result_free(result);
1240  return NULL;
1241  }
1242  break;
1243 
1244  case DB_TYPE_ENUM:
1245  /*
1246  * Enum needs to be handled elsewhere since we don't know the
1247  * enum_set_t here.
1248  */
1249  case DB_TYPE_INT32:
1250  case DB_TYPE_UINT32:
1251  if (bind->bind->buffer_type != MYSQL_TYPE_LONG
1252  || (bind->bind->is_unsigned
1253  && db_value_from_uint32(db_value_set_get(value_set, value), *((db_type_uint32_t*)bind->bind->buffer)))
1254  || (!bind->bind->is_unsigned
1255  && db_value_from_int32(db_value_set_get(value_set, value), *((db_type_int32_t*)bind->bind->buffer))))
1256  {
1257  db_result_free(result);
1258  return NULL;
1259  }
1260  break;
1261 
1262  case DB_TYPE_INT64:
1263  case DB_TYPE_UINT64:
1264  if (bind->bind->buffer_type != MYSQL_TYPE_LONGLONG
1265  || (bind->bind->is_unsigned
1266  && db_value_from_uint64(db_value_set_get(value_set, value), *((db_type_uint64_t*)bind->bind->buffer)))
1267  || (!bind->bind->is_unsigned
1268  && db_value_from_int64(db_value_set_get(value_set, value), *((db_type_int64_t*)bind->bind->buffer))))
1269  {
1270  db_result_free(result);
1271  return NULL;
1272  }
1273  break;
1274 
1275  case DB_TYPE_TEXT:
1276  if (bind->bind->buffer_type != MYSQL_TYPE_STRING
1277  || (!bind->length
1278  && db_value_from_text(db_value_set_get(value_set, value), ""))
1279  || (bind->length
1280  && db_value_from_text2(db_value_set_get(value_set, value), (char*)bind->bind->buffer, bind->length)))
1281  {
1282  db_result_free(result);
1283  return NULL;
1284  }
1285  break;
1286 
1287  default:
1288  db_result_free(result);
1289  return NULL;
1290  }
1291 
1292  object_field = db_object_field_next(object_field);
1293  value++;
1294  bind = bind->next;
1295  }
1296  return result;
1297 }
1298 
1299 static int db_backend_mysql_create(void* data, const db_object_t* object, const db_object_field_list_t* object_field_list, const db_value_set_t* value_set) {
1300  db_backend_mysql_t* backend_mysql = (db_backend_mysql_t*)data;
1301  const db_object_field_t* object_field;
1302  const db_object_field_t* revision_field = NULL;
1303  char sql[4*1024];
1304  char* sqlp;
1305  int ret, left, first;
1306  db_backend_mysql_statement_t* statement = NULL;
1308  db_value_t revision = DB_VALUE_EMPTY;
1309 
1310  if (!__mysql_initialized) {
1311  return DB_ERROR_UNKNOWN;
1312  }
1313  if (!backend_mysql) {
1314  return DB_ERROR_UNKNOWN;
1315  }
1316  if (!object) {
1317  return DB_ERROR_UNKNOWN;
1318  }
1319  if (!object_field_list) {
1320  return DB_ERROR_UNKNOWN;
1321  }
1322  if (!value_set) {
1323  return DB_ERROR_UNKNOWN;
1324  }
1325 
1326  /*
1327  * Check if the object has a revision field and keep it for later use.
1328  */
1330  while (object_field) {
1331  if (db_object_field_type(object_field) == DB_TYPE_REVISION) {
1332  if (revision_field) {
1333  /*
1334  * We do not support multiple revision fields.
1335  */
1336  return DB_ERROR_UNKNOWN;
1337  }
1338 
1339  revision_field = object_field;
1340  }
1341  object_field = db_object_field_next(object_field);
1342  }
1343 
1344  left = sizeof(sql);
1345  sqlp = sql;
1346  memset(sql, 0, left);
1347 
1348  if (!db_object_field_list_begin(object_field_list) && !revision_field) {
1349  /*
1350  * Special case when tables has no fields except maybe a primary key.
1351  */
1352  if ((ret = snprintf(sqlp, left, "INSERT INTO %s () VALUES ()", db_object_table(object))) >= left) {
1353  return DB_ERROR_UNKNOWN;
1354  }
1355  sqlp += ret;
1356  left -= ret;
1357  }
1358  else {
1359  if ((ret = snprintf(sqlp, left, "INSERT INTO %s (", db_object_table(object))) >= left) {
1360  return DB_ERROR_UNKNOWN;
1361  }
1362  sqlp += ret;
1363  left -= ret;
1364 
1365  /*
1366  * Add the fields from the given object_field_list.
1367  */
1368  object_field = db_object_field_list_begin(object_field_list);
1369  first = 1;
1370  while (object_field) {
1371  if (first) {
1372  if ((ret = snprintf(sqlp, left, " %s", db_object_field_name(object_field))) >= left) {
1373  return DB_ERROR_UNKNOWN;
1374  }
1375  first = 0;
1376  }
1377  else {
1378  if ((ret = snprintf(sqlp, left, ", %s", db_object_field_name(object_field))) >= left) {
1379  return DB_ERROR_UNKNOWN;
1380  }
1381  }
1382  sqlp += ret;
1383  left -= ret;
1384 
1385  object_field = db_object_field_next(object_field);
1386  }
1387 
1388  /*
1389  * Add the revision field if we have one.
1390  */
1391  if (revision_field) {
1392  if (first) {
1393  if ((ret = snprintf(sqlp, left, " %s", db_object_field_name(revision_field))) >= left) {
1394  return DB_ERROR_UNKNOWN;
1395  }
1396  first = 0;
1397  }
1398  else {
1399  if ((ret = snprintf(sqlp, left, ", %s", db_object_field_name(revision_field))) >= left) {
1400  return DB_ERROR_UNKNOWN;
1401  }
1402  }
1403  sqlp += ret;
1404  left -= ret;
1405  }
1406 
1407  if ((ret = snprintf(sqlp, left, " ) VALUES (")) >= left) {
1408  return DB_ERROR_UNKNOWN;
1409  }
1410  sqlp += ret;
1411  left -= ret;
1412 
1413  /*
1414  * Mark all the fields for binding from the object_field_list.
1415  */
1416  object_field = db_object_field_list_begin(object_field_list);
1417  first = 1;
1418  while (object_field) {
1419  if (first) {
1420  if ((ret = snprintf(sqlp, left, " ?")) >= left) {
1421  return DB_ERROR_UNKNOWN;
1422  }
1423  first = 0;
1424  }
1425  else {
1426  if ((ret = snprintf(sqlp, left, ", ?")) >= left) {
1427  return DB_ERROR_UNKNOWN;
1428  }
1429  }
1430  sqlp += ret;
1431  left -= ret;
1432 
1433  object_field = db_object_field_next(object_field);
1434  }
1435 
1436  /*
1437  * Mark revision field for binding if we have one.
1438  */
1439  if (revision_field) {
1440  if (first) {
1441  if ((ret = snprintf(sqlp, left, " ?")) >= left) {
1442  return DB_ERROR_UNKNOWN;
1443  }
1444  first = 0;
1445  }
1446  else {
1447  if ((ret = snprintf(sqlp, left, ", ?")) >= left) {
1448  return DB_ERROR_UNKNOWN;
1449  }
1450  }
1451  sqlp += ret;
1452  left -= ret;
1453  }
1454 
1455  if ((ret = snprintf(sqlp, left, " )")) >= left) {
1456  return DB_ERROR_UNKNOWN;
1457  }
1458  sqlp += ret;
1459  left -= ret;
1460  }
1461 
1462  /*
1463  * Prepare the SQL, create a MySQL statement.
1464  */
1465  if (__db_backend_mysql_prepare(backend_mysql, &statement, sql, strlen(sql), db_object_object_field_list(object))
1466  || !statement
1467  || !(bind = statement->bind_input))
1468  {
1469  __db_backend_mysql_finish(statement);
1470  return DB_ERROR_UNKNOWN;
1471  }
1472 
1473  /*
1474  * Bind all the values from value_set.
1475  */
1476  if (__db_backend_mysql_bind_value_set(&bind, value_set)) {
1477  __db_backend_mysql_finish(statement);
1478  return DB_ERROR_UNKNOWN;
1479  }
1480 
1481  /*
1482  * Bind the revision field value if we have one.
1483  */
1484  if (revision_field) {
1485  if (db_value_from_int64(&revision, 1)
1486  || __db_backend_mysql_bind_value(bind, &revision))
1487  {
1488  db_value_reset(&revision);
1489  __db_backend_mysql_finish(statement);
1490  return DB_ERROR_UNKNOWN;
1491  }
1492  db_value_reset(&revision);
1493  }
1494 
1495  /*
1496  * Execute the SQL.
1497  */
1498  if (__db_backend_mysql_execute(statement)
1499  || mysql_stmt_affected_rows(statement->statement) != 1)
1500  {
1501  __db_backend_mysql_finish(statement);
1502  return DB_ERROR_UNKNOWN;
1503  }
1504  __db_backend_mysql_finish(statement);
1505 
1506  return DB_OK;
1507 }
1508 
1509 static db_result_list_t* db_backend_mysql_read(void* data, const db_object_t* object, const db_join_list_t* join_list, const db_clause_list_t* clause_list) {
1510  db_backend_mysql_t* backend_mysql = (db_backend_mysql_t*)data;
1511  const db_object_field_t* object_field;
1512  const db_join_t* join;
1513  char sql[4*1024];
1514  char* sqlp;
1515  int ret, left, first;
1516  db_result_list_t* result_list;
1517  db_backend_mysql_statement_t* statement = NULL;
1519 
1520  if (!__mysql_initialized) {
1521  return NULL;
1522  }
1523  if (!backend_mysql) {
1524  return NULL;
1525  }
1526  if (!object) {
1527  return NULL;
1528  }
1529 
1530  left = sizeof(sql);
1531  sqlp = sql;
1532  memset(sql, 0, left);
1533 
1534  if ((ret = snprintf(sqlp, left, "SELECT")) >= left) {
1535  return NULL;
1536  }
1537  sqlp += ret;
1538  left -= ret;
1539 
1541  first = 1;
1542  while (object_field) {
1543  if (first) {
1544  if ((ret = snprintf(sqlp, left, " %s.%s", db_object_table(object), db_object_field_name(object_field))) >= left) {
1545  return NULL;
1546  }
1547  first = 0;
1548  }
1549  else {
1550  if ((ret = snprintf(sqlp, left, ", %s.%s", db_object_table(object), db_object_field_name(object_field))) >= left) {
1551  return NULL;
1552  }
1553  }
1554  sqlp += ret;
1555  left -= ret;
1556 
1557  object_field = db_object_field_next(object_field);
1558  }
1559 
1560  if ((ret = snprintf(sqlp, left, " FROM %s", db_object_table(object))) >= left) {
1561  return NULL;
1562  }
1563  sqlp += ret;
1564  left -= ret;
1565 
1566  if (join_list) {
1567  join = db_join_list_begin(join_list);
1568  while (join) {
1569  if ((ret = snprintf(sqlp, left, " INNER JOIN %s ON %s.%s = %s.%s",
1570  db_join_to_table(join),
1571  db_join_to_table(join),
1572  db_join_to_field(join),
1573  db_join_from_table(join),
1574  db_join_from_field(join))) >= left)
1575  {
1576  return NULL;
1577  }
1578  sqlp += ret;
1579  left -= ret;
1580  join = db_join_next(join);
1581  }
1582  }
1583 
1584  if (clause_list) {
1585  if (db_clause_list_begin(clause_list)) {
1586  if ((ret = snprintf(sqlp, left, " WHERE")) >= left) {
1587  return NULL;
1588  }
1589  sqlp += ret;
1590  left -= ret;
1591  }
1592  if (__db_backend_mysql_build_clause(object, clause_list, &sqlp, &left)) {
1593  return NULL;
1594  }
1595  }
1596 
1597  if (__db_backend_mysql_prepare(backend_mysql, &statement, sql, strlen(sql), db_object_object_field_list(object))
1598  || !statement)
1599  {
1600  __db_backend_mysql_finish(statement);
1601  return NULL;
1602  }
1603 
1604  bind = statement->bind_input;
1605 
1606  if (clause_list) {
1607  if (__db_backend_mysql_bind_clause(&bind, clause_list)) {
1608  __db_backend_mysql_finish(statement);
1609  return NULL;
1610  }
1611  }
1612 
1613  /*
1614  * Execute the SQL.
1615  */
1616  if (__db_backend_mysql_execute(statement)) {
1617  __db_backend_mysql_finish(statement);
1618  return NULL;
1619  }
1620 
1621  if (!(result_list = db_result_list_new())
1622  || db_result_list_set_next(result_list, db_backend_mysql_next, statement, mysql_stmt_affected_rows(statement->statement)))
1623  {
1624  db_result_list_free(result_list);
1625  __db_backend_mysql_finish(statement);
1626  return NULL;
1627  }
1628  return result_list;
1629 }
1630 
1631 static int db_backend_mysql_update(void* data, const db_object_t* object, const db_object_field_list_t* object_field_list, const db_value_set_t* value_set, const db_clause_list_t* clause_list) {
1632  db_backend_mysql_t* backend_mysql = (db_backend_mysql_t*)data;
1633  const db_object_field_t* object_field;
1634  const db_object_field_t* revision_field = NULL;
1635  const db_clause_t* clause;
1636  const db_clause_t* revision_clause = NULL;
1637  db_type_int64_t revision_number = -1;
1638  char sql[4*1024];
1639  char* sqlp;
1640  int ret, left, first;
1641  db_backend_mysql_statement_t* statement = NULL;
1643  db_value_t revision = DB_VALUE_EMPTY;
1644  db_type_int32_t int32;
1645  db_type_uint32_t uint32;
1646  db_type_int64_t int64;
1647  db_type_uint64_t uint64;
1648 
1649  if (!__mysql_initialized) {
1650  return DB_ERROR_UNKNOWN;
1651  }
1652  if (!backend_mysql) {
1653  return DB_ERROR_UNKNOWN;
1654  }
1655  if (!object) {
1656  return DB_ERROR_UNKNOWN;
1657  }
1658  if (!object_field_list) {
1659  return DB_ERROR_UNKNOWN;
1660  }
1661  if (!value_set) {
1662  return DB_ERROR_UNKNOWN;
1663  }
1664 
1665  /*
1666  * Check if the object has a revision field and keep it for later use.
1667  */
1669  while (object_field) {
1670  if (db_object_field_type(object_field) == DB_TYPE_REVISION) {
1671  if (revision_field) {
1672  /*
1673  * We do not support multiple revision fields.
1674  */
1675  return DB_ERROR_UNKNOWN;
1676  }
1677 
1678  revision_field = object_field;
1679  }
1680  object_field = db_object_field_next(object_field);
1681  }
1682  if (revision_field) {
1683  /*
1684  * If we have a revision field we should also have it in the clause,
1685  * find it and get the value for later use or return error if not found.
1686  */
1687  clause = db_clause_list_begin(clause_list);
1688  while (clause) {
1689  if (!strcmp(db_clause_field(clause), db_object_field_name(revision_field))) {
1690  revision_clause = clause;
1691  break;
1692  }
1693  clause = db_clause_next(clause);
1694  }
1695  if (!revision_clause) {
1696  return DB_ERROR_UNKNOWN;
1697  }
1698  switch (db_value_type(db_clause_value(revision_clause))) {
1699  case DB_TYPE_INT32:
1700  if (db_value_to_int32(db_clause_value(revision_clause), &int32)) {
1701  return DB_ERROR_UNKNOWN;
1702  }
1703  revision_number = int32;
1704  break;
1705 
1706  case DB_TYPE_UINT32:
1707  if (db_value_to_uint32(db_clause_value(revision_clause), &uint32)) {
1708  return DB_ERROR_UNKNOWN;
1709  }
1710  revision_number = uint32;
1711  break;
1712 
1713  case DB_TYPE_INT64:
1714  if (db_value_to_int64(db_clause_value(revision_clause), &int64)) {
1715  return DB_ERROR_UNKNOWN;
1716  }
1717  revision_number = int64;
1718  break;
1719 
1720  case DB_TYPE_UINT64:
1721  if (db_value_to_uint64(db_clause_value(revision_clause), &uint64)) {
1722  return DB_ERROR_UNKNOWN;
1723  }
1724  revision_number = uint64;
1725  break;
1726 
1727  default:
1728  return DB_ERROR_UNKNOWN;
1729  }
1730  }
1731 
1732  left = sizeof(sql);
1733  sqlp = sql;
1734  memset(sql, 0, left);
1735 
1736  if ((ret = snprintf(sqlp, left, "UPDATE %s SET", db_object_table(object))) >= left) {
1737  return DB_ERROR_UNKNOWN;
1738  }
1739  sqlp += ret;
1740  left -= ret;
1741 
1742  /*
1743  * Build the update SQL from the object_field_list.
1744  */
1745  object_field = db_object_field_list_begin(object_field_list);
1746  first = 1;
1747  while (object_field) {
1748  if (first) {
1749  if ((ret = snprintf(sqlp, left, " %s = ?", db_object_field_name(object_field))) >= left) {
1750  return DB_ERROR_UNKNOWN;
1751  }
1752  first = 0;
1753  }
1754  else {
1755  if ((ret = snprintf(sqlp, left, ", %s = ?", db_object_field_name(object_field))) >= left) {
1756  return DB_ERROR_UNKNOWN;
1757  }
1758  }
1759  sqlp += ret;
1760  left -= ret;
1761 
1762  object_field = db_object_field_next(object_field);
1763  }
1764 
1765  /*
1766  * Add a new revision if we have any.
1767  */
1768  if (revision_field) {
1769  if (first) {
1770  if ((ret = snprintf(sqlp, left, " %s = ?", db_object_field_name(revision_field))) >= left) {
1771  return DB_ERROR_UNKNOWN;
1772  }
1773  first = 0;
1774  }
1775  else {
1776  if ((ret = snprintf(sqlp, left, ", %s = ?", db_object_field_name(revision_field))) >= left) {
1777  return DB_ERROR_UNKNOWN;
1778  }
1779  }
1780  sqlp += ret;
1781  left -= ret;
1782  }
1783 
1784  /*
1785  * Build the clauses.
1786  */
1787  if (clause_list) {
1788  if (db_clause_list_begin(clause_list)) {
1789  if ((ret = snprintf(sqlp, left, " WHERE")) >= left) {
1790  return DB_ERROR_UNKNOWN;
1791  }
1792  sqlp += ret;
1793  left -= ret;
1794  }
1795  if (__db_backend_mysql_build_clause(object, clause_list, &sqlp, &left)) {
1796  return DB_ERROR_UNKNOWN;
1797  }
1798  }
1799 
1800  /*
1801  * Prepare the SQL.
1802  */
1803  if (__db_backend_mysql_prepare(backend_mysql, &statement, sql, strlen(sql), db_object_object_field_list(object))
1804  || !statement)
1805  {
1806  __db_backend_mysql_finish(statement);
1807  return DB_ERROR_UNKNOWN;
1808  }
1809 
1810  bind = statement->bind_input;
1811 
1812  /*
1813  * Bind all the values from value_set.
1814  */
1815  if (value_set) {
1816  if (__db_backend_mysql_bind_value_set(&bind, value_set)) {
1817  __db_backend_mysql_finish(statement);
1818  return DB_ERROR_UNKNOWN;
1819  }
1820  }
1821 
1822  /*
1823  * Bind the new revision if we have any.
1824  */
1825  if (revision_field) {
1826  if (db_value_from_int64(&revision, revision_number + 1)
1827  || __db_backend_mysql_bind_value(bind, &revision))
1828  {
1829  db_value_reset(&revision);
1830  __db_backend_mysql_finish(statement);
1831  return DB_ERROR_UNKNOWN;
1832  }
1833 
1834  if (bind) {
1835  bind = bind->next;
1836  }
1837  }
1838 
1839  /*
1840  * Bind the clauses values.
1841  */
1842  if (clause_list) {
1843  if (__db_backend_mysql_bind_clause(&bind, clause_list)) {
1844  __db_backend_mysql_finish(statement);
1845  return DB_ERROR_UNKNOWN;
1846  }
1847  }
1848 
1849  /*
1850  * Execute the SQL.
1851  */
1852  if (__db_backend_mysql_execute(statement)) {
1853  __db_backend_mysql_finish(statement);
1854  return DB_ERROR_UNKNOWN;
1855  }
1856 
1857  /*
1858  * If we are using revision we have to have a positive number of changes
1859  * otherwise its a failure.
1860  */
1861  if (revision_field) {
1862  if (mysql_stmt_affected_rows(statement->statement) < 1) {
1863  __db_backend_mysql_finish(statement);
1864  return DB_ERROR_UNKNOWN;
1865  }
1866  }
1867 
1868  __db_backend_mysql_finish(statement);
1869  return DB_OK;
1870 }
1871 
1872 static int db_backend_mysql_delete(void* data, const db_object_t* object, const db_clause_list_t* clause_list) {
1873  db_backend_mysql_t* backend_mysql = (db_backend_mysql_t*)data;
1874  char sql[4*1024];
1875  char* sqlp;
1876  int ret, left;
1877  const db_object_field_t* revision_field = NULL;
1878  const db_object_field_t* object_field;
1879  const db_clause_t* clause;
1880  db_backend_mysql_statement_t* statement = NULL;
1882 
1883  if (!__mysql_initialized) {
1884  return DB_ERROR_UNKNOWN;
1885  }
1886  if (!backend_mysql) {
1887  return DB_ERROR_UNKNOWN;
1888  }
1889  if (!object) {
1890  return DB_ERROR_UNKNOWN;
1891  }
1892 
1893  /*
1894  * Check if the object has a revision field and keep it for later use.
1895  */
1897  while (object_field) {
1898  if (db_object_field_type(object_field) == DB_TYPE_REVISION) {
1899  if (revision_field) {
1900  /*
1901  * We do not support multiple revision fields.
1902  */
1903  return DB_ERROR_UNKNOWN;
1904  }
1905 
1906  revision_field = object_field;
1907  }
1908  object_field = db_object_field_next(object_field);
1909  }
1910  if (revision_field) {
1911  /*
1912  * If we have a revision field we should also have it in the clause,
1913  * find it or return error if not found.
1914  */
1915  clause = db_clause_list_begin(clause_list);
1916  while (clause) {
1917  if (!strcmp(db_clause_field(clause), db_object_field_name(revision_field))) {
1918  break;
1919  }
1920  clause = db_clause_next(clause);
1921  }
1922  if (!clause) {
1923  return DB_ERROR_UNKNOWN;
1924  }
1925  }
1926 
1927  left = sizeof(sql);
1928  sqlp = sql;
1929  memset(sql, 0, left);
1930 
1931  if ((ret = snprintf(sqlp, left, "DELETE FROM %s", db_object_table(object))) >= left) {
1932  return DB_ERROR_UNKNOWN;
1933  }
1934  sqlp += ret;
1935  left -= ret;
1936 
1937  if (clause_list) {
1938  if (db_clause_list_begin(clause_list)) {
1939  if ((ret = snprintf(sqlp, left, " WHERE")) >= left) {
1940  return DB_ERROR_UNKNOWN;
1941  }
1942  sqlp += ret;
1943  left -= ret;
1944  }
1945  if (__db_backend_mysql_build_clause(object, clause_list, &sqlp, &left)) {
1946  return DB_ERROR_UNKNOWN;
1947  }
1948  }
1949 
1950  if (__db_backend_mysql_prepare(backend_mysql, &statement, sql, strlen(sql), db_object_object_field_list(object))
1951  || !statement)
1952  {
1953  __db_backend_mysql_finish(statement);
1954  return DB_ERROR_UNKNOWN;
1955  }
1956 
1957  bind = statement->bind_input;
1958 
1959  if (clause_list) {
1960  if (__db_backend_mysql_bind_clause(&bind, clause_list)) {
1961  __db_backend_mysql_finish(statement);
1962  return DB_ERROR_UNKNOWN;
1963  }
1964  }
1965 
1966  if (__db_backend_mysql_execute(statement)) {
1967  __db_backend_mysql_finish(statement);
1968  return DB_ERROR_UNKNOWN;
1969  }
1970 
1971  /*
1972  * If we are using revision we have to have a positive number of changes
1973  * otherwise its a failure.
1974  */
1975  if (revision_field) {
1976  if (mysql_stmt_affected_rows(statement->statement) < 1) {
1977  __db_backend_mysql_finish(statement);
1978  return DB_ERROR_UNKNOWN;
1979  }
1980  }
1981 
1982  __db_backend_mysql_finish(statement);
1983  return DB_OK;
1984 }
1985 
1986 static int db_backend_mysql_count(void* data, const db_object_t* object, const db_join_list_t* join_list, const db_clause_list_t* clause_list, size_t* count) {
1987  db_backend_mysql_t* backend_mysql = (db_backend_mysql_t*)data;
1988  const db_join_t* join;
1989  char sql[4*1024];
1990  char* sqlp;
1991  int ret, left;
1992  db_backend_mysql_statement_t* statement = NULL;
1994  db_object_field_list_t* object_field_list;
1995  db_object_field_t* object_field = NULL;
1996 
1997  if (!__mysql_initialized) {
1998  return DB_ERROR_UNKNOWN;
1999  }
2000  if (!backend_mysql) {
2001  return DB_ERROR_UNKNOWN;
2002  }
2003  if (!object) {
2004  return DB_ERROR_UNKNOWN;
2005  }
2006  if (!count) {
2007  return DB_ERROR_UNKNOWN;
2008  }
2009 
2010  left = sizeof(sql);
2011  sqlp = sql;
2012  memset(sql, 0, left);
2013 
2014  if ((ret = snprintf(sqlp, left, "SELECT COUNT(*)")) >= left) {
2015  return DB_ERROR_UNKNOWN;
2016  }
2017  sqlp += ret;
2018  left -= ret;
2019 
2020  if ((ret = snprintf(sqlp, left, " FROM %s", db_object_table(object))) >= left) {
2021  return DB_ERROR_UNKNOWN;
2022  }
2023  sqlp += ret;
2024  left -= ret;
2025 
2026  if (join_list) {
2027  join = db_join_list_begin(join_list);
2028  while (join) {
2029  if ((ret = snprintf(sqlp, left, " INNER JOIN %s ON %s.%s = %s.%s",
2030  db_join_to_table(join),
2031  db_join_to_table(join),
2032  db_join_to_field(join),
2033  db_join_from_table(join),
2034  db_join_from_field(join))) >= left)
2035  {
2036  return DB_ERROR_UNKNOWN;
2037  }
2038  sqlp += ret;
2039  left -= ret;
2040  join = db_join_next(join);
2041  }
2042  }
2043 
2044  if (clause_list) {
2045  if (db_clause_list_begin(clause_list)) {
2046  if ((ret = snprintf(sqlp, left, " WHERE")) >= left) {
2047  return DB_ERROR_UNKNOWN;
2048  }
2049  sqlp += ret;
2050  left -= ret;
2051  }
2052  if (__db_backend_mysql_build_clause(object, clause_list, &sqlp, &left)) {
2053  return DB_ERROR_UNKNOWN;
2054  }
2055  }
2056 
2057  if (!(object_field_list = db_object_field_list_new())
2058  || !(object_field = db_object_field_new())
2059  || db_object_field_set_name(object_field, "countField")
2060  || db_object_field_set_type(object_field, DB_TYPE_UINT32)
2061  || db_object_field_list_add(object_field_list, object_field))
2062  {
2063  db_object_field_free(object_field);
2064  db_object_field_list_free(object_field_list);
2065  return DB_ERROR_UNKNOWN;
2066  }
2067 
2068  if (__db_backend_mysql_prepare(backend_mysql, &statement, sql, strlen(sql), object_field_list)
2069  || !statement)
2070  {
2071  db_object_field_list_free(object_field_list);
2072  __db_backend_mysql_finish(statement);
2073  return DB_ERROR_UNKNOWN;
2074  }
2075  db_object_field_list_free(object_field_list);
2076 
2077  bind = statement->bind_input;
2078 
2079  if (clause_list) {
2080  if (__db_backend_mysql_bind_clause(&bind, clause_list)) {
2081  __db_backend_mysql_finish(statement);
2082  return DB_ERROR_UNKNOWN;
2083  }
2084  }
2085 
2086  if (__db_backend_mysql_execute(statement)) {
2087  __db_backend_mysql_finish(statement);
2088  return DB_ERROR_UNKNOWN;
2089  }
2090 
2091  if (__db_backend_mysql_fetch(statement)) {
2092  __db_backend_mysql_finish(statement);
2093  return DB_ERROR_UNKNOWN;
2094  }
2095 
2096  bind = statement->bind_output;
2097  if (!bind || !bind->bind || !bind->bind->buffer
2098  || bind->bind->buffer_type != MYSQL_TYPE_LONG
2099  || !bind->bind->is_unsigned
2100  || bind->length != sizeof(db_type_uint32_t))
2101  {
2102  __db_backend_mysql_finish(statement);
2103  return DB_ERROR_UNKNOWN;
2104  }
2105 
2106  *count = *((db_type_uint32_t*)bind->bind->buffer);
2107  __db_backend_mysql_finish(statement);
2108 
2109  return DB_OK;
2110 }
2111 
2112 static void db_backend_mysql_free(void* data) {
2113  db_backend_mysql_t* backend_mysql = (db_backend_mysql_t*)data;
2114 
2115  if (backend_mysql) {
2116  if (backend_mysql->db) {
2117  (void)db_backend_mysql_disconnect(backend_mysql);
2118  }
2119  free(backend_mysql);
2120  }
2121 }
2122 
2123 static int db_backend_mysql_transaction_begin(void* data) {
2124  db_backend_mysql_t* backend_mysql = (db_backend_mysql_t*)data;
2125  static const char* sql = "BEGIN TRANSACTION";
2126  db_backend_mysql_statement_t* statement = NULL;
2127 
2128  if (!__mysql_initialized) {
2129  return DB_ERROR_UNKNOWN;
2130  }
2131  if (!backend_mysql) {
2132  return DB_ERROR_UNKNOWN;
2133  }
2134  if (backend_mysql->transaction) {
2135  return DB_ERROR_UNKNOWN;
2136  }
2137 
2138  if (__db_backend_mysql_prepare(backend_mysql, &statement, sql, strlen(sql), NULL)) {
2139  return DB_ERROR_UNKNOWN;
2140  }
2141 
2142  if (__db_backend_mysql_execute(statement)) {
2143  __db_backend_mysql_finish(statement);
2144  return DB_ERROR_UNKNOWN;
2145  }
2146  __db_backend_mysql_finish(statement);
2147 
2148  backend_mysql->transaction = 1;
2149  return DB_OK;
2150 }
2151 
2152 static int db_backend_mysql_transaction_commit(void* data) {
2153  db_backend_mysql_t* backend_mysql = (db_backend_mysql_t*)data;
2154  static const char* sql = "COMMIT TRANSACTION";
2155  db_backend_mysql_statement_t* statement = NULL;
2156 
2157  if (!__mysql_initialized) {
2158  return DB_ERROR_UNKNOWN;
2159  }
2160  if (!backend_mysql) {
2161  return DB_ERROR_UNKNOWN;
2162  }
2163  if (!backend_mysql->transaction) {
2164  return DB_ERROR_UNKNOWN;
2165  }
2166 
2167  if (__db_backend_mysql_prepare(backend_mysql, &statement, sql, strlen(sql), NULL)) {
2168  return DB_ERROR_UNKNOWN;
2169  }
2170 
2171  if (__db_backend_mysql_execute(statement)) {
2172  __db_backend_mysql_finish(statement);
2173  return DB_ERROR_UNKNOWN;
2174  }
2175  __db_backend_mysql_finish(statement);
2176 
2177  backend_mysql->transaction = 0;
2178  return DB_OK;
2179 }
2180 
2181 static int db_backend_mysql_transaction_rollback(void* data) {
2182  db_backend_mysql_t* backend_mysql = (db_backend_mysql_t*)data;
2183  static const char* sql = "ROLLBACK TRANSACTION";
2184  db_backend_mysql_statement_t* statement = NULL;
2185 
2186  if (!__mysql_initialized) {
2187  return DB_ERROR_UNKNOWN;
2188  }
2189  if (!backend_mysql) {
2190  return DB_ERROR_UNKNOWN;
2191  }
2192  if (!backend_mysql->transaction) {
2193  return DB_ERROR_UNKNOWN;
2194  }
2195 
2196  if (__db_backend_mysql_prepare(backend_mysql, &statement, sql, strlen(sql), NULL)) {
2197  return DB_ERROR_UNKNOWN;
2198  }
2199 
2200  if (__db_backend_mysql_execute(statement)) {
2201  __db_backend_mysql_finish(statement);
2202  return DB_ERROR_UNKNOWN;
2203  }
2204  __db_backend_mysql_finish(statement);
2205 
2206  backend_mysql->transaction = 0;
2207  return DB_OK;
2208 }
2209 
2211  db_backend_handle_t* backend_handle = NULL;
2212  db_backend_mysql_t* backend_mysql =
2213  (db_backend_mysql_t*)calloc(1, sizeof(db_backend_mysql_t));
2214 
2215  if (backend_mysql && (backend_handle = db_backend_handle_new())) {
2216  if (db_backend_handle_set_data(backend_handle, (void*)backend_mysql)
2217  || db_backend_handle_set_initialize(backend_handle, db_backend_mysql_initialize)
2218  || db_backend_handle_set_shutdown(backend_handle, db_backend_mysql_shutdown)
2219  || db_backend_handle_set_connect(backend_handle, db_backend_mysql_connect)
2220  || db_backend_handle_set_disconnect(backend_handle, db_backend_mysql_disconnect)
2221  || db_backend_handle_set_create(backend_handle, db_backend_mysql_create)
2222  || db_backend_handle_set_read(backend_handle, db_backend_mysql_read)
2223  || db_backend_handle_set_update(backend_handle, db_backend_mysql_update)
2224  || db_backend_handle_set_delete(backend_handle, db_backend_mysql_delete)
2225  || db_backend_handle_set_count(backend_handle, db_backend_mysql_count)
2226  || db_backend_handle_set_free(backend_handle, db_backend_mysql_free)
2227  || db_backend_handle_set_transaction_begin(backend_handle, db_backend_mysql_transaction_begin)
2228  || db_backend_handle_set_transaction_commit(backend_handle, db_backend_mysql_transaction_commit)
2229  || db_backend_handle_set_transaction_rollback(backend_handle, db_backend_mysql_transaction_rollback))
2230  {
2231  db_backend_handle_free(backend_handle);
2232  free(backend_mysql);
2233  return NULL;
2234  }
2235  }
2236  return backend_handle;
2237 }
db_backend_mysql_bind_t * bind_input
db_backend_mysql_bind_t * bind_output
struct db_backend_mysql db_backend_mysql_t
int db_value_from_uint32(db_value_t *value, db_type_uint32_t from_uint32)
Definition: db_value.c:492
int db_value_from_int64(db_value_t *value, db_type_int64_t from_int64)
Definition: db_value.c:505
int64_t db_type_int64_t
Definition: db_type.h:46
db_object_field_list_t * db_object_field_list_new(void)
Definition: db_object.c:174
int db_object_field_set_name(db_object_field_t *object_field, const char *name)
Definition: db_object.c:110
const db_type_int32_t * db_value_int32(const db_value_t *value)
Definition: db_value.c:277
int db_backend_handle_set_create(db_backend_handle_t *backend_handle, db_backend_handle_create_t create_function)
Definition: db_backend.c:214
void ods_log_debug(const char *format,...)
Definition: log.c:41
db_object_field_list_t * object_field_list
const db_value_t * db_value_set_at(const db_value_set_t *value_set, size_t at)
Definition: db_value.c:742
size_t db_object_field_list_size(const db_object_field_list_t *object_field_list)
Definition: db_object.c:292
void db_value_set_free(db_value_set_t *value_set)
Definition: db_value.c:697
int db_value_to_uint32(const db_value_t *value, db_type_uint32_t *to_uint32)
Definition: db_value.c:372
int db_value_to_uint64(const db_value_t *value, db_type_uint64_t *to_uint64)
Definition: db_value.c:402
#define DB_ERROR_UNKNOWN
Definition: db_error.h:40
int db_value_enum_value(const db_value_t *value, int *enum_value)
Definition: db_value.c:332
const char * db_join_to_table(const db_join_t *join)
Definition: db_join.c:57
const db_join_t * db_join_next(const db_join_t *join)
Definition: db_join.c:73
db_result_t * db_result_new(void)
Definition: db_result.c:38
db_backend_mysql_t * backend_mysql
int db_value_from_uint64(db_value_t *value, db_type_uint64_t from_uint64)
Definition: db_value.c:518
const db_type_uint64_t * db_value_uint64(const db_value_t *value)
Definition: db_value.c:310
int db_backend_handle_set_data(db_backend_handle_t *backend_handle, void *data)
Definition: db_backend.c:295
#define DB_VALUE_EMPTY
Definition: db_value.h:60
unsigned int timeout
int db_object_field_set_type(db_object_field_t *object_field, db_type_t type)
Definition: db_object.c:122
const db_clause_list_t * db_clause_list(const db_clause_t *clause)
Definition: db_clause.c:101
int db_value_to_int64(const db_value_t *value, db_type_int64_t *to_int64)
Definition: db_value.c:387
const db_type_int64_t * db_value_int64(const db_value_t *value)
Definition: db_value.c:299
void ods_log_info(const char *format,...)
Definition: log.c:55
const char * db_join_to_field(const db_join_t *join)
Definition: db_join.c:65
void db_backend_handle_free(db_backend_handle_t *backend_handle)
Definition: db_backend.c:56
const char * db_clause_field(const db_clause_t *clause)
Definition: db_clause.c:69
db_backend_mysql_bind_t * bind_input_end
db_backend_handle_t * db_backend_handle_new(void)
Definition: db_backend.c:49
void ods_log_error(const char *format,...)
Definition: log.c:69
const char * db_object_table(const db_object_t *object)
Definition: db_object.c:327
int db_value_from_text(db_value_t *value, const char *from_text)
Definition: db_value.c:531
int db_backend_handle_set_connect(db_backend_handle_t *backend_handle, db_backend_handle_connect_t connect_function)
Definition: db_backend.c:196
const char * db_object_field_name(const db_object_field_t *object_field)
Definition: db_object.c:94
int db_backend_handle_set_update(db_backend_handle_t *backend_handle, db_backend_handle_update_t update_function)
Definition: db_backend.c:232
db_object_field_list_t * db_object_field_list_new_copy(const db_object_field_list_t *from_object_field_list)
Definition: db_object.c:182
int db_backend_handle_set_free(db_backend_handle_t *backend_handle, db_backend_handle_free_t free_function)
Definition: db_backend.c:259
const db_object_field_t * db_object_field_next(const db_object_field_t *object_field)
Definition: db_object.c:162
const db_clause_t * db_clause_list_begin(const db_clause_list_t *clause_list)
Definition: db_clause.c:255
int db_value_from_text2(db_value_t *value, const char *from_text, size_t size)
Definition: db_value.c:550
size_t db_value_set_size(const db_value_set_t *value_set)
Definition: db_value.c:734
int db_value_set_primary_key(db_value_t *value)
Definition: db_value.c:595
#define DB_BACKEND_MYSQL_STRING_MIN_SIZE
const db_clause_t * db_clause_next(const db_clause_t *clause)
Definition: db_clause.c:179
void db_result_list_free(db_result_list_t *result_list)
Definition: db_result.c:160
int db_result_set_value_set(db_result_t *result, db_value_set_t *value_set)
Definition: db_result.c:105
int db_backend_handle_set_transaction_commit(db_backend_handle_t *backend_handle, db_backend_handle_transaction_commit_t transaction_commit_function)
Definition: db_backend.c:277
int db_backend_handle_set_delete(db_backend_handle_t *backend_handle, db_backend_handle_delete_t delete_function)
Definition: db_backend.c:241
void db_value_reset(db_value_t *value)
Definition: db_value.c:60
db_backend_mysql_bind_t * next
db_object_field_t * db_object_field_new(void)
Definition: db_object.c:40
int db_result_list_set_next(db_result_list_t *result_list, db_result_list_next_t next_function, void *next_data, size_t size)
Definition: db_result.c:234
int db_backend_handle_set_shutdown(db_backend_handle_t *backend_handle, db_backend_handle_shutdown_t shutdown_function)
Definition: db_backend.c:187
void db_object_field_free(db_object_field_t *object_field)
Definition: db_object.c:69
db_value_set_t * db_value_set_new(size_t size)
Definition: db_value.c:622
#define DB_BACKEND_MYSQL_DEFAULT_TIMEOUT
const char * db_join_from_field(const db_join_t *join)
Definition: db_join.c:49
int32_t db_type_int32_t
Definition: db_type.h:38
void db_object_field_list_free(db_object_field_list_t *object_field_list)
Definition: db_object.c:199
void db_result_free(db_result_t *result)
Definition: db_result.c:63
db_type_t db_object_field_type(const db_object_field_t *object_field)
Definition: db_object.c:102
const db_configuration_t * db_configuration_list_find(const db_configuration_list_t *configuration_list, const char *name)
#define DB_OK
Definition: db_error.h:36
int db_value_from_int32(db_value_t *value, db_type_int32_t from_int32)
Definition: db_value.c:479
db_result_list_t * db_result_list_new(void)
Definition: db_result.c:134
db_backend_mysql_bind_t * bind_output_end
struct db_backend_mysql_statement db_backend_mysql_statement_t
const db_object_field_list_t * db_object_object_field_list(const db_object_t *object)
Definition: db_object.c:334
int db_backend_handle_set_transaction_rollback(db_backend_handle_t *backend_handle, db_backend_handle_transaction_rollback_t transaction_rollback_function)
Definition: db_backend.c:286
int db_backend_handle_set_disconnect(db_backend_handle_t *backend_handle, db_backend_handle_disconnect_t disconnect_function)
Definition: db_backend.c:205
const char * db_join_from_table(const db_join_t *join)
Definition: db_join.c:41
int db_backend_handle_set_transaction_begin(db_backend_handle_t *backend_handle, db_backend_handle_transaction_begin_t transaction_begin_function)
Definition: db_backend.c:268
int db_backend_handle_set_count(db_backend_handle_t *backend_handle, db_backend_handle_count_t count_function)
Definition: db_backend.c:250
db_type_t db_value_type(const db_value_t *value)
Definition: db_value.c:269
const db_value_t * db_clause_value(const db_clause_t *clause)
Definition: db_clause.c:85
const char * db_configuration_value(const db_configuration_t *configuration)
const char * db_value_text(const db_value_t *value)
Definition: db_value.c:321
db_clause_type_t db_clause_type(const db_clause_t *clause)
Definition: db_clause.c:77
const db_join_t * db_join_list_begin(const db_join_list_t *join_list)
Definition: db_join.c:85
int db_backend_handle_set_read(db_backend_handle_t *backend_handle, db_backend_handle_read_t read_function)
Definition: db_backend.c:223
const db_object_field_t * db_object_field_list_begin(const db_object_field_list_t *object_field_list)
Definition: db_object.c:284
const db_type_uint32_t * db_value_uint32(const db_value_t *value)
Definition: db_value.c:288
uint64_t db_type_uint64_t
Definition: db_type.h:50
db_backend_handle_t * db_backend_mysql_new_handle(void)
uint32_t db_type_uint32_t
Definition: db_type.h:42
int db_object_field_list_add(db_object_field_list_t *object_field_list, db_object_field_t *object_field)
Definition: db_object.c:254
db_value_t * db_value_set_get(db_value_set_t *value_set, size_t at)
Definition: db_value.c:756
int db_backend_handle_set_initialize(db_backend_handle_t *backend_handle, db_backend_handle_initialize_t initialize_function)
Definition: db_backend.c:178
db_clause_operator_t db_clause_operator(const db_clause_t *clause)
Definition: db_clause.c:93
int db_value_to_int32(const db_value_t *value, db_type_int32_t *to_int32)
Definition: db_value.c:357