2 * Bacula Catalog Database Get record interface routines
3 * Note, these routines generally get a record by id or
4 * by name. If more logic is involved, the routine
7 * Kern Sibbald, March 2000
13 Copyright (C) 2000-2005 Kern Sibbald
15 This program is free software; you can redistribute it and/or
16 modify it under the terms of the GNU General Public License
17 version 2 as amended with additional clauses defined in the
18 file LICENSE in the main source directory.
20 This program is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 the file LICENSE for additional details.
28 /* The following is necessary so that we do not include
29 * the dummy external definition of DB.
31 #define __SQL_C /* indicate that this is sql.c */
36 #if HAVE_SQLITE3 || HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL
38 /* -----------------------------------------------------------------------
40 * Generic Routines (or almost generic)
42 * -----------------------------------------------------------------------
45 /* Forward referenced functions */
46 static int db_get_file_record(JCR *jcr, B_DB *mdb, JOB_DBR *jr, FILE_DBR *fdbr);
47 static int db_get_filename_record(JCR *jcr, B_DB *mdb);
48 static int db_get_path_record(JCR *jcr, B_DB *mdb);
51 /* Imported subroutines */
52 extern void print_result(B_DB *mdb);
53 extern int QueryDB(const char *file, int line, JCR *jcr, B_DB *db, char *select_cmd);
54 extern void split_path_and_file(JCR *jcr, B_DB *mdb, const char *fname);
59 * Given a full filename (with path), look up the File record
60 * (with attributes) in the database.
62 * Returns: 0 on failure
63 * 1 on success with the File record in FILE_DBR
65 int db_get_file_attributes_record(JCR *jcr, B_DB *mdb, char *fname, JOB_DBR *jr, FILE_DBR *fdbr)
68 Dmsg1(100, "db_get_file_att_record fname=%s \n", fname);
71 split_path_and_file(jcr, mdb, fname);
73 fdbr->FilenameId = db_get_filename_record(jcr, mdb);
75 fdbr->PathId = db_get_path_record(jcr, mdb);
77 stat = db_get_file_record(jcr, mdb, jr, fdbr);
87 * Returns: 0 on failure
90 * DO NOT use Jmsg in this routine.
92 * Note in this routine, we do not use Jmsg because it may be
93 * called to get attributes of a non-existent file, which is
94 * "normal" if a new file is found during Verify.
97 int db_get_file_record(JCR *jcr, B_DB *mdb, JOB_DBR *jr, FILE_DBR *fdbr)
101 char ed1[50], ed2[50], ed3[50];
103 if (jcr->JobLevel == L_VERIFY_DISK_TO_CATALOG) {
105 "SELECT FileId, LStat, MD5 FROM File,Job WHERE "
106 "File.JobId=Job.JobId AND File.PathId=%s AND "
107 "File.FilenameId=%s AND Job.Type='B' AND Job.JobSTATUS='T' AND "
108 "ClientId=%s ORDER BY StartTime DESC LIMIT 1",
109 edit_int64(fdbr->PathId, ed1),
110 edit_int64(fdbr->FilenameId, ed2),
111 edit_int64(jr->ClientId,ed3));
115 "SELECT FileId, LStat, MD5 FROM File WHERE File.JobId=%s AND File.PathId=%s AND "
116 "File.FilenameId=%s",
117 edit_int64(fdbr->JobId, ed1),
118 edit_int64(fdbr->PathId, ed2),
119 edit_int64(fdbr->FilenameId,ed3));
121 Dmsg3(050, "Get_file_record JobId=%u FilenameId=%u PathId=%u\n",
122 fdbr->JobId, fdbr->FilenameId, fdbr->PathId);
124 Dmsg1(100, "Query=%s\n", mdb->cmd);
126 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
127 mdb->num_rows = sql_num_rows(mdb);
128 Dmsg1(050, "get_file_record num_rows=%d\n", (int)mdb->num_rows);
129 if (mdb->num_rows > 1) {
130 Mmsg1(mdb->errmsg, _("get_file_record want 1 got rows=%d\n"),
133 if (mdb->num_rows >= 1) {
134 if ((row = sql_fetch_row(mdb)) == NULL) {
135 Mmsg1(mdb->errmsg, _("Error fetching row: %s\n"), sql_strerror(mdb));
137 fdbr->FileId = (FileId_t)str_to_int64(row[0]);
138 bstrncpy(fdbr->LStat, row[1], sizeof(fdbr->LStat));
139 bstrncpy(fdbr->SIG, row[2], sizeof(fdbr->SIG));
143 Mmsg2(mdb->errmsg, _("File record for PathId=%s FilenameId=%s not found.\n"),
144 edit_int64(fdbr->PathId, ed1),
145 edit_int64(fdbr->FilenameId, ed2));
147 sql_free_result(mdb);
149 Mmsg(mdb->errmsg, _("File record not found in Catalog.\n"));
155 /* Get Filename record
156 * Returns: 0 on failure
157 * FilenameId on success
159 * DO NOT use Jmsg in this routine (see notes for get_file_record)
161 static int db_get_filename_record(JCR *jcr, B_DB *mdb)
166 mdb->esc_name = check_pool_memory_size(mdb->esc_name, 2*mdb->fnl+2);
167 db_escape_string(mdb->esc_name, mdb->fname, mdb->fnl);
169 Mmsg(mdb->cmd, "SELECT FilenameId FROM Filename WHERE Name='%s'", mdb->esc_name);
170 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
172 mdb->num_rows = sql_num_rows(mdb);
173 if (mdb->num_rows > 1) {
174 Mmsg2(mdb->errmsg, _("More than one Filename!: %s for file: %s\n"),
175 edit_uint64(mdb->num_rows, ed1), mdb->fname);
176 Jmsg(jcr, M_WARNING, 0, "%s", mdb->errmsg);
178 if (mdb->num_rows >= 1) {
179 if ((row = sql_fetch_row(mdb)) == NULL) {
180 Mmsg1(mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb));
182 FilenameId = str_to_int64(row[0]);
183 if (FilenameId <= 0) {
184 Mmsg2(mdb->errmsg, _("Get DB Filename record %s found bad record: %d\n"),
185 mdb->cmd, FilenameId);
190 Mmsg1(mdb->errmsg, _("Filename record: %s not found.\n"), mdb->fname);
192 sql_free_result(mdb);
194 Mmsg(mdb->errmsg, _("Filename record: %s not found in Catalog.\n"), mdb->fname);
200 * Returns: 0 on failure
203 * DO NOT use Jmsg in this routine (see notes for get_file_record)
205 static int db_get_path_record(JCR *jcr, B_DB *mdb)
210 mdb->esc_name = check_pool_memory_size(mdb->esc_name, 2*mdb->pnl+2);
211 db_escape_string(mdb->esc_name, mdb->path, mdb->pnl);
213 if (mdb->cached_path_id != 0 && mdb->cached_path_len == mdb->pnl &&
214 strcmp(mdb->cached_path, mdb->path) == 0) {
215 return mdb->cached_path_id;
218 Mmsg(mdb->cmd, "SELECT PathId FROM Path WHERE Path='%s'", mdb->esc_name);
220 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
222 mdb->num_rows = sql_num_rows(mdb);
223 if (mdb->num_rows > 1) {
224 Mmsg2(mdb->errmsg, _("More than one Path!: %s for path: %s\n"),
225 edit_uint64(mdb->num_rows, ed1), mdb->path);
226 Jmsg(jcr, M_WARNING, 0, "%s", mdb->errmsg);
228 /* Even if there are multiple paths, take the first one */
229 if (mdb->num_rows >= 1) {
230 if ((row = sql_fetch_row(mdb)) == NULL) {
231 Mmsg1(mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb));
233 PathId = str_to_int64(row[0]);
235 Mmsg2(mdb->errmsg, _("Get DB path record %s found bad record: %s\n"),
236 mdb->cmd, edit_int64(PathId, ed1));
240 if (PathId != mdb->cached_path_id) {
241 mdb->cached_path_id = PathId;
242 mdb->cached_path_len = mdb->pnl;
243 pm_strcpy(mdb->cached_path, mdb->path);
248 Mmsg1(mdb->errmsg, _("Path record: %s not found.\n"), mdb->path);
250 sql_free_result(mdb);
252 Mmsg(mdb->errmsg, _("Path record: %s not found in Catalog.\n"), mdb->path);
259 * Get Job record for given JobId or Job name
260 * Returns: 0 on failure
263 int db_get_job_record(JCR *jcr, B_DB *mdb, JOB_DBR *jr)
269 if (jr->JobId == 0) {
270 Mmsg(mdb->cmd, "SELECT VolSessionId,VolSessionTime,"
271 "PoolId,StartTime,EndTime,JobFiles,JobBytes,JobTDate,Job,JobStatus,"
272 "Type,Level,ClientId,Name "
273 "FROM Job WHERE Job='%s'", jr->Job);
275 Mmsg(mdb->cmd, "SELECT VolSessionId,VolSessionTime,"
276 "PoolId,StartTime,EndTime,JobFiles,JobBytes,JobTDate,Job,JobStatus,"
277 "Type,Level,ClientId,Name "
278 "FROM Job WHERE JobId=%s",
279 edit_int64(jr->JobId, ed1));
282 if (!QUERY_DB(jcr, mdb, mdb->cmd)) {
284 return 0; /* failed */
286 if ((row = sql_fetch_row(mdb)) == NULL) {
287 Mmsg1(mdb->errmsg, _("No Job found for JobId %s\n"), edit_int64(jr->JobId, ed1));
288 sql_free_result(mdb);
290 return 0; /* failed */
293 jr->VolSessionId = str_to_uint64(row[0]);
294 jr->VolSessionTime = str_to_uint64(row[1]);
295 jr->PoolId = str_to_int64(row[2]);
296 bstrncpy(jr->cStartTime, row[3]!=NULL?row[3]:"", sizeof(jr->cStartTime));
297 bstrncpy(jr->cEndTime, row[4]!=NULL?row[4]:"", sizeof(jr->cEndTime));
298 jr->JobFiles = str_to_int64(row[5]);
299 jr->JobBytes = str_to_int64(row[6]);
300 jr->JobTDate = str_to_int64(row[7]);
301 bstrncpy(jr->Job, row[8]!=NULL?row[8]:"", sizeof(jr->Job));
302 jr->JobStatus = (int)*row[9];
303 jr->JobType = (int)*row[10];
304 jr->JobLevel = (int)*row[11];
305 jr->ClientId = str_to_uint64(row[12]!=NULL?row[12]:(char *)"");
306 bstrncpy(jr->Name, row[13]!=NULL?row[13]:"", sizeof(jr->Name));
307 sql_free_result(mdb);
314 * Find VolumeNames for a given JobId
315 * Returns: 0 on error or no Volumes found
316 * number of volumes on success
317 * Volumes are concatenated in VolumeNames
318 * separated by a vertical bar (|) in the order
319 * that they were written.
321 * Returns: number of volumes on success
323 int db_get_job_volume_names(JCR *jcr, B_DB *mdb, JobId_t JobId, POOLMEM **VolumeNames)
331 /* Get one entry per VolumeName, but "sort" by VolIndex */
333 "SELECT VolumeName,MAX(VolIndex) FROM JobMedia,Media WHERE "
334 "JobMedia.JobId=%s AND JobMedia.MediaId=Media.MediaId "
335 "GROUP BY VolumeName "
336 "ORDER BY 2 ASC", edit_int64(JobId,ed1));
338 Dmsg1(130, "VolNam=%s\n", mdb->cmd);
340 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
341 mdb->num_rows = sql_num_rows(mdb);
342 Dmsg1(130, "Num rows=%d\n", mdb->num_rows);
343 if (mdb->num_rows <= 0) {
344 Mmsg1(mdb->errmsg, _("No volumes found for JobId=%d\n"), JobId);
347 stat = mdb->num_rows;
348 for (i=0; i < stat; i++) {
349 if ((row = sql_fetch_row(mdb)) == NULL) {
350 Mmsg2(mdb->errmsg, _("Error fetching row %d: ERR=%s\n"), i, sql_strerror(mdb));
351 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
355 if (*VolumeNames[0] != 0) {
356 pm_strcat(VolumeNames, "|");
358 pm_strcat(VolumeNames, row[0]);
362 sql_free_result(mdb);
364 Mmsg(mdb->errmsg, _("No Volume for JobId %d found in Catalog.\n"), JobId);
371 * Find Volume parameters for a give JobId
372 * Returns: 0 on error or no Volumes found
373 * number of volumes on success
374 * List of Volumes and start/end file/blocks (malloced structure!)
376 * Returns: number of volumes on success
378 int db_get_job_volume_parameters(JCR *jcr, B_DB *mdb, JobId_t JobId, VOL_PARAMS **VolParams)
384 VOL_PARAMS *Vols = NULL;
388 "SELECT VolumeName,MediaType,FirstIndex,LastIndex,StartFile,"
389 "JobMedia.EndFile,StartBlock,JobMedia.EndBlock,Copy,Stripe"
390 " FROM JobMedia,Media WHERE JobMedia.JobId=%s"
391 " AND JobMedia.MediaId=Media.MediaId ORDER BY VolIndex,JobMediaId",
392 edit_int64(JobId, ed1));
394 Dmsg1(130, "VolNam=%s\n", mdb->cmd);
395 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
396 mdb->num_rows = sql_num_rows(mdb);
397 Dmsg1(130, "Num rows=%d\n", mdb->num_rows);
398 if (mdb->num_rows <= 0) {
399 Mmsg1(mdb->errmsg, _("No volumes found for JobId=%d\n"), JobId);
402 stat = mdb->num_rows;
404 *VolParams = Vols = (VOL_PARAMS *)malloc(stat * sizeof(VOL_PARAMS));
406 for (i=0; i < stat; i++) {
407 if ((row = sql_fetch_row(mdb)) == NULL) {
408 Mmsg2(mdb->errmsg, _("Error fetching row %d: ERR=%s\n"), i, sql_strerror(mdb));
409 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
413 bstrncpy(Vols[i].VolumeName, row[0], MAX_NAME_LENGTH);
414 bstrncpy(Vols[i].MediaType, row[1], MAX_NAME_LENGTH);
415 Vols[i].FirstIndex = str_to_uint64(row[2]);
416 Vols[i].LastIndex = str_to_uint64(row[3]);
417 Vols[i].StartFile = str_to_uint64(row[4]);
418 Vols[i].EndFile = str_to_uint64(row[5]);
419 Vols[i].StartBlock = str_to_uint64(row[6]);
420 Vols[i].EndBlock = str_to_uint64(row[7]);
421 // Vols[i].Copy = str_to_uint64(row[8]);
422 // Vols[i].Stripe = str_to_uint64(row[9]);
426 sql_free_result(mdb);
435 * Get the number of pool records
437 * Returns: -1 on failure
440 int db_get_num_pool_records(JCR *jcr, B_DB *mdb)
445 Mmsg(mdb->cmd, "SELECT count(*) from Pool");
446 stat = get_sql_record_max(jcr, mdb);
452 * This function returns a list of all the Pool record ids.
453 * The caller must free ids if non-NULL.
455 * Returns 0: on failure
458 int db_get_pool_ids(JCR *jcr, B_DB *mdb, int *num_ids, uint32_t *ids[])
467 Mmsg(mdb->cmd, "SELECT PoolId FROM Pool");
468 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
469 *num_ids = sql_num_rows(mdb);
471 id = (uint32_t *)malloc(*num_ids * sizeof(uint32_t));
472 while ((row = sql_fetch_row(mdb)) != NULL) {
473 id[i++] = str_to_uint64(row[0]);
477 sql_free_result(mdb);
480 Mmsg(mdb->errmsg, _("Pool id select failed: ERR=%s\n"), sql_strerror(mdb));
481 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
489 * This function returns a list of all the Client record ids.
490 * The caller must free ids if non-NULL.
492 * Returns 0: on failure
495 int db_get_client_ids(JCR *jcr, B_DB *mdb, int *num_ids, uint32_t *ids[])
504 Mmsg(mdb->cmd, "SELECT ClientId FROM Client");
505 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
506 *num_ids = sql_num_rows(mdb);
508 id = (uint32_t *)malloc(*num_ids * sizeof(uint32_t));
509 while ((row = sql_fetch_row(mdb)) != NULL) {
510 id[i++] = str_to_uint64(row[0]);
514 sql_free_result(mdb);
517 Mmsg(mdb->errmsg, _("Client id select failed: ERR=%s\n"), sql_strerror(mdb));
518 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
528 * If the PoolId is non-zero, we get its record,
529 * otherwise, we search on the PoolName
531 * Returns: false on failure
534 bool db_get_pool_record(JCR *jcr, B_DB *mdb, POOL_DBR *pdbr)
541 if (pdbr->PoolId != 0) { /* find by id */
543 "SELECT PoolId,Name,NumVols,MaxVols,UseOnce,UseCatalog,AcceptAnyVolume,"
544 "AutoPrune,Recycle,VolRetention,VolUseDuration,MaxVolJobs,MaxVolFiles,"
545 "MaxVolBytes,PoolType,LabelType,LabelFormat FROM Pool WHERE Pool.PoolId=%s",
546 edit_int64(pdbr->PoolId, ed1));
547 } else { /* find by name */
549 "SELECT PoolId,Name,NumVols,MaxVols,UseOnce,UseCatalog,AcceptAnyVolume,"
550 "AutoPrune,Recycle,VolRetention,VolUseDuration,MaxVolJobs,MaxVolFiles,"
551 "MaxVolBytes,PoolType,LabelType,LabelFormat FROM Pool WHERE Pool.Name='%s'",
555 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
556 mdb->num_rows = sql_num_rows(mdb);
557 if (mdb->num_rows > 1) {
559 Mmsg1(mdb->errmsg, _("More than one Pool!: %s\n"),
560 edit_uint64(mdb->num_rows, ed1));
561 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
562 } else if (mdb->num_rows == 1) {
563 if ((row = sql_fetch_row(mdb)) == NULL) {
564 Mmsg1(mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb));
565 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
567 pdbr->PoolId = str_to_int64(row[0]);
568 bstrncpy(pdbr->Name, row[1]!=NULL?row[1]:"", sizeof(pdbr->Name));
569 pdbr->NumVols = str_to_int64(row[2]);
570 pdbr->MaxVols = str_to_int64(row[3]);
571 pdbr->UseOnce = str_to_int64(row[4]);
572 pdbr->UseCatalog = str_to_int64(row[5]);
573 pdbr->AcceptAnyVolume = str_to_int64(row[6]);
574 pdbr->AutoPrune = str_to_int64(row[7]);
575 pdbr->Recycle = str_to_int64(row[8]);
576 pdbr->VolRetention = str_to_int64(row[9]);
577 pdbr->VolUseDuration = str_to_int64(row[10]);
578 pdbr->MaxVolJobs = str_to_int64(row[11]);
579 pdbr->MaxVolFiles = str_to_int64(row[12]);
580 pdbr->MaxVolBytes = str_to_uint64(row[13]);
581 bstrncpy(pdbr->PoolType, row[14]!=NULL?row[14]:"", sizeof(pdbr->PoolType));
582 pdbr->LabelType = str_to_int64(row[15]);
583 bstrncpy(pdbr->LabelFormat, row[16]!=NULL?row[16]:"", sizeof(pdbr->LabelFormat));
587 sql_free_result(mdb);
591 Mmsg(mdb->cmd, "SELECT count(*) from Media WHERE PoolId=%s",
592 edit_int64(pdbr->PoolId, ed1));
593 NumVols = get_sql_record_max(jcr, mdb);
594 Dmsg2(400, "Actual NumVols=%d Pool NumVols=%d\n", NumVols, pdbr->NumVols);
595 if (NumVols != pdbr->NumVols) {
596 pdbr->NumVols = NumVols;
597 db_update_pool_record(jcr, mdb, pdbr);
600 Mmsg(mdb->errmsg, _("Pool record not found in Catalog.\n"));
607 * If the ClientId is non-zero, we get its record,
608 * otherwise, we search on the Client Name
610 * Returns: 0 on failure
613 int db_get_client_record(JCR *jcr, B_DB *mdb, CLIENT_DBR *cdbr)
620 if (cdbr->ClientId != 0) { /* find by id */
622 "SELECT ClientId,Name,Uname,AutoPrune,FileRetention,JobRetention "
623 "FROM Client WHERE Client.ClientId=%s",
624 edit_int64(cdbr->ClientId, ed1));
625 } else { /* find by name */
627 "SELECT ClientId,Name,Uname,AutoPrune,FileRetention,JobRetention "
628 "FROM Client WHERE Client.Name='%s'", cdbr->Name);
631 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
632 mdb->num_rows = sql_num_rows(mdb);
633 if (mdb->num_rows > 1) {
634 Mmsg1(mdb->errmsg, _("More than one Client!: %s\n"),
635 edit_uint64(mdb->num_rows, ed1));
636 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
637 } else if (mdb->num_rows == 1) {
638 if ((row = sql_fetch_row(mdb)) == NULL) {
639 Mmsg1(mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb));
640 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
642 cdbr->ClientId = str_to_int64(row[0]);
643 bstrncpy(cdbr->Name, row[1]!=NULL?row[1]:"", sizeof(cdbr->Name));
644 bstrncpy(cdbr->Uname, row[2]!=NULL?row[2]:"", sizeof(cdbr->Uname));
645 cdbr->AutoPrune = str_to_int64(row[3]);
646 cdbr->FileRetention = str_to_int64(row[4]);
647 cdbr->JobRetention = str_to_int64(row[5]);
651 Mmsg(mdb->errmsg, _("Client record not found in Catalog.\n"));
653 sql_free_result(mdb);
655 Mmsg(mdb->errmsg, _("Client record not found in Catalog.\n"));
664 * Returns: 0 on failure
667 int db_get_counter_record(JCR *jcr, B_DB *mdb, COUNTER_DBR *cr)
672 Mmsg(mdb->cmd, "SELECT MinValue,MaxValue,CurrentValue,WrapCounter "
673 "FROM Counters WHERE Counter='%s'", cr->Counter);
675 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
676 mdb->num_rows = sql_num_rows(mdb);
678 /* If more than one, report error, but return first row */
679 if (mdb->num_rows > 1) {
680 Mmsg1(mdb->errmsg, _("More than one Counter!: %d\n"), (int)(mdb->num_rows));
681 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
683 if (mdb->num_rows >= 1) {
684 if ((row = sql_fetch_row(mdb)) == NULL) {
685 Mmsg1(mdb->errmsg, _("error fetching Counter row: %s\n"), sql_strerror(mdb));
686 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
687 sql_free_result(mdb);
691 cr->MinValue = str_to_int64(row[0]);
692 cr->MaxValue = str_to_int64(row[1]);
693 cr->CurrentValue = str_to_int64(row[2]);
695 bstrncpy(cr->WrapCounter, row[3], sizeof(cr->WrapCounter));
697 cr->WrapCounter[0] = 0;
699 sql_free_result(mdb);
703 sql_free_result(mdb);
705 Mmsg(mdb->errmsg, _("Counter record: %s not found in Catalog.\n"), cr->Counter);
712 /* Get FileSet Record
713 * If the FileSetId is non-zero, we get its record,
714 * otherwise, we search on the name
716 * Returns: 0 on failure
719 int db_get_fileset_record(JCR *jcr, B_DB *mdb, FILESET_DBR *fsr)
726 if (fsr->FileSetId != 0) { /* find by id */
728 "SELECT FileSetId,FileSet,MD5,CreateTime FROM FileSet "
729 "WHERE FileSetId=%s",
730 edit_int64(fsr->FileSetId, ed1));
731 } else { /* find by name */
733 "SELECT FileSetId,FileSet,MD5,CreateTime FROM FileSet "
734 "WHERE FileSet='%s' ORDER BY CreateTime DESC LIMIT 1", fsr->FileSet);
737 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
738 mdb->num_rows = sql_num_rows(mdb);
739 if (mdb->num_rows > 1) {
741 Mmsg1(mdb->errmsg, _("Error got %s FileSets but expected only one!\n"),
742 edit_uint64(mdb->num_rows, ed1));
743 sql_data_seek(mdb, mdb->num_rows-1);
745 if ((row = sql_fetch_row(mdb)) == NULL) {
746 Mmsg1(mdb->errmsg, _("FileSet record \"%s\" not found.\n"), fsr->FileSet);
748 fsr->FileSetId = str_to_int64(row[0]);
749 bstrncpy(fsr->FileSet, row[1]!=NULL?row[1]:"", sizeof(fsr->FileSet));
750 bstrncpy(fsr->MD5, row[2]!=NULL?row[2]:"", sizeof(fsr->MD5));
751 bstrncpy(fsr->cCreateTime, row[3]!=NULL?row[3]:"", sizeof(fsr->cCreateTime));
752 stat = fsr->FileSetId;
754 sql_free_result(mdb);
756 Mmsg(mdb->errmsg, _("FileSet record not found in Catalog.\n"));
764 * Get the number of Media records
766 * Returns: -1 on failure
769 int db_get_num_media_records(JCR *jcr, B_DB *mdb)
774 Mmsg(mdb->cmd, "SELECT count(*) from Media");
775 stat = get_sql_record_max(jcr, mdb);
782 * This function returns a list of all the Media record ids for
784 * The caller must free ids if non-NULL.
786 * Returns false: on failure
789 bool db_get_media_ids(JCR *jcr, B_DB *mdb, uint32_t PoolId, int *num_ids, uint32_t *ids[])
799 Mmsg(mdb->cmd, "SELECT MediaId FROM Media WHERE PoolId=%s",
800 edit_int64(PoolId, ed1));
801 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
802 *num_ids = sql_num_rows(mdb);
804 id = (uint32_t *)malloc(*num_ids * sizeof(uint32_t));
805 while ((row = sql_fetch_row(mdb)) != NULL) {
806 id[i++] = str_to_uint64(row[0]);
810 sql_free_result(mdb);
813 Mmsg(mdb->errmsg, _("Media id select failed: ERR=%s\n"), sql_strerror(mdb));
814 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
824 * Returns: false: on failure
827 bool db_get_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr)
834 if (mr->MediaId == 0 && mr->VolumeName[0] == 0) {
835 Mmsg(mdb->cmd, "SELECT count(*) from Media");
836 mr->MediaId = get_sql_record_max(jcr, mdb);
840 if (mr->MediaId != 0) { /* find by id */
841 Mmsg(mdb->cmd, "SELECT MediaId,VolumeName,VolJobs,VolFiles,VolBlocks,"
842 "VolBytes,VolMounts,VolErrors,VolWrites,MaxVolBytes,VolCapacityBytes,"
843 "MediaType,VolStatus,PoolId,VolRetention,VolUseDuration,MaxVolJobs,"
844 "MaxVolFiles,Recycle,Slot,FirstWritten,LastWritten,InChanger,"
845 "EndFile,EndBlock,VolParts,LabelType,LabelDate,StorageId "
846 "FROM Media WHERE MediaId=%s",
847 edit_int64(mr->MediaId, ed1));
848 } else { /* find by name */
849 Mmsg(mdb->cmd, "SELECT MediaId,VolumeName,VolJobs,VolFiles,VolBlocks,"
850 "VolBytes,VolMounts,VolErrors,VolWrites,MaxVolBytes,VolCapacityBytes,"
851 "MediaType,VolStatus,PoolId,VolRetention,VolUseDuration,MaxVolJobs,"
852 "MaxVolFiles,Recycle,Slot,FirstWritten,LastWritten,InChanger,"
853 "EndFile,EndBlock,VolParts,LabelType,LabelDate,StorageId "
854 "FROM Media WHERE VolumeName='%s'", mr->VolumeName);
857 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
859 mdb->num_rows = sql_num_rows(mdb);
860 if (mdb->num_rows > 1) {
861 Mmsg1(mdb->errmsg, _("More than one Volume!: %s\n"),
862 edit_uint64(mdb->num_rows, ed1));
863 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
864 } else if (mdb->num_rows == 1) {
865 if ((row = sql_fetch_row(mdb)) == NULL) {
866 Mmsg1(mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb));
867 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
870 mr->MediaId = str_to_int64(row[0]);
871 bstrncpy(mr->VolumeName, row[1]!=NULL?row[1]:"", sizeof(mr->VolumeName));
872 mr->VolJobs = str_to_int64(row[2]);
873 mr->VolFiles = str_to_int64(row[3]);
874 mr->VolBlocks = str_to_int64(row[4]);
875 mr->VolBytes = str_to_uint64(row[5]);
876 mr->VolMounts = str_to_int64(row[6]);
877 mr->VolErrors = str_to_int64(row[7]);
878 mr->VolWrites = str_to_int64(row[8]);
879 mr->MaxVolBytes = str_to_uint64(row[9]);
880 mr->VolCapacityBytes = str_to_uint64(row[10]);
881 bstrncpy(mr->MediaType, row[11]!=NULL?row[11]:"", sizeof(mr->MediaType));
882 bstrncpy(mr->VolStatus, row[12]!=NULL?row[12]:"", sizeof(mr->VolStatus));
883 mr->PoolId = str_to_int64(row[13]);
884 mr->VolRetention = str_to_uint64(row[14]);
885 mr->VolUseDuration = str_to_uint64(row[15]);
886 mr->MaxVolJobs = str_to_int64(row[16]);
887 mr->MaxVolFiles = str_to_int64(row[17]);
888 mr->Recycle = str_to_int64(row[18]);
889 mr->Slot = str_to_int64(row[19]);
890 bstrncpy(mr->cFirstWritten, row[20]!=NULL?row[20]:"", sizeof(mr->cFirstWritten));
891 mr->FirstWritten = (time_t)str_to_utime(mr->cFirstWritten);
892 bstrncpy(mr->cLastWritten, row[21]!=NULL?row[21]:"", sizeof(mr->cLastWritten));
893 mr->LastWritten = (time_t)str_to_utime(mr->cLastWritten);
894 mr->InChanger = str_to_uint64(row[22]);
895 mr->EndFile = str_to_uint64(row[23]);
896 mr->EndBlock = str_to_uint64(row[24]);
897 mr->VolParts = str_to_int64(row[25]);
898 mr->LabelType = str_to_int64(row[26]);
899 bstrncpy(mr->cLabelDate, row[27]!=NULL?row[27]:"", sizeof(mr->cLabelDate));
900 mr->LabelDate = (time_t)str_to_utime(mr->cLabelDate);
901 mr->StorageId = str_to_int64(row[28]);
905 if (mr->MediaId != 0) {
906 Mmsg1(mdb->errmsg, _("Media record MediaId=%s not found.\n"),
907 edit_int64(mr->MediaId, ed1));
909 Mmsg1(mdb->errmsg, _("Media record for Volume \"%s\" not found.\n"),
913 sql_free_result(mdb);
915 if (mr->MediaId != 0) {
916 Mmsg(mdb->errmsg, _("Media record for MediaId=%u not found in Catalog.\n"),
919 Mmsg(mdb->errmsg, _("Media record for Vol=%s not found in Catalog.\n"),
927 #endif /* HAVE_SQLITE3 || HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL*/