2 * Bacula Catalog Database Create record interface routines
4 * Kern Sibbald, March 2000
9 Bacula® - The Network Backup Solution
11 Copyright (C) 2000-2006 Free Software Foundation Europe e.V.
13 The main author of Bacula is Kern Sibbald, with contributions from
14 many others, a complete list can be found in the file AUTHORS.
15 This program is Free Software; you can redistribute it and/or
16 modify it under the terms of version two of the GNU General Public
17 License as published by the Free Software Foundation plus additions
18 that are listed in the file LICENSE.
20 This program is distributed in the hope that it will be useful, but
21 WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 General Public License for more details.
25 You should have received a copy of the GNU General Public License
26 along with this program; if not, write to the Free Software
27 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
30 Bacula® is a registered trademark of John Walker.
31 The licensor of Bacula is the Free Software Foundation Europe
32 (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
33 Switzerland, email:ftf@fsfeurope.org.
36 /* The following is necessary so that we do not include
37 * the dummy external definition of DB.
39 #define __SQL_C /* indicate that this is sql.c */
44 static const int dbglevel = 500;
46 #if HAVE_SQLITE3 || HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL
48 /* -----------------------------------------------------------------------
50 * Generic Routines (or almost generic)
52 * -----------------------------------------------------------------------
55 /* Forward referenced subroutines */
56 static int db_create_file_record(JCR *jcr, B_DB *mdb, ATTR_DBR *ar);
57 static int db_create_filename_record(JCR *jcr, B_DB *mdb, ATTR_DBR *ar);
58 static int db_create_path_record(JCR *jcr, B_DB *mdb, ATTR_DBR *ar);
61 /* Create a new record for the Job
62 * Returns: false on failure
66 db_create_job_record(JCR *jcr, B_DB *mdb, JOB_DBR *jr)
68 char dt[MAX_TIME_LENGTH];
77 stime = jr->SchedTime;
80 (void)localtime_r(&stime, &tm);
81 strftime(dt, sizeof(dt), "%Y-%m-%d %H:%M:%S", &tm);
82 JobTDate = (utime_t)stime;
86 "INSERT INTO Job (Job,Name,Type,Level,JobStatus,SchedTime,JobTDate,ClientId) "
87 "VALUES ('%s','%s','%c','%c','%c','%s',%s,%s)",
88 jr->Job, jr->Name, (char)(jr->JobType), (char)(jr->JobLevel),
89 (char)(jr->JobStatus), dt, edit_uint64(JobTDate, ed1),
90 edit_int64(jr->ClientId, ed2));
92 if (!INSERT_DB(jcr, mdb, mdb->cmd)) {
93 Mmsg2(&mdb->errmsg, _("Create DB Job record %s failed. ERR=%s\n"),
94 mdb->cmd, sql_strerror(mdb));
98 jr->JobId = sql_insert_id(mdb, NT_("Job"));
106 /* Create a JobMedia record for medium used this job
107 * Returns: false on failure
111 db_create_jobmedia_record(JCR *jcr, B_DB *mdb, JOBMEDIA_DBR *jm)
115 char ed1[50], ed2[50];
119 /* Now get count for VolIndex */
120 Mmsg(mdb->cmd, "SELECT count(*) from JobMedia WHERE JobId=%s",
121 edit_int64(jm->JobId, ed1));
122 count = get_sql_record_max(jcr, mdb);
128 /* Note, jm->Strip is not used and is not likely to be used
129 * in the near future, so I have removed it from the insert
130 * to save space in the DB. KES June 2006.
133 "INSERT INTO JobMedia (JobId,MediaId,FirstIndex,LastIndex,"
134 "StartFile,EndFile,StartBlock,EndBlock,VolIndex,Copy) "
135 "VALUES (%s,%s,%u,%u,%u,%u,%u,%u,%u,%u)",
136 edit_int64(jm->JobId, ed1),
137 edit_int64(jm->MediaId, ed2),
138 jm->FirstIndex, jm->LastIndex,
139 jm->StartFile, jm->EndFile, jm->StartBlock, jm->EndBlock,count,
142 Dmsg0(300, mdb->cmd);
143 if (!INSERT_DB(jcr, mdb, mdb->cmd)) {
144 Mmsg2(&mdb->errmsg, _("Create JobMedia record %s failed: ERR=%s\n"), mdb->cmd,
148 /* Worked, now update the Media record with the EndFile and EndBlock */
150 "UPDATE Media SET EndFile=%u, EndBlock=%u WHERE MediaId=%u",
151 jm->EndFile, jm->EndBlock, jm->MediaId);
152 if (!UPDATE_DB(jcr, mdb, mdb->cmd)) {
153 Mmsg2(&mdb->errmsg, _("Update Media record %s failed: ERR=%s\n"), mdb->cmd,
159 Dmsg0(300, "Return from JobMedia\n");
165 /* Create Unique Pool record
166 * Returns: false on failure
170 db_create_pool_record(JCR *jcr, B_DB *mdb, POOL_DBR *pr)
173 char ed1[30], ed2[30], ed3[50];
175 Dmsg0(200, "In create pool\n");
177 Mmsg(mdb->cmd, "SELECT PoolId,Name FROM Pool WHERE Name='%s'", pr->Name);
178 Dmsg1(200, "selectpool: %s\n", mdb->cmd);
180 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
181 mdb->num_rows = sql_num_rows(mdb);
182 if (mdb->num_rows > 0) {
183 Mmsg1(&mdb->errmsg, _("pool record %s already exists\n"), pr->Name);
184 sql_free_result(mdb);
188 sql_free_result(mdb);
193 "INSERT INTO Pool (Name,NumVols,MaxVols,UseOnce,UseCatalog,"
194 "AcceptAnyVolume,AutoPrune,Recycle,VolRetention,VolUseDuration,"
195 "MaxVolJobs,MaxVolFiles,MaxVolBytes,PoolType,LabelType,LabelFormat) "
196 "VALUES ('%s',%u,%u,%d,%d,%d,%d,%d,%s,%s,%u,%u,%s,'%s',%d,'%s')",
198 pr->NumVols, pr->MaxVols,
199 pr->UseOnce, pr->UseCatalog,
201 pr->AutoPrune, pr->Recycle,
202 edit_uint64(pr->VolRetention, ed1),
203 edit_uint64(pr->VolUseDuration, ed2),
204 pr->MaxVolJobs, pr->MaxVolFiles,
205 edit_uint64(pr->MaxVolBytes, ed3),
206 pr->PoolType, pr->LabelType, pr->LabelFormat);
207 Dmsg1(200, "Create Pool: %s\n", mdb->cmd);
208 if (!INSERT_DB(jcr, mdb, mdb->cmd)) {
209 Mmsg2(&mdb->errmsg, _("Create db Pool record %s failed: ERR=%s\n"),
210 mdb->cmd, sql_strerror(mdb));
214 pr->PoolId = sql_insert_id(mdb, NT_("Pool"));
222 * Create Unique Device record
223 * Returns: false on failure
227 db_create_device_record(JCR *jcr, B_DB *mdb, DEVICE_DBR *dr)
230 char ed1[30], ed2[30];
232 Dmsg0(200, "In create Device\n");
234 Mmsg(mdb->cmd, "SELECT DeviceId,Name FROM Device WHERE Name='%s'", dr->Name);
235 Dmsg1(200, "selectdevice: %s\n", mdb->cmd);
237 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
238 mdb->num_rows = sql_num_rows(mdb);
239 if (mdb->num_rows > 0) {
240 Mmsg1(&mdb->errmsg, _("Device record %s already exists\n"), dr->Name);
241 sql_free_result(mdb);
245 sql_free_result(mdb);
250 "INSERT INTO Device (Name,MediaTypeId,StorageId) VALUES ('%s',%s,%s)",
252 edit_uint64(dr->MediaTypeId, ed1),
253 edit_int64(dr->StorageId, ed2));
254 Dmsg1(200, "Create Device: %s\n", mdb->cmd);
255 if (!INSERT_DB(jcr, mdb, mdb->cmd)) {
256 Mmsg2(&mdb->errmsg, _("Create db Device record %s failed: ERR=%s\n"),
257 mdb->cmd, sql_strerror(mdb));
261 dr->DeviceId = sql_insert_id(mdb, NT_("Device"));
271 * Create a Unique record for Storage -- no duplicates
272 * Returns: false on failure
273 * true on success with id in sr->StorageId
275 bool db_create_storage_record(JCR *jcr, B_DB *mdb, STORAGE_DBR *sr)
281 Mmsg(mdb->cmd, "SELECT StorageId,AutoChanger FROM Storage WHERE Name='%s'", sr->Name);
285 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
286 mdb->num_rows = sql_num_rows(mdb);
287 /* If more than one, report error, but return first row */
288 if (mdb->num_rows > 1) {
289 Mmsg1(&mdb->errmsg, _("More than one Storage record!: %d\n"), (int)(mdb->num_rows));
290 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
292 if (mdb->num_rows >= 1) {
293 if ((row = sql_fetch_row(mdb)) == NULL) {
294 Mmsg1(&mdb->errmsg, _("error fetching Storage row: %s\n"), sql_strerror(mdb));
295 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
296 sql_free_result(mdb);
300 sr->StorageId = str_to_int64(row[0]);
301 sr->AutoChanger = atoi(row[1]); /* bool */
302 sql_free_result(mdb);
306 sql_free_result(mdb);
310 Mmsg(mdb->cmd, "INSERT INTO Storage (Name,AutoChanger)"
311 " VALUES ('%s',%d)", sr->Name, sr->AutoChanger);
313 if (!INSERT_DB(jcr, mdb, mdb->cmd)) {
314 Mmsg2(&mdb->errmsg, _("Create DB Storage record %s failed. ERR=%s\n"),
315 mdb->cmd, sql_strerror(mdb));
316 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
319 sr->StorageId = sql_insert_id(mdb, NT_("Storage"));
329 * Create Unique MediaType record
330 * Returns: false on failure
334 db_create_mediatype_record(JCR *jcr, B_DB *mdb, MEDIATYPE_DBR *mr)
338 Dmsg0(200, "In create mediatype\n");
340 Mmsg(mdb->cmd, "SELECT MediaTypeId,MediaType FROM MediaType WHERE MediaType='%s'", mr->MediaType);
341 Dmsg1(200, "selectmediatype: %s\n", mdb->cmd);
343 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
344 mdb->num_rows = sql_num_rows(mdb);
345 if (mdb->num_rows > 0) {
346 Mmsg1(&mdb->errmsg, _("mediatype record %s already exists\n"), mr->MediaType);
347 sql_free_result(mdb);
351 sql_free_result(mdb);
356 "INSERT INTO MediaType (MediaType,ReadOnly) "
360 Dmsg1(200, "Create mediatype: %s\n", mdb->cmd);
361 if (!INSERT_DB(jcr, mdb, mdb->cmd)) {
362 Mmsg2(&mdb->errmsg, _("Create db mediatype record %s failed: ERR=%s\n"),
363 mdb->cmd, sql_strerror(mdb));
367 mr->MediaTypeId = sql_insert_id(mdb, NT_("MediaType"));
376 * Create Media record. VolumeName and non-zero Slot must be unique
378 * Returns: 0 on failure
382 db_create_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr)
385 char ed1[50], ed2[50], ed3[50], ed4[50], ed5[50], ed6[50], ed7[50], ed8[50];
386 char ed9[50], ed10[50], ed11[50], ed12[50];
390 Mmsg(mdb->cmd, "SELECT MediaId FROM Media WHERE VolumeName='%s'",
392 Dmsg1(500, "selectpool: %s\n", mdb->cmd);
394 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
395 mdb->num_rows = sql_num_rows(mdb);
396 if (mdb->num_rows > 0) {
397 Mmsg1(&mdb->errmsg, _("Volume \"%s\" already exists.\n"), mr->VolumeName);
398 sql_free_result(mdb);
402 sql_free_result(mdb);
407 "INSERT INTO Media (VolumeName,MediaType,MediaTypeId,PoolId,MaxVolBytes,"
408 "VolCapacityBytes,Recycle,VolRetention,VolUseDuration,MaxVolJobs,MaxVolFiles,"
409 "VolStatus,Slot,VolBytes,InChanger,VolReadTime,VolWriteTime,VolParts,"
410 "EndFile,EndBlock,LabelType,StorageId,DeviceId,LocationId,"
411 "ScratchPoolId,RecyclePoolId,Enabled)"
412 "VALUES ('%s','%s',0,%u,%s,%s,%d,%s,%s,%u,%u,'%s',%d,%s,%d,%s,%s,%d,0,0,%d,%s,"
415 mr->MediaType, mr->PoolId,
416 edit_uint64(mr->MaxVolBytes,ed1),
417 edit_uint64(mr->VolCapacityBytes, ed2),
419 edit_uint64(mr->VolRetention, ed3),
420 edit_uint64(mr->VolUseDuration, ed4),
425 edit_uint64(mr->VolBytes, ed5),
427 edit_uint64(mr->VolReadTime, ed6),
428 edit_uint64(mr->VolWriteTime, ed7),
431 edit_int64(mr->StorageId, ed8),
432 edit_int64(mr->DeviceId, ed9),
433 edit_int64(mr->LocationId, ed10),
434 edit_int64(mr->ScratchPoolId, ed11),
435 edit_int64(mr->RecyclePoolId, ed12),
440 Dmsg1(500, "Create Volume: %s\n", mdb->cmd);
441 if (!INSERT_DB(jcr, mdb, mdb->cmd)) {
442 Mmsg2(&mdb->errmsg, _("Create DB Media record %s failed. ERR=%s\n"),
443 mdb->cmd, sql_strerror(mdb));
446 mr->MediaId = sql_insert_id(mdb, NT_("Media"));
448 if (mr->set_label_date) {
449 char dt[MAX_TIME_LENGTH];
450 if (mr->LabelDate == 0) {
451 mr->LabelDate = time(NULL);
453 (void)localtime_r(&mr->LabelDate, &tm);
454 strftime(dt, sizeof(dt), "%Y-%m-%d %H:%M:%S", &tm);
455 Mmsg(mdb->cmd, "UPDATE Media SET LabelDate='%s' "
456 "WHERE MediaId=%d", dt, mr->MediaId);
457 stat = UPDATE_DB(jcr, mdb, mdb->cmd);
462 * Make sure that if InChanger is non-zero any other identical slot
463 * has InChanger zero.
465 db_make_inchanger_unique(jcr, mdb, mr);
472 * Create a Unique record for the client -- no duplicates
473 * Returns: 0 on failure
474 * 1 on success with id in cr->ClientId
476 int db_create_client_record(JCR *jcr, B_DB *mdb, CLIENT_DBR *cr)
480 char ed1[50], ed2[50];
483 Mmsg(mdb->cmd, "SELECT ClientId,Uname FROM Client WHERE Name='%s'", cr->Name);
486 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
487 mdb->num_rows = sql_num_rows(mdb);
488 /* If more than one, report error, but return first row */
489 if (mdb->num_rows > 1) {
490 Mmsg1(&mdb->errmsg, _("More than one Client!: %d\n"), (int)(mdb->num_rows));
491 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
493 if (mdb->num_rows >= 1) {
494 if ((row = sql_fetch_row(mdb)) == NULL) {
495 Mmsg1(&mdb->errmsg, _("error fetching Client row: %s\n"), sql_strerror(mdb));
496 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
497 sql_free_result(mdb);
501 cr->ClientId = str_to_int64(row[0]);
503 bstrncpy(cr->Uname, row[1], sizeof(cr->Uname));
505 cr->Uname[0] = 0; /* no name */
507 sql_free_result(mdb);
511 sql_free_result(mdb);
515 Mmsg(mdb->cmd, "INSERT INTO Client (Name,Uname,AutoPrune,"
516 "FileRetention,JobRetention) VALUES "
517 "('%s','%s',%d,%s,%s)", cr->Name, cr->Uname, cr->AutoPrune,
518 edit_uint64(cr->FileRetention, ed1),
519 edit_uint64(cr->JobRetention, ed2));
521 if (!INSERT_DB(jcr, mdb, mdb->cmd)) {
522 Mmsg2(&mdb->errmsg, _("Create DB Client record %s failed. ERR=%s\n"),
523 mdb->cmd, sql_strerror(mdb));
524 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
528 cr->ClientId = sql_insert_id(mdb, NT_("Client"));
540 * Create a Unique record for the counter -- no duplicates
541 * Returns: 0 on failure
542 * 1 on success with counter filled in
544 int db_create_counter_record(JCR *jcr, B_DB *mdb, COUNTER_DBR *cr)
550 memset(&mcr, 0, sizeof(mcr));
551 bstrncpy(mcr.Counter, cr->Counter, sizeof(mcr.Counter));
552 if (db_get_counter_record(jcr, mdb, &mcr)) {
553 memcpy(cr, &mcr, sizeof(COUNTER_DBR));
559 Mmsg(mdb->cmd, "INSERT INTO Counters (Counter,MinValue,MaxValue,CurrentValue,"
560 "WrapCounter) VALUES ('%s','%d','%d','%d','%s')",
561 cr->Counter, cr->MinValue, cr->MaxValue, cr->CurrentValue,
564 if (!INSERT_DB(jcr, mdb, mdb->cmd)) {
565 Mmsg2(&mdb->errmsg, _("Create DB Counters record %s failed. ERR=%s\n"),
566 mdb->cmd, sql_strerror(mdb));
567 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
578 * Create a FileSet record. This record is unique in the
579 * name and the MD5 signature of the include/exclude sets.
580 * Returns: 0 on failure
581 * 1 on success with FileSetId in record
583 bool db_create_fileset_record(JCR *jcr, B_DB *mdb, FILESET_DBR *fsr)
590 fsr->created = false;
591 Mmsg(mdb->cmd, "SELECT FileSetId,CreateTime FROM FileSet WHERE "
592 "FileSet='%s' AND MD5='%s'", fsr->FileSet, fsr->MD5);
595 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
596 mdb->num_rows = sql_num_rows(mdb);
597 if (mdb->num_rows > 1) {
598 Mmsg1(&mdb->errmsg, _("More than one FileSet!: %d\n"), (int)(mdb->num_rows));
599 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
601 if (mdb->num_rows >= 1) {
602 if ((row = sql_fetch_row(mdb)) == NULL) {
603 Mmsg1(&mdb->errmsg, _("error fetching FileSet row: ERR=%s\n"), sql_strerror(mdb));
604 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
605 sql_free_result(mdb);
609 fsr->FileSetId = str_to_int64(row[0]);
610 if (row[1] == NULL) {
611 fsr->cCreateTime[0] = 0;
613 bstrncpy(fsr->cCreateTime, row[1], sizeof(fsr->cCreateTime));
615 sql_free_result(mdb);
619 sql_free_result(mdb);
622 if (fsr->CreateTime == 0 && fsr->cCreateTime[0] == 0) {
623 fsr->CreateTime = time(NULL);
625 (void)localtime_r(&fsr->CreateTime, &tm);
626 strftime(fsr->cCreateTime, sizeof(fsr->cCreateTime), "%Y-%m-%d %H:%M:%S", &tm);
629 Mmsg(mdb->cmd, "INSERT INTO FileSet (FileSet,MD5,CreateTime) "
630 "VALUES ('%s','%s','%s')", fsr->FileSet, fsr->MD5, fsr->cCreateTime);
632 if (!INSERT_DB(jcr, mdb, mdb->cmd)) {
633 Mmsg2(&mdb->errmsg, _("Create DB FileSet record %s failed. ERR=%s\n"),
634 mdb->cmd, sql_strerror(mdb));
635 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
639 fsr->FileSetId = sql_insert_id(mdb, NT_("FileSet"));
652 * dev_t st_dev; * device *
653 * ino_t st_ino; * inode *
654 * mode_t st_mode; * protection *
655 * nlink_t st_nlink; * number of hard links *
656 * uid_t st_uid; * user ID of owner *
657 * gid_t st_gid; * group ID of owner *
658 * dev_t st_rdev; * device type (if inode device) *
659 * off_t st_size; * total size, in bytes *
660 * unsigned long st_blksize; * blocksize for filesystem I/O *
661 * unsigned long st_blocks; * number of blocks allocated *
662 * time_t st_atime; * time of last access *
663 * time_t st_mtime; * time of last modification *
664 * time_t st_ctime; * time of last inode change *
668 /* All db_batch_* functions are used to do bulk batch insert in File/Filename/Path
669 * tables. This code can be activated by adding "#define HAVE_BATCH_FILE_INSERT 1"
673 * - bulk load a temp table
674 * - insert missing filenames into filename with a single query (lock filenames
675 * - table before that to avoid possible duplicate inserts with concurrent update)
676 * - insert missing paths into path with another single query
677 * - then insert the join between the temp, filename and path tables into file.
680 int db_batch_start(B_DB *mdb)
682 return sql_query(mdb,
683 " CREATE TEMPORARY TABLE batch "
684 " (fileindex integer, "
692 int db_batch_insert(B_DB *mdb, ATTR_DBR *ar)
698 mdb->esc_name = check_pool_memory_size(mdb->esc_name, mdb->fnl*2+1);
699 db_escape_string(mdb->esc_name, mdb->fname, mdb->fnl);
701 mdb->esc_name2 = check_pool_memory_size(mdb->esc_name2, mdb->pnl*2+1);
702 db_escape_string(mdb->esc_name2, mdb->path, mdb->pnl);
704 if (ar->Digest == NULL || ar->Digest[0] == 0) {
710 len = Mmsg(mdb->cmd, "INSERT INTO batch VALUES (%u,%s,'%s','%s','%s','%s')",
711 ar->FileIndex, edit_int64(ar->JobId,ed1), mdb->path,
712 mdb->fname, ar->attr, digest);
714 sql_query(mdb, mdb->cmd);
719 /* set error to something to abort operation */
720 int db_batch_end(B_DB *mdb, const char *error)
723 Dmsg0(50, "db_batch_end started");
732 int db_create_batch_file_record(JCR *jcr)
734 Dmsg0(50,"db_create_file_record : no files");
736 if (!jcr->db_batch) { /* no files to backup ? */
737 Dmsg0(50,"db_create_file_record : no files\n");
741 if (sql_batch_end(jcr->db_batch, NULL)) {
742 Jmsg(jcr, M_FATAL, 0, "Bad batch end %s\n", jcr->db_batch->errmsg);
746 /* we have to lock tables */
747 if (sql_query(jcr->db_batch, sql_batch_lock_path_query))
749 Jmsg(jcr, M_FATAL, 0, "Can't lock Path table %s\n", jcr->db_batch->errmsg);
753 if (sql_query(jcr->db_batch, sql_batch_fill_path_query))
755 Jmsg(jcr, M_FATAL, 0, "Can't fill Path table %s\n",jcr->db_batch->errmsg);
756 sql_query(jcr->db_batch, sql_batch_unlock_tables_query);
760 if (sql_query(jcr->db_batch, sql_batch_unlock_tables_query))
762 Jmsg(jcr, M_FATAL, 0, "Can't unlock Path table %s\n", jcr->db_batch->errmsg);
766 /* we have to lock tables */
767 if (sql_query(jcr->db_batch, sql_batch_lock_filename_query))
769 Jmsg(jcr, M_FATAL, 0, "Can't lock Filename table %s\n", jcr->db_batch->errmsg);
773 if (sql_query(jcr->db_batch, sql_batch_fill_filename_query))
775 Jmsg(jcr,M_FATAL,0,"Can't fill Filename table %s\n",jcr->db_batch->errmsg);
776 sql_query(jcr->db_batch, sql_batch_unlock_tables_query);
780 if (sql_query(jcr->db_batch, sql_batch_unlock_tables_query)) {
781 Jmsg(jcr, M_FATAL, 0, "Can't unlock Filename table %s\n", jcr->db_batch->errmsg);
785 if (sql_query(jcr->db_batch,
786 " INSERT INTO File (FileIndex, JobId, PathId, FilenameId, LStat, MD5)"
787 " SELECT batch.FileIndex, batch.JobId, Path.PathId, "
788 " Filename.FilenameId,batch.LStat, batch.MD5 "
790 " JOIN Path ON (batch.Path = Path.Path) "
791 " JOIN Filename ON (batch.Name = Filename.Name) "))
793 Jmsg(jcr, M_FATAL, 0, "Can't fill File table %s\n", jcr->db_batch->errmsg);
797 sql_query(jcr->db_batch, "DROP TABLE batch");
802 #ifdef HAVE_BATCH_FILE_INSERT
804 * Create File record in B_DB
806 * In order to reduce database size, we store the File attributes,
807 * the FileName, and the Path separately. In principle, there
808 * is a single FileName record and a single Path record, no matter
809 * how many times it occurs. This is this subroutine, we separate
810 * the file and the path and fill temporary tables with this three records.
812 int db_create_file_attributes_record(JCR *jcr, B_DB *_mdb, ATTR_DBR *ar)
815 Dmsg1(dbglevel, "Fname=%s\n", ar->fname);
816 Dmsg0(dbglevel, "put_file_into_catalog\n");
818 if (!jcr->db_batch) {
819 jcr->db_batch = db_init_database(jcr,
822 jcr->db->db_password,
826 1 /* multi_db = true */);
828 if (!jcr->db_batch || !db_open_database(jcr, jcr->db_batch)) {
829 Jmsg(jcr, M_FATAL, 0, _("Could not open database \"%s\".\n"),
832 Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db_batch));
837 sql_batch_start(jcr->db_batch);
840 B_DB *mdb = jcr->db_batch;
843 * Make sure we have an acceptable attributes record.
845 if (!(ar->Stream == STREAM_UNIX_ATTRIBUTES ||
846 ar->Stream == STREAM_UNIX_ATTRIBUTES_EX)) {
847 Mmsg1(&mdb->errmsg, _("Attempt to put non-attributes into catalog. Stream=%d\n"),
849 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
853 split_path_and_file(jcr, mdb, ar->fname);
857 if (jcr->changes > 100000) {
858 sql_batch_end(mdb, NULL);
859 sql_batch_start(mdb);
864 return (sql_batch_insert(mdb, ar) == 0);
867 #else /* ! HAVE_BATCH_FILE_INSERT */
870 * Create File record in B_DB
872 * In order to reduce database size, we store the File attributes,
873 * the FileName, and the Path separately. In principle, there
874 * is a single FileName record and a single Path record, no matter
875 * how many times it occurs. This is this subroutine, we separate
876 * the file and the path and create three database records.
878 int db_create_file_attributes_record(JCR *jcr, B_DB *mdb, ATTR_DBR *ar)
882 Dmsg1(dbglevel, "Fname=%s\n", ar->fname);
883 Dmsg0(dbglevel, "put_file_into_catalog\n");
885 * Make sure we have an acceptable attributes record.
887 if (!(ar->Stream == STREAM_UNIX_ATTRIBUTES ||
888 ar->Stream == STREAM_UNIX_ATTRIBUTES_EX)) {
889 Mmsg1(&mdb->errmsg, _("Attempt to put non-attributes into catalog. Stream=%d\n"),
891 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
896 split_path_and_file(jcr, mdb, ar->fname);
898 if (!db_create_filename_record(jcr, mdb, ar)) {
901 Dmsg1(dbglevel, "db_create_filename_record: %s\n", mdb->esc_name);
904 if (!db_create_path_record(jcr, mdb, ar)) {
907 Dmsg1(dbglevel, "db_create_path_record: %s\n", mdb->esc_name);
909 /* Now create master File record */
910 if (!db_create_file_record(jcr, mdb, ar)) {
913 Dmsg0(dbglevel, "db_create_file_record OK\n");
915 Dmsg3(dbglevel, "CreateAttributes Path=%s File=%s FilenameId=%d\n", mdb->path, mdb->fname, ar->FilenameId);
924 #endif /* ! HAVE_BATCH_FILE_INSERT */
927 * This is the master File entry containing the attributes.
928 * The filename and path records have already been created.
930 static int db_create_file_record(JCR *jcr, B_DB *mdb, ATTR_DBR *ar)
933 static char *no_digest = "0";
938 ASSERT(ar->FilenameId);
940 if (ar->Digest == NULL || ar->Digest[0] == 0) {
948 "INSERT INTO File (FileIndex,JobId,PathId,FilenameId,"
949 "LStat,MD5) VALUES (%u,%u,%u,%u,'%s','%s')",
950 ar->FileIndex, ar->JobId, ar->PathId, ar->FilenameId,
953 if (!INSERT_DB(jcr, mdb, mdb->cmd)) {
954 Mmsg2(&mdb->errmsg, _("Create db File record %s failed. ERR=%s"),
955 mdb->cmd, sql_strerror(mdb));
956 Jmsg(jcr, M_FATAL, 0, "%s", mdb->errmsg);
960 ar->FileId = sql_insert_id(mdb, NT_("File"));
966 /* Create a Unique record for the Path -- no duplicates */
967 static int db_create_path_record(JCR *jcr, B_DB *mdb, ATTR_DBR *ar)
972 mdb->esc_name = check_pool_memory_size(mdb->esc_name, 2*mdb->pnl+2);
973 db_escape_string(mdb->esc_name, mdb->path, mdb->pnl);
975 if (mdb->cached_path_id != 0 && mdb->cached_path_len == mdb->pnl &&
976 strcmp(mdb->cached_path, mdb->path) == 0) {
977 ar->PathId = mdb->cached_path_id;
981 Mmsg(mdb->cmd, "SELECT PathId FROM Path WHERE Path='%s'", mdb->esc_name);
983 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
984 mdb->num_rows = sql_num_rows(mdb);
985 if (mdb->num_rows > 1) {
987 Mmsg2(&mdb->errmsg, _("More than one Path!: %s for path: %s\n"),
988 edit_uint64(mdb->num_rows, ed1), mdb->path);
989 Jmsg(jcr, M_WARNING, 0, "%s", mdb->errmsg);
991 /* Even if there are multiple paths, take the first one */
992 if (mdb->num_rows >= 1) {
993 if ((row = sql_fetch_row(mdb)) == NULL) {
994 Mmsg1(&mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb));
995 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
996 sql_free_result(mdb);
1001 ar->PathId = str_to_int64(row[0]);
1002 sql_free_result(mdb);
1004 if (ar->PathId != mdb->cached_path_id) {
1005 mdb->cached_path_id = ar->PathId;
1006 mdb->cached_path_len = mdb->pnl;
1007 pm_strcpy(mdb->cached_path, mdb->path);
1012 sql_free_result(mdb);
1015 Mmsg(mdb->cmd, "INSERT INTO Path (Path) VALUES ('%s')", mdb->esc_name);
1017 if (!INSERT_DB(jcr, mdb, mdb->cmd)) {
1018 Mmsg2(&mdb->errmsg, _("Create db Path record %s failed. ERR=%s\n"),
1019 mdb->cmd, sql_strerror(mdb));
1020 Jmsg(jcr, M_FATAL, 0, "%s", mdb->errmsg);
1024 ar->PathId = sql_insert_id(mdb, NT_("Path"));
1029 if (stat && ar->PathId != mdb->cached_path_id) {
1030 mdb->cached_path_id = ar->PathId;
1031 mdb->cached_path_len = mdb->pnl;
1032 pm_strcpy(mdb->cached_path, mdb->path);
1037 /* Create a Unique record for the filename -- no duplicates */
1038 static int db_create_filename_record(JCR *jcr, B_DB *mdb, ATTR_DBR *ar)
1042 mdb->esc_name = check_pool_memory_size(mdb->esc_name, 2*mdb->fnl+2);
1043 db_escape_string(mdb->esc_name, mdb->fname, mdb->fnl);
1045 Mmsg(mdb->cmd, "SELECT FilenameId FROM Filename WHERE Name='%s'", mdb->esc_name);
1047 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
1048 mdb->num_rows = sql_num_rows(mdb);
1049 if (mdb->num_rows > 1) {
1051 Mmsg2(&mdb->errmsg, _("More than one Filename! %s for file: %s\n"),
1052 edit_uint64(mdb->num_rows, ed1), mdb->fname);
1053 Jmsg(jcr, M_WARNING, 0, "%s", mdb->errmsg);
1055 if (mdb->num_rows >= 1) {
1056 if ((row = sql_fetch_row(mdb)) == NULL) {
1057 Mmsg2(&mdb->errmsg, _("Error fetching row for file=%s: ERR=%s\n"),
1058 mdb->fname, sql_strerror(mdb));
1059 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
1062 ar->FilenameId = str_to_int64(row[0]);
1064 sql_free_result(mdb);
1065 return ar->FilenameId > 0;
1067 sql_free_result(mdb);
1070 Mmsg(mdb->cmd, "INSERT INTO Filename (Name) VALUES ('%s')", mdb->esc_name);
1072 if (!INSERT_DB(jcr, mdb, mdb->cmd)) {
1073 Mmsg2(&mdb->errmsg, _("Create db Filename record %s failed. ERR=%s\n"),
1074 mdb->cmd, sql_strerror(mdb));
1075 Jmsg(jcr, M_FATAL, 0, "%s", mdb->errmsg);
1078 ar->FilenameId = sql_insert_id(mdb, NT_("Filename"));
1080 return ar->FilenameId > 0;
1083 #endif /* HAVE_SQLITE3 || HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL */