2 Bacula® - The Network Backup Solution
4 Copyright (C) 2000-2014 Free Software Foundation Europe e.V.
6 The main author of Bacula is Kern Sibbald, with contributions from many
7 others, a complete list can be found in the file AUTHORS.
9 You may use this file and others of this release according to the
10 license defined in the LICENSE file, which includes the Affero General
11 Public License, v3.0 ("AGPLv3") and some additional permissions and
12 terms pursuant to its AGPLv3 Section 7.
14 Bacula® is a registered trademark of Kern Sibbald.
17 * Bacula Catalog Database interface routines
19 * Almost generic set of SQL database interface routines
20 * (with a little more work)
21 * SQL engine specific routines are in mysql.c, postgresql.c,
24 * Written by Kern Sibbald, March 2000
30 #if HAVE_SQLITE3 || HAVE_MYSQL || HAVE_POSTGRESQL
36 /* Forward referenced subroutines */
37 void print_dashes(B_DB *mdb);
38 void print_result(B_DB *mdb);
40 dbid_list::dbid_list()
42 memset(this, 0, sizeof(dbid_list));
44 DBId = (DBId_t *)malloc(max_ids * sizeof(DBId_t));
45 num_ids = num_seen = tot_ids = 0;
49 dbid_list::~dbid_list()
55 * Called here to retrieve an string list from the database
57 int db_string_list_handler(void *ctx, int num_fields, char **row)
59 alist **val = (alist **)ctx;
62 (*val)->append(bstrdup(row[0]));
69 * Called here to retrieve an integer from the database
71 int db_int_handler(void *ctx, int num_fields, char **row)
73 uint32_t *val = (uint32_t *)ctx;
75 Dmsg1(800, "int_handler starts with row pointing at %x\n", row);
78 Dmsg1(800, "int_handler finds '%s'\n", row[0]);
79 *val = str_to_int64(row[0]);
81 Dmsg0(800, "int_handler finds zero\n");
84 Dmsg0(800, "int_handler finishes\n");
89 * Called here to retrieve a 32/64 bit integer from the database.
90 * The returned integer will be extended to 64 bit.
92 int db_int64_handler(void *ctx, int num_fields, char **row)
94 db_int64_ctx *lctx = (db_int64_ctx *)ctx;
97 lctx->value = str_to_int64(row[0]);
104 * Called here to retrieve a btime from the database.
105 * The returned integer will be extended to 64 bit.
107 int db_strtime_handler(void *ctx, int num_fields, char **row)
109 db_int64_ctx *lctx = (db_int64_ctx *)ctx;
112 lctx->value = str_to_utime(row[0]);
119 * Use to build a comma separated list of values from a query. "10,20,30"
121 int db_list_handler(void *ctx, int num_fields, char **row)
123 db_list_ctx *lctx = (db_list_ctx *)ctx;
124 if (num_fields == 1 && row[0]) {
131 * specific context passed from db_check_max_connections to db_max_connections_handler.
133 struct max_connections_context {
135 uint32_t nr_connections;
139 * Called here to retrieve an integer from the database
141 static inline int db_max_connections_handler(void *ctx, int num_fields, char **row)
143 struct max_connections_context *context;
146 context = (struct max_connections_context *)ctx;
147 switch (db_get_type_index(context->db)) {
155 context->nr_connections = str_to_int64(row[index]);
157 Dmsg0(800, "int_handler finds zero\n");
158 context->nr_connections = 0;
164 * Check catalog max_connections setting
166 bool db_check_max_connections(JCR *jcr, B_DB *mdb, uint32_t max_concurrent_jobs)
168 struct max_connections_context context;
170 /* Without Batch insert, no need to verify max_connections */
171 if (!mdb->batch_insert_available())
175 context.nr_connections = 0;
177 /* Check max_connections setting */
178 if (!db_sql_query(mdb, sql_get_max_connections[db_get_type_index(mdb)],
179 db_max_connections_handler, &context)) {
180 Jmsg(jcr, M_ERROR, 0, "Can't verify max_connections settings %s", mdb->errmsg);
183 if (context.nr_connections && max_concurrent_jobs && max_concurrent_jobs > context.nr_connections) {
185 _("Potential performance problem:\n"
186 "max_connections=%d set for %s database \"%s\" should be larger than Director's "
187 "MaxConcurrentJobs=%d\n"),
188 context.nr_connections, db_get_type(mdb), mdb->get_db_name(), max_concurrent_jobs);
189 Jmsg(jcr, M_WARNING, 0, "%s", mdb->errmsg);
196 /* NOTE!!! The following routines expect that the
197 * calling subroutine sets and clears the mutex
200 /* Check that the tables correspond to the version we want */
201 bool check_tables_version(JCR *jcr, B_DB *mdb)
203 uint32_t bacula_db_version = 0;
204 const char *query = "SELECT VersionId FROM Version";
206 bacula_db_version = 0;
207 if (!db_sql_query(mdb, query, db_int_handler, (void *)&bacula_db_version)) {
208 Jmsg(jcr, M_FATAL, 0, "%s", mdb->errmsg);
211 if (bacula_db_version != BDB_VERSION) {
212 Mmsg(mdb->errmsg, "Version error for database \"%s\". Wanted %d, got %d\n",
213 mdb->get_db_name(), BDB_VERSION, bacula_db_version);
214 Jmsg(jcr, M_FATAL, 0, "%s", mdb->errmsg);
221 * Utility routine for queries. The database MUST be locked before calling here.
222 * Returns: 0 on failure
226 QueryDB(const char *file, int line, JCR *jcr, B_DB *mdb, char *cmd)
228 sql_free_result(mdb);
229 if (!sql_query(mdb, cmd, QF_STORE_RESULT)) {
230 m_msg(file, line, &mdb->errmsg, _("query %s failed:\n%s\n"), cmd, sql_strerror(mdb));
231 j_msg(file, line, jcr, M_FATAL, 0, "%s", mdb->errmsg);
233 j_msg(file, line, jcr, M_INFO, 0, "%s\n", cmd);
242 * Utility routine to do inserts
243 * Returns: 0 on failure
247 InsertDB(const char *file, int line, JCR *jcr, B_DB *mdb, char *cmd)
251 if (!sql_query(mdb, cmd)) {
252 m_msg(file, line, &mdb->errmsg, _("insert %s failed:\n%s\n"), cmd, sql_strerror(mdb));
253 j_msg(file, line, jcr, M_FATAL, 0, "%s", mdb->errmsg);
255 j_msg(file, line, jcr, M_INFO, 0, "%s\n", cmd);
259 num_rows = sql_affected_rows(mdb);
262 m_msg(file, line, &mdb->errmsg, _("Insertion problem: affected_rows=%s\n"),
263 edit_uint64(num_rows, ed1));
265 j_msg(file, line, jcr, M_INFO, 0, "%s\n", cmd);
273 /* Utility routine for updates.
274 * Returns: 0 on failure
278 UpdateDB(const char *file, int line, JCR *jcr, B_DB *mdb, char *cmd)
282 if (!sql_query(mdb, cmd)) {
283 m_msg(file, line, &mdb->errmsg, _("update %s failed:\n%s\n"), cmd, sql_strerror(mdb));
284 j_msg(file, line, jcr, M_ERROR, 0, "%s", mdb->errmsg);
286 j_msg(file, line, jcr, M_INFO, 0, "%s\n", cmd);
290 num_rows = sql_affected_rows(mdb);
293 m_msg(file, line, &mdb->errmsg, _("Update failed: affected_rows=%s for %s\n"),
294 edit_uint64(num_rows, ed1), cmd);
296 // j_msg(file, line, jcr, M_INFO, 0, "%s\n", cmd);
305 * Utility routine for deletes
307 * Returns: -1 on error
308 * n number of rows affected
311 DeleteDB(const char *file, int line, JCR *jcr, B_DB *mdb, char *cmd)
314 if (!sql_query(mdb, cmd)) {
315 m_msg(file, line, &mdb->errmsg, _("delete %s failed:\n%s\n"), cmd, sql_strerror(mdb));
316 j_msg(file, line, jcr, M_ERROR, 0, "%s", mdb->errmsg);
318 j_msg(file, line, jcr, M_INFO, 0, "%s\n", cmd);
323 return sql_affected_rows(mdb);
328 * Get record max. Query is already in mdb->cmd
331 * Returns: -1 on failure
334 int get_sql_record_max(JCR *jcr, B_DB *mdb)
339 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
340 if ((row = sql_fetch_row(mdb)) == NULL) {
341 Mmsg1(&mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb));
344 stat = str_to_int64(row[0]);
346 sql_free_result(mdb);
348 Mmsg1(&mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb));
355 * Return pre-edited error message
357 char *db_strerror(B_DB *mdb)
363 * Given a full filename, split it into its path
364 * and filename parts. They are returned in pool memory
365 * in the mdb structure.
367 void split_path_and_file(JCR *jcr, B_DB *mdb, const char *fname)
371 /* Find path without the filename.
372 * I.e. everything after the last / is a "filename".
373 * OK, maybe it is a directory name, but we treat it like
374 * a filename. If we don't find a / then the whole name
375 * must be a path name (e.g. c:).
377 for (p=f=fname; *p; p++) {
378 if (IsPathSeparator(*p)) {
379 f = p; /* set pos of last slash */
382 if (IsPathSeparator(*f)) { /* did we find a slash? */
383 f++; /* yes, point to filename */
384 } else { /* no, whole thing must be path name */
388 /* If filename doesn't exist (i.e. root directory), we
389 * simply create a blank name consisting of a single
390 * space. This makes handling zero length filenames
395 mdb->fname = check_pool_memory_size(mdb->fname, mdb->fnl+1);
396 memcpy(mdb->fname, f, mdb->fnl); /* copy filename */
397 mdb->fname[mdb->fnl] = 0;
403 mdb->pnl = f - fname;
405 mdb->path = check_pool_memory_size(mdb->path, mdb->pnl+1);
406 memcpy(mdb->path, fname, mdb->pnl);
407 mdb->path[mdb->pnl] = 0;
409 Mmsg1(&mdb->errmsg, _("Path length is zero. File=%s\n"), fname);
410 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
415 Dmsg2(500, "split path=%s file=%s\n", mdb->path, mdb->fname);
419 * Set maximum field length to something reasonable
421 static int max_length(int max_length)
423 int max_len = max_length;
427 } else if (max_len > 100) {
434 * List dashes as part of header for listing SQL results in a table
436 void list_dashes(B_DB *mdb, DB_LIST_HANDLER *send, void *ctx)
443 sql_field_seek(mdb, 0);
445 num_fields = sql_num_fields(mdb);
446 for (i = 0; i < num_fields; i++) {
447 field = sql_fetch_field(mdb);
451 len = max_length(field->max_length + 2);
452 for (j = 0; j < len; j++) {
460 /* Small handler to print the last line of a list xxx command */
461 static void last_line_handler(void *vctx, const char *str)
463 LIST_CTX *ctx = (LIST_CTX *)vctx;
464 bstrncat(ctx->line, str, sizeof(ctx->line));
467 int list_result(void *vctx, int nb_col, char **row)
470 int i, col_len, max_len = 0;
472 char buf[2000], ewc[30];
474 LIST_CTX *pctx = (LIST_CTX *)vctx;
475 DB_LIST_HANDLER *send = pctx->send;
476 e_list_type type = pctx->type;
477 B_DB *mdb = pctx->mdb;
478 void *ctx = pctx->ctx;
479 JCR *jcr = pctx->jcr;
481 num_fields = sql_num_fields(mdb);
485 Dmsg1(800, "list_result starts looking at %d fields\n", num_fields);
486 /* determine column display widths */
487 sql_field_seek(mdb, 0);
488 for (i = 0; i < num_fields; i++) {
489 Dmsg1(800, "list_result processing field %d\n", i);
490 field = sql_fetch_field(mdb);
494 col_len = cstrlen(field->name);
495 if (type == VERT_LIST) {
496 if (col_len > max_len) {
500 if (sql_field_is_numeric(mdb, field->type) && (int)field->max_length > 0) { /* fixup for commas */
501 field->max_length += (field->max_length - 1) / 3;
503 if (col_len < (int)field->max_length) {
504 col_len = field->max_length;
506 if (col_len < 4 && !sql_field_is_not_null(mdb, field->flags)) {
507 col_len = 4; /* 4 = length of the word "NULL" */
509 field->max_length = col_len; /* reset column info */
515 Dmsg0(800, "list_result finished first loop\n");
516 if (type == VERT_LIST) {
520 Dmsg1(800, "list_result starts second loop looking at %d fields\n", num_fields);
522 /* Keep the result to display the same line at the end of the table */
523 list_dashes(mdb, last_line_handler, pctx);
524 send(ctx, pctx->line);
527 sql_field_seek(mdb, 0);
528 for (i = 0; i < num_fields; i++) {
529 Dmsg1(800, "list_result looking at field %d\n", i);
530 field = sql_fetch_field(mdb);
534 max_len = max_length(field->max_length);
535 bsnprintf(buf, sizeof(buf), " %-*s |", max_len, field->name);
539 list_dashes(mdb, send, ctx);
542 Dmsg1(800, "list_result starts third loop looking at %d fields\n", num_fields);
544 sql_field_seek(mdb, 0);
546 for (i = 0; i < num_fields; i++) {
547 field = sql_fetch_field(mdb);
551 max_len = max_length(field->max_length);
552 if (row[i] == NULL) {
553 bsnprintf(buf, sizeof(buf), " %-*s |", max_len, "NULL");
554 } else if (sql_field_is_numeric(mdb, field->type) && !jcr->gui && is_an_integer(row[i])) {
555 bsnprintf(buf, sizeof(buf), " %*s |", max_len,
556 add_commas(row[i], ewc));
558 bsnprintf(buf, sizeof(buf), " %-*s |", max_len, row[i]);
567 Dmsg1(800, "list_result starts vertical list at %d fields\n", num_fields);
569 sql_field_seek(mdb, 0);
570 for (i = 0; i < num_fields; i++) {
571 field = sql_fetch_field(mdb);
575 if (row[i] == NULL) {
576 bsnprintf(buf, sizeof(buf), " %*s: %s\n", max_len, field->name, "NULL");
577 } else if (sql_field_is_numeric(mdb, field->type) && !jcr->gui && is_an_integer(row[i])) {
578 bsnprintf(buf, sizeof(buf), " %*s: %s\n", max_len, field->name,
579 add_commas(row[i], ewc));
581 bsnprintf(buf, sizeof(buf), " %*s: %s\n", max_len, field->name, row[i]);
590 * If full_list is set, we list vertically, otherwise, we
591 * list on one line horizontally.
592 * Return number of rows
594 int list_result(JCR *jcr, B_DB *mdb, DB_LIST_HANDLER *send, void *ctx, e_list_type type)
598 int i, col_len, max_len = 0;
600 char buf[2000], ewc[30];
602 Dmsg0(800, "list_result starts\n");
603 if (sql_num_rows(mdb) == 0) {
604 send(ctx, _("No results to list.\n"));
605 return sql_num_rows(mdb);
608 num_fields = sql_num_fields(mdb);
609 Dmsg1(800, "list_result starts looking at %d fields\n", num_fields);
610 /* determine column display widths */
611 sql_field_seek(mdb, 0);
612 for (i = 0; i < num_fields; i++) {
613 Dmsg1(800, "list_result processing field %d\n", i);
614 field = sql_fetch_field(mdb);
618 col_len = cstrlen(field->name);
619 if (type == VERT_LIST) {
620 if (col_len > max_len) {
624 if (sql_field_is_numeric(mdb, field->type) && (int)field->max_length > 0) { /* fixup for commas */
625 field->max_length += (field->max_length - 1) / 3;
627 if (col_len < (int)field->max_length) {
628 col_len = field->max_length;
630 if (col_len < 4 && !sql_field_is_not_null(mdb, field->flags)) {
631 col_len = 4; /* 4 = length of the word "NULL" */
633 field->max_length = col_len; /* reset column info */
637 Dmsg0(800, "list_result finished first loop\n");
638 if (type == VERT_LIST) {
642 Dmsg1(800, "list_result starts second loop looking at %d fields\n", num_fields);
643 list_dashes(mdb, send, ctx);
645 sql_field_seek(mdb, 0);
646 for (i = 0; i < num_fields; i++) {
647 Dmsg1(800, "list_result looking at field %d\n", i);
648 field = sql_fetch_field(mdb);
652 max_len = max_length(field->max_length);
653 bsnprintf(buf, sizeof(buf), " %-*s |", max_len, field->name);
657 list_dashes(mdb, send, ctx);
659 Dmsg1(800, "list_result starts third loop looking at %d fields\n", num_fields);
660 while ((row = sql_fetch_row(mdb)) != NULL) {
661 sql_field_seek(mdb, 0);
663 for (i = 0; i < num_fields; i++) {
664 field = sql_fetch_field(mdb);
668 max_len = max_length(field->max_length);
669 if (row[i] == NULL) {
670 bsnprintf(buf, sizeof(buf), " %-*s |", max_len, "NULL");
671 } else if (sql_field_is_numeric(mdb, field->type) && !jcr->gui && is_an_integer(row[i])) {
672 bsnprintf(buf, sizeof(buf), " %*s |", max_len,
673 add_commas(row[i], ewc));
675 bsnprintf(buf, sizeof(buf), " %-*s |", max_len, row[i]);
681 list_dashes(mdb, send, ctx);
682 return sql_num_rows(mdb);
686 Dmsg1(800, "list_result starts vertical list at %d fields\n", num_fields);
687 while ((row = sql_fetch_row(mdb)) != NULL) {
688 sql_field_seek(mdb, 0);
689 for (i = 0; i < num_fields; i++) {
690 field = sql_fetch_field(mdb);
694 if (row[i] == NULL) {
695 bsnprintf(buf, sizeof(buf), " %*s: %s\n", max_len, field->name, "NULL");
696 } else if (sql_field_is_numeric(mdb, field->type) && !jcr->gui && is_an_integer(row[i])) {
697 bsnprintf(buf, sizeof(buf), " %*s: %s\n", max_len, field->name,
698 add_commas(row[i], ewc));
700 bsnprintf(buf, sizeof(buf), " %*s: %s\n", max_len, field->name, row[i]);
706 return sql_num_rows(mdb);
710 * Open a new connexion to mdb catalog. This function is used
711 * by batch and accurate mode.
713 bool db_open_batch_connexion(JCR *jcr, B_DB *mdb)
717 multi_db = mdb->batch_insert_available();
719 if (!jcr->db_batch) {
720 jcr->db_batch = db_clone_database_connection(mdb, jcr, multi_db);
721 if (!jcr->db_batch) {
722 Mmsg0(&mdb->errmsg, _("Could not init database batch connection\n"));
723 Jmsg(jcr, M_FATAL, 0, "%s", mdb->errmsg);
727 if (!db_open_database(jcr, jcr->db_batch)) {
728 Mmsg2(&mdb->errmsg, _("Could not open database \"%s\": ERR=%s\n"),
729 jcr->db_batch->get_db_name(), db_strerror(jcr->db_batch));
730 Jmsg(jcr, M_FATAL, 0, "%s", mdb->errmsg);
738 * !!! WARNING !!! Use this function only when bacula is stopped.
739 * ie, after a fatal signal and before exiting the program
740 * Print information about a B_DB object.
742 void db_debug_print(JCR *jcr, FILE *fp)
750 fprintf(fp, "B_DB=%p db_name=%s db_user=%s connected=%s\n",
751 mdb, NPRTB(mdb->get_db_name()), NPRTB(mdb->get_db_user()), mdb->is_connected() ? "true" : "false");
752 fprintf(fp, "\tcmd=\"%s\" changes=%i\n", NPRTB(mdb->cmd), mdb->changes);
753 mdb->print_lock_info(fp);
756 #endif /* HAVE_SQLITE3 || HAVE_MYSQL || HAVE_POSTGRESQL */