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);
52 * Given a full filename (with path), look up the File record
53 * (with attributes) in the database.
55 * Returns: 0 on failure
56 * 1 on success with the File record in FILE_DBR
58 int db_get_file_attributes_record(JCR *jcr, B_DB *mdb, char *fname, JOB_DBR *jr, FILE_DBR *fdbr)
61 Dmsg1(100, "db_get_file_att_record fname=%s \n", fname);
64 split_path_and_file(jcr, mdb, fname);
66 fdbr->FilenameId = db_get_filename_record(jcr, mdb);
68 fdbr->PathId = db_get_path_record(jcr, mdb);
70 stat = db_get_file_record(jcr, mdb, jr, fdbr);
80 * Returns: 0 on failure
83 * DO NOT use Jmsg in this routine.
85 * Note in this routine, we do not use Jmsg because it may be
86 * called to get attributes of a non-existent file, which is
87 * "normal" if a new file is found during Verify.
90 int db_get_file_record(JCR *jcr, B_DB *mdb, JOB_DBR *jr, FILE_DBR *fdbr)
94 char ed1[50], ed2[50], ed3[50];
96 if (jcr->JobLevel == L_VERIFY_DISK_TO_CATALOG) {
98 "SELECT FileId, LStat, MD5 FROM File,Job WHERE "
99 "File.JobId=Job.JobId AND File.PathId=%s AND "
100 "File.FilenameId=%s AND Job.Type='B' AND Job.JobSTATUS='T' AND "
101 "ClientId=%s ORDER BY StartTime DESC LIMIT 1",
102 edit_int64(fdbr->PathId, ed1),
103 edit_int64(fdbr->FilenameId, ed2),
104 edit_int64(jr->ClientId,ed3));
108 "SELECT FileId, LStat, MD5 FROM File WHERE File.JobId=%s AND File.PathId=%s AND "
109 "File.FilenameId=%s",
110 edit_int64(fdbr->JobId, ed1),
111 edit_int64(fdbr->PathId, ed2),
112 edit_int64(fdbr->FilenameId,ed3));
114 Dmsg3(050, "Get_file_record JobId=%u FilenameId=%u PathId=%u\n",
115 fdbr->JobId, fdbr->FilenameId, fdbr->PathId);
117 Dmsg1(100, "Query=%s\n", mdb->cmd);
119 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
120 mdb->num_rows = sql_num_rows(mdb);
121 Dmsg1(050, "get_file_record num_rows=%d\n", (int)mdb->num_rows);
122 if (mdb->num_rows > 1) {
123 Mmsg1(mdb->errmsg, _("get_file_record want 1 got rows=%d\n"),
126 if (mdb->num_rows >= 1) {
127 if ((row = sql_fetch_row(mdb)) == NULL) {
128 Mmsg1(mdb->errmsg, _("Error fetching row: %s\n"), sql_strerror(mdb));
130 fdbr->FileId = (FileId_t)str_to_int64(row[0]);
131 bstrncpy(fdbr->LStat, row[1], sizeof(fdbr->LStat));
132 bstrncpy(fdbr->Digest, row[2], sizeof(fdbr->Digest));
136 Mmsg2(mdb->errmsg, _("File record for PathId=%s FilenameId=%s not found.\n"),
137 edit_int64(fdbr->PathId, ed1),
138 edit_int64(fdbr->FilenameId, ed2));
140 sql_free_result(mdb);
142 Mmsg(mdb->errmsg, _("File record not found in Catalog.\n"));
148 /* Get Filename record
149 * Returns: 0 on failure
150 * FilenameId on success
152 * DO NOT use Jmsg in this routine (see notes for get_file_record)
154 static int db_get_filename_record(JCR *jcr, B_DB *mdb)
159 mdb->esc_name = check_pool_memory_size(mdb->esc_name, 2*mdb->fnl+2);
160 db_escape_string(mdb->esc_name, mdb->fname, mdb->fnl);
162 Mmsg(mdb->cmd, "SELECT FilenameId FROM Filename WHERE Name='%s'", mdb->esc_name);
163 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
165 mdb->num_rows = sql_num_rows(mdb);
166 if (mdb->num_rows > 1) {
167 Mmsg2(mdb->errmsg, _("More than one Filename!: %s for file: %s\n"),
168 edit_uint64(mdb->num_rows, ed1), mdb->fname);
169 Jmsg(jcr, M_WARNING, 0, "%s", mdb->errmsg);
171 if (mdb->num_rows >= 1) {
172 if ((row = sql_fetch_row(mdb)) == NULL) {
173 Mmsg1(mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb));
175 FilenameId = str_to_int64(row[0]);
176 if (FilenameId <= 0) {
177 Mmsg2(mdb->errmsg, _("Get DB Filename record %s found bad record: %d\n"),
178 mdb->cmd, FilenameId);
183 Mmsg1(mdb->errmsg, _("Filename record: %s not found.\n"), mdb->fname);
185 sql_free_result(mdb);
187 Mmsg(mdb->errmsg, _("Filename record: %s not found in Catalog.\n"), mdb->fname);
193 * Returns: 0 on failure
196 * DO NOT use Jmsg in this routine (see notes for get_file_record)
198 static int db_get_path_record(JCR *jcr, B_DB *mdb)
203 mdb->esc_name = check_pool_memory_size(mdb->esc_name, 2*mdb->pnl+2);
204 db_escape_string(mdb->esc_name, mdb->path, mdb->pnl);
206 if (mdb->cached_path_id != 0 && mdb->cached_path_len == mdb->pnl &&
207 strcmp(mdb->cached_path, mdb->path) == 0) {
208 return mdb->cached_path_id;
211 Mmsg(mdb->cmd, "SELECT PathId FROM Path WHERE Path='%s'", mdb->esc_name);
213 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
215 mdb->num_rows = sql_num_rows(mdb);
216 if (mdb->num_rows > 1) {
217 Mmsg2(mdb->errmsg, _("More than one Path!: %s for path: %s\n"),
218 edit_uint64(mdb->num_rows, ed1), mdb->path);
219 Jmsg(jcr, M_WARNING, 0, "%s", mdb->errmsg);
221 /* Even if there are multiple paths, take the first one */
222 if (mdb->num_rows >= 1) {
223 if ((row = sql_fetch_row(mdb)) == NULL) {
224 Mmsg1(mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb));
226 PathId = str_to_int64(row[0]);
228 Mmsg2(mdb->errmsg, _("Get DB path record %s found bad record: %s\n"),
229 mdb->cmd, edit_int64(PathId, ed1));
233 if (PathId != mdb->cached_path_id) {
234 mdb->cached_path_id = PathId;
235 mdb->cached_path_len = mdb->pnl;
236 pm_strcpy(mdb->cached_path, mdb->path);
241 Mmsg1(mdb->errmsg, _("Path record: %s not found.\n"), mdb->path);
243 sql_free_result(mdb);
245 Mmsg(mdb->errmsg, _("Path record: %s not found in Catalog.\n"), mdb->path);
252 * Get Job record for given JobId or Job name
253 * Returns: false on failure
256 bool db_get_job_record(JCR *jcr, B_DB *mdb, JOB_DBR *jr)
262 if (jr->JobId == 0) {
263 Mmsg(mdb->cmd, "SELECT VolSessionId,VolSessionTime,"
264 "PoolId,StartTime,EndTime,JobFiles,JobBytes,JobTDate,Job,JobStatus,"
265 "Type,Level,ClientId,Name "
266 "FROM Job WHERE Job='%s'", jr->Job);
268 Mmsg(mdb->cmd, "SELECT VolSessionId,VolSessionTime,"
269 "PoolId,StartTime,EndTime,JobFiles,JobBytes,JobTDate,Job,JobStatus,"
270 "Type,Level,ClientId,Name,PriorJobId,RealEndTime "
271 "FROM Job WHERE JobId=%s",
272 edit_int64(jr->JobId, ed1));
275 if (!QUERY_DB(jcr, mdb, mdb->cmd)) {
277 return false; /* failed */
279 if ((row = sql_fetch_row(mdb)) == NULL) {
280 Mmsg1(mdb->errmsg, _("No Job found for JobId %s\n"), edit_int64(jr->JobId, ed1));
281 sql_free_result(mdb);
283 return false; /* failed */
286 jr->VolSessionId = str_to_uint64(row[0]);
287 jr->VolSessionTime = str_to_uint64(row[1]);
288 jr->PoolId = str_to_int64(row[2]);
289 bstrncpy(jr->cStartTime, row[3]!=NULL?row[3]:"", sizeof(jr->cStartTime));
290 bstrncpy(jr->cEndTime, row[4]!=NULL?row[4]:"", sizeof(jr->cEndTime));
291 jr->JobFiles = str_to_int64(row[5]);
292 jr->JobBytes = str_to_int64(row[6]);
293 jr->JobTDate = str_to_int64(row[7]);
294 bstrncpy(jr->Job, row[8]!=NULL?row[8]:"", sizeof(jr->Job));
295 jr->JobStatus = (int)*row[9];
296 jr->JobType = (int)*row[10];
297 jr->JobLevel = (int)*row[11];
298 jr->ClientId = str_to_uint64(row[12]!=NULL?row[12]:(char *)"");
299 bstrncpy(jr->Name, row[13]!=NULL?row[13]:"", sizeof(jr->Name));
300 jr->PriorJobId = str_to_uint64(row[14]!=NULL?row[14]:(char *)"");
301 bstrncpy(jr->cRealEndTime, row[15]!=NULL?row[15]:"", sizeof(jr->cRealEndTime));
302 sql_free_result(mdb);
309 * Find VolumeNames for a given JobId
310 * Returns: 0 on error or no Volumes found
311 * number of volumes on success
312 * Volumes are concatenated in VolumeNames
313 * separated by a vertical bar (|) in the order
314 * that they were written.
316 * Returns: number of volumes on success
318 int db_get_job_volume_names(JCR *jcr, B_DB *mdb, JobId_t JobId, POOLMEM **VolumeNames)
326 /* Get one entry per VolumeName, but "sort" by VolIndex */
328 "SELECT VolumeName,MAX(VolIndex) FROM JobMedia,Media WHERE "
329 "JobMedia.JobId=%s AND JobMedia.MediaId=Media.MediaId "
330 "GROUP BY VolumeName "
331 "ORDER BY 2 ASC", edit_int64(JobId,ed1));
333 Dmsg1(130, "VolNam=%s\n", mdb->cmd);
335 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
336 mdb->num_rows = sql_num_rows(mdb);
337 Dmsg1(130, "Num rows=%d\n", mdb->num_rows);
338 if (mdb->num_rows <= 0) {
339 Mmsg1(mdb->errmsg, _("No volumes found for JobId=%d\n"), JobId);
342 stat = mdb->num_rows;
343 for (i=0; i < stat; i++) {
344 if ((row = sql_fetch_row(mdb)) == NULL) {
345 Mmsg2(mdb->errmsg, _("Error fetching row %d: ERR=%s\n"), i, sql_strerror(mdb));
346 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
350 if (*VolumeNames[0] != 0) {
351 pm_strcat(VolumeNames, "|");
353 pm_strcat(VolumeNames, row[0]);
357 sql_free_result(mdb);
359 Mmsg(mdb->errmsg, _("No Volume for JobId %d found in Catalog.\n"), JobId);
366 * Find Volume parameters for a give JobId
367 * Returns: 0 on error or no Volumes found
368 * number of volumes on success
369 * List of Volumes and start/end file/blocks (malloced structure!)
371 * Returns: number of volumes on success
373 int db_get_job_volume_parameters(JCR *jcr, B_DB *mdb, JobId_t JobId, VOL_PARAMS **VolParams)
379 VOL_PARAMS *Vols = NULL;
383 "SELECT VolumeName,MediaType,FirstIndex,LastIndex,StartFile,"
384 "JobMedia.EndFile,StartBlock,JobMedia.EndBlock,Copy,"
386 " FROM JobMedia,Media WHERE JobMedia.JobId=%s"
387 " AND JobMedia.MediaId=Media.MediaId ORDER BY VolIndex,JobMediaId",
388 edit_int64(JobId, ed1));
390 Dmsg1(130, "VolNam=%s\n", mdb->cmd);
391 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
392 mdb->num_rows = sql_num_rows(mdb);
393 Dmsg1(200, "Num rows=%d\n", mdb->num_rows);
394 if (mdb->num_rows <= 0) {
395 Mmsg1(mdb->errmsg, _("No volumes found for JobId=%d\n"), JobId);
398 stat = mdb->num_rows;
401 *VolParams = Vols = (VOL_PARAMS *)malloc(stat * sizeof(VOL_PARAMS));
402 SId = (DBId_t *)malloc(stat * sizeof(DBId_t));
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);
414 bstrncpy(Vols[i].VolumeName, row[0], MAX_NAME_LENGTH);
415 bstrncpy(Vols[i].MediaType, row[1], MAX_NAME_LENGTH);
416 Vols[i].FirstIndex = str_to_uint64(row[2]);
417 Vols[i].LastIndex = str_to_uint64(row[3]);
418 Vols[i].StartFile = str_to_uint64(row[4]);
419 Vols[i].EndFile = str_to_uint64(row[5]);
420 Vols[i].StartBlock = str_to_uint64(row[6]);
421 Vols[i].EndBlock = str_to_uint64(row[7]);
422 // Vols[i].Copy = str_to_uint64(row[8]);
423 Vols[i].Slot = str_to_uint64(row[9]);
424 StorageId = str_to_uint64(row[10]);
425 Vols[i].Storage[0] = 0;
429 for (i=0; i < stat; i++) {
431 Mmsg(mdb->cmd, "SELECT Name from Storage WHERE StorageId=%s",
432 edit_int64(SId[i], ed1));
433 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
434 if ((row = sql_fetch_row(mdb)) != NULL) {
435 bstrncpy(Vols[i].Storage, row[0], MAX_NAME_LENGTH);
441 sql_free_result(mdb);
450 * Get the number of pool records
452 * Returns: -1 on failure
455 int db_get_num_pool_records(JCR *jcr, B_DB *mdb)
460 Mmsg(mdb->cmd, "SELECT count(*) from Pool");
461 stat = get_sql_record_max(jcr, mdb);
467 * This function returns a list of all the Pool record ids.
468 * The caller must free ids if non-NULL.
470 * Returns 0: on failure
473 int db_get_pool_ids(JCR *jcr, B_DB *mdb, int *num_ids, uint32_t *ids[])
482 Mmsg(mdb->cmd, "SELECT PoolId FROM Pool");
483 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
484 *num_ids = sql_num_rows(mdb);
486 id = (uint32_t *)malloc(*num_ids * sizeof(uint32_t));
487 while ((row = sql_fetch_row(mdb)) != NULL) {
488 id[i++] = str_to_uint64(row[0]);
492 sql_free_result(mdb);
495 Mmsg(mdb->errmsg, _("Pool id select failed: ERR=%s\n"), sql_strerror(mdb));
496 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
504 * This function returns a list of all the Client record ids.
505 * The caller must free ids if non-NULL.
507 * Returns 0: on failure
510 int db_get_client_ids(JCR *jcr, B_DB *mdb, int *num_ids, uint32_t *ids[])
519 Mmsg(mdb->cmd, "SELECT ClientId FROM Client");
520 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
521 *num_ids = sql_num_rows(mdb);
523 id = (uint32_t *)malloc(*num_ids * sizeof(uint32_t));
524 while ((row = sql_fetch_row(mdb)) != NULL) {
525 id[i++] = str_to_uint64(row[0]);
529 sql_free_result(mdb);
532 Mmsg(mdb->errmsg, _("Client id select failed: ERR=%s\n"), sql_strerror(mdb));
533 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
543 * If the PoolId is non-zero, we get its record,
544 * otherwise, we search on the PoolName
546 * Returns: false on failure
549 bool db_get_pool_record(JCR *jcr, B_DB *mdb, POOL_DBR *pdbr)
556 if (pdbr->PoolId != 0) { /* find by id */
558 "SELECT PoolId,Name,NumVols,MaxVols,UseOnce,UseCatalog,AcceptAnyVolume,"
559 "AutoPrune,Recycle,VolRetention,VolUseDuration,MaxVolJobs,MaxVolFiles,"
560 "MaxVolBytes,PoolType,LabelType,LabelFormat FROM Pool WHERE Pool.PoolId=%s",
561 edit_int64(pdbr->PoolId, ed1));
562 } else { /* find by name */
564 "SELECT PoolId,Name,NumVols,MaxVols,UseOnce,UseCatalog,AcceptAnyVolume,"
565 "AutoPrune,Recycle,VolRetention,VolUseDuration,MaxVolJobs,MaxVolFiles,"
566 "MaxVolBytes,PoolType,LabelType,LabelFormat FROM Pool WHERE Pool.Name='%s'",
570 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
571 mdb->num_rows = sql_num_rows(mdb);
572 if (mdb->num_rows > 1) {
574 Mmsg1(mdb->errmsg, _("More than one Pool!: %s\n"),
575 edit_uint64(mdb->num_rows, ed1));
576 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
577 } else if (mdb->num_rows == 1) {
578 if ((row = sql_fetch_row(mdb)) == NULL) {
579 Mmsg1(mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb));
580 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
582 pdbr->PoolId = str_to_int64(row[0]);
583 bstrncpy(pdbr->Name, row[1]!=NULL?row[1]:"", sizeof(pdbr->Name));
584 pdbr->NumVols = str_to_int64(row[2]);
585 pdbr->MaxVols = str_to_int64(row[3]);
586 pdbr->UseOnce = str_to_int64(row[4]);
587 pdbr->UseCatalog = str_to_int64(row[5]);
588 pdbr->AcceptAnyVolume = str_to_int64(row[6]);
589 pdbr->AutoPrune = str_to_int64(row[7]);
590 pdbr->Recycle = str_to_int64(row[8]);
591 pdbr->VolRetention = str_to_int64(row[9]);
592 pdbr->VolUseDuration = str_to_int64(row[10]);
593 pdbr->MaxVolJobs = str_to_int64(row[11]);
594 pdbr->MaxVolFiles = str_to_int64(row[12]);
595 pdbr->MaxVolBytes = str_to_uint64(row[13]);
596 bstrncpy(pdbr->PoolType, row[14]!=NULL?row[14]:"", sizeof(pdbr->PoolType));
597 pdbr->LabelType = str_to_int64(row[15]);
598 bstrncpy(pdbr->LabelFormat, row[16]!=NULL?row[16]:"", sizeof(pdbr->LabelFormat));
602 sql_free_result(mdb);
606 Mmsg(mdb->cmd, "SELECT count(*) from Media WHERE PoolId=%s",
607 edit_int64(pdbr->PoolId, ed1));
608 NumVols = get_sql_record_max(jcr, mdb);
609 Dmsg2(400, "Actual NumVols=%d Pool NumVols=%d\n", NumVols, pdbr->NumVols);
610 if (NumVols != pdbr->NumVols) {
611 pdbr->NumVols = NumVols;
612 db_update_pool_record(jcr, mdb, pdbr);
615 Mmsg(mdb->errmsg, _("Pool record not found in Catalog.\n"));
622 * If the ClientId is non-zero, we get its record,
623 * otherwise, we search on the Client Name
625 * Returns: 0 on failure
628 int db_get_client_record(JCR *jcr, B_DB *mdb, CLIENT_DBR *cdbr)
635 if (cdbr->ClientId != 0) { /* find by id */
637 "SELECT ClientId,Name,Uname,AutoPrune,FileRetention,JobRetention "
638 "FROM Client WHERE Client.ClientId=%s",
639 edit_int64(cdbr->ClientId, ed1));
640 } else { /* find by name */
642 "SELECT ClientId,Name,Uname,AutoPrune,FileRetention,JobRetention "
643 "FROM Client WHERE Client.Name='%s'", cdbr->Name);
646 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
647 mdb->num_rows = sql_num_rows(mdb);
648 if (mdb->num_rows > 1) {
649 Mmsg1(mdb->errmsg, _("More than one Client!: %s\n"),
650 edit_uint64(mdb->num_rows, ed1));
651 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
652 } else if (mdb->num_rows == 1) {
653 if ((row = sql_fetch_row(mdb)) == NULL) {
654 Mmsg1(mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb));
655 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
657 cdbr->ClientId = str_to_int64(row[0]);
658 bstrncpy(cdbr->Name, row[1]!=NULL?row[1]:"", sizeof(cdbr->Name));
659 bstrncpy(cdbr->Uname, row[2]!=NULL?row[2]:"", sizeof(cdbr->Uname));
660 cdbr->AutoPrune = str_to_int64(row[3]);
661 cdbr->FileRetention = str_to_int64(row[4]);
662 cdbr->JobRetention = str_to_int64(row[5]);
666 Mmsg(mdb->errmsg, _("Client record not found in Catalog.\n"));
668 sql_free_result(mdb);
670 Mmsg(mdb->errmsg, _("Client record not found in Catalog.\n"));
679 * Returns: 0 on failure
682 int db_get_counter_record(JCR *jcr, B_DB *mdb, COUNTER_DBR *cr)
687 Mmsg(mdb->cmd, "SELECT MinValue,MaxValue,CurrentValue,WrapCounter "
688 "FROM Counters WHERE Counter='%s'", cr->Counter);
690 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
691 mdb->num_rows = sql_num_rows(mdb);
693 /* If more than one, report error, but return first row */
694 if (mdb->num_rows > 1) {
695 Mmsg1(mdb->errmsg, _("More than one Counter!: %d\n"), (int)(mdb->num_rows));
696 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
698 if (mdb->num_rows >= 1) {
699 if ((row = sql_fetch_row(mdb)) == NULL) {
700 Mmsg1(mdb->errmsg, _("error fetching Counter row: %s\n"), sql_strerror(mdb));
701 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
702 sql_free_result(mdb);
706 cr->MinValue = str_to_int64(row[0]);
707 cr->MaxValue = str_to_int64(row[1]);
708 cr->CurrentValue = str_to_int64(row[2]);
710 bstrncpy(cr->WrapCounter, row[3], sizeof(cr->WrapCounter));
712 cr->WrapCounter[0] = 0;
714 sql_free_result(mdb);
718 sql_free_result(mdb);
720 Mmsg(mdb->errmsg, _("Counter record: %s not found in Catalog.\n"), cr->Counter);
727 /* Get FileSet Record
728 * If the FileSetId is non-zero, we get its record,
729 * otherwise, we search on the name
731 * Returns: 0 on failure
734 int db_get_fileset_record(JCR *jcr, B_DB *mdb, FILESET_DBR *fsr)
741 if (fsr->FileSetId != 0) { /* find by id */
743 "SELECT FileSetId,FileSet,MD5,CreateTime FROM FileSet "
744 "WHERE FileSetId=%s",
745 edit_int64(fsr->FileSetId, ed1));
746 } else { /* find by name */
748 "SELECT FileSetId,FileSet,MD5,CreateTime FROM FileSet "
749 "WHERE FileSet='%s' ORDER BY CreateTime DESC LIMIT 1", fsr->FileSet);
752 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
753 mdb->num_rows = sql_num_rows(mdb);
754 if (mdb->num_rows > 1) {
756 Mmsg1(mdb->errmsg, _("Error got %s FileSets but expected only one!\n"),
757 edit_uint64(mdb->num_rows, ed1));
758 sql_data_seek(mdb, mdb->num_rows-1);
760 if ((row = sql_fetch_row(mdb)) == NULL) {
761 Mmsg1(mdb->errmsg, _("FileSet record \"%s\" not found.\n"), fsr->FileSet);
763 fsr->FileSetId = str_to_int64(row[0]);
764 bstrncpy(fsr->FileSet, row[1]!=NULL?row[1]:"", sizeof(fsr->FileSet));
765 bstrncpy(fsr->MD5, row[2]!=NULL?row[2]:"", sizeof(fsr->MD5));
766 bstrncpy(fsr->cCreateTime, row[3]!=NULL?row[3]:"", sizeof(fsr->cCreateTime));
767 stat = fsr->FileSetId;
769 sql_free_result(mdb);
771 Mmsg(mdb->errmsg, _("FileSet record not found in Catalog.\n"));
779 * Get the number of Media records
781 * Returns: -1 on failure
784 int db_get_num_media_records(JCR *jcr, B_DB *mdb)
789 Mmsg(mdb->cmd, "SELECT count(*) from Media");
790 stat = get_sql_record_max(jcr, mdb);
797 * This function returns a list of all the Media record ids for
799 * The caller must free ids if non-NULL.
801 * Returns false: on failure
804 bool db_get_media_ids(JCR *jcr, B_DB *mdb, uint32_t PoolId, int *num_ids, uint32_t *ids[])
814 Mmsg(mdb->cmd, "SELECT MediaId FROM Media WHERE PoolId=%s",
815 edit_int64(PoolId, ed1));
816 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
817 *num_ids = sql_num_rows(mdb);
819 id = (uint32_t *)malloc(*num_ids * sizeof(uint32_t));
820 while ((row = sql_fetch_row(mdb)) != NULL) {
821 id[i++] = str_to_uint64(row[0]);
825 sql_free_result(mdb);
828 Mmsg(mdb->errmsg, _("Media id select failed: ERR=%s\n"), sql_strerror(mdb));
829 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
839 * Returns: false: on failure
842 bool db_get_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr)
849 if (mr->MediaId == 0 && mr->VolumeName[0] == 0) {
850 Mmsg(mdb->cmd, "SELECT count(*) from Media");
851 mr->MediaId = get_sql_record_max(jcr, mdb);
855 if (mr->MediaId != 0) { /* find by id */
856 Mmsg(mdb->cmd, "SELECT MediaId,VolumeName,VolJobs,VolFiles,VolBlocks,"
857 "VolBytes,VolMounts,VolErrors,VolWrites,MaxVolBytes,VolCapacityBytes,"
858 "MediaType,VolStatus,PoolId,VolRetention,VolUseDuration,MaxVolJobs,"
859 "MaxVolFiles,Recycle,Slot,FirstWritten,LastWritten,InChanger,"
860 "EndFile,EndBlock,VolParts,LabelType,LabelDate,StorageId,"
861 "Enabled,LocationId,RecycleCount,InitialWrite,"
862 "ScratchPoolId,RecyclePoolId "
863 "FROM Media WHERE MediaId=%s",
864 edit_int64(mr->MediaId, ed1));
865 } else { /* find by name */
866 Mmsg(mdb->cmd, "SELECT MediaId,VolumeName,VolJobs,VolFiles,VolBlocks,"
867 "VolBytes,VolMounts,VolErrors,VolWrites,MaxVolBytes,VolCapacityBytes,"
868 "MediaType,VolStatus,PoolId,VolRetention,VolUseDuration,MaxVolJobs,"
869 "MaxVolFiles,Recycle,Slot,FirstWritten,LastWritten,InChanger,"
870 "EndFile,EndBlock,VolParts,LabelType,LabelDate,StorageId,"
871 "Enabled,LocationId,RecycleCount,InitialWrite,"
872 "ScratchPoolId,RecyclePoolId "
873 "FROM Media WHERE VolumeName='%s'", mr->VolumeName);
876 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
878 mdb->num_rows = sql_num_rows(mdb);
879 if (mdb->num_rows > 1) {
880 Mmsg1(mdb->errmsg, _("More than one Volume!: %s\n"),
881 edit_uint64(mdb->num_rows, ed1));
882 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
883 } else if (mdb->num_rows == 1) {
884 if ((row = sql_fetch_row(mdb)) == NULL) {
885 Mmsg1(mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb));
886 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
889 mr->MediaId = str_to_int64(row[0]);
890 bstrncpy(mr->VolumeName, row[1]!=NULL?row[1]:"", sizeof(mr->VolumeName));
891 mr->VolJobs = str_to_int64(row[2]);
892 mr->VolFiles = str_to_int64(row[3]);
893 mr->VolBlocks = str_to_int64(row[4]);
894 mr->VolBytes = str_to_uint64(row[5]);
895 mr->VolMounts = str_to_int64(row[6]);
896 mr->VolErrors = str_to_int64(row[7]);
897 mr->VolWrites = str_to_int64(row[8]);
898 mr->MaxVolBytes = str_to_uint64(row[9]);
899 mr->VolCapacityBytes = str_to_uint64(row[10]);
900 bstrncpy(mr->MediaType, row[11]!=NULL?row[11]:"", sizeof(mr->MediaType));
901 bstrncpy(mr->VolStatus, row[12]!=NULL?row[12]:"", sizeof(mr->VolStatus));
902 mr->PoolId = str_to_int64(row[13]);
903 mr->VolRetention = str_to_uint64(row[14]);
904 mr->VolUseDuration = str_to_uint64(row[15]);
905 mr->MaxVolJobs = str_to_int64(row[16]);
906 mr->MaxVolFiles = str_to_int64(row[17]);
907 mr->Recycle = str_to_int64(row[18]);
908 mr->Slot = str_to_int64(row[19]);
909 bstrncpy(mr->cFirstWritten, row[20]!=NULL?row[20]:"", sizeof(mr->cFirstWritten));
910 mr->FirstWritten = (time_t)str_to_utime(mr->cFirstWritten);
911 bstrncpy(mr->cLastWritten, row[21]!=NULL?row[21]:"", sizeof(mr->cLastWritten));
912 mr->LastWritten = (time_t)str_to_utime(mr->cLastWritten);
913 mr->InChanger = str_to_uint64(row[22]);
914 mr->EndFile = str_to_uint64(row[23]);
915 mr->EndBlock = str_to_uint64(row[24]);
916 mr->VolParts = str_to_int64(row[25]);
917 mr->LabelType = str_to_int64(row[26]);
918 bstrncpy(mr->cLabelDate, row[27]!=NULL?row[27]:"", sizeof(mr->cLabelDate));
919 mr->LabelDate = (time_t)str_to_utime(mr->cLabelDate);
920 mr->StorageId = str_to_int64(row[28]);
921 mr->Enabled = str_to_int64(row[29]);
922 mr->LocationId = str_to_int64(row[30]);
923 mr->RecycleCount = str_to_int64(row[31]);
924 bstrncpy(mr->cInitialWrite, row[32]!=NULL?row[32]:"", sizeof(mr->cInitialWrite));
925 mr->InitialWrite = (time_t)str_to_utime(mr->cInitialWrite);
926 mr->ScratchPoolId = str_to_int64(row[33]);
927 mr->RecyclePoolId = str_to_int64(row[34]);
932 if (mr->MediaId != 0) {
933 Mmsg1(mdb->errmsg, _("Media record MediaId=%s not found.\n"),
934 edit_int64(mr->MediaId, ed1));
936 Mmsg1(mdb->errmsg, _("Media record for Volume \"%s\" not found.\n"),
940 sql_free_result(mdb);
942 if (mr->MediaId != 0) {
943 Mmsg(mdb->errmsg, _("Media record for MediaId=%u not found in Catalog.\n"),
946 Mmsg(mdb->errmsg, _("Media record for Vol=%s not found in Catalog.\n"),
954 #endif /* HAVE_SQLITE3 || HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL*/