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-2006 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->Digest, row[2], sizeof(fdbr->Digest));
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: false on failure
263 bool 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,PriorJobId,RealEndTime "
278 "FROM Job WHERE JobId=%s",
279 edit_int64(jr->JobId, ed1));
282 if (!QUERY_DB(jcr, mdb, mdb->cmd)) {
284 return false; /* 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 false; /* 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 jr->PriorJobId = str_to_uint64(row[14]!=NULL?row[14]:(char *)"");
308 bstrncpy(jr->cRealEndTime, row[15]!=NULL?row[15]:"", sizeof(jr->cRealEndTime));
309 sql_free_result(mdb);
316 * Find VolumeNames for a given JobId
317 * Returns: 0 on error or no Volumes found
318 * number of volumes on success
319 * Volumes are concatenated in VolumeNames
320 * separated by a vertical bar (|) in the order
321 * that they were written.
323 * Returns: number of volumes on success
325 int db_get_job_volume_names(JCR *jcr, B_DB *mdb, JobId_t JobId, POOLMEM **VolumeNames)
333 /* Get one entry per VolumeName, but "sort" by VolIndex */
335 "SELECT VolumeName,MAX(VolIndex) FROM JobMedia,Media WHERE "
336 "JobMedia.JobId=%s AND JobMedia.MediaId=Media.MediaId "
337 "GROUP BY VolumeName "
338 "ORDER BY 2 ASC", edit_int64(JobId,ed1));
340 Dmsg1(130, "VolNam=%s\n", mdb->cmd);
342 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
343 mdb->num_rows = sql_num_rows(mdb);
344 Dmsg1(130, "Num rows=%d\n", mdb->num_rows);
345 if (mdb->num_rows <= 0) {
346 Mmsg1(mdb->errmsg, _("No volumes found for JobId=%d\n"), JobId);
349 stat = mdb->num_rows;
350 for (i=0; i < stat; i++) {
351 if ((row = sql_fetch_row(mdb)) == NULL) {
352 Mmsg2(mdb->errmsg, _("Error fetching row %d: ERR=%s\n"), i, sql_strerror(mdb));
353 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
357 if (*VolumeNames[0] != 0) {
358 pm_strcat(VolumeNames, "|");
360 pm_strcat(VolumeNames, row[0]);
364 sql_free_result(mdb);
366 Mmsg(mdb->errmsg, _("No Volume for JobId %d found in Catalog.\n"), JobId);
373 * Find Volume parameters for a give JobId
374 * Returns: 0 on error or no Volumes found
375 * number of volumes on success
376 * List of Volumes and start/end file/blocks (malloced structure!)
378 * Returns: number of volumes on success
380 int db_get_job_volume_parameters(JCR *jcr, B_DB *mdb, JobId_t JobId, VOL_PARAMS **VolParams)
386 VOL_PARAMS *Vols = NULL;
390 "SELECT VolumeName,MediaType,FirstIndex,LastIndex,StartFile,"
391 "JobMedia.EndFile,StartBlock,JobMedia.EndBlock,Copy,"
393 " FROM JobMedia,Media WHERE JobMedia.JobId=%s"
394 " AND JobMedia.MediaId=Media.MediaId ORDER BY VolIndex,JobMediaId",
395 edit_int64(JobId, ed1));
397 Dmsg1(130, "VolNam=%s\n", mdb->cmd);
398 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
399 mdb->num_rows = sql_num_rows(mdb);
400 Dmsg1(200, "Num rows=%d\n", mdb->num_rows);
401 if (mdb->num_rows <= 0) {
402 Mmsg1(mdb->errmsg, _("No volumes found for JobId=%d\n"), JobId);
405 stat = mdb->num_rows;
408 *VolParams = Vols = (VOL_PARAMS *)malloc(stat * sizeof(VOL_PARAMS));
409 SId = (DBId_t *)malloc(stat * sizeof(DBId_t));
413 for (i=0; i < stat; i++) {
414 if ((row = sql_fetch_row(mdb)) == NULL) {
415 Mmsg2(mdb->errmsg, _("Error fetching row %d: ERR=%s\n"), i, sql_strerror(mdb));
416 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
421 bstrncpy(Vols[i].VolumeName, row[0], MAX_NAME_LENGTH);
422 bstrncpy(Vols[i].MediaType, row[1], MAX_NAME_LENGTH);
423 Vols[i].FirstIndex = str_to_uint64(row[2]);
424 Vols[i].LastIndex = str_to_uint64(row[3]);
425 Vols[i].StartFile = str_to_uint64(row[4]);
426 Vols[i].EndFile = str_to_uint64(row[5]);
427 Vols[i].StartBlock = str_to_uint64(row[6]);
428 Vols[i].EndBlock = str_to_uint64(row[7]);
429 // Vols[i].Copy = str_to_uint64(row[8]);
430 Vols[i].Slot = str_to_uint64(row[9]);
431 StorageId = str_to_uint64(row[10]);
432 Vols[i].Storage[0] = 0;
436 for (i=0; i < stat; i++) {
438 Mmsg(mdb->cmd, "SELECT Name from Storage WHERE StorageId=%s",
439 edit_int64(SId[i], ed1));
440 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
441 if ((row = sql_fetch_row(mdb)) != NULL) {
442 bstrncpy(Vols[i].Storage, row[0], MAX_NAME_LENGTH);
448 sql_free_result(mdb);
457 * Get the number of pool records
459 * Returns: -1 on failure
462 int db_get_num_pool_records(JCR *jcr, B_DB *mdb)
467 Mmsg(mdb->cmd, "SELECT count(*) from Pool");
468 stat = get_sql_record_max(jcr, mdb);
474 * This function returns a list of all the Pool record ids.
475 * The caller must free ids if non-NULL.
477 * Returns 0: on failure
480 int db_get_pool_ids(JCR *jcr, B_DB *mdb, int *num_ids, uint32_t *ids[])
489 Mmsg(mdb->cmd, "SELECT PoolId FROM Pool");
490 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
491 *num_ids = sql_num_rows(mdb);
493 id = (uint32_t *)malloc(*num_ids * sizeof(uint32_t));
494 while ((row = sql_fetch_row(mdb)) != NULL) {
495 id[i++] = str_to_uint64(row[0]);
499 sql_free_result(mdb);
502 Mmsg(mdb->errmsg, _("Pool id select failed: ERR=%s\n"), sql_strerror(mdb));
503 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
511 * This function returns a list of all the Client record ids.
512 * The caller must free ids if non-NULL.
514 * Returns 0: on failure
517 int db_get_client_ids(JCR *jcr, B_DB *mdb, int *num_ids, uint32_t *ids[])
526 Mmsg(mdb->cmd, "SELECT ClientId FROM Client");
527 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
528 *num_ids = sql_num_rows(mdb);
530 id = (uint32_t *)malloc(*num_ids * sizeof(uint32_t));
531 while ((row = sql_fetch_row(mdb)) != NULL) {
532 id[i++] = str_to_uint64(row[0]);
536 sql_free_result(mdb);
539 Mmsg(mdb->errmsg, _("Client id select failed: ERR=%s\n"), sql_strerror(mdb));
540 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
550 * If the PoolId is non-zero, we get its record,
551 * otherwise, we search on the PoolName
553 * Returns: false on failure
556 bool db_get_pool_record(JCR *jcr, B_DB *mdb, POOL_DBR *pdbr)
563 if (pdbr->PoolId != 0) { /* find by id */
565 "SELECT PoolId,Name,NumVols,MaxVols,UseOnce,UseCatalog,AcceptAnyVolume,"
566 "AutoPrune,Recycle,VolRetention,VolUseDuration,MaxVolJobs,MaxVolFiles,"
567 "MaxVolBytes,PoolType,LabelType,LabelFormat FROM Pool WHERE Pool.PoolId=%s",
568 edit_int64(pdbr->PoolId, ed1));
569 } else { /* find by name */
571 "SELECT PoolId,Name,NumVols,MaxVols,UseOnce,UseCatalog,AcceptAnyVolume,"
572 "AutoPrune,Recycle,VolRetention,VolUseDuration,MaxVolJobs,MaxVolFiles,"
573 "MaxVolBytes,PoolType,LabelType,LabelFormat FROM Pool WHERE Pool.Name='%s'",
577 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
578 mdb->num_rows = sql_num_rows(mdb);
579 if (mdb->num_rows > 1) {
581 Mmsg1(mdb->errmsg, _("More than one Pool!: %s\n"),
582 edit_uint64(mdb->num_rows, ed1));
583 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
584 } else if (mdb->num_rows == 1) {
585 if ((row = sql_fetch_row(mdb)) == NULL) {
586 Mmsg1(mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb));
587 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
589 pdbr->PoolId = str_to_int64(row[0]);
590 bstrncpy(pdbr->Name, row[1]!=NULL?row[1]:"", sizeof(pdbr->Name));
591 pdbr->NumVols = str_to_int64(row[2]);
592 pdbr->MaxVols = str_to_int64(row[3]);
593 pdbr->UseOnce = str_to_int64(row[4]);
594 pdbr->UseCatalog = str_to_int64(row[5]);
595 pdbr->AcceptAnyVolume = str_to_int64(row[6]);
596 pdbr->AutoPrune = str_to_int64(row[7]);
597 pdbr->Recycle = str_to_int64(row[8]);
598 pdbr->VolRetention = str_to_int64(row[9]);
599 pdbr->VolUseDuration = str_to_int64(row[10]);
600 pdbr->MaxVolJobs = str_to_int64(row[11]);
601 pdbr->MaxVolFiles = str_to_int64(row[12]);
602 pdbr->MaxVolBytes = str_to_uint64(row[13]);
603 bstrncpy(pdbr->PoolType, row[14]!=NULL?row[14]:"", sizeof(pdbr->PoolType));
604 pdbr->LabelType = str_to_int64(row[15]);
605 bstrncpy(pdbr->LabelFormat, row[16]!=NULL?row[16]:"", sizeof(pdbr->LabelFormat));
609 sql_free_result(mdb);
613 Mmsg(mdb->cmd, "SELECT count(*) from Media WHERE PoolId=%s",
614 edit_int64(pdbr->PoolId, ed1));
615 NumVols = get_sql_record_max(jcr, mdb);
616 Dmsg2(400, "Actual NumVols=%d Pool NumVols=%d\n", NumVols, pdbr->NumVols);
617 if (NumVols != pdbr->NumVols) {
618 pdbr->NumVols = NumVols;
619 db_update_pool_record(jcr, mdb, pdbr);
622 Mmsg(mdb->errmsg, _("Pool record not found in Catalog.\n"));
629 * If the ClientId is non-zero, we get its record,
630 * otherwise, we search on the Client Name
632 * Returns: 0 on failure
635 int db_get_client_record(JCR *jcr, B_DB *mdb, CLIENT_DBR *cdbr)
642 if (cdbr->ClientId != 0) { /* find by id */
644 "SELECT ClientId,Name,Uname,AutoPrune,FileRetention,JobRetention "
645 "FROM Client WHERE Client.ClientId=%s",
646 edit_int64(cdbr->ClientId, ed1));
647 } else { /* find by name */
649 "SELECT ClientId,Name,Uname,AutoPrune,FileRetention,JobRetention "
650 "FROM Client WHERE Client.Name='%s'", cdbr->Name);
653 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
654 mdb->num_rows = sql_num_rows(mdb);
655 if (mdb->num_rows > 1) {
656 Mmsg1(mdb->errmsg, _("More than one Client!: %s\n"),
657 edit_uint64(mdb->num_rows, ed1));
658 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
659 } else if (mdb->num_rows == 1) {
660 if ((row = sql_fetch_row(mdb)) == NULL) {
661 Mmsg1(mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb));
662 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
664 cdbr->ClientId = str_to_int64(row[0]);
665 bstrncpy(cdbr->Name, row[1]!=NULL?row[1]:"", sizeof(cdbr->Name));
666 bstrncpy(cdbr->Uname, row[2]!=NULL?row[2]:"", sizeof(cdbr->Uname));
667 cdbr->AutoPrune = str_to_int64(row[3]);
668 cdbr->FileRetention = str_to_int64(row[4]);
669 cdbr->JobRetention = str_to_int64(row[5]);
673 Mmsg(mdb->errmsg, _("Client record not found in Catalog.\n"));
675 sql_free_result(mdb);
677 Mmsg(mdb->errmsg, _("Client record not found in Catalog.\n"));
686 * Returns: 0 on failure
689 int db_get_counter_record(JCR *jcr, B_DB *mdb, COUNTER_DBR *cr)
694 Mmsg(mdb->cmd, "SELECT MinValue,MaxValue,CurrentValue,WrapCounter "
695 "FROM Counters WHERE Counter='%s'", cr->Counter);
697 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
698 mdb->num_rows = sql_num_rows(mdb);
700 /* If more than one, report error, but return first row */
701 if (mdb->num_rows > 1) {
702 Mmsg1(mdb->errmsg, _("More than one Counter!: %d\n"), (int)(mdb->num_rows));
703 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
705 if (mdb->num_rows >= 1) {
706 if ((row = sql_fetch_row(mdb)) == NULL) {
707 Mmsg1(mdb->errmsg, _("error fetching Counter row: %s\n"), sql_strerror(mdb));
708 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
709 sql_free_result(mdb);
713 cr->MinValue = str_to_int64(row[0]);
714 cr->MaxValue = str_to_int64(row[1]);
715 cr->CurrentValue = str_to_int64(row[2]);
717 bstrncpy(cr->WrapCounter, row[3], sizeof(cr->WrapCounter));
719 cr->WrapCounter[0] = 0;
721 sql_free_result(mdb);
725 sql_free_result(mdb);
727 Mmsg(mdb->errmsg, _("Counter record: %s not found in Catalog.\n"), cr->Counter);
734 /* Get FileSet Record
735 * If the FileSetId is non-zero, we get its record,
736 * otherwise, we search on the name
738 * Returns: 0 on failure
741 int db_get_fileset_record(JCR *jcr, B_DB *mdb, FILESET_DBR *fsr)
748 if (fsr->FileSetId != 0) { /* find by id */
750 "SELECT FileSetId,FileSet,MD5,CreateTime FROM FileSet "
751 "WHERE FileSetId=%s",
752 edit_int64(fsr->FileSetId, ed1));
753 } else { /* find by name */
755 "SELECT FileSetId,FileSet,MD5,CreateTime FROM FileSet "
756 "WHERE FileSet='%s' ORDER BY CreateTime DESC LIMIT 1", fsr->FileSet);
759 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
760 mdb->num_rows = sql_num_rows(mdb);
761 if (mdb->num_rows > 1) {
763 Mmsg1(mdb->errmsg, _("Error got %s FileSets but expected only one!\n"),
764 edit_uint64(mdb->num_rows, ed1));
765 sql_data_seek(mdb, mdb->num_rows-1);
767 if ((row = sql_fetch_row(mdb)) == NULL) {
768 Mmsg1(mdb->errmsg, _("FileSet record \"%s\" not found.\n"), fsr->FileSet);
770 fsr->FileSetId = str_to_int64(row[0]);
771 bstrncpy(fsr->FileSet, row[1]!=NULL?row[1]:"", sizeof(fsr->FileSet));
772 bstrncpy(fsr->MD5, row[2]!=NULL?row[2]:"", sizeof(fsr->MD5));
773 bstrncpy(fsr->cCreateTime, row[3]!=NULL?row[3]:"", sizeof(fsr->cCreateTime));
774 stat = fsr->FileSetId;
776 sql_free_result(mdb);
778 Mmsg(mdb->errmsg, _("FileSet record not found in Catalog.\n"));
786 * Get the number of Media records
788 * Returns: -1 on failure
791 int db_get_num_media_records(JCR *jcr, B_DB *mdb)
796 Mmsg(mdb->cmd, "SELECT count(*) from Media");
797 stat = get_sql_record_max(jcr, mdb);
804 * This function returns a list of all the Media record ids for
806 * The caller must free ids if non-NULL.
808 * Returns false: on failure
811 bool db_get_media_ids(JCR *jcr, B_DB *mdb, uint32_t PoolId, int *num_ids, uint32_t *ids[])
821 Mmsg(mdb->cmd, "SELECT MediaId FROM Media WHERE PoolId=%s",
822 edit_int64(PoolId, ed1));
823 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
824 *num_ids = sql_num_rows(mdb);
826 id = (uint32_t *)malloc(*num_ids * sizeof(uint32_t));
827 while ((row = sql_fetch_row(mdb)) != NULL) {
828 id[i++] = str_to_uint64(row[0]);
832 sql_free_result(mdb);
835 Mmsg(mdb->errmsg, _("Media id select failed: ERR=%s\n"), sql_strerror(mdb));
836 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
846 * Returns: false: on failure
849 bool db_get_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr)
856 if (mr->MediaId == 0 && mr->VolumeName[0] == 0) {
857 Mmsg(mdb->cmd, "SELECT count(*) from Media");
858 mr->MediaId = get_sql_record_max(jcr, mdb);
862 if (mr->MediaId != 0) { /* find by id */
863 Mmsg(mdb->cmd, "SELECT MediaId,VolumeName,VolJobs,VolFiles,VolBlocks,"
864 "VolBytes,VolMounts,VolErrors,VolWrites,MaxVolBytes,VolCapacityBytes,"
865 "MediaType,VolStatus,PoolId,VolRetention,VolUseDuration,MaxVolJobs,"
866 "MaxVolFiles,Recycle,Slot,FirstWritten,LastWritten,InChanger,"
867 "EndFile,EndBlock,VolParts,LabelType,LabelDate,StorageId,"
868 "Enabled,LocationId,RecycleCount,InitialWrite,"
869 "ScratchPoolId,RecyclePoolId "
870 "FROM Media WHERE MediaId=%s",
871 edit_int64(mr->MediaId, ed1));
872 } else { /* find by name */
873 Mmsg(mdb->cmd, "SELECT MediaId,VolumeName,VolJobs,VolFiles,VolBlocks,"
874 "VolBytes,VolMounts,VolErrors,VolWrites,MaxVolBytes,VolCapacityBytes,"
875 "MediaType,VolStatus,PoolId,VolRetention,VolUseDuration,MaxVolJobs,"
876 "MaxVolFiles,Recycle,Slot,FirstWritten,LastWritten,InChanger,"
877 "EndFile,EndBlock,VolParts,LabelType,LabelDate,StorageId,"
878 "Enabled,LocationId,RecycleCount,InitialWrite,"
879 "ScratchPoolId,RecyclePoolId "
880 "FROM Media WHERE VolumeName='%s'", mr->VolumeName);
883 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
885 mdb->num_rows = sql_num_rows(mdb);
886 if (mdb->num_rows > 1) {
887 Mmsg1(mdb->errmsg, _("More than one Volume!: %s\n"),
888 edit_uint64(mdb->num_rows, ed1));
889 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
890 } else if (mdb->num_rows == 1) {
891 if ((row = sql_fetch_row(mdb)) == NULL) {
892 Mmsg1(mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb));
893 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
896 mr->MediaId = str_to_int64(row[0]);
897 bstrncpy(mr->VolumeName, row[1]!=NULL?row[1]:"", sizeof(mr->VolumeName));
898 mr->VolJobs = str_to_int64(row[2]);
899 mr->VolFiles = str_to_int64(row[3]);
900 mr->VolBlocks = str_to_int64(row[4]);
901 mr->VolBytes = str_to_uint64(row[5]);
902 mr->VolMounts = str_to_int64(row[6]);
903 mr->VolErrors = str_to_int64(row[7]);
904 mr->VolWrites = str_to_int64(row[8]);
905 mr->MaxVolBytes = str_to_uint64(row[9]);
906 mr->VolCapacityBytes = str_to_uint64(row[10]);
907 bstrncpy(mr->MediaType, row[11]!=NULL?row[11]:"", sizeof(mr->MediaType));
908 bstrncpy(mr->VolStatus, row[12]!=NULL?row[12]:"", sizeof(mr->VolStatus));
909 mr->PoolId = str_to_int64(row[13]);
910 mr->VolRetention = str_to_uint64(row[14]);
911 mr->VolUseDuration = str_to_uint64(row[15]);
912 mr->MaxVolJobs = str_to_int64(row[16]);
913 mr->MaxVolFiles = str_to_int64(row[17]);
914 mr->Recycle = str_to_int64(row[18]);
915 mr->Slot = str_to_int64(row[19]);
916 bstrncpy(mr->cFirstWritten, row[20]!=NULL?row[20]:"", sizeof(mr->cFirstWritten));
917 mr->FirstWritten = (time_t)str_to_utime(mr->cFirstWritten);
918 bstrncpy(mr->cLastWritten, row[21]!=NULL?row[21]:"", sizeof(mr->cLastWritten));
919 mr->LastWritten = (time_t)str_to_utime(mr->cLastWritten);
920 mr->InChanger = str_to_uint64(row[22]);
921 mr->EndFile = str_to_uint64(row[23]);
922 mr->EndBlock = str_to_uint64(row[24]);
923 mr->VolParts = str_to_int64(row[25]);
924 mr->LabelType = str_to_int64(row[26]);
925 bstrncpy(mr->cLabelDate, row[27]!=NULL?row[27]:"", sizeof(mr->cLabelDate));
926 mr->LabelDate = (time_t)str_to_utime(mr->cLabelDate);
927 mr->StorageId = str_to_int64(row[28]);
928 mr->Enabled = str_to_int64(row[29]);
929 mr->LocationId = str_to_int64(row[30]);
930 mr->RecycleCount = str_to_int64(row[31]);
931 bstrncpy(mr->cInitialWrite, row[32]!=NULL?row[32]:"", sizeof(mr->cInitialWrite));
932 mr->InitialWrite = (time_t)str_to_utime(mr->cInitialWrite);
933 mr->ScratchPoolId = str_to_int64(row[33]);
934 mr->RecyclePoolId = str_to_int64(row[34]);
939 if (mr->MediaId != 0) {
940 Mmsg1(mdb->errmsg, _("Media record MediaId=%s not found.\n"),
941 edit_int64(mr->MediaId, ed1));
943 Mmsg1(mdb->errmsg, _("Media record for Volume \"%s\" not found.\n"),
947 sql_free_result(mdb);
949 if (mr->MediaId != 0) {
950 Mmsg(mdb->errmsg, _("Media record for MediaId=%u not found in Catalog.\n"),
953 Mmsg(mdb->errmsg, _("Media record for Vol=%s not found in Catalog.\n"),
961 #endif /* HAVE_SQLITE3 || HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL*/