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 John Walker.
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 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
63 * Retrieve database type
72 * Initialize database data structure. In principal this should
73 * never have errors, or it is really fatal.
76 db_init_database(JCR *jcr, const char *db_name, const char *db_user, const char *db_password,
77 const char *db_address, int db_port, const char *db_socket,
78 int mult_db_connections)
82 char db_driverdir[256];
84 /* Constraint the db_driver */
86 Jmsg(jcr, M_FATAL, 0, _("A dbi driver for DBI must be supplied.\n"));
90 /* Do the correct selection of driver.
91 * Can be one of the varius supported by libdbi
95 bstrncpy(db_driver,"mysql", sizeof(db_driver));
97 case SQL_TYPE_POSTGRESQL:
98 bstrncpy(db_driver,"pgsql", sizeof(db_driver));
100 case SQL_TYPE_SQLITE:
101 bstrncpy(db_driver,"pgsql", sizeof(db_driver));
105 /* Set db_driverdir whereis is the libdbi drivers */
106 bstrncpy(db_driverdir, DBI_DRIVER_DIR, 255);
109 Jmsg(jcr, M_FATAL, 0, _("A user name for DBI must be supplied.\n"));
112 P(mutex); /* lock DB queue */
113 if (!mult_db_connections) {
114 /* Look to see if DB already open */
115 for (mdb=NULL; (mdb=(B_DB *)qnext(&db_list, &mdb->bq)); ) {
116 if (bstrcmp(mdb->db_name, db_name) &&
117 bstrcmp(mdb->db_address, db_address) &&
118 bstrcmp(mdb->db_driver, db_driver) &&
119 mdb->db_port == db_port) {
120 Dmsg4(100, "DB REopen %d %s %s erro: %d\n", mdb->ref_count, db_driver, db_name,
121 dbi_conn_error(mdb->db, NULL));
124 return mdb; /* already open */
128 Dmsg0(100, "db_open first time\n");
129 mdb = (B_DB *)malloc(sizeof(B_DB));
130 memset(mdb, 0, sizeof(B_DB));
131 mdb->db_name = bstrdup(db_name);
132 mdb->db_user = bstrdup(db_user);
134 mdb->db_password = bstrdup(db_password);
137 mdb->db_address = bstrdup(db_address);
140 mdb->db_socket = bstrdup(db_socket);
143 mdb->db_driverdir = bstrdup(db_driverdir);
146 mdb->db_driver = bstrdup(db_driver);
148 mdb->db_type = db_type;
149 mdb->db_port = db_port;
150 mdb->have_insert_id = TRUE;
151 mdb->errmsg = get_pool_memory(PM_EMSG); /* get error message buffer */
153 mdb->cmd = get_pool_memory(PM_EMSG); /* get command buffer */
154 mdb->cached_path = get_pool_memory(PM_FNAME);
155 mdb->cached_path_id = 0;
157 mdb->fname = get_pool_memory(PM_FNAME);
158 mdb->path = get_pool_memory(PM_FNAME);
159 mdb->esc_name = get_pool_memory(PM_FNAME);
160 mdb->esc_path = get_pool_memory(PM_FNAME);
161 mdb->allow_transactions = mult_db_connections;
162 qinsert(&db_list, &mdb->bq); /* put db in list */
168 * Now actually open the database. This can generate errors,
169 * which are returned in the errmsg
171 * DO NOT close the database or free(mdb) here !!!!
174 db_open_database(JCR *jcr, B_DB *mdb)
183 if (mdb->connected) {
187 mdb->connected = false;
189 if ((errstat=rwl_init(&mdb->lock)) != 0) {
191 Mmsg1(&mdb->errmsg, _("Unable to initialize DB lock. ERR=%s\n"),
192 be.bstrerror(errstat));
198 bsnprintf(buf, sizeof(buf), "%d", mdb->db_port);
204 numdrivers = dbi_initialize_r(mdb->db_driverdir, &(mdb->instance));
205 if (numdrivers < 0) {
206 Mmsg2(&mdb->errmsg, _("Unable to locate the DBD drivers to DBI interface in: \n"
207 "db_driverdir=%s. It is probaly not found any drivers\n"),
208 mdb->db_driverdir,numdrivers);
212 mdb->db = (void **)dbi_conn_new_r(mdb->db_driver, mdb->instance);
213 dbi_conn_set_option(mdb->db, "host", mdb->db_address); /* default = localhost */
214 dbi_conn_set_option(mdb->db, "port", port); /* default port */
215 dbi_conn_set_option(mdb->db, "username", mdb->db_user); /* login name */
216 dbi_conn_set_option(mdb->db, "password", mdb->db_password); /* password */
217 dbi_conn_set_option(mdb->db, "dbname", mdb->db_name); /* database name */
219 /* If connection fails, try at 5 sec intervals for 30 seconds. */
220 for (int retry=0; retry < 6; retry++) {
222 dbstat = dbi_conn_connect(mdb->db);
227 dbi_conn_error(mdb->db, &errmsg);
228 Dmsg1(50, "dbi error: %s\n", errmsg);
235 Mmsg3(&mdb->errmsg, _("Unable to connect to DBI interface.\n"
236 "Type=%s Database=%s User=%s\n"
237 "It is probably not running or your password is incorrect.\n"),
238 mdb->db_driver, mdb->db_name, mdb->db_user);
243 Dmsg0(50, "dbi_real_connect done\n");
244 Dmsg3(50, "db_user=%s db_name=%s db_password=%s\n",
245 mdb->db_user, mdb->db_name,
246 mdb->db_password==NULL?"(NULL)":mdb->db_password);
248 mdb->connected = true;
250 if (!check_tables_version(jcr, mdb)) {
255 switch (mdb->db_type) {
257 /* Set connection timeout to 8 days specialy for batch mode */
258 sql_query(mdb, "SET wait_timeout=691200");
259 sql_query(mdb, "SET interactive_timeout=691200");
261 case SQL_TYPE_POSTGRESQL:
262 /* tell PostgreSQL we are using standard conforming strings
263 and avoid warnings such as:
264 WARNING: nonstandard use of \\ in a string literal
266 sql_query(mdb, "SET datestyle TO 'ISO, YMD'");
267 sql_query(mdb, "set standard_conforming_strings=on");
269 case SQL_TYPE_SQLITE:
278 db_close_database(JCR *jcr, B_DB *mdb)
283 db_end_transaction(jcr, mdb);
285 sql_free_result(mdb);
287 if (mdb->ref_count == 0) {
289 if (mdb->connected && mdb->db) {
291 dbi_shutdown_r(mdb->instance);
293 mdb->instance = NULL;
295 rwl_destroy(&mdb->lock);
296 free_pool_memory(mdb->errmsg);
297 free_pool_memory(mdb->cmd);
298 free_pool_memory(mdb->cached_path);
299 free_pool_memory(mdb->fname);
300 free_pool_memory(mdb->path);
301 free_pool_memory(mdb->esc_name);
302 free_pool_memory(mdb->esc_path);
309 if (mdb->db_password) {
310 free(mdb->db_password);
312 if (mdb->db_address) {
313 free(mdb->db_address);
315 if (mdb->db_socket) {
316 free(mdb->db_socket);
318 if (mdb->db_driverdir) {
319 free(mdb->db_driverdir);
321 if (mdb->db_driver) {
322 free(mdb->db_driver);
329 void db_thread_cleanup()
333 * Return the next unique index (auto-increment) for
334 * the given table. Return NULL on error.
337 int db_next_index(JCR *jcr, B_DB *mdb, char *table, char *index)
339 strcpy(index, "NULL");
345 * Escape strings so that DBI is happy
347 * NOTE! len is the length of the old string. Your new
348 * string must be long enough (max 2*old+1) to hold
349 * the escaped output.
351 * dbi_conn_quote_string_copy receives a pointer to pointer.
352 * We need copy the value of pointer to snew because libdbi change the
356 db_escape_string(JCR *jcr, B_DB *mdb, char *snew, char *old, int len)
364 /* correct the size of old basead in len
365 * and copy new string to inew
367 inew = (char *)malloc(sizeof(char) * len + 1);
368 bstrncpy(inew,old,len + 1);
369 /* escape the correct size of old */
370 dbi_conn_escape_string_copy(mdb->db, inew, &pnew);
372 /* copy the escaped string to snew */
373 bstrncpy(snew, pnew, 2 * len + 1);
376 Dmsg2(500, "dbi_conn_escape_string_copy %p %s\n",snew,snew);
381 * Submit a general SQL command (cmd), and for each row returned,
382 * the sqlite_handler is called with the ctx.
384 bool db_sql_query(B_DB *mdb, const char *query, DB_RESULT_HANDLER *result_handler, void *ctx)
388 Dmsg0(500, "db_sql_query started\n");
391 if (sql_query(mdb, query) != 0) {
392 Mmsg(mdb->errmsg, _("Query failed: %s: ERR=%s\n"), query, sql_strerror(mdb));
394 Dmsg0(500, "db_sql_query failed\n");
397 Dmsg0(500, "db_sql_query succeeded. checking handler\n");
399 if (result_handler != NULL) {
400 Dmsg0(500, "db_sql_query invoking handler\n");
401 if ((mdb->result = sql_store_result(mdb)) != NULL) {
402 int num_fields = sql_num_fields(mdb);
404 Dmsg0(500, "db_sql_query sql_store_result suceeded\n");
405 while ((row = sql_fetch_row(mdb)) != NULL) {
407 Dmsg0(500, "db_sql_query sql_fetch_row worked\n");
408 if (result_handler(ctx, num_fields, row))
412 sql_free_result(mdb);
417 Dmsg0(500, "db_sql_query finished\n");
424 DBI_ROW my_dbi_fetch_row(B_DB *mdb)
427 DBI_ROW row = NULL; // by default, return NULL
429 Dmsg0(500, "my_dbi_fetch_row start\n");
431 if (!mdb->row || mdb->row_size < mdb->num_fields) {
432 int num_fields = mdb->num_fields;
433 Dmsg1(500, "we have need space of %d bytes\n", sizeof(char *) * mdb->num_fields);
436 Dmsg0(500, "my_dbi_fetch_row freeing space\n");
437 Dmsg2(500, "my_dbi_free_row row: '%p' num_fields: '%d'\n", mdb->row, mdb->num_fields);
438 if (mdb->num_rows != 0) {
439 for(j = 0; j < mdb->num_fields; j++) {
440 Dmsg2(500, "my_dbi_free_row row '%p' '%d'\n", mdb->row[j], j);
448 num_fields += 20; /* add a bit extra */
449 mdb->row = (DBI_ROW)malloc(sizeof(char *) * num_fields);
450 mdb->row_size = num_fields;
452 // now reset the row_number now that we have the space allocated
456 // if still within the result set
457 if (mdb->row_number <= mdb->num_rows) {
458 Dmsg2(500, "my_dbi_fetch_row row number '%d' is acceptable (0..%d)\n", mdb->row_number, mdb->num_rows);
459 // get each value from this row
460 for (j = 0; j < mdb->num_fields; j++) {
461 mdb->row[j] = my_dbi_getvalue(mdb->result, mdb->row_number, j);
462 Dmsg3(500, "my_dbi_fetch_row field '%p' '%d' has value '%s'\n",mdb->row[j], j, mdb->row[j]);
464 // increment the row number for the next call
469 Dmsg2(500, "my_dbi_fetch_row row number '%d' is NOT acceptable (0..%d)\n", mdb->row_number, mdb->num_rows);
472 Dmsg1(500, "my_dbi_fetch_row finishes returning %p\n", row);
477 int my_dbi_max_length(B_DB *mdb, int field_num) {
479 // for a given column, find the max length
487 for (i = 0; i < mdb->num_rows; i++) {
488 if (my_dbi_getisnull(mdb->result, i, field_num)) {
489 this_length = 4; // "NULL"
492 cbuf = my_dbi_getvalue(mdb->result, i, field_num);
493 this_length = cstrlen(cbuf);
497 if (max_length < this_length) {
498 max_length = this_length;
505 DBI_FIELD * my_dbi_fetch_field(B_DB *mdb)
510 Dmsg0(500, "my_dbi_fetch_field starts\n");
512 if (!mdb->fields || mdb->fields_size < mdb->num_fields) {
516 Dmsg1(500, "allocating space for %d fields\n", mdb->num_fields);
517 mdb->fields = (DBI_FIELD *)malloc(sizeof(DBI_FIELD) * mdb->num_fields);
518 mdb->fields_size = mdb->num_fields;
520 for (i = 0; i < mdb->num_fields; i++) {
522 Dmsg1(500, "filling field %d\n", i);
523 mdb->fields[i].name = (char *)dbi_result_get_field_name(mdb->result, dbi_index);
524 mdb->fields[i].max_length = my_dbi_max_length(mdb, i);
525 mdb->fields[i].type = dbi_result_get_field_type_idx(mdb->result, dbi_index);
526 mdb->fields[i].flags = dbi_result_get_field_attribs_idx(mdb->result, dbi_index);
528 Dmsg4(500, "my_dbi_fetch_field finds field '%s' has length='%d' type='%d' and IsNull=%d\n",
529 mdb->fields[i].name, mdb->fields[i].max_length, mdb->fields[i].type,
530 mdb->fields[i].flags);
534 // increment field number for the next time around
536 Dmsg0(500, "my_dbi_fetch_field finishes\n");
537 return &mdb->fields[mdb->field_number++];
540 void my_dbi_data_seek(B_DB *mdb, int row)
542 // set the row number to be returned on the next call
543 // to my_dbi_fetch_row
544 mdb->row_number = row;
547 void my_dbi_field_seek(B_DB *mdb, int field)
549 mdb->field_number = field;
553 * Note, if this routine returns 1 (failure), Bacula expects
554 * that no result has been stored.
556 * Returns: 0 on success
560 int my_dbi_query(B_DB *mdb, const char *query)
563 Dmsg1(500, "my_dbi_query started %s\n", query);
564 // We are starting a new query. reset everything.
566 mdb->row_number = -1;
567 mdb->field_number = -1;
570 dbi_result_free(mdb->result); /* hmm, someone forgot to free?? */
574 mdb->result = (void **)dbi_conn_query(mdb->db, query);
577 Dmsg2(50, "Query failed: %s %p\n", query, mdb->result);
581 mdb->status = (dbi_error_flag) dbi_conn_error(mdb->db, &errmsg);
583 if (mdb->status == DBI_ERROR_NONE) {
584 Dmsg1(500, "we have a result\n", query);
586 // how many fields in the set?
587 mdb->num_fields = dbi_result_get_numfields(mdb->result);
588 Dmsg1(500, "we have %d fields\n", mdb->num_fields);
590 mdb->num_rows = dbi_result_get_numrows(mdb->result);
591 Dmsg1(500, "we have %d rows\n", mdb->num_rows);
593 mdb->status = (dbi_error_flag) 0; /* succeed */
595 Dmsg1(50, "Result status failed: %s\n", query);
599 Dmsg0(500, "my_dbi_query finishing\n");
603 mdb->status = (dbi_error_flag) dbi_conn_error(mdb->db,&errmsg);
604 //dbi_conn_error(mdb->db, &errmsg);
605 Dmsg4(500, "my_dbi_query we failed dbi error: "
606 "'%s' '%p' '%d' flag '%d''\n", errmsg, mdb->result, mdb->result, mdb->status);
607 dbi_result_free(mdb->result);
609 mdb->status = (dbi_error_flag) 1; /* failed */
613 void my_dbi_free_result(B_DB *mdb)
619 Dmsg1(500, "my_dbi_free_result result '%p'\n", mdb->result);
620 dbi_result_free(mdb->result);
626 Dmsg2(500, "my_dbi_free_result row: '%p' num_fields: '%d'\n", mdb->row, mdb->num_fields);
627 if (mdb->num_rows != 0) {
628 for(i = 0; i < mdb->num_fields; i++) {
629 Dmsg2(500, "my_dbi_free_result row '%p' '%d'\n", mdb->row[i], i);
644 //Dmsg0(500, "my_dbi_free_result finish\n");
648 const char *my_dbi_strerror(B_DB *mdb)
652 dbi_conn_error(mdb->db, &errmsg);
657 #ifdef HAVE_BATCH_FILE_INSERT
660 * This can be a bit strang but is the one way to do
665 int my_dbi_batch_start(JCR *jcr, B_DB *mdb)
667 char *query = "COPY batch FROM STDIN";
669 Dmsg0(500, "my_dbi_batch_start started\n");
671 switch (mdb->db_type) {
674 if (my_dbi_query(mdb,
675 "CREATE TEMPORARY TABLE batch ("
681 "MD5 tinyblob)") == 1)
683 Dmsg0(500, "my_dbi_batch_start failed\n");
687 Dmsg0(500, "my_dbi_batch_start finishing\n");
690 case SQL_TYPE_POSTGRESQL:
692 //query = "COPY batch FROM STDIN";
694 if (my_dbi_query(mdb,
695 "CREATE TEMPORARY TABLE batch ("
701 "md5 varchar)") == 1)
703 Dmsg0(500, "my_dbi_batch_start failed\n");
707 // We are starting a new query. reset everything.
709 mdb->row_number = -1;
710 mdb->field_number = -1;
712 my_dbi_free_result(mdb);
714 for (int i=0; i < 10; i++) {
715 my_dbi_query(mdb, query);
722 Dmsg1(50, "Query failed: %s\n", query);
726 mdb->status = (dbi_error_flag)dbi_conn_error(mdb->db, NULL);
727 //mdb->status = DBI_ERROR_NONE;
729 if (mdb->status == DBI_ERROR_NONE) {
730 // how many fields in the set?
731 mdb->num_fields = dbi_result_get_numfields(mdb->result);
732 mdb->num_rows = dbi_result_get_numrows(mdb->result);
733 mdb->status = (dbi_error_flag) 1;
735 Dmsg1(50, "Result status failed: %s\n", query);
739 Dmsg0(500, "my_postgresql_batch_start finishing\n");
743 case SQL_TYPE_SQLITE:
745 if (my_dbi_query(mdb,
746 "CREATE TEMPORARY TABLE batch ("
752 "MD5 tinyblob)") == 1)
754 Dmsg0(500, "my_dbi_batch_start failed\n");
758 Dmsg0(500, "my_dbi_batch_start finishing\n");
764 Mmsg1(&mdb->errmsg, _("error starting batch mode: %s"), my_dbi_strerror(mdb));
765 mdb->status = (dbi_error_flag) 0;
766 my_dbi_free_result(mdb);
771 /* set error to something to abort operation */
772 int my_dbi_batch_end(JCR *jcr, B_DB *mdb, const char *error)
776 int (*custom_function)(void*, const char*) = NULL;
777 dbi_conn_t *myconn = (dbi_conn_t *)(mdb->db);
779 Dmsg0(500, "my_dbi_batch_end started\n");
781 if (!mdb) { /* no files ? */
785 switch (mdb->db_type) {
788 mdb->status = (dbi_error_flag) 0;
791 case SQL_TYPE_POSTGRESQL:
792 custom_function = (custom_function_end_t)dbi_driver_specific_function(dbi_conn_get_driver(mdb->db), "PQputCopyEnd");
796 res = (*custom_function)(myconn->connection, error);
797 } while (res == 0 && --count > 0);
801 mdb->status = (dbi_error_flag) 1;
805 Dmsg0(500, "we failed\n");
806 mdb->status = (dbi_error_flag) 0;
807 //Mmsg1(&mdb->errmsg, _("error ending batch mode: %s"), PQerrorMessage(mdb->db));
810 case SQL_TYPE_SQLITE:
812 mdb->status = (dbi_error_flag) 0;
817 Dmsg0(500, "my_dbi_batch_end finishing\n");
823 * This function is big and use a big switch.
824 * In near future is better split in small functions
828 int my_dbi_batch_insert(JCR *jcr, B_DB *mdb, ATTR_DBR *ar)
832 dbi_conn_t *myconn = (dbi_conn_t *)(mdb->db);
833 int (*custom_function)(void*, const char*, int) = NULL;
834 char* (*custom_function_error)(void*) = NULL;
839 Dmsg0(500, "my_dbi_batch_insert started \n");
841 mdb->esc_name = check_pool_memory_size(mdb->esc_name, mdb->fnl*2+1);
842 mdb->esc_path = check_pool_memory_size(mdb->esc_path, mdb->pnl*2+1);
844 if (ar->Digest == NULL || ar->Digest[0] == 0) {
850 switch (mdb->db_type) {
852 db_escape_string(jcr, mdb, mdb->esc_name, mdb->fname, mdb->fnl);
853 db_escape_string(jcr, mdb, mdb->esc_path, mdb->path, mdb->pnl);
854 len = Mmsg(mdb->cmd, "INSERT INTO batch VALUES (%u,%s,'%s','%s','%s','%s')",
855 ar->FileIndex, edit_int64(ar->JobId,ed1), mdb->esc_path,
856 mdb->esc_name, ar->attr, digest);
858 if (my_dbi_query(mdb,mdb->cmd) == 1)
860 Dmsg0(500, "my_dbi_batch_insert failed\n");
864 Dmsg0(500, "my_dbi_batch_insert finishing\n");
868 case SQL_TYPE_POSTGRESQL:
869 my_postgresql_copy_escape(mdb->esc_name, mdb->fname, mdb->fnl);
870 my_postgresql_copy_escape(mdb->esc_path, mdb->path, mdb->pnl);
871 len = Mmsg(mdb->cmd, "%u\t%s\t%s\t%s\t%s\t%s\n",
872 ar->FileIndex, edit_int64(ar->JobId, ed1), mdb->esc_path,
873 mdb->esc_name, ar->attr, digest);
875 /* libdbi don't support CopyData and we need call a postgresql
876 * specific function to do this work
878 Dmsg2(500, "my_dbi_batch_insert :\n %s \ncmd_size: %d",mdb->cmd, len);
879 if ((custom_function = (custom_function_insert_t)dbi_driver_specific_function(dbi_conn_get_driver(mdb->db),
880 "PQputCopyData")) != NULL) {
882 res = (*custom_function)(myconn->connection, mdb->cmd, len);
883 } while (res == 0 && --count > 0);
888 mdb->status = (dbi_error_flag) 1;
892 Dmsg0(500, "my_dbi_batch_insert failed\n");
896 Dmsg0(500, "my_dbi_batch_insert finishing\n");
899 // ensure to detect a PQerror
900 custom_function_error = (custom_function_error_t)dbi_driver_specific_function(dbi_conn_get_driver(mdb->db), "PQerrorMessage");
901 Dmsg1(500, "my_dbi_batch_insert failed\n PQerrorMessage: %s", (*custom_function_error)(myconn->connection));
905 case SQL_TYPE_SQLITE:
906 db_escape_string(jcr, mdb, mdb->esc_name, mdb->fname, mdb->fnl);
907 db_escape_string(jcr, mdb, mdb->esc_path, mdb->path, mdb->pnl);
908 len = Mmsg(mdb->cmd, "INSERT INTO batch VALUES (%u,%s,'%s','%s','%s','%s')",
909 ar->FileIndex, edit_int64(ar->JobId,ed1), mdb->esc_path,
910 mdb->esc_name, ar->attr, digest);
911 if (my_dbi_query(mdb,mdb->cmd) == 1)
913 Dmsg0(500, "my_dbi_batch_insert failed\n");
917 Dmsg0(500, "my_dbi_batch_insert finishing\n");
924 Mmsg1(&mdb->errmsg, _("error inserting batch mode: %s"), my_dbi_strerror(mdb));
925 mdb->status = (dbi_error_flag) 0;
926 my_dbi_free_result(mdb);
931 * Escape strings so that PostgreSQL is happy on COPY
933 * NOTE! len is the length of the old string. Your new
934 * string must be long enough (max 2*old+1) to hold
935 * the escaped output.
937 char *my_postgresql_copy_escape(char *dest, char *src, size_t len)
939 /* we have to escape \t, \n, \r, \ */
942 while (len > 0 && *src) {
977 #endif /* HAVE_BATCH_FILE_INSERT */
981 * int PQgetisnull(const PGresult *res,
983 * int column_number);
985 * use dbi_result_seek_row to search in result set
987 int my_dbi_getisnull(dbi_result *result, int row_number, int column_number) {
990 if(row_number == 0) {
996 if(dbi_result_seek_row(result, row_number)) {
998 i = dbi_result_field_is_null_idx(result,column_number);
1009 * char *PQgetvalue(const PGresult *res,
1011 * int column_number);
1013 * use dbi_result_seek_row to search in result set
1014 * use example to return only strings
1016 char *my_dbi_getvalue(dbi_result *result, int row_number, unsigned int column_number) {
1018 /* TODO: This is very bad, need refactoring */
1019 //POOLMEM *buf = get_pool_memory(PM_FNAME);
1022 const char *field_name;
1023 unsigned short dbitype;
1024 int32_t field_length = 0;
1027 /* correct the index for dbi interface
1028 * dbi index begins 1
1029 * I prefer do not change others functions
1031 Dmsg3(600, "my_dbi_getvalue pre-starting result '%p' row number '%d' column number '%d'\n",
1032 result, row_number, column_number);
1036 if(row_number == 0) {
1040 Dmsg3(600, "my_dbi_getvalue starting result '%p' row number '%d' column number '%d'\n",
1041 result, row_number, column_number);
1043 if(dbi_result_seek_row(result, row_number)) {
1045 field_name = dbi_result_get_field_name(result, column_number);
1046 field_length = dbi_result_get_field_length(result, field_name);
1047 dbitype = dbi_result_get_field_type_idx(result,column_number);
1050 //buf = check_pool_memory_size(buf, field_length + 1);
1051 buf = (char *)malloc(sizeof(char *) * field_length + 1);
1054 //buf = check_pool_memory_size(buf, 50);
1055 buf = (char *)malloc(sizeof(char *) * 50);
1058 Dmsg4(500, "my_dbi_getvalue result '%p' type '%d' \n\tfield name '%s'\n\t"
1059 "field_length '%d'\n",
1060 result, dbitype, field_name, field_length);
1063 case DBI_TYPE_INTEGER:
1064 num = dbi_result_get_longlong(result, field_name);
1065 edit_int64(num, buf);
1066 field_length = strlen(buf);
1068 case DBI_TYPE_STRING:
1070 field_length = bsnprintf(buf, field_length + 1, "%s",
1071 dbi_result_get_string(result, field_name));
1076 case DBI_TYPE_BINARY:
1077 /* dbi_result_get_binary return a NULL pointer if value is empty
1078 * following, change this to what Bacula espected
1081 field_length = bsnprintf(buf, field_length + 1, "%s",
1082 dbi_result_get_binary(result, field_name));
1087 case DBI_TYPE_DATETIME:
1091 last = dbi_result_get_datetime(result, field_name);
1094 field_length = bsnprintf(buf, 20, "0000-00-00 00:00:00");
1096 (void)localtime_r(&last, &tm);
1097 field_length = bsnprintf(buf, 20, "%04d-%02d-%02d %02d:%02d:%02d",
1098 (tm.tm_year + 1900), (tm.tm_mon + 1), tm.tm_mday,
1099 tm.tm_hour, tm.tm_min, tm.tm_sec);
1105 dbi_conn_error(dbi_result_get_conn(result), &errmsg);
1106 Dmsg1(500, "my_dbi_getvalue error: %s\n", errmsg);
1109 Dmsg3(500, "my_dbi_getvalue finish result '%p' num bytes '%d' data '%s'\n",
1110 result, field_length, buf);
1115 //int my_dbi_getvalue(dbi_result *result, int row_number, unsigned int column_number, char *value) {
1118 // const char *errmsg;
1120 // const char *field_name;
1121 // unsigned short dbitype;
1122 // int32_t field_length = 0;
1125 // /* correct the index for dbi interface
1126 // * dbi index begins 1
1127 // * I prefer do not change others functions
1129 // Dmsg3(600, "my_dbi_getvalue pre-starting result '%p' row number '%d' column number '%d'\n",
1130 // result, row_number, column_number);
1134 // if(row_number == 0) {
1138 // Dmsg3(600, "my_dbi_getvalue starting result '%p' row number '%d' column number '%d'\n",
1139 // result, row_number, column_number);
1141 // if(dbi_result_seek_row(result, row_number)) {
1143 // field_name = dbi_result_get_field_name(result, column_number);
1144 // field_length = dbi_result_get_field_length(result, field_name);
1145 // dbitype = dbi_result_get_field_type_idx(result,column_number);
1147 // Dmsg4(500, "my_dbi_getvalue result '%p' type '%d' \n\tfield name '%s'\n\t"
1148 // "field_length '%d'\n", result, dbitype, field_name, field_length);
1150 // switch (dbitype) {
1151 // case DBI_TYPE_INTEGER:
1152 // v = (int64_t *)malloc(sizeof(int64_t));
1153 // error = dbi_result_bind_longlong(result, field_name, (int64_t *)v);
1154 // // transform in string
1155 // num = *(int64_t *)v;
1156 // edit_int64(num, value);
1157 // field_length = strlen(value);
1159 // case DBI_TYPE_STRING:
1160 // if(field_length) {
1161 // dbi_result_bind_string(result, field_name, (const char **)v);
1162 // value = (char *) v;
1167 // case DBI_TYPE_BINARY:
1168 // if(field_length) {
1169 // dbi_result_bind_binary(result, field_name, (const unsigned char **)v);
1170 // value = (char *)v;
1175 // case DBI_TYPE_DATETIME:
1179 // v = (time_t *)dbi_result_get_datetime(result, field_name);
1180 // dbi_result_bind_datetime(result, field_name, (time_t *)v);
1182 // field_length = bsnprintf(value, 20, "0000-00-00 00:00:00");
1184 // (void)localtime_r((time_t *)v, &tm);
1185 // field_length = bsnprintf(value, 20, "%04d-%02d-%02d %02d:%02d:%02d",
1186 // (tm.tm_year + 1900), (tm.tm_mon + 1), tm.tm_mday,
1187 // tm.tm_hour, tm.tm_min, tm.tm_sec);
1193 // dbi_conn_error(dbi_result_get_conn(result), &errmsg);
1194 // Dmsg1(500, "my_dbi_getvalue error: %s\n", errmsg);
1197 // Dmsg2(500, "my_dbi_getvalue finish result '%p' num bytes '%d'\n",
1198 // result, field_length);
1203 int my_dbi_sql_insert_id(B_DB *mdb, char *table_name)
1206 Obtain the current value of the sequence that
1207 provides the serial value for primary key of the table.
1209 currval is local to our session. It is not affected by
1212 Determine the name of the sequence.
1213 PostgreSQL automatically creates a sequence using
1214 <table>_<column>_seq.
1215 At the time of writing, all tables used this format for
1216 for their primary key: <table>id
1217 Except for basefiles which has a primary key on baseid.
1218 Therefore, we need to special case that one table.
1220 everything else can use the PostgreSQL formula.
1226 if (mdb->db_type == SQL_TYPE_POSTGRESQL) {
1228 if (strcasecmp(table_name, "basefiles") == 0) {
1229 bstrncpy(sequence, "basefiles_baseid", sizeof(sequence));
1231 bstrncpy(sequence, table_name, sizeof(sequence));
1232 bstrncat(sequence, "_", sizeof(sequence));
1233 bstrncat(sequence, table_name, sizeof(sequence));
1234 bstrncat(sequence, "id", sizeof(sequence));
1237 bstrncat(sequence, "_seq", sizeof(sequence));
1238 id = dbi_conn_sequence_last(mdb->db, NT_(sequence));
1240 id = dbi_conn_sequence_last(mdb->db, NT_(table_name));
1246 #ifdef HAVE_BATCH_FILE_INSERT
1247 const char *my_dbi_batch_lock_path_query[3] = {
1249 "LOCK TABLES Path write, batch write, Path as p write",
1251 "BEGIN; LOCK TABLE Path IN SHARE ROW EXCLUSIVE MODE",
1255 const char *my_dbi_batch_lock_filename_query[3] = {
1257 "LOCK TABLES Filename write, batch write, Filename as f write",
1259 "BEGIN; LOCK TABLE Filename IN SHARE ROW EXCLUSIVE MODE",
1263 const char *my_dbi_batch_unlock_tables_query[3] = {
1271 const char *my_dbi_batch_fill_path_query[3] = {
1273 "INSERT INTO Path (Path) "
1274 "SELECT a.Path FROM "
1275 "(SELECT DISTINCT Path FROM batch) AS a WHERE NOT EXISTS "
1276 "(SELECT Path FROM Path AS p WHERE p.Path = a.Path)",
1278 "INSERT INTO Path (Path) "
1279 "SELECT a.Path FROM "
1280 "(SELECT DISTINCT Path FROM batch) AS a "
1281 "WHERE NOT EXISTS (SELECT Path FROM Path WHERE Path = a.Path) ",
1283 "INSERT INTO Path (Path)"
1284 " SELECT DISTINCT Path FROM batch"
1285 " EXCEPT SELECT Path FROM Path"};
1287 const char *my_dbi_batch_fill_filename_query[3] = {
1289 "INSERT INTO Filename (Name) "
1290 "SELECT a.Name FROM "
1291 "(SELECT DISTINCT Name FROM batch) AS a WHERE NOT EXISTS "
1292 "(SELECT Name FROM Filename AS f WHERE f.Name = a.Name)",
1294 "INSERT INTO Filename (Name) "
1295 "SELECT a.Name FROM "
1296 "(SELECT DISTINCT Name FROM batch) as a "
1298 "(SELECT Name FROM Filename WHERE Name = a.Name)",
1300 "INSERT INTO Filename (Name)"
1301 " SELECT DISTINCT Name FROM batch "
1302 " EXCEPT SELECT Name FROM Filename"};
1303 #endif /* HAVE_BATCH_FILE_INSERT */
1305 #endif /* HAVE_DBI */