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
12 Bacula® - The Network Backup Solution
14 Copyright (C) 2000-2007 Free Software Foundation Europe e.V.
16 The main author of Bacula is Kern Sibbald, with contributions from
17 many others, a complete list can be found in the file AUTHORS.
18 This program is Free Software; you can redistribute it and/or
19 modify it under the terms of version two of the GNU General Public
20 License as published by the Free Software Foundation plus additions
21 that are listed in the file LICENSE.
23 This program is distributed in the hope that it will be useful, but
24 WITHOUT ANY WARRANTY; without even the implied warranty of
25 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
26 General Public License for more details.
28 You should have received a copy of the GNU General Public License
29 along with this program; if not, write to the Free Software
30 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
33 Bacula® is a registered trademark of John Walker.
34 The licensor of Bacula is the Free Software Foundation Europe
35 (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
36 Switzerland, email:ftf@fsfeurope.org.
41 /* The following is necessary so that we do not include
42 * the dummy external definition of DB.
44 #define __SQL_C /* indicate that this is sql.c */
49 #if HAVE_SQLITE3 || HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL
51 /* -----------------------------------------------------------------------
53 * Generic Routines (or almost generic)
55 * -----------------------------------------------------------------------
58 /* Forward referenced functions */
59 static int db_get_file_record(JCR *jcr, B_DB *mdb, JOB_DBR *jr, FILE_DBR *fdbr);
60 static int db_get_filename_record(JCR *jcr, B_DB *mdb);
61 static int db_get_path_record(JCR *jcr, B_DB *mdb);
65 * Given a full filename (with path), look up the File record
66 * (with attributes) in the database.
68 * Returns: 0 on failure
69 * 1 on success with the File record in FILE_DBR
71 int db_get_file_attributes_record(JCR *jcr, B_DB *mdb, char *fname, JOB_DBR *jr, FILE_DBR *fdbr)
74 Dmsg1(100, "db_get_file_att_record fname=%s \n", fname);
77 split_path_and_file(jcr, mdb, fname);
79 fdbr->FilenameId = db_get_filename_record(jcr, mdb);
81 fdbr->PathId = db_get_path_record(jcr, mdb);
83 stat = db_get_file_record(jcr, mdb, jr, fdbr);
93 * Returns: 0 on failure
96 * DO NOT use Jmsg in this routine.
98 * Note in this routine, we do not use Jmsg because it may be
99 * called to get attributes of a non-existent file, which is
100 * "normal" if a new file is found during Verify.
103 int db_get_file_record(JCR *jcr, B_DB *mdb, JOB_DBR *jr, FILE_DBR *fdbr)
107 char ed1[50], ed2[50], ed3[50];
109 if (jcr->JobLevel == L_VERIFY_DISK_TO_CATALOG) {
111 "SELECT FileId, LStat, MD5 FROM File,Job WHERE "
112 "File.JobId=Job.JobId AND File.PathId=%s AND "
113 "File.FilenameId=%s AND Job.Type='B' AND Job.JobSTATUS='T' AND "
114 "ClientId=%s ORDER BY StartTime DESC LIMIT 1",
115 edit_int64(fdbr->PathId, ed1),
116 edit_int64(fdbr->FilenameId, ed2),
117 edit_int64(jr->ClientId,ed3));
121 "SELECT FileId, LStat, MD5 FROM File WHERE File.JobId=%s AND File.PathId=%s AND "
122 "File.FilenameId=%s",
123 edit_int64(fdbr->JobId, ed1),
124 edit_int64(fdbr->PathId, ed2),
125 edit_int64(fdbr->FilenameId,ed3));
127 Dmsg3(050, "Get_file_record JobId=%u FilenameId=%u PathId=%u\n",
128 fdbr->JobId, fdbr->FilenameId, fdbr->PathId);
130 Dmsg1(100, "Query=%s\n", mdb->cmd);
132 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
133 mdb->num_rows = sql_num_rows(mdb);
134 Dmsg1(050, "get_file_record num_rows=%d\n", (int)mdb->num_rows);
135 if (mdb->num_rows > 1) {
136 Mmsg1(mdb->errmsg, _("get_file_record want 1 got rows=%d\n"),
139 if (mdb->num_rows >= 1) {
140 if ((row = sql_fetch_row(mdb)) == NULL) {
141 Mmsg1(mdb->errmsg, _("Error fetching row: %s\n"), sql_strerror(mdb));
143 fdbr->FileId = (FileId_t)str_to_int64(row[0]);
144 bstrncpy(fdbr->LStat, row[1], sizeof(fdbr->LStat));
145 bstrncpy(fdbr->Digest, row[2], sizeof(fdbr->Digest));
149 Mmsg2(mdb->errmsg, _("File record for PathId=%s FilenameId=%s not found.\n"),
150 edit_int64(fdbr->PathId, ed1),
151 edit_int64(fdbr->FilenameId, ed2));
153 sql_free_result(mdb);
155 Mmsg(mdb->errmsg, _("File record not found in Catalog.\n"));
161 /* Get Filename record
162 * Returns: 0 on failure
163 * FilenameId on success
165 * DO NOT use Jmsg in this routine (see notes for get_file_record)
167 static int db_get_filename_record(JCR *jcr, B_DB *mdb)
172 mdb->esc_name = check_pool_memory_size(mdb->esc_name, 2*mdb->fnl+2);
173 db_escape_string(mdb->esc_name, mdb->fname, mdb->fnl);
175 Mmsg(mdb->cmd, "SELECT FilenameId FROM Filename WHERE Name='%s'", mdb->esc_name);
176 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
178 mdb->num_rows = sql_num_rows(mdb);
179 if (mdb->num_rows > 1) {
180 Mmsg2(mdb->errmsg, _("More than one Filename!: %s for file: %s\n"),
181 edit_uint64(mdb->num_rows, ed1), mdb->fname);
182 Jmsg(jcr, M_WARNING, 0, "%s", mdb->errmsg);
184 if (mdb->num_rows >= 1) {
185 if ((row = sql_fetch_row(mdb)) == NULL) {
186 Mmsg1(mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb));
188 FilenameId = str_to_int64(row[0]);
189 if (FilenameId <= 0) {
190 Mmsg2(mdb->errmsg, _("Get DB Filename record %s found bad record: %d\n"),
191 mdb->cmd, FilenameId);
196 Mmsg1(mdb->errmsg, _("Filename record: %s not found.\n"), mdb->fname);
198 sql_free_result(mdb);
200 Mmsg(mdb->errmsg, _("Filename record: %s not found in Catalog.\n"), mdb->fname);
206 * Returns: 0 on failure
209 * DO NOT use Jmsg in this routine (see notes for get_file_record)
211 static int db_get_path_record(JCR *jcr, B_DB *mdb)
216 mdb->esc_name = check_pool_memory_size(mdb->esc_name, 2*mdb->pnl+2);
217 db_escape_string(mdb->esc_name, mdb->path, mdb->pnl);
219 if (mdb->cached_path_id != 0 && mdb->cached_path_len == mdb->pnl &&
220 strcmp(mdb->cached_path, mdb->path) == 0) {
221 return mdb->cached_path_id;
224 Mmsg(mdb->cmd, "SELECT PathId FROM Path WHERE Path='%s'", mdb->esc_name);
226 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
228 mdb->num_rows = sql_num_rows(mdb);
229 if (mdb->num_rows > 1) {
230 Mmsg2(mdb->errmsg, _("More than one Path!: %s for path: %s\n"),
231 edit_uint64(mdb->num_rows, ed1), mdb->path);
232 Jmsg(jcr, M_WARNING, 0, "%s", mdb->errmsg);
234 /* Even if there are multiple paths, take the first one */
235 if (mdb->num_rows >= 1) {
236 if ((row = sql_fetch_row(mdb)) == NULL) {
237 Mmsg1(mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb));
239 PathId = str_to_int64(row[0]);
241 Mmsg2(mdb->errmsg, _("Get DB path record %s found bad record: %s\n"),
242 mdb->cmd, edit_int64(PathId, ed1));
246 if (PathId != mdb->cached_path_id) {
247 mdb->cached_path_id = PathId;
248 mdb->cached_path_len = mdb->pnl;
249 pm_strcpy(mdb->cached_path, mdb->path);
254 Mmsg1(mdb->errmsg, _("Path record: %s not found.\n"), mdb->path);
256 sql_free_result(mdb);
258 Mmsg(mdb->errmsg, _("Path record: %s not found in Catalog.\n"), mdb->path);
265 * Get Job record for given JobId or Job name
266 * Returns: false on failure
269 bool db_get_job_record(JCR *jcr, B_DB *mdb, JOB_DBR *jr)
275 if (jr->JobId == 0) {
276 Mmsg(mdb->cmd, "SELECT VolSessionId,VolSessionTime,"
277 "PoolId,StartTime,EndTime,JobFiles,JobBytes,JobTDate,Job,JobStatus,"
278 "Type,Level,ClientId,Name,PriorJobId,RealEndTime,JobId "
279 "FROM Job WHERE Job='%s'", jr->Job);
281 Mmsg(mdb->cmd, "SELECT VolSessionId,VolSessionTime,"
282 "PoolId,StartTime,EndTime,JobFiles,JobBytes,JobTDate,Job,JobStatus,"
283 "Type,Level,ClientId,Name,PriorJobId,RealEndTime,JobId "
284 "FROM Job WHERE JobId=%s",
285 edit_int64(jr->JobId, ed1));
288 if (!QUERY_DB(jcr, mdb, mdb->cmd)) {
290 return false; /* failed */
292 if ((row = sql_fetch_row(mdb)) == NULL) {
293 Mmsg1(mdb->errmsg, _("No Job found for JobId %s\n"), edit_int64(jr->JobId, ed1));
294 sql_free_result(mdb);
296 return false; /* failed */
299 jr->VolSessionId = str_to_uint64(row[0]);
300 jr->VolSessionTime = str_to_uint64(row[1]);
301 jr->PoolId = str_to_int64(row[2]);
302 bstrncpy(jr->cStartTime, row[3]!=NULL?row[3]:"", sizeof(jr->cStartTime));
303 bstrncpy(jr->cEndTime, row[4]!=NULL?row[4]:"", sizeof(jr->cEndTime));
304 jr->JobFiles = str_to_int64(row[5]);
305 jr->JobBytes = str_to_int64(row[6]);
306 jr->JobTDate = str_to_int64(row[7]);
307 bstrncpy(jr->Job, row[8]!=NULL?row[8]:"", sizeof(jr->Job));
308 jr->JobStatus = (int)*row[9];
309 jr->JobType = (int)*row[10];
310 jr->JobLevel = (int)*row[11];
311 jr->ClientId = str_to_uint64(row[12]!=NULL?row[12]:(char *)"");
312 bstrncpy(jr->Name, row[13]!=NULL?row[13]:"", sizeof(jr->Name));
313 jr->PriorJobId = str_to_uint64(row[14]!=NULL?row[14]:(char *)"");
314 bstrncpy(jr->cRealEndTime, row[15]!=NULL?row[15]:"", sizeof(jr->cRealEndTime));
315 if (jr->JobId == 0) {
316 jr->JobId = str_to_int64(row[16]);
318 sql_free_result(mdb);
325 * Find VolumeNames for a given JobId
326 * Returns: 0 on error or no Volumes found
327 * number of volumes on success
328 * Volumes are concatenated in VolumeNames
329 * separated by a vertical bar (|) in the order
330 * that they were written.
332 * Returns: number of volumes on success
334 int db_get_job_volume_names(JCR *jcr, B_DB *mdb, JobId_t JobId, POOLMEM **VolumeNames)
342 /* Get one entry per VolumeName, but "sort" by VolIndex */
344 "SELECT VolumeName,MAX(VolIndex) FROM JobMedia,Media WHERE "
345 "JobMedia.JobId=%s AND JobMedia.MediaId=Media.MediaId "
346 "GROUP BY VolumeName "
347 "ORDER BY 2 ASC", edit_int64(JobId,ed1));
349 Dmsg1(130, "VolNam=%s\n", mdb->cmd);
351 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
352 mdb->num_rows = sql_num_rows(mdb);
353 Dmsg1(130, "Num rows=%d\n", mdb->num_rows);
354 if (mdb->num_rows <= 0) {
355 Mmsg1(mdb->errmsg, _("No volumes found for JobId=%d\n"), JobId);
358 stat = mdb->num_rows;
359 for (i=0; i < stat; i++) {
360 if ((row = sql_fetch_row(mdb)) == NULL) {
361 Mmsg2(mdb->errmsg, _("Error fetching row %d: ERR=%s\n"), i, sql_strerror(mdb));
362 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
366 if (*VolumeNames[0] != 0) {
367 pm_strcat(VolumeNames, "|");
369 pm_strcat(VolumeNames, row[0]);
373 sql_free_result(mdb);
375 Mmsg(mdb->errmsg, _("No Volume for JobId %d found in Catalog.\n"), JobId);
382 * Find Volume parameters for a give JobId
383 * Returns: 0 on error or no Volumes found
384 * number of volumes on success
385 * List of Volumes and start/end file/blocks (malloced structure!)
387 * Returns: number of volumes on success
389 int db_get_job_volume_parameters(JCR *jcr, B_DB *mdb, JobId_t JobId, VOL_PARAMS **VolParams)
395 VOL_PARAMS *Vols = NULL;
399 "SELECT VolumeName,MediaType,FirstIndex,LastIndex,StartFile,"
400 "JobMedia.EndFile,StartBlock,JobMedia.EndBlock,Copy,"
402 " FROM JobMedia,Media WHERE JobMedia.JobId=%s"
403 " AND JobMedia.MediaId=Media.MediaId ORDER BY VolIndex,JobMediaId",
404 edit_int64(JobId, ed1));
406 Dmsg1(130, "VolNam=%s\n", mdb->cmd);
407 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
408 mdb->num_rows = sql_num_rows(mdb);
409 Dmsg1(200, "Num rows=%d\n", mdb->num_rows);
410 if (mdb->num_rows <= 0) {
411 Mmsg1(mdb->errmsg, _("No volumes found for JobId=%d\n"), JobId);
414 stat = mdb->num_rows;
417 *VolParams = Vols = (VOL_PARAMS *)malloc(stat * sizeof(VOL_PARAMS));
418 SId = (DBId_t *)malloc(stat * sizeof(DBId_t));
422 for (i=0; i < stat; i++) {
423 if ((row = sql_fetch_row(mdb)) == NULL) {
424 Mmsg2(mdb->errmsg, _("Error fetching row %d: ERR=%s\n"), i, sql_strerror(mdb));
425 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
430 bstrncpy(Vols[i].VolumeName, row[0], MAX_NAME_LENGTH);
431 bstrncpy(Vols[i].MediaType, row[1], MAX_NAME_LENGTH);
432 Vols[i].FirstIndex = str_to_uint64(row[2]);
433 Vols[i].LastIndex = str_to_uint64(row[3]);
434 Vols[i].StartFile = str_to_uint64(row[4]);
435 Vols[i].EndFile = str_to_uint64(row[5]);
436 Vols[i].StartBlock = str_to_uint64(row[6]);
437 Vols[i].EndBlock = str_to_uint64(row[7]);
438 // Vols[i].Copy = str_to_uint64(row[8]);
439 Vols[i].Slot = str_to_uint64(row[9]);
440 StorageId = str_to_uint64(row[10]);
441 Vols[i].Storage[0] = 0;
445 for (i=0; i < stat; i++) {
447 Mmsg(mdb->cmd, "SELECT Name from Storage WHERE StorageId=%s",
448 edit_int64(SId[i], ed1));
449 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
450 if ((row = sql_fetch_row(mdb)) != NULL) {
451 bstrncpy(Vols[i].Storage, row[0], MAX_NAME_LENGTH);
457 sql_free_result(mdb);
466 * Get the number of pool records
468 * Returns: -1 on failure
471 int db_get_num_pool_records(JCR *jcr, B_DB *mdb)
476 Mmsg(mdb->cmd, "SELECT count(*) from Pool");
477 stat = get_sql_record_max(jcr, mdb);
483 * This function returns a list of all the Pool record ids.
484 * The caller must free ids if non-NULL.
486 * Returns 0: on failure
489 int db_get_pool_ids(JCR *jcr, B_DB *mdb, int *num_ids, uint32_t *ids[])
498 Mmsg(mdb->cmd, "SELECT PoolId FROM Pool");
499 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
500 *num_ids = sql_num_rows(mdb);
502 id = (uint32_t *)malloc(*num_ids * sizeof(uint32_t));
503 while ((row = sql_fetch_row(mdb)) != NULL) {
504 id[i++] = str_to_uint64(row[0]);
508 sql_free_result(mdb);
511 Mmsg(mdb->errmsg, _("Pool id select failed: ERR=%s\n"), sql_strerror(mdb));
512 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
520 * This function returns a list of all the Client record ids.
521 * The caller must free ids if non-NULL.
523 * Returns 0: on failure
526 int db_get_client_ids(JCR *jcr, B_DB *mdb, int *num_ids, uint32_t *ids[])
535 Mmsg(mdb->cmd, "SELECT ClientId FROM Client");
536 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
537 *num_ids = sql_num_rows(mdb);
539 id = (uint32_t *)malloc(*num_ids * sizeof(uint32_t));
540 while ((row = sql_fetch_row(mdb)) != NULL) {
541 id[i++] = str_to_uint64(row[0]);
545 sql_free_result(mdb);
548 Mmsg(mdb->errmsg, _("Client id select failed: ERR=%s\n"), sql_strerror(mdb));
549 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
559 * If the PoolId is non-zero, we get its record,
560 * otherwise, we search on the PoolName
562 * Returns: false on failure
565 bool db_get_pool_record(JCR *jcr, B_DB *mdb, POOL_DBR *pdbr)
572 if (pdbr->PoolId != 0) { /* find by id */
574 "SELECT PoolId,Name,NumVols,MaxVols,UseOnce,UseCatalog,AcceptAnyVolume,"
575 "AutoPrune,Recycle,VolRetention,VolUseDuration,MaxVolJobs,MaxVolFiles,"
576 "MaxVolBytes,PoolType,LabelType,LabelFormat FROM Pool WHERE Pool.PoolId=%s",
577 edit_int64(pdbr->PoolId, ed1));
578 } else { /* find by name */
580 "SELECT PoolId,Name,NumVols,MaxVols,UseOnce,UseCatalog,AcceptAnyVolume,"
581 "AutoPrune,Recycle,VolRetention,VolUseDuration,MaxVolJobs,MaxVolFiles,"
582 "MaxVolBytes,PoolType,LabelType,LabelFormat FROM Pool WHERE Pool.Name='%s'",
586 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
587 mdb->num_rows = sql_num_rows(mdb);
588 if (mdb->num_rows > 1) {
590 Mmsg1(mdb->errmsg, _("More than one Pool!: %s\n"),
591 edit_uint64(mdb->num_rows, ed1));
592 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
593 } else if (mdb->num_rows == 1) {
594 if ((row = sql_fetch_row(mdb)) == NULL) {
595 Mmsg1(mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb));
596 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
598 pdbr->PoolId = str_to_int64(row[0]);
599 bstrncpy(pdbr->Name, row[1]!=NULL?row[1]:"", sizeof(pdbr->Name));
600 pdbr->NumVols = str_to_int64(row[2]);
601 pdbr->MaxVols = str_to_int64(row[3]);
602 pdbr->UseOnce = str_to_int64(row[4]);
603 pdbr->UseCatalog = str_to_int64(row[5]);
604 pdbr->AcceptAnyVolume = str_to_int64(row[6]);
605 pdbr->AutoPrune = str_to_int64(row[7]);
606 pdbr->Recycle = str_to_int64(row[8]);
607 pdbr->VolRetention = str_to_int64(row[9]);
608 pdbr->VolUseDuration = str_to_int64(row[10]);
609 pdbr->MaxVolJobs = str_to_int64(row[11]);
610 pdbr->MaxVolFiles = str_to_int64(row[12]);
611 pdbr->MaxVolBytes = str_to_uint64(row[13]);
612 bstrncpy(pdbr->PoolType, row[14]!=NULL?row[14]:"", sizeof(pdbr->PoolType));
613 pdbr->LabelType = str_to_int64(row[15]);
614 bstrncpy(pdbr->LabelFormat, row[16]!=NULL?row[16]:"", sizeof(pdbr->LabelFormat));
618 sql_free_result(mdb);
622 Mmsg(mdb->cmd, "SELECT count(*) from Media WHERE PoolId=%s",
623 edit_int64(pdbr->PoolId, ed1));
624 NumVols = get_sql_record_max(jcr, mdb);
625 Dmsg2(400, "Actual NumVols=%d Pool NumVols=%d\n", NumVols, pdbr->NumVols);
626 if (NumVols != pdbr->NumVols) {
627 pdbr->NumVols = NumVols;
628 db_update_pool_record(jcr, mdb, pdbr);
631 Mmsg(mdb->errmsg, _("Pool record not found in Catalog.\n"));
638 * If the ClientId is non-zero, we get its record,
639 * otherwise, we search on the Client Name
641 * Returns: 0 on failure
644 int db_get_client_record(JCR *jcr, B_DB *mdb, CLIENT_DBR *cdbr)
651 if (cdbr->ClientId != 0) { /* find by id */
653 "SELECT ClientId,Name,Uname,AutoPrune,FileRetention,JobRetention "
654 "FROM Client WHERE Client.ClientId=%s",
655 edit_int64(cdbr->ClientId, ed1));
656 } else { /* find by name */
658 "SELECT ClientId,Name,Uname,AutoPrune,FileRetention,JobRetention "
659 "FROM Client WHERE Client.Name='%s'", cdbr->Name);
662 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
663 mdb->num_rows = sql_num_rows(mdb);
664 if (mdb->num_rows > 1) {
665 Mmsg1(mdb->errmsg, _("More than one Client!: %s\n"),
666 edit_uint64(mdb->num_rows, ed1));
667 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
668 } else if (mdb->num_rows == 1) {
669 if ((row = sql_fetch_row(mdb)) == NULL) {
670 Mmsg1(mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb));
671 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
673 cdbr->ClientId = str_to_int64(row[0]);
674 bstrncpy(cdbr->Name, row[1]!=NULL?row[1]:"", sizeof(cdbr->Name));
675 bstrncpy(cdbr->Uname, row[2]!=NULL?row[2]:"", sizeof(cdbr->Uname));
676 cdbr->AutoPrune = str_to_int64(row[3]);
677 cdbr->FileRetention = str_to_int64(row[4]);
678 cdbr->JobRetention = str_to_int64(row[5]);
682 Mmsg(mdb->errmsg, _("Client record not found in Catalog.\n"));
684 sql_free_result(mdb);
686 Mmsg(mdb->errmsg, _("Client record not found in Catalog.\n"));
695 * Returns: 0 on failure
698 int db_get_counter_record(JCR *jcr, B_DB *mdb, COUNTER_DBR *cr)
703 Mmsg(mdb->cmd, "SELECT MinValue,MaxValue,CurrentValue,WrapCounter "
704 "FROM Counters WHERE Counter='%s'", cr->Counter);
706 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
707 mdb->num_rows = sql_num_rows(mdb);
709 /* If more than one, report error, but return first row */
710 if (mdb->num_rows > 1) {
711 Mmsg1(mdb->errmsg, _("More than one Counter!: %d\n"), (int)(mdb->num_rows));
712 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
714 if (mdb->num_rows >= 1) {
715 if ((row = sql_fetch_row(mdb)) == NULL) {
716 Mmsg1(mdb->errmsg, _("error fetching Counter row: %s\n"), sql_strerror(mdb));
717 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
718 sql_free_result(mdb);
722 cr->MinValue = str_to_int64(row[0]);
723 cr->MaxValue = str_to_int64(row[1]);
724 cr->CurrentValue = str_to_int64(row[2]);
726 bstrncpy(cr->WrapCounter, row[3], sizeof(cr->WrapCounter));
728 cr->WrapCounter[0] = 0;
730 sql_free_result(mdb);
734 sql_free_result(mdb);
736 Mmsg(mdb->errmsg, _("Counter record: %s not found in Catalog.\n"), cr->Counter);
743 /* Get FileSet Record
744 * If the FileSetId is non-zero, we get its record,
745 * otherwise, we search on the name
747 * Returns: 0 on failure
750 int db_get_fileset_record(JCR *jcr, B_DB *mdb, FILESET_DBR *fsr)
757 if (fsr->FileSetId != 0) { /* find by id */
759 "SELECT FileSetId,FileSet,MD5,CreateTime FROM FileSet "
760 "WHERE FileSetId=%s",
761 edit_int64(fsr->FileSetId, ed1));
762 } else { /* find by name */
764 "SELECT FileSetId,FileSet,MD5,CreateTime FROM FileSet "
765 "WHERE FileSet='%s' ORDER BY CreateTime DESC LIMIT 1", fsr->FileSet);
768 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
769 mdb->num_rows = sql_num_rows(mdb);
770 if (mdb->num_rows > 1) {
772 Mmsg1(mdb->errmsg, _("Error got %s FileSets but expected only one!\n"),
773 edit_uint64(mdb->num_rows, ed1));
774 sql_data_seek(mdb, mdb->num_rows-1);
776 if ((row = sql_fetch_row(mdb)) == NULL) {
777 Mmsg1(mdb->errmsg, _("FileSet record \"%s\" not found.\n"), fsr->FileSet);
779 fsr->FileSetId = str_to_int64(row[0]);
780 bstrncpy(fsr->FileSet, row[1]!=NULL?row[1]:"", sizeof(fsr->FileSet));
781 bstrncpy(fsr->MD5, row[2]!=NULL?row[2]:"", sizeof(fsr->MD5));
782 bstrncpy(fsr->cCreateTime, row[3]!=NULL?row[3]:"", sizeof(fsr->cCreateTime));
783 stat = fsr->FileSetId;
785 sql_free_result(mdb);
787 Mmsg(mdb->errmsg, _("FileSet record not found in Catalog.\n"));
795 * Get the number of Media records
797 * Returns: -1 on failure
800 int db_get_num_media_records(JCR *jcr, B_DB *mdb)
805 Mmsg(mdb->cmd, "SELECT count(*) from Media");
806 stat = get_sql_record_max(jcr, mdb);
813 * This function returns a list of all the Media record ids for
815 * The caller must free ids if non-NULL.
817 * Returns false: on failure
820 bool db_get_media_ids(JCR *jcr, B_DB *mdb, uint32_t PoolId, int *num_ids, uint32_t *ids[])
830 Mmsg(mdb->cmd, "SELECT MediaId FROM Media WHERE PoolId=%s",
831 edit_int64(PoolId, ed1));
832 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
833 *num_ids = sql_num_rows(mdb);
835 id = (uint32_t *)malloc(*num_ids * sizeof(uint32_t));
836 while ((row = sql_fetch_row(mdb)) != NULL) {
837 id[i++] = str_to_uint64(row[0]);
841 sql_free_result(mdb);
844 Mmsg(mdb->errmsg, _("Media id select failed: ERR=%s\n"), sql_strerror(mdb));
845 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
855 * Returns: false: on failure
858 bool db_get_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr)
865 if (mr->MediaId == 0 && mr->VolumeName[0] == 0) {
866 Mmsg(mdb->cmd, "SELECT count(*) from Media");
867 mr->MediaId = get_sql_record_max(jcr, mdb);
871 if (mr->MediaId != 0) { /* find by id */
872 Mmsg(mdb->cmd, "SELECT MediaId,VolumeName,VolJobs,VolFiles,VolBlocks,"
873 "VolBytes,VolMounts,VolErrors,VolWrites,MaxVolBytes,VolCapacityBytes,"
874 "MediaType,VolStatus,PoolId,VolRetention,VolUseDuration,MaxVolJobs,"
875 "MaxVolFiles,Recycle,Slot,FirstWritten,LastWritten,InChanger,"
876 "EndFile,EndBlock,VolParts,LabelType,LabelDate,StorageId,"
877 "Enabled,LocationId,RecycleCount,InitialWrite,"
878 "ScratchPoolId,RecyclePoolId "
879 "FROM Media WHERE MediaId=%s",
880 edit_int64(mr->MediaId, ed1));
881 } else { /* find by name */
882 Mmsg(mdb->cmd, "SELECT MediaId,VolumeName,VolJobs,VolFiles,VolBlocks,"
883 "VolBytes,VolMounts,VolErrors,VolWrites,MaxVolBytes,VolCapacityBytes,"
884 "MediaType,VolStatus,PoolId,VolRetention,VolUseDuration,MaxVolJobs,"
885 "MaxVolFiles,Recycle,Slot,FirstWritten,LastWritten,InChanger,"
886 "EndFile,EndBlock,VolParts,LabelType,LabelDate,StorageId,"
887 "Enabled,LocationId,RecycleCount,InitialWrite,"
888 "ScratchPoolId,RecyclePoolId "
889 "FROM Media WHERE VolumeName='%s'", mr->VolumeName);
892 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
894 mdb->num_rows = sql_num_rows(mdb);
895 if (mdb->num_rows > 1) {
896 Mmsg1(mdb->errmsg, _("More than one Volume!: %s\n"),
897 edit_uint64(mdb->num_rows, ed1));
898 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
899 } else if (mdb->num_rows == 1) {
900 if ((row = sql_fetch_row(mdb)) == NULL) {
901 Mmsg1(mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb));
902 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
905 mr->MediaId = str_to_int64(row[0]);
906 bstrncpy(mr->VolumeName, row[1]!=NULL?row[1]:"", sizeof(mr->VolumeName));
907 mr->VolJobs = str_to_int64(row[2]);
908 mr->VolFiles = str_to_int64(row[3]);
909 mr->VolBlocks = str_to_int64(row[4]);
910 mr->VolBytes = str_to_uint64(row[5]);
911 mr->VolMounts = str_to_int64(row[6]);
912 mr->VolErrors = str_to_int64(row[7]);
913 mr->VolWrites = str_to_int64(row[8]);
914 mr->MaxVolBytes = str_to_uint64(row[9]);
915 mr->VolCapacityBytes = str_to_uint64(row[10]);
916 bstrncpy(mr->MediaType, row[11]!=NULL?row[11]:"", sizeof(mr->MediaType));
917 bstrncpy(mr->VolStatus, row[12]!=NULL?row[12]:"", sizeof(mr->VolStatus));
918 mr->PoolId = str_to_int64(row[13]);
919 mr->VolRetention = str_to_uint64(row[14]);
920 mr->VolUseDuration = str_to_uint64(row[15]);
921 mr->MaxVolJobs = str_to_int64(row[16]);
922 mr->MaxVolFiles = str_to_int64(row[17]);
923 mr->Recycle = str_to_int64(row[18]);
924 mr->Slot = str_to_int64(row[19]);
925 bstrncpy(mr->cFirstWritten, row[20]!=NULL?row[20]:"", sizeof(mr->cFirstWritten));
926 mr->FirstWritten = (time_t)str_to_utime(mr->cFirstWritten);
927 bstrncpy(mr->cLastWritten, row[21]!=NULL?row[21]:"", sizeof(mr->cLastWritten));
928 mr->LastWritten = (time_t)str_to_utime(mr->cLastWritten);
929 mr->InChanger = str_to_uint64(row[22]);
930 mr->EndFile = str_to_uint64(row[23]);
931 mr->EndBlock = str_to_uint64(row[24]);
932 mr->VolParts = str_to_int64(row[25]);
933 mr->LabelType = str_to_int64(row[26]);
934 bstrncpy(mr->cLabelDate, row[27]!=NULL?row[27]:"", sizeof(mr->cLabelDate));
935 mr->LabelDate = (time_t)str_to_utime(mr->cLabelDate);
936 mr->StorageId = str_to_int64(row[28]);
937 mr->Enabled = str_to_int64(row[29]);
938 mr->LocationId = str_to_int64(row[30]);
939 mr->RecycleCount = str_to_int64(row[31]);
940 bstrncpy(mr->cInitialWrite, row[32]!=NULL?row[32]:"", sizeof(mr->cInitialWrite));
941 mr->InitialWrite = (time_t)str_to_utime(mr->cInitialWrite);
942 mr->ScratchPoolId = str_to_int64(row[33]);
943 mr->RecyclePoolId = str_to_int64(row[34]);
948 if (mr->MediaId != 0) {
949 Mmsg1(mdb->errmsg, _("Media record MediaId=%s not found.\n"),
950 edit_int64(mr->MediaId, ed1));
952 Mmsg1(mdb->errmsg, _("Media record for Volume \"%s\" not found.\n"),
956 sql_free_result(mdb);
958 if (mr->MediaId != 0) {
959 Mmsg(mdb->errmsg, _("Media record for MediaId=%u not found in Catalog.\n"),
962 Mmsg(mdb->errmsg, _("Media record for Vol=%s not found in Catalog.\n"),
970 #endif /* HAVE_SQLITE3 || HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL*/