2 Bacula® - The Network Backup Solution
4 Copyright (C) 2003-2008 Free Software Foundation Europe e.V.
6 The main author of Bacula is Kern Sibbald, with contributions from
7 many others, a complete list can be found in the file AUTHORS.
8 This program is Free Software; you can redistribute it and/or
9 modify it under the terms of version two of the GNU General Public
10 License as published by the Free Software Foundation and included
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 Bacula® is a registered trademark of Kern Sibbald.
24 The licensor of Bacula is the Free Software Foundation Europe
25 (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26 Switzerland, email:ftf@fsfeurope.org.
29 * Bacula Catalog Database routines specific to DBI
30 * These are DBI specific routines
32 * João Henrique Freitas, December 2007
33 * based upon work done by Dan Langille, December 2003 and
34 * by Kern Sibbald, March 2000
40 /* The following is necessary so that we do not include
41 * the dummy external definition of DB.
43 #define __SQL_C /* indicate that this is sql.c */
50 /* -----------------------------------------------------------------------
52 * DBI dependent defines and subroutines
54 * -----------------------------------------------------------------------
57 /* List of open databases */
58 static BQUEUE db_list = {&db_list, &db_list};
60 /* Control allocated fields by my_dbi_getvalue */
61 static BQUEUE dbi_getvalue_list = {&dbi_getvalue_list, &dbi_getvalue_list};
63 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
66 * Retrieve database type
75 * Initialize database data structure. In principal this should
76 * never have errors, or it is really fatal.
79 db_init_database(JCR *jcr, const char *db_name, const char *db_user, const char *db_password,
80 const char *db_address, int db_port, const char *db_socket,
81 int mult_db_connections)
85 char db_driverdir[256];
87 /* Constraint the db_driver */
89 Jmsg(jcr, M_FATAL, 0, _("A dbi driver for DBI must be supplied.\n"));
93 /* Do the correct selection of driver.
94 * Can be one of the varius supported by libdbi
98 bstrncpy(db_driver,"mysql", sizeof(db_driver));
100 case SQL_TYPE_POSTGRESQL:
101 bstrncpy(db_driver,"pgsql", sizeof(db_driver));
103 case SQL_TYPE_SQLITE:
104 bstrncpy(db_driver,"sqlite", sizeof(db_driver));
106 case SQL_TYPE_SQLITE3:
107 bstrncpy(db_driver,"sqlite3", sizeof(db_driver));
111 /* Set db_driverdir whereis is the libdbi drivers */
112 bstrncpy(db_driverdir, DBI_DRIVER_DIR, 255);
115 Jmsg(jcr, M_FATAL, 0, _("A user name for DBI must be supplied.\n"));
118 P(mutex); /* lock DB queue */
119 if (!mult_db_connections) {
120 /* Look to see if DB already open */
121 for (mdb=NULL; (mdb=(B_DB *)qnext(&db_list, &mdb->bq)); ) {
122 if (bstrcmp(mdb->db_name, db_name) &&
123 bstrcmp(mdb->db_address, db_address) &&
124 bstrcmp(mdb->db_driver, db_driver) &&
125 mdb->db_port == db_port) {
126 Dmsg4(100, "DB REopen %d %s %s erro: %d\n", mdb->ref_count, db_driver, db_name,
127 dbi_conn_error(mdb->db, NULL));
130 return mdb; /* already open */
134 Dmsg0(100, "db_open first time\n");
135 mdb = (B_DB *)malloc(sizeof(B_DB));
136 memset(mdb, 0, sizeof(B_DB));
137 mdb->db_name = bstrdup(db_name);
138 mdb->db_user = bstrdup(db_user);
140 mdb->db_password = bstrdup(db_password);
143 mdb->db_address = bstrdup(db_address);
146 mdb->db_socket = bstrdup(db_socket);
149 mdb->db_driverdir = bstrdup(db_driverdir);
152 mdb->db_driver = bstrdup(db_driver);
154 mdb->db_type = db_type;
155 mdb->db_port = db_port;
156 mdb->have_insert_id = TRUE;
157 mdb->errmsg = get_pool_memory(PM_EMSG); /* get error message buffer */
159 mdb->cmd = get_pool_memory(PM_EMSG); /* get command buffer */
160 mdb->cached_path = get_pool_memory(PM_FNAME);
161 mdb->cached_path_id = 0;
163 mdb->fname = get_pool_memory(PM_FNAME);
164 mdb->path = get_pool_memory(PM_FNAME);
165 mdb->esc_name = get_pool_memory(PM_FNAME);
166 mdb->esc_path = get_pool_memory(PM_FNAME);
167 mdb->allow_transactions = mult_db_connections;
168 qinsert(&db_list, &mdb->bq); /* put db in list */
174 * Now actually open the database. This can generate errors,
175 * which are returned in the errmsg
177 * DO NOT close the database or free(mdb) here !!!!
180 db_open_database(JCR *jcr, B_DB *mdb)
188 char *db_name = NULL;
192 if (mdb->connected) {
196 mdb->connected = false;
198 if ((errstat=rwl_init(&mdb->lock)) != 0) {
200 Mmsg1(&mdb->errmsg, _("Unable to initialize DB lock. ERR=%s\n"),
201 be.bstrerror(errstat));
207 bsnprintf(buf, sizeof(buf), "%d", mdb->db_port);
213 numdrivers = dbi_initialize_r(mdb->db_driverdir, &(mdb->instance));
214 if (numdrivers < 0) {
215 Mmsg2(&mdb->errmsg, _("Unable to locate the DBD drivers to DBI interface in: \n"
216 "db_driverdir=%s. It is probaly not found any drivers\n"),
217 mdb->db_driverdir,numdrivers);
221 mdb->db = (void **)dbi_conn_new_r(mdb->db_driver, mdb->instance);
222 /* Can be many types of databases */
223 switch (mdb->db_type) {
225 dbi_conn_set_option(mdb->db, "host", mdb->db_address); /* default = localhost */
226 dbi_conn_set_option(mdb->db, "port", port); /* default port */
227 dbi_conn_set_option(mdb->db, "username", mdb->db_user); /* login name */
228 dbi_conn_set_option(mdb->db, "password", mdb->db_password); /* password */
229 dbi_conn_set_option(mdb->db, "dbname", mdb->db_name); /* database name */
231 case SQL_TYPE_POSTGRESQL:
232 dbi_conn_set_option(mdb->db, "host", mdb->db_address);
233 dbi_conn_set_option(mdb->db, "port", port);
234 dbi_conn_set_option(mdb->db, "username", mdb->db_user);
235 dbi_conn_set_option(mdb->db, "password", mdb->db_password);
236 dbi_conn_set_option(mdb->db, "dbname", mdb->db_name);
238 case SQL_TYPE_SQLITE:
239 len = strlen(working_directory) + 5;
240 db_dir = (char *)malloc(len);
241 strcpy(db_dir, working_directory);
243 len = strlen(mdb->db_name) + 5;
244 db_name = (char *)malloc(len);
245 strcpy(db_name, mdb->db_name);
246 strcat(db_name, ".db");
247 dbi_conn_set_option(mdb->db, "sqlite_dbdir", db_dir);
248 dbi_conn_set_option(mdb->db, "dbname", db_name);
250 case SQL_TYPE_SQLITE3:
251 len = strlen(working_directory) + 5;
252 db_dir = (char *)malloc(len);
253 strcpy(db_dir, working_directory);
255 len = strlen(mdb->db_name) + 5;
256 db_name = (char *)malloc(len);
257 strcpy(db_name, mdb->db_name);
258 strcat(db_name, ".db");
259 dbi_conn_set_option(mdb->db, "sqlite3_dbdir", db_dir);
260 dbi_conn_set_option(mdb->db, "dbname", db_name);
261 Dmsg2(500, "SQLITE: %s %s\n", db_dir, db_name);
265 /* If connection fails, try at 5 sec intervals for 30 seconds. */
266 for (int retry=0; retry < 6; retry++) {
268 dbstat = dbi_conn_connect(mdb->db);
273 dbi_conn_error(mdb->db, &errmsg);
274 Dmsg1(50, "dbi error: %s\n", errmsg);
281 Mmsg3(&mdb->errmsg, _("Unable to connect to DBI interface.\n"
282 "Type=%s Database=%s User=%s\n"
283 "It is probably not running or your password is incorrect.\n"),
284 mdb->db_driver, mdb->db_name, mdb->db_user);
289 Dmsg0(50, "dbi_real_connect done\n");
290 Dmsg3(50, "db_user=%s db_name=%s db_password=%s\n",
291 mdb->db_user, mdb->db_name,
292 mdb->db_password==NULL?"(NULL)":mdb->db_password);
294 mdb->connected = true;
296 if (!check_tables_version(jcr, mdb)) {
301 switch (mdb->db_type) {
303 /* Set connection timeout to 8 days specialy for batch mode */
304 sql_query(mdb, "SET wait_timeout=691200");
305 sql_query(mdb, "SET interactive_timeout=691200");
307 case SQL_TYPE_POSTGRESQL:
308 /* tell PostgreSQL we are using standard conforming strings
309 and avoid warnings such as:
310 WARNING: nonstandard use of \\ in a string literal
312 sql_query(mdb, "SET datestyle TO 'ISO, YMD'");
313 sql_query(mdb, "set standard_conforming_strings=on");
329 db_close_database(JCR *jcr, B_DB *mdb)
334 db_end_transaction(jcr, mdb);
336 sql_free_result(mdb);
338 if (mdb->ref_count == 0) {
340 if (mdb->connected && mdb->db) {
342 dbi_shutdown_r(mdb->instance);
344 mdb->instance = NULL;
346 rwl_destroy(&mdb->lock);
347 free_pool_memory(mdb->errmsg);
348 free_pool_memory(mdb->cmd);
349 free_pool_memory(mdb->cached_path);
350 free_pool_memory(mdb->fname);
351 free_pool_memory(mdb->path);
352 free_pool_memory(mdb->esc_name);
353 free_pool_memory(mdb->esc_path);
360 if (mdb->db_password) {
361 free(mdb->db_password);
363 if (mdb->db_address) {
364 free(mdb->db_address);
366 if (mdb->db_socket) {
367 free(mdb->db_socket);
369 if (mdb->db_driverdir) {
370 free(mdb->db_driverdir);
372 if (mdb->db_driver) {
373 free(mdb->db_driver);
380 void db_thread_cleanup()
384 * Return the next unique index (auto-increment) for
385 * the given table. Return NULL on error.
388 int db_next_index(JCR *jcr, B_DB *mdb, char *table, char *index)
390 strcpy(index, "NULL");
396 * Escape strings so that DBI is happy
398 * NOTE! len is the length of the old string. Your new
399 * string must be long enough (max 2*old+1) to hold
400 * the escaped output.
402 * dbi_conn_quote_string_copy receives a pointer to pointer.
403 * We need copy the value of pointer to snew because libdbi change the
407 db_escape_string(JCR *jcr, B_DB *mdb, char *snew, char *old, int len)
415 /* correct the size of old basead in len
416 * and copy new string to inew
418 inew = (char *)malloc(sizeof(char) * len + 1);
419 bstrncpy(inew,old,len + 1);
420 /* escape the correct size of old */
421 dbi_conn_escape_string_copy(mdb->db, inew, &pnew);
423 /* copy the escaped string to snew */
424 bstrncpy(snew, pnew, 2 * len + 1);
427 Dmsg2(500, "dbi_conn_escape_string_copy %p %s\n",snew,snew);
432 * Submit a general SQL command (cmd), and for each row returned,
433 * the sqlite_handler is called with the ctx.
435 bool db_sql_query(B_DB *mdb, const char *query, DB_RESULT_HANDLER *result_handler, void *ctx)
439 Dmsg0(500, "db_sql_query started\n");
442 if (sql_query(mdb, query) != 0) {
443 Mmsg(mdb->errmsg, _("Query failed: %s: ERR=%s\n"), query, sql_strerror(mdb));
445 Dmsg0(500, "db_sql_query failed\n");
448 Dmsg0(500, "db_sql_query succeeded. checking handler\n");
450 if (result_handler != NULL) {
451 Dmsg0(500, "db_sql_query invoking handler\n");
452 if ((mdb->result = sql_store_result(mdb)) != NULL) {
453 int num_fields = sql_num_fields(mdb);
455 Dmsg0(500, "db_sql_query sql_store_result suceeded\n");
456 while ((row = sql_fetch_row(mdb)) != NULL) {
458 Dmsg0(500, "db_sql_query sql_fetch_row worked\n");
459 if (result_handler(ctx, num_fields, row))
463 sql_free_result(mdb);
468 Dmsg0(500, "db_sql_query finished\n");
475 DBI_ROW my_dbi_fetch_row(B_DB *mdb)
478 DBI_ROW row = NULL; // by default, return NULL
480 Dmsg0(500, "my_dbi_fetch_row start\n");
481 if ((!mdb->row || mdb->row_size < mdb->num_fields) && mdb->num_rows > 0) {
482 int num_fields = mdb->num_fields;
483 Dmsg1(500, "we have need space of %d bytes\n", sizeof(char *) * mdb->num_fields);
486 Dmsg0(500, "my_dbi_fetch_row freeing space\n");
487 Dmsg2(500, "my_dbi_free_row row: '%p' num_fields: '%d'\n", mdb->row, mdb->num_fields);
488 if (mdb->num_rows != 0) {
489 for(j = 0; j < mdb->num_fields; j++) {
490 Dmsg2(500, "my_dbi_free_row row '%p' '%d'\n", mdb->row[j], j);
498 //num_fields += 20; /* add a bit extra */
499 mdb->row = (DBI_ROW)malloc(sizeof(char *) * num_fields);
500 mdb->row_size = num_fields;
502 // now reset the row_number now that we have the space allocated
506 // if still within the result set
507 if (mdb->row_number <= mdb->num_rows && mdb->row_number != DBI_ERROR_BADPTR) {
508 Dmsg2(500, "my_dbi_fetch_row row number '%d' is acceptable (1..%d)\n", mdb->row_number, mdb->num_rows);
509 // get each value from this row
510 for (j = 0; j < mdb->num_fields; j++) {
511 mdb->row[j] = my_dbi_getvalue(mdb->result, mdb->row_number, j);
512 // allocate space to queue row
513 mdb->field_get = (DBI_FIELD_GET *)malloc(sizeof(DBI_FIELD_GET));
514 // store the pointer in queue
515 mdb->field_get->value = mdb->row[j];
516 Dmsg4(500, "my_dbi_fetch_row row[%d] field: '%p' in queue: '%p' has value: '%s'\n",
517 j, mdb->row[j], mdb->field_get->value, mdb->row[j]);
518 // insert in queue to future free
519 qinsert(&dbi_getvalue_list, &mdb->field_get->bq);
521 // increment the row number for the next call
526 Dmsg2(500, "my_dbi_fetch_row row number '%d' is NOT acceptable (1..%d)\n", mdb->row_number, mdb->num_rows);
529 Dmsg1(500, "my_dbi_fetch_row finishes returning %p\n", row);
534 int my_dbi_max_length(B_DB *mdb, int field_num) {
536 // for a given column, find the max length
544 for (i = 0; i < mdb->num_rows; i++) {
545 if (my_dbi_getisnull(mdb->result, i, field_num)) {
546 this_length = 4; // "NULL"
548 cbuf = my_dbi_getvalue(mdb->result, i, field_num);
549 this_length = cstrlen(cbuf);
550 // cbuf is always free
554 if (max_length < this_length) {
555 max_length = this_length;
562 DBI_FIELD * my_dbi_fetch_field(B_DB *mdb)
567 Dmsg0(500, "my_dbi_fetch_field starts\n");
569 if (!mdb->fields || mdb->fields_size < mdb->num_fields) {
573 Dmsg1(500, "allocating space for %d fields\n", mdb->num_fields);
574 mdb->fields = (DBI_FIELD *)malloc(sizeof(DBI_FIELD) * mdb->num_fields);
575 mdb->fields_size = mdb->num_fields;
577 for (i = 0; i < mdb->num_fields; i++) {
578 // num_fileds is starting at 1, increment i by 1
580 Dmsg1(500, "filling field %d\n", i);
581 mdb->fields[i].name = (char *)dbi_result_get_field_name(mdb->result, dbi_index);
582 mdb->fields[i].max_length = my_dbi_max_length(mdb, i);
583 mdb->fields[i].type = dbi_result_get_field_type_idx(mdb->result, dbi_index);
584 mdb->fields[i].flags = dbi_result_get_field_attribs_idx(mdb->result, dbi_index);
586 Dmsg4(500, "my_dbi_fetch_field finds field '%s' has length='%d' type='%d' and IsNull=%d\n",
587 mdb->fields[i].name, mdb->fields[i].max_length, mdb->fields[i].type,
588 mdb->fields[i].flags);
592 // increment field number for the next time around
594 Dmsg0(500, "my_dbi_fetch_field finishes\n");
595 return &mdb->fields[mdb->field_number++];
598 void my_dbi_data_seek(B_DB *mdb, int row)
600 // set the row number to be returned on the next call
601 // to my_dbi_fetch_row
602 mdb->row_number = row;
605 void my_dbi_field_seek(B_DB *mdb, int field)
607 mdb->field_number = field;
611 * Note, if this routine returns 1 (failure), Bacula expects
612 * that no result has been stored.
614 * Returns: 0 on success
618 int my_dbi_query(B_DB *mdb, const char *query)
621 Dmsg1(500, "my_dbi_query started %s\n", query);
622 // We are starting a new query. reset everything.
624 mdb->row_number = -1;
625 mdb->field_number = -1;
628 dbi_result_free(mdb->result); /* hmm, someone forgot to free?? */
632 mdb->result = (void **)dbi_conn_query(mdb->db, query);
635 Dmsg2(50, "Query failed: %s %p\n", query, mdb->result);
639 mdb->status = (dbi_error_flag) dbi_conn_error(mdb->db, &errmsg);
641 if (mdb->status == DBI_ERROR_NONE) {
642 Dmsg1(500, "we have a result\n", query);
644 // how many fields in the set?
645 // num_fields starting at 1
646 mdb->num_fields = dbi_result_get_numfields(mdb->result);
647 Dmsg1(500, "we have %d fields\n", mdb->num_fields);
648 // if no result num_rows is 0
649 mdb->num_rows = dbi_result_get_numrows(mdb->result);
650 Dmsg1(500, "we have %d rows\n", mdb->num_rows);
652 mdb->status = (dbi_error_flag) 0; /* succeed */
654 Dmsg1(50, "Result status failed: %s\n", query);
658 Dmsg0(500, "my_dbi_query finishing\n");
662 mdb->status = (dbi_error_flag) dbi_conn_error(mdb->db,&errmsg);
663 //dbi_conn_error(mdb->db, &errmsg);
664 Dmsg4(500, "my_dbi_query we failed dbi error: "
665 "'%s' '%p' '%d' flag '%d''\n", errmsg, mdb->result, mdb->result, mdb->status);
666 dbi_result_free(mdb->result);
668 mdb->status = (dbi_error_flag) 1; /* failed */
672 void my_dbi_free_result(B_DB *mdb)
678 Dmsg1(500, "my_dbi_free_result result '%p'\n", mdb->result);
679 dbi_result_free(mdb->result);
688 /* now is time to free all value return by my_dbi_get_value
689 * this is necessary because libdbi don't free memory return by yours results
690 * and Bacula has some routine wich call more than once time my_dbi_fetch_row
692 * Using a queue to store all pointer allocate is a good way to free all things
695 while((f=(DBI_FIELD_GET *)qremove(&dbi_getvalue_list))) {
696 Dmsg2(500, "my_dbi_free_result field value: '%p' in queue: '%p'\n", f->value, f);
708 Dmsg0(500, "my_dbi_free_result finish\n");
712 const char *my_dbi_strerror(B_DB *mdb)
716 dbi_conn_error(mdb->db, &errmsg);
721 #ifdef HAVE_BATCH_FILE_INSERT
724 * This can be a bit strang but is the one way to do
729 int my_dbi_batch_start(JCR *jcr, B_DB *mdb)
731 char *query = "COPY batch FROM STDIN";
733 Dmsg0(500, "my_dbi_batch_start started\n");
735 switch (mdb->db_type) {
738 if (my_dbi_query(mdb,
739 "CREATE TEMPORARY TABLE batch ("
745 "MD5 tinyblob)") == 1)
747 Dmsg0(500, "my_dbi_batch_start failed\n");
751 Dmsg0(500, "my_dbi_batch_start finishing\n");
754 case SQL_TYPE_POSTGRESQL:
756 if (my_dbi_query(mdb, "CREATE TEMPORARY TABLE batch ("
762 "md5 varchar)") == 1)
764 Dmsg0(500, "my_dbi_batch_start failed\n");
768 // We are starting a new query. reset everything.
770 mdb->row_number = -1;
771 mdb->field_number = -1;
773 my_dbi_free_result(mdb);
775 for (int i=0; i < 10; i++) {
776 my_dbi_query(mdb, query);
783 Dmsg1(50, "Query failed: %s\n", query);
787 mdb->status = (dbi_error_flag)dbi_conn_error(mdb->db, NULL);
788 //mdb->status = DBI_ERROR_NONE;
790 if (mdb->status == DBI_ERROR_NONE) {
791 // how many fields in the set?
792 mdb->num_fields = dbi_result_get_numfields(mdb->result);
793 mdb->num_rows = dbi_result_get_numrows(mdb->result);
794 mdb->status = (dbi_error_flag) 1;
796 Dmsg1(50, "Result status failed: %s\n", query);
800 Dmsg0(500, "my_postgresql_batch_start finishing\n");
804 case SQL_TYPE_SQLITE:
806 if (my_dbi_query(mdb, "CREATE TEMPORARY TABLE batch ("
812 "MD5 tinyblob)") == 1)
814 Dmsg0(500, "my_dbi_batch_start failed\n");
818 Dmsg0(500, "my_dbi_batch_start finishing\n");
821 case SQL_TYPE_SQLITE3:
823 if (my_dbi_query(mdb, "CREATE TEMPORARY TABLE batch ("
829 "MD5 tinyblob)") == 1)
831 Dmsg0(500, "my_dbi_batch_start failed\n");
835 Dmsg0(500, "my_dbi_batch_start finishing\n");
841 Mmsg1(&mdb->errmsg, _("error starting batch mode: %s"), my_dbi_strerror(mdb));
842 mdb->status = (dbi_error_flag) 0;
843 my_dbi_free_result(mdb);
848 /* set error to something to abort operation */
849 int my_dbi_batch_end(JCR *jcr, B_DB *mdb, const char *error)
853 int (*custom_function)(void*, const char*) = NULL;
854 dbi_conn_t *myconn = (dbi_conn_t *)(mdb->db);
856 Dmsg0(500, "my_dbi_batch_end started\n");
858 if (!mdb) { /* no files ? */
862 switch (mdb->db_type) {
865 mdb->status = (dbi_error_flag) 0;
868 case SQL_TYPE_POSTGRESQL:
869 custom_function = (custom_function_end_t)dbi_driver_specific_function(dbi_conn_get_driver(mdb->db), "PQputCopyEnd");
873 res = (*custom_function)(myconn->connection, error);
874 } while (res == 0 && --count > 0);
878 mdb->status = (dbi_error_flag) 1;
882 Dmsg0(500, "we failed\n");
883 mdb->status = (dbi_error_flag) 0;
884 //Mmsg1(&mdb->errmsg, _("error ending batch mode: %s"), PQerrorMessage(mdb->db));
887 case SQL_TYPE_SQLITE:
889 mdb->status = (dbi_error_flag) 0;
892 case SQL_TYPE_SQLITE3:
894 mdb->status = (dbi_error_flag) 0;
899 Dmsg0(500, "my_dbi_batch_end finishing\n");
905 * This function is big and use a big switch.
906 * In near future is better split in small functions
910 int my_dbi_batch_insert(JCR *jcr, B_DB *mdb, ATTR_DBR *ar)
914 dbi_conn_t *myconn = (dbi_conn_t *)(mdb->db);
915 int (*custom_function)(void*, const char*, int) = NULL;
916 char* (*custom_function_error)(void*) = NULL;
921 Dmsg0(500, "my_dbi_batch_insert started \n");
923 mdb->esc_name = check_pool_memory_size(mdb->esc_name, mdb->fnl*2+1);
924 mdb->esc_path = check_pool_memory_size(mdb->esc_path, mdb->pnl*2+1);
926 if (ar->Digest == NULL || ar->Digest[0] == 0) {
932 switch (mdb->db_type) {
934 db_escape_string(jcr, mdb, mdb->esc_name, mdb->fname, mdb->fnl);
935 db_escape_string(jcr, mdb, mdb->esc_path, mdb->path, mdb->pnl);
936 len = Mmsg(mdb->cmd, "INSERT INTO batch VALUES (%u,%s,'%s','%s','%s','%s')",
937 ar->FileIndex, edit_int64(ar->JobId,ed1), mdb->esc_path,
938 mdb->esc_name, ar->attr, digest);
940 if (my_dbi_query(mdb,mdb->cmd) == 1)
942 Dmsg0(500, "my_dbi_batch_insert failed\n");
946 Dmsg0(500, "my_dbi_batch_insert finishing\n");
950 case SQL_TYPE_POSTGRESQL:
951 my_postgresql_copy_escape(mdb->esc_name, mdb->fname, mdb->fnl);
952 my_postgresql_copy_escape(mdb->esc_path, mdb->path, mdb->pnl);
953 len = Mmsg(mdb->cmd, "%u\t%s\t%s\t%s\t%s\t%s\n",
954 ar->FileIndex, edit_int64(ar->JobId, ed1), mdb->esc_path,
955 mdb->esc_name, ar->attr, digest);
957 /* libdbi don't support CopyData and we need call a postgresql
958 * specific function to do this work
960 Dmsg2(500, "my_dbi_batch_insert :\n %s \ncmd_size: %d",mdb->cmd, len);
961 if ((custom_function = (custom_function_insert_t)dbi_driver_specific_function(dbi_conn_get_driver(mdb->db),
962 "PQputCopyData")) != NULL) {
964 res = (*custom_function)(myconn->connection, mdb->cmd, len);
965 } while (res == 0 && --count > 0);
970 mdb->status = (dbi_error_flag) 1;
974 Dmsg0(500, "my_dbi_batch_insert failed\n");
978 Dmsg0(500, "my_dbi_batch_insert finishing\n");
981 // ensure to detect a PQerror
982 custom_function_error = (custom_function_error_t)dbi_driver_specific_function(dbi_conn_get_driver(mdb->db), "PQerrorMessage");
983 Dmsg1(500, "my_dbi_batch_insert failed\n PQerrorMessage: %s", (*custom_function_error)(myconn->connection));
987 case SQL_TYPE_SQLITE:
988 db_escape_string(jcr, mdb, mdb->esc_name, mdb->fname, mdb->fnl);
989 db_escape_string(jcr, mdb, mdb->esc_path, mdb->path, mdb->pnl);
990 len = Mmsg(mdb->cmd, "INSERT INTO batch VALUES (%u,%s,'%s','%s','%s','%s')",
991 ar->FileIndex, edit_int64(ar->JobId,ed1), mdb->esc_path,
992 mdb->esc_name, ar->attr, digest);
993 if (my_dbi_query(mdb,mdb->cmd) == 1)
995 Dmsg0(500, "my_dbi_batch_insert failed\n");
999 Dmsg0(500, "my_dbi_batch_insert finishing\n");
1003 case SQL_TYPE_SQLITE3:
1004 db_escape_string(jcr, mdb, mdb->esc_name, mdb->fname, mdb->fnl);
1005 db_escape_string(jcr, mdb, mdb->esc_path, mdb->path, mdb->pnl);
1006 len = Mmsg(mdb->cmd, "INSERT INTO batch VALUES (%u,%s,'%s','%s','%s','%s')",
1007 ar->FileIndex, edit_int64(ar->JobId,ed1), mdb->esc_path,
1008 mdb->esc_name, ar->attr, digest);
1009 if (my_dbi_query(mdb,mdb->cmd) == 1)
1011 Dmsg0(500, "my_dbi_batch_insert failed\n");
1015 Dmsg0(500, "my_dbi_batch_insert finishing\n");
1022 Mmsg1(&mdb->errmsg, _("error inserting batch mode: %s"), my_dbi_strerror(mdb));
1023 mdb->status = (dbi_error_flag) 0;
1024 my_dbi_free_result(mdb);
1029 * Escape strings so that PostgreSQL is happy on COPY
1031 * NOTE! len is the length of the old string. Your new
1032 * string must be long enough (max 2*old+1) to hold
1033 * the escaped output.
1035 char *my_postgresql_copy_escape(char *dest, char *src, size_t len)
1037 /* we have to escape \t, \n, \r, \ */
1040 while (len > 0 && *src) {
1075 #endif /* HAVE_BATCH_FILE_INSERT */
1079 * int PQgetisnull(const PGresult *res,
1081 * int column_number);
1083 * use dbi_result_seek_row to search in result set
1085 int my_dbi_getisnull(dbi_result *result, int row_number, int column_number) {
1088 if(row_number == 0) {
1094 if(dbi_result_seek_row(result, row_number)) {
1096 i = dbi_result_field_is_null_idx(result,column_number);
1107 * char *PQgetvalue(const PGresult *res,
1109 * int column_number);
1111 * use dbi_result_seek_row to search in result set
1112 * use example to return only strings
1114 char *my_dbi_getvalue(dbi_result *result, int row_number, unsigned int column_number) {
1118 const char *field_name;
1119 unsigned short dbitype;
1120 size_t field_length;
1123 /* correct the index for dbi interface
1124 * dbi index begins 1
1125 * I prefer do not change others functions
1127 Dmsg3(600, "my_dbi_getvalue pre-starting result '%p' row number '%d' column number '%d'\n",
1128 result, row_number, column_number);
1132 if(row_number == 0) {
1136 Dmsg3(600, "my_dbi_getvalue starting result '%p' row number '%d' column number '%d'\n",
1137 result, row_number, column_number);
1139 if(dbi_result_seek_row(result, row_number)) {
1141 field_name = dbi_result_get_field_name(result, column_number);
1142 field_length = dbi_result_get_field_length(result, field_name);
1143 dbitype = dbi_result_get_field_type_idx(result,column_number);
1145 Dmsg3(500, "my_dbi_getvalue start: type: '%d' "
1146 "field_length bytes: '%d' fieldname: '%s'\n",
1147 dbitype, field_length, field_name);
1150 //buf = (char *)malloc(sizeof(char *) * field_length + 1);
1151 buf = (char *)malloc(field_length + 1);
1154 buf = (char *)malloc(sizeof(char *) * 50);
1158 case DBI_TYPE_INTEGER:
1159 num = dbi_result_get_longlong(result, field_name);
1160 edit_int64(num, buf);
1161 field_length = strlen(buf);
1163 case DBI_TYPE_STRING:
1165 field_length = bsnprintf(buf, field_length + 1, "%s",
1166 dbi_result_get_string(result, field_name));
1171 case DBI_TYPE_BINARY:
1172 /* dbi_result_get_binary return a NULL pointer if value is empty
1173 * following, change this to what Bacula espected
1176 field_length = bsnprintf(buf, field_length + 1, "%s",
1177 dbi_result_get_binary(result, field_name));
1182 case DBI_TYPE_DATETIME:
1186 last = dbi_result_get_datetime(result, field_name);
1189 field_length = bsnprintf(buf, 20, "0000-00-00 00:00:00");
1191 (void)localtime_r(&last, &tm);
1192 field_length = bsnprintf(buf, 20, "%04d-%02d-%02d %02d:%02d:%02d",
1193 (tm.tm_year + 1900), (tm.tm_mon + 1), tm.tm_mday,
1194 tm.tm_hour, tm.tm_min, tm.tm_sec);
1200 dbi_conn_error(dbi_result_get_conn(result), &errmsg);
1201 Dmsg1(500, "my_dbi_getvalue error: %s\n", errmsg);
1204 Dmsg3(500, "my_dbi_getvalue finish buffer: '%p' num bytes: '%d' data: '%s'\n",
1205 buf, field_length, buf);
1207 // don't worry about this buf
1211 int my_dbi_sql_insert_id(B_DB *mdb, char *table_name)
1214 Obtain the current value of the sequence that
1215 provides the serial value for primary key of the table.
1217 currval is local to our session. It is not affected by
1220 Determine the name of the sequence.
1221 PostgreSQL automatically creates a sequence using
1222 <table>_<column>_seq.
1223 At the time of writing, all tables used this format for
1224 for their primary key: <table>id
1225 Except for basefiles which has a primary key on baseid.
1226 Therefore, we need to special case that one table.
1228 everything else can use the PostgreSQL formula.
1234 if (mdb->db_type == SQL_TYPE_POSTGRESQL) {
1236 if (strcasecmp(table_name, "basefiles") == 0) {
1237 bstrncpy(sequence, "basefiles_baseid", sizeof(sequence));
1239 bstrncpy(sequence, table_name, sizeof(sequence));
1240 bstrncat(sequence, "_", sizeof(sequence));
1241 bstrncat(sequence, table_name, sizeof(sequence));
1242 bstrncat(sequence, "id", sizeof(sequence));
1245 bstrncat(sequence, "_seq", sizeof(sequence));
1246 id = dbi_conn_sequence_last(mdb->db, NT_(sequence));
1248 id = dbi_conn_sequence_last(mdb->db, NT_(table_name));
1254 #ifdef HAVE_BATCH_FILE_INSERT
1255 const char *my_dbi_batch_lock_path_query[4] = {
1257 "LOCK TABLES Path write, batch write, Path as p write",
1259 "BEGIN; LOCK TABLE Path IN SHARE ROW EXCLUSIVE MODE",
1265 const char *my_dbi_batch_lock_filename_query[4] = {
1267 "LOCK TABLES Filename write, batch write, Filename as f write",
1269 "BEGIN; LOCK TABLE Filename IN SHARE ROW EXCLUSIVE MODE",
1275 const char *my_dbi_batch_unlock_tables_query[4] = {
1285 const char *my_dbi_batch_fill_path_query[4] = {
1287 "INSERT INTO Path (Path) "
1288 "SELECT a.Path FROM "
1289 "(SELECT DISTINCT Path FROM batch) AS a WHERE NOT EXISTS "
1290 "(SELECT Path FROM Path AS p WHERE p.Path = a.Path)",
1292 "INSERT INTO Path (Path) "
1293 "SELECT a.Path FROM "
1294 "(SELECT DISTINCT Path FROM batch) AS a "
1295 "WHERE NOT EXISTS (SELECT Path FROM Path WHERE Path = a.Path) ",
1297 "INSERT INTO Path (Path)"
1298 " SELECT DISTINCT Path FROM batch"
1299 " EXCEPT SELECT Path FROM Path",
1301 "INSERT INTO Path (Path)"
1302 " SELECT DISTINCT Path FROM batch"
1303 " EXCEPT SELECT Path FROM Path"};
1305 const char *my_dbi_batch_fill_filename_query[4] = {
1307 "INSERT INTO Filename (Name) "
1308 "SELECT a.Name FROM "
1309 "(SELECT DISTINCT Name FROM batch) AS a WHERE NOT EXISTS "
1310 "(SELECT Name FROM Filename AS f WHERE f.Name = a.Name)",
1312 "INSERT INTO Filename (Name) "
1313 "SELECT a.Name FROM "
1314 "(SELECT DISTINCT Name FROM batch) as a "
1316 "(SELECT Name FROM Filename WHERE Name = a.Name)",
1318 "INSERT INTO Filename (Name)"
1319 " SELECT DISTINCT Name FROM batch "
1320 " EXCEPT SELECT Name FROM Filename",
1322 "INSERT INTO Filename (Name)"
1323 " SELECT DISTINCT Name FROM batch "
1324 " EXCEPT SELECT Name FROM Filename"};
1326 #endif /* HAVE_BATCH_FILE_INSERT */
1328 #endif /* HAVE_DBI */