1 /*
2 Bacula(R) - The Network Backup Solution
3
4 Copyright (C) 2000-2020 Kern Sibbald
5
6 The original author of Bacula is Kern Sibbald, with contributions
7 from many others, a complete list can be found in the file AUTHORS.
8
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.
13
14 This notice must be preserved when any source code is
15 conveyed and/or propagated.
16
17 Bacula(R) is a registered trademark of Kern Sibbald.
18 */
19 /*
20 * Bacula Catalog Database routines specific to SQLite
21 *
22 * Written by Kern Sibbald, January 2002
23 *
24 * Note: at one point, this file was changed to class based by a certain
25 * programmer, and other than "wrapping" in a class, which is a trivial
26 * change for a C++ programmer, nothing substantial was done, yet all the
27 * code was recommitted under this programmer's name. Consequently, we
28 * undo those changes here.
29 */
30
31 #include "bacula.h"
32
33 #if HAVE_SQLITE3
34
35 #include "cats.h"
36 #include <sqlite3.h>
37 #define __BDB_SQLITE_H_ 1
38 #include "bdb_sqlite.h"
39
40 /* -----------------------------------------------------------------------
41 *
42 * SQLite dependent defines and subroutines
43 *
44 * -----------------------------------------------------------------------
45 */
46
47 /* List of open databases */
48 static dlist *db_list = NULL;
49
50 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
51
52 /*
53 * When using mult_db_connections
54 * sqlite can be BUSY. We just need sleep a little in this case.
55 */
my_sqlite_busy_handler(void * arg,int calls)56 static int my_sqlite_busy_handler(void *arg, int calls)
57 {
58 bmicrosleep(0, 500);
59 return 1;
60 }
61
BDB_SQLITE()62 BDB_SQLITE::BDB_SQLITE()
63 {
64 BDB_SQLITE *mdb = this;
65
66 if (db_list == NULL) {
67 db_list = New(dlist(mdb, &mdb->m_link));
68 }
69 mdb->m_db_driver_type = SQL_DRIVER_TYPE_SQLITE3;
70 mdb->m_db_type = SQL_TYPE_SQLITE3;
71 mdb->m_db_driver = bstrdup("SQLite3");
72
73 mdb->errmsg = get_pool_memory(PM_EMSG); /* get error message buffer */
74 mdb->errmsg[0] = 0;
75 mdb->cmd = get_pool_memory(PM_EMSG); /* get command buffer */
76 mdb->cached_path = get_pool_memory(PM_FNAME);
77 mdb->cached_path_id = 0;
78 mdb->m_ref_count = 1;
79 mdb->fname = get_pool_memory(PM_FNAME);
80 mdb->path = get_pool_memory(PM_FNAME);
81 mdb->esc_name = get_pool_memory(PM_FNAME);
82 mdb->esc_path = get_pool_memory(PM_FNAME);
83 mdb->esc_obj = get_pool_memory(PM_FNAME);
84 mdb->m_use_fatal_jmsg = true;
85
86 /* Initialize the private members. */
87 mdb->m_db_handle = NULL;
88 mdb->m_result = NULL;
89 mdb->m_sqlite_errmsg = NULL;
90
91 db_list->append(this);
92 }
93
~BDB_SQLITE()94 BDB_SQLITE::~BDB_SQLITE()
95 {
96 }
97
98 /*
99 * Initialize database data structure. In principal this should
100 * never have errors, or it is really fatal.
101 */
db_init_database(JCR * jcr,const char * db_driver,const char * db_name,const char * db_user,const char * db_password,const char * db_address,int db_port,const char * db_socket,const char * db_ssl_mode,const char * db_ssl_key,const char * db_ssl_cert,const char * db_ssl_ca,const char * db_ssl_capath,const char * db_ssl_cipher,bool mult_db_connections,bool disable_batch_insert)102 BDB *db_init_database(JCR *jcr, const char *db_driver, const char *db_name, const char *db_user,
103 const char *db_password, const char *db_address, int db_port, const char *db_socket,
104 const char *db_ssl_mode, const char *db_ssl_key,
105 const char *db_ssl_cert, const char *db_ssl_ca,
106 const char *db_ssl_capath, const char *db_ssl_cipher,
107 bool mult_db_connections, bool disable_batch_insert)
108 {
109 BDB_SQLITE *mdb = NULL;
110
111 P(mutex); /* lock DB queue */
112 /*
113 * Look to see if DB already open
114 */
115 if (db_list && !mult_db_connections) {
116 foreach_dlist(mdb, db_list) {
117 if (mdb->bdb_match_database(db_driver, db_name, db_address, db_port)) {
118 Dmsg1(300, "DB REopen %s\n", db_name);
119 mdb->increment_refcount();
120 goto bail_out;
121 }
122 }
123 }
124 Dmsg0(300, "db_init_database first time\n");
125 mdb = New(BDB_SQLITE());
126
127 mdb->m_db_name = bstrdup(db_name);
128 if (disable_batch_insert) {
129 mdb->m_disabled_batch_insert = true;
130 mdb->m_have_batch_insert = false;
131 } else {
132 mdb->m_disabled_batch_insert = false;
133 #ifdef USE_BATCH_FILE_INSERT
134 #ifdef HAVE_SQLITE3_THREADSAFE
135 mdb->m_have_batch_insert = sqlite3_threadsafe();
136 #else
137 mdb->m_have_batch_insert = false;
138 #endif /* HAVE_SQLITE3_THREADSAFE */
139 #else
140 mdb->m_have_batch_insert = false;
141 #endif /* USE_BATCH_FILE_INSERT */
142 }
143 mdb->m_allow_transactions = mult_db_connections;
144
145 /* At this time, when mult_db_connections == true, this is for
146 * specific console command such as bvfs or batch mode, and we don't
147 * want to share a batch mode or bvfs. In the future, we can change
148 * the creation function to add this parameter.
149 */
150 mdb->m_dedicated = mult_db_connections;
151
152 bail_out:
153 V(mutex);
154 return mdb;
155 }
156
157
158 /*
159 * Now actually open the database. This can generate errors,
160 * which are returned in the errmsg
161 *
162 * DO NOT close the database or delete mdb here !!!!
163 */
bdb_open_database(JCR * jcr)164 bool BDB_SQLITE::bdb_open_database(JCR *jcr)
165 {
166 bool retval = false;
167 char *db_file;
168 int len;
169 struct stat statbuf;
170 int ret;
171 int errstat;
172 int retry = 0;
173 BDB_SQLITE *mdb = this;
174
175 P(mutex);
176 if (mdb->m_connected) {
177 retval = true;
178 goto bail_out;
179 }
180
181 if ((errstat=rwl_init(&mdb->m_lock)) != 0) {
182 berrno be;
183 Mmsg1(&mdb->errmsg, _("Unable to initialize DB lock. ERR=%s\n"),
184 be.bstrerror(errstat));
185 goto bail_out;
186 }
187
188 /*
189 * Open the database
190 */
191 len = strlen(working_directory) + strlen(mdb->m_db_name) + 5;
192 db_file = (char *)malloc(len);
193 strcpy(db_file, working_directory);
194 strcat(db_file, "/");
195 strcat(db_file, m_db_name);
196 strcat(db_file, ".db");
197 if (stat(db_file, &statbuf) != 0) {
198 Mmsg1(&mdb->errmsg, _("Database %s does not exist, please create it.\n"),
199 db_file);
200 free(db_file);
201 goto bail_out;
202 }
203
204 for (mdb->m_db_handle = NULL; !mdb->m_db_handle && retry++ < 10; ) {
205 ret = sqlite3_open(db_file, &mdb->m_db_handle);
206 if (ret != SQLITE_OK) {
207 mdb->m_sqlite_errmsg = (char *)sqlite3_errmsg(mdb->m_db_handle);
208 sqlite3_close(mdb->m_db_handle);
209 mdb->m_db_handle = NULL;
210 } else {
211 mdb->m_sqlite_errmsg = NULL;
212 }
213
214 Dmsg0(300, "sqlite_open\n");
215 if (!mdb->m_db_handle) {
216 bmicrosleep(1, 0);
217 }
218 }
219 if (mdb->m_db_handle == NULL) {
220 Mmsg2(&mdb->errmsg, _("Unable to open Database=%s. ERR=%s\n"),
221 db_file, mdb->m_sqlite_errmsg ? mdb->m_sqlite_errmsg : _("unknown"));
222 free(db_file);
223 goto bail_out;
224 }
225 mdb->m_connected = true;
226 free(db_file);
227
228 /*
229 * Set busy handler to wait when we use mult_db_connections = true
230 */
231 sqlite3_busy_handler(mdb->m_db_handle, my_sqlite_busy_handler, NULL);
232
233 #if defined(SQLITE3_INIT_QUERY)
234 sql_query(SQLITE3_INIT_QUERY);
235 #endif
236
237 if (!bdb_check_version(jcr)) {
238 goto bail_out;
239 }
240
241 retval = true;
242
243 bail_out:
244 V(mutex);
245 return retval;
246 }
247
bdb_close_database(JCR * jcr)248 void BDB_SQLITE::bdb_close_database(JCR *jcr)
249 {
250 BDB_SQLITE *mdb = this;
251
252 if (mdb->m_connected) {
253 bdb_end_transaction(jcr);
254 }
255 P(mutex);
256 mdb->m_ref_count--;
257 if (mdb->m_ref_count == 0) {
258 if (mdb->m_connected) {
259 sql_free_result();
260 }
261 db_list->remove(mdb);
262 if (mdb->m_connected && mdb->m_db_handle) {
263 sqlite3_close(mdb->m_db_handle);
264 }
265 if (is_rwl_valid(&mdb->m_lock)) {
266 rwl_destroy(&mdb->m_lock);
267 }
268 free_pool_memory(mdb->errmsg);
269 free_pool_memory(mdb->cmd);
270 free_pool_memory(mdb->cached_path);
271 free_pool_memory(mdb->fname);
272 free_pool_memory(mdb->path);
273 free_pool_memory(mdb->esc_name);
274 free_pool_memory(mdb->esc_path);
275 free_pool_memory(mdb->esc_obj);
276 if (mdb->m_db_driver) {
277 free(mdb->m_db_driver);
278 }
279 if (mdb->m_db_name) {
280 free(mdb->m_db_name);
281 }
282 delete this;
283 if (db_list->size() == 0) {
284 delete db_list;
285 db_list = NULL;
286 }
287 }
288 V(mutex);
289 }
290
bdb_thread_cleanup(void)291 void BDB_SQLITE::bdb_thread_cleanup(void)
292 {
293 sqlite3_thread_cleanup();
294 }
295
296 /*
297 * Escape strings so SQLite is happy
298 *
299 * len is the length of the old string. Your new
300 * string must be long enough (max 2*old+1) to hold
301 * the escaped output.
302 */
bdb_escape_string(JCR * jcr,char * snew,char * sold,int len)303 void BDB_SQLITE::bdb_escape_string(JCR *jcr, char *snew, char *sold, int len)
304 {
305 char *n, *o;
306
307 n = snew;
308 o = sold;
309 while (len--) {
310 switch (*o) {
311 case '\'':
312 *n++ = '\'';
313 *n++ = '\'';
314 o++;
315 break;
316 case 0:
317 *n++ = '\\';
318 *n++ = 0;
319 o++;
320 break;
321 default:
322 *n++ = *o++;
323 break;
324 }
325 }
326 *n = 0;
327 }
328
329 /*
330 * Escape binary object so that SQLite is happy
331 * Memory is stored in BDB struct, no need to free it
332 *
333 * TODO: this should be implemented (escape \0)
334 */
bdb_escape_object(JCR * jcr,char * old,int len)335 char *BDB_SQLITE::bdb_escape_object(JCR *jcr, char *old, int len)
336 {
337 int l;
338 int max = len*2; /* TODO: too big, should be *4/3 */
339
340 esc_obj = check_pool_memory_size(esc_obj, max);
341 l = bin_to_base64(esc_obj, max, old, len, true);
342 esc_obj[l] = 0;
343 ASSERT(l < max); /* TODO: add check for l */
344
345 return esc_obj;
346 }
347
348 /*
349 * Unescape binary object so that SQLIte is happy
350 *
351 * TODO: need to be implemented (escape \0)
352 */
353
bdb_unescape_object(JCR * jcr,char * from,int32_t expected_len,POOLMEM ** dest,int32_t * dest_len)354 void BDB_SQLITE::bdb_unescape_object(JCR *jcr, char *from, int32_t expected_len,
355 POOLMEM **dest, int32_t *dest_len)
356 {
357 if (!from) {
358 *dest[0] = 0;
359 *dest_len = 0;
360 return;
361 }
362 *dest = check_pool_memory_size(*dest, expected_len+1);
363 base64_to_bin(*dest, expected_len+1, from, strlen(from));
364 *dest_len = expected_len;
365 (*dest)[expected_len] = 0;
366 }
367
368 /*
369 * Start a transaction. This groups inserts and makes things
370 * more efficient. Usually started when inserting file attributes.
371 */
bdb_start_transaction(JCR * jcr)372 void BDB_SQLITE::bdb_start_transaction(JCR *jcr)
373 {
374 BDB_SQLITE *mdb = this;
375
376 if (!jcr->attr) {
377 jcr->attr = get_pool_memory(PM_FNAME);
378 }
379 if (!jcr->ar) {
380 jcr->ar = (ATTR_DBR *)malloc(sizeof(ATTR_DBR));
381 memset(jcr->ar, 0, sizeof(ATTR_DBR));
382 }
383
384 if (!mdb->m_allow_transactions) {
385 return;
386 }
387
388 bdb_lock();
389 /*
390 * Allow only 10,000 changes per transaction
391 */
392 if (mdb->m_transaction && mdb->changes > 10000) {
393 bdb_end_transaction(jcr);
394 }
395 if (!mdb->m_transaction) {
396 sql_query("BEGIN"); /* begin transaction */
397 Dmsg0(400, "Start SQLite transaction\n");
398 mdb->m_transaction = true;
399 }
400 bdb_unlock();
401 }
402
bdb_end_transaction(JCR * jcr)403 void BDB_SQLITE::bdb_end_transaction(JCR *jcr)
404 {
405 BDB_SQLITE *mdb = this;
406 if (!mdb->m_allow_transactions) {
407 return;
408 }
409
410 bdb_lock();
411 if (mdb->m_transaction) {
412 sql_query("COMMIT"); /* end transaction */
413 mdb->m_transaction = false;
414 Dmsg1(400, "End SQLite transaction changes=%d\n", changes);
415 }
416 mdb->changes = 0;
417 bdb_unlock();
418 }
419
420 struct rh_data {
421 BDB_SQLITE *mdb;
422 DB_RESULT_HANDLER *result_handler;
423 void *ctx;
424 bool initialized;
425 };
426
427 /*
428 * Convert SQLite's callback into Bacula DB callback
429 */
sqlite_result_handler(void * arh_data,int num_fields,char ** rows,char ** col_names)430 static int sqlite_result_handler(void *arh_data, int num_fields, char **rows, char **col_names)
431 {
432 struct rh_data *rh_data = (struct rh_data *)arh_data;
433
434 /* The db_sql_query doesn't have access to m_results, so if we wan't to get
435 * fields information, we need to use col_names
436 */
437 if (!rh_data->initialized) {
438 rh_data->mdb->set_column_names(col_names, num_fields);
439 rh_data->initialized = true;
440 }
441 if (rh_data->result_handler) {
442 (*(rh_data->result_handler))(rh_data->ctx, num_fields, rows);
443 }
444
445 return 0;
446 }
447
448 /*
449 * Submit a general SQL command (cmd), and for each row returned,
450 * the result_handler is called with the ctx.
451 */
bdb_sql_query(const char * query,DB_RESULT_HANDLER * result_handler,void * ctx)452 bool BDB_SQLITE::bdb_sql_query(const char *query, DB_RESULT_HANDLER *result_handler, void *ctx)
453 {
454 BDB_SQLITE *mdb = this;
455 bool retval = false;
456 int stat;
457 struct rh_data rh_data;
458
459 Dmsg1(500, "db_sql_query starts with '%s'\n", query);
460
461 bdb_lock();
462 mdb->errmsg[0] = 0;
463 if (mdb->m_sqlite_errmsg) {
464 sqlite3_free(mdb->m_sqlite_errmsg);
465 mdb->m_sqlite_errmsg = NULL;
466 }
467 sql_free_result();
468
469 rh_data.ctx = ctx;
470 rh_data.mdb = this;
471 rh_data.initialized = false;
472 rh_data.result_handler = result_handler;
473
474 stat = sqlite3_exec(m_db_handle, query, sqlite_result_handler,
475 (void *)&rh_data, &m_sqlite_errmsg);
476
477 if (stat != SQLITE_OK) {
478 Mmsg(mdb->errmsg, _("Query failed: %s: ERR=%s\n"), query, sql_strerror());
479 Dmsg0(500, "db_sql_query finished\n");
480 goto bail_out;
481 }
482 Dmsg0(500, "db_sql_query finished\n");
483 sql_free_result();
484 retval = true;
485
486 bail_out:
487 bdb_unlock();
488 return retval;
489 }
490
491 /*
492 * Submit a sqlite query and retrieve all the data
493 */
sql_query(const char * query,int flags)494 bool BDB_SQLITE::sql_query(const char *query, int flags)
495 {
496 int stat;
497 bool retval = false;
498 BDB_SQLITE *mdb = this;
499
500 Dmsg1(500, "sql_query starts with '%s'\n", query);
501
502 sql_free_result();
503 if (mdb->m_sqlite_errmsg) {
504 sqlite3_free(mdb->m_sqlite_errmsg);
505 mdb->m_sqlite_errmsg = NULL;
506 }
507
508 stat = sqlite3_get_table(m_db_handle, (char *)query, &m_result,
509 &m_num_rows, &m_num_fields, &m_sqlite_errmsg);
510
511 mdb->m_row_number = 0; /* no row fetched */
512 if (stat != 0) { /* something went wrong */
513 mdb->m_num_rows = mdb->m_num_fields = 0;
514 Dmsg0(500, "sql_query finished\n");
515 } else {
516 Dmsg0(500, "sql_query finished\n");
517 retval = true;
518 }
519 return retval;
520 }
521
sql_free_result(void)522 void BDB_SQLITE::sql_free_result(void)
523 {
524 BDB_SQLITE *mdb = this;
525
526 bdb_lock();
527 if (mdb->m_fields) {
528 free(mdb->m_fields);
529 mdb->m_fields = NULL;
530 }
531 if (mdb->m_result) {
532 sqlite3_free_table(mdb->m_result);
533 mdb->m_result = NULL;
534 }
535 mdb->m_col_names = NULL;
536 mdb->m_num_rows = mdb->m_num_fields = 0;
537 bdb_unlock();
538 }
539
540 /*
541 * Fetch one row at a time
542 */
sql_fetch_row(void)543 SQL_ROW BDB_SQLITE::sql_fetch_row(void)
544 {
545 BDB_SQLITE *mdb = this;
546 if (!mdb->m_result || (mdb->m_row_number >= mdb->m_num_rows)) {
547 return NULL;
548 }
549 mdb->m_row_number++;
550 return &mdb->m_result[mdb->m_num_fields * mdb->m_row_number];
551 }
552
sql_strerror(void)553 const char *BDB_SQLITE::sql_strerror(void)
554 {
555 BDB_SQLITE *mdb = this;
556 return mdb->m_sqlite_errmsg ? mdb->m_sqlite_errmsg : "unknown";
557 }
558
sql_data_seek(int row)559 void BDB_SQLITE::sql_data_seek(int row)
560 {
561 BDB_SQLITE *mdb = this;
562 /* Set the row number to be returned on the next call to sql_fetch_row */
563 mdb->m_row_number = row;
564 }
565
sql_affected_rows(void)566 int BDB_SQLITE::sql_affected_rows(void)
567 {
568 BDB_SQLITE *mdb = this;
569 return sqlite3_changes(mdb->m_db_handle);
570 }
571
sql_insert_autokey_record(const char * query,const char * table_name)572 uint64_t BDB_SQLITE::sql_insert_autokey_record(const char *query, const char *table_name)
573 {
574 BDB_SQLITE *mdb = this;
575 /* First execute the insert query and then retrieve the currval. */
576 if (!sql_query(query)) {
577 return 0;
578 }
579
580 mdb->m_num_rows = sql_affected_rows();
581 if (mdb->m_num_rows != 1) {
582 return 0;
583 }
584
585 mdb->changes++;
586
587 return sqlite3_last_insert_rowid(mdb->m_db_handle);
588 }
589
sql_fetch_field(void)590 SQL_FIELD *BDB_SQLITE::sql_fetch_field(void)
591 {
592 BDB_SQLITE *mdb = this;
593 int i, j, len;
594
595 /* We are in the middle of a db_sql_query and we want to get fields info */
596 if (mdb->m_col_names != NULL) {
597 if (mdb->m_num_fields > mdb->m_field_number) {
598 mdb->m_sql_field.name = mdb->m_col_names[mdb->m_field_number];
599 /* We don't have the maximum field length, so we can use 80 as
600 * estimation.
601 */
602 len = MAX(cstrlen(mdb->m_sql_field.name), 80/mdb->m_num_fields);
603 mdb->m_sql_field.max_length = len;
604
605 mdb->m_field_number++;
606 mdb->m_sql_field.type = 0; /* not numeric */
607 mdb->m_sql_field.flags = 1; /* not null */
608 return &mdb->m_sql_field;
609 } else { /* too much fetch_field() */
610 return NULL;
611 }
612 }
613
614 /* We are after a sql_query() that stores the result in m_results */
615 if (!mdb->m_fields || mdb->m_fields_size < mdb->m_num_fields) {
616 if (mdb->m_fields) {
617 free(mdb->m_fields);
618 mdb->m_fields = NULL;
619 }
620 Dmsg1(500, "allocating space for %d fields\n", m_num_fields);
621 mdb->m_fields = (SQL_FIELD *)malloc(sizeof(SQL_FIELD) * mdb->m_num_fields);
622 mdb->m_fields_size = mdb->m_num_fields;
623
624 for (i = 0; i < mdb->m_num_fields; i++) {
625 Dmsg1(500, "filling field %d\n", i);
626 mdb->m_fields[i].name = mdb->m_result[i];
627 mdb->m_fields[i].max_length = cstrlen(mdb->m_fields[i].name);
628 for (j = 1; j <= mdb->m_num_rows; j++) {
629 if (mdb->m_result[i + mdb->m_num_fields * j]) {
630 len = (uint32_t)cstrlen(mdb->m_result[i + mdb->m_num_fields * j]);
631 } else {
632 len = 0;
633 }
634 if (len > mdb->m_fields[i].max_length) {
635 mdb->m_fields[i].max_length = len;
636 }
637 }
638 mdb->m_fields[i].type = 0;
639 mdb->m_fields[i].flags = 1; /* not null */
640
641 Dmsg4(500, "sql_fetch_field finds field '%s' has length='%d' type='%d' and IsNull=%d\n",
642 mdb->m_fields[i].name, mdb->m_fields[i].max_length, mdb->m_fields[i].type, mdb->m_fields[i].flags);
643 }
644 }
645
646 /* Increment field number for the next time around */
647 return &mdb->m_fields[mdb->m_field_number++];
648 }
649
sql_field_is_not_null(int field_type)650 bool BDB_SQLITE::sql_field_is_not_null(int field_type)
651 {
652 if (field_type == 1) {
653 return true;
654 }
655 return false;
656 }
657
sql_field_is_numeric(int field_type)658 bool BDB_SQLITE::sql_field_is_numeric(int field_type)
659 {
660 if (field_type == 1) {
661 return true;
662 }
663 return false;
664 }
665
666 /*
667 * Returns true if OK
668 * false if failed
669 */
sql_batch_start(JCR * jcr)670 bool BDB_SQLITE::sql_batch_start(JCR *jcr)
671 {
672 bool ret;
673
674 bdb_lock();
675 ret = sql_query("CREATE TEMPORARY TABLE batch ("
676 "FileIndex integer,"
677 "JobId integer,"
678 "Path blob,"
679 "Name blob,"
680 "LStat tinyblob,"
681 "MD5 tinyblob,"
682 "DeltaSeq integer)");
683 bdb_unlock();
684
685 return ret;
686 }
687
688 /* Set error to something to abort operation */
689 /*
690 * Returns true if OK
691 * false if failed
692 */
sql_batch_end(JCR * jcr,const char * error)693 bool BDB_SQLITE::sql_batch_end(JCR *jcr, const char *error)
694 {
695 m_status = 0;
696 return true;
697 }
698
699 /*
700 * Returns true if OK
701 * false if failed
702 */
sql_batch_insert(JCR * jcr,ATTR_DBR * ar)703 bool BDB_SQLITE::sql_batch_insert(JCR *jcr, ATTR_DBR *ar)
704 {
705 BDB_SQLITE *mdb = this;
706 const char *digest;
707 char ed1[50];
708
709 mdb->esc_name = check_pool_memory_size(mdb->esc_name, mdb->fnl*2+1);
710 bdb_escape_string(jcr, mdb->esc_name, mdb->fname, mdb->fnl);
711
712 mdb->esc_path = check_pool_memory_size(mdb->esc_path, mdb->pnl*2+1);
713 bdb_escape_string(jcr, mdb->esc_path, mdb->path, mdb->pnl);
714
715 if (ar->Digest == NULL || ar->Digest[0] == 0) {
716 digest = "0";
717 } else {
718 digest = ar->Digest;
719 }
720
721 Mmsg(mdb->cmd, "INSERT INTO batch VALUES "
722 "(%d,%s,'%s','%s','%s','%s',%u)",
723 ar->FileIndex, edit_int64(ar->JobId,ed1), mdb->esc_path,
724 mdb->esc_name, ar->attr, digest, ar->DeltaSeq);
725
726 return sql_query(mdb->cmd);
727 }
728
729
730 #endif /* HAVE_SQLITE3 */
731