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-2006 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 "
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 "
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 sql_free_result(mdb);
322 * Find VolumeNames for a given JobId
323 * Returns: 0 on error or no Volumes found
324 * number of volumes on success
325 * Volumes are concatenated in VolumeNames
326 * separated by a vertical bar (|) in the order
327 * that they were written.
329 * Returns: number of volumes on success
331 int db_get_job_volume_names(JCR *jcr, B_DB *mdb, JobId_t JobId, POOLMEM **VolumeNames)
339 /* Get one entry per VolumeName, but "sort" by VolIndex */
341 "SELECT VolumeName,MAX(VolIndex) FROM JobMedia,Media WHERE "
342 "JobMedia.JobId=%s AND JobMedia.MediaId=Media.MediaId "
343 "GROUP BY VolumeName "
344 "ORDER BY 2 ASC", edit_int64(JobId,ed1));
346 Dmsg1(130, "VolNam=%s\n", mdb->cmd);
348 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
349 mdb->num_rows = sql_num_rows(mdb);
350 Dmsg1(130, "Num rows=%d\n", mdb->num_rows);
351 if (mdb->num_rows <= 0) {
352 Mmsg1(mdb->errmsg, _("No volumes found for JobId=%d\n"), JobId);
355 stat = mdb->num_rows;
356 for (i=0; i < stat; i++) {
357 if ((row = sql_fetch_row(mdb)) == NULL) {
358 Mmsg2(mdb->errmsg, _("Error fetching row %d: ERR=%s\n"), i, sql_strerror(mdb));
359 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
363 if (*VolumeNames[0] != 0) {
364 pm_strcat(VolumeNames, "|");
366 pm_strcat(VolumeNames, row[0]);
370 sql_free_result(mdb);
372 Mmsg(mdb->errmsg, _("No Volume for JobId %d found in Catalog.\n"), JobId);
379 * Find Volume parameters for a give JobId
380 * Returns: 0 on error or no Volumes found
381 * number of volumes on success
382 * List of Volumes and start/end file/blocks (malloced structure!)
384 * Returns: number of volumes on success
386 int db_get_job_volume_parameters(JCR *jcr, B_DB *mdb, JobId_t JobId, VOL_PARAMS **VolParams)
392 VOL_PARAMS *Vols = NULL;
396 "SELECT VolumeName,MediaType,FirstIndex,LastIndex,StartFile,"
397 "JobMedia.EndFile,StartBlock,JobMedia.EndBlock,Copy,"
399 " FROM JobMedia,Media WHERE JobMedia.JobId=%s"
400 " AND JobMedia.MediaId=Media.MediaId ORDER BY VolIndex,JobMediaId",
401 edit_int64(JobId, ed1));
403 Dmsg1(130, "VolNam=%s\n", mdb->cmd);
404 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
405 mdb->num_rows = sql_num_rows(mdb);
406 Dmsg1(200, "Num rows=%d\n", mdb->num_rows);
407 if (mdb->num_rows <= 0) {
408 Mmsg1(mdb->errmsg, _("No volumes found for JobId=%d\n"), JobId);
411 stat = mdb->num_rows;
414 *VolParams = Vols = (VOL_PARAMS *)malloc(stat * sizeof(VOL_PARAMS));
415 SId = (DBId_t *)malloc(stat * sizeof(DBId_t));
419 for (i=0; i < stat; i++) {
420 if ((row = sql_fetch_row(mdb)) == NULL) {
421 Mmsg2(mdb->errmsg, _("Error fetching row %d: ERR=%s\n"), i, sql_strerror(mdb));
422 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
427 bstrncpy(Vols[i].VolumeName, row[0], MAX_NAME_LENGTH);
428 bstrncpy(Vols[i].MediaType, row[1], MAX_NAME_LENGTH);
429 Vols[i].FirstIndex = str_to_uint64(row[2]);
430 Vols[i].LastIndex = str_to_uint64(row[3]);
431 Vols[i].StartFile = str_to_uint64(row[4]);
432 Vols[i].EndFile = str_to_uint64(row[5]);
433 Vols[i].StartBlock = str_to_uint64(row[6]);
434 Vols[i].EndBlock = str_to_uint64(row[7]);
435 // Vols[i].Copy = str_to_uint64(row[8]);
436 Vols[i].Slot = str_to_uint64(row[9]);
437 StorageId = str_to_uint64(row[10]);
438 Vols[i].Storage[0] = 0;
442 for (i=0; i < stat; i++) {
444 Mmsg(mdb->cmd, "SELECT Name from Storage WHERE StorageId=%s",
445 edit_int64(SId[i], ed1));
446 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
447 if ((row = sql_fetch_row(mdb)) != NULL) {
448 bstrncpy(Vols[i].Storage, row[0], MAX_NAME_LENGTH);
454 sql_free_result(mdb);
463 * Get the number of pool records
465 * Returns: -1 on failure
468 int db_get_num_pool_records(JCR *jcr, B_DB *mdb)
473 Mmsg(mdb->cmd, "SELECT count(*) from Pool");
474 stat = get_sql_record_max(jcr, mdb);
480 * This function returns a list of all the Pool record ids.
481 * The caller must free ids if non-NULL.
483 * Returns 0: on failure
486 int db_get_pool_ids(JCR *jcr, B_DB *mdb, int *num_ids, uint32_t *ids[])
495 Mmsg(mdb->cmd, "SELECT PoolId FROM Pool");
496 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
497 *num_ids = sql_num_rows(mdb);
499 id = (uint32_t *)malloc(*num_ids * sizeof(uint32_t));
500 while ((row = sql_fetch_row(mdb)) != NULL) {
501 id[i++] = str_to_uint64(row[0]);
505 sql_free_result(mdb);
508 Mmsg(mdb->errmsg, _("Pool id select failed: ERR=%s\n"), sql_strerror(mdb));
509 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
517 * This function returns a list of all the Client record ids.
518 * The caller must free ids if non-NULL.
520 * Returns 0: on failure
523 int db_get_client_ids(JCR *jcr, B_DB *mdb, int *num_ids, uint32_t *ids[])
532 Mmsg(mdb->cmd, "SELECT ClientId FROM Client");
533 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
534 *num_ids = sql_num_rows(mdb);
536 id = (uint32_t *)malloc(*num_ids * sizeof(uint32_t));
537 while ((row = sql_fetch_row(mdb)) != NULL) {
538 id[i++] = str_to_uint64(row[0]);
542 sql_free_result(mdb);
545 Mmsg(mdb->errmsg, _("Client id select failed: ERR=%s\n"), sql_strerror(mdb));
546 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
556 * If the PoolId is non-zero, we get its record,
557 * otherwise, we search on the PoolName
559 * Returns: false on failure
562 bool db_get_pool_record(JCR *jcr, B_DB *mdb, POOL_DBR *pdbr)
569 if (pdbr->PoolId != 0) { /* find by id */
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.PoolId=%s",
574 edit_int64(pdbr->PoolId, ed1));
575 } else { /* find by name */
577 "SELECT PoolId,Name,NumVols,MaxVols,UseOnce,UseCatalog,AcceptAnyVolume,"
578 "AutoPrune,Recycle,VolRetention,VolUseDuration,MaxVolJobs,MaxVolFiles,"
579 "MaxVolBytes,PoolType,LabelType,LabelFormat FROM Pool WHERE Pool.Name='%s'",
583 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
584 mdb->num_rows = sql_num_rows(mdb);
585 if (mdb->num_rows > 1) {
587 Mmsg1(mdb->errmsg, _("More than one Pool!: %s\n"),
588 edit_uint64(mdb->num_rows, ed1));
589 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
590 } else if (mdb->num_rows == 1) {
591 if ((row = sql_fetch_row(mdb)) == NULL) {
592 Mmsg1(mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb));
593 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
595 pdbr->PoolId = str_to_int64(row[0]);
596 bstrncpy(pdbr->Name, row[1]!=NULL?row[1]:"", sizeof(pdbr->Name));
597 pdbr->NumVols = str_to_int64(row[2]);
598 pdbr->MaxVols = str_to_int64(row[3]);
599 pdbr->UseOnce = str_to_int64(row[4]);
600 pdbr->UseCatalog = str_to_int64(row[5]);
601 pdbr->AcceptAnyVolume = str_to_int64(row[6]);
602 pdbr->AutoPrune = str_to_int64(row[7]);
603 pdbr->Recycle = str_to_int64(row[8]);
604 pdbr->VolRetention = str_to_int64(row[9]);
605 pdbr->VolUseDuration = str_to_int64(row[10]);
606 pdbr->MaxVolJobs = str_to_int64(row[11]);
607 pdbr->MaxVolFiles = str_to_int64(row[12]);
608 pdbr->MaxVolBytes = str_to_uint64(row[13]);
609 bstrncpy(pdbr->PoolType, row[14]!=NULL?row[14]:"", sizeof(pdbr->PoolType));
610 pdbr->LabelType = str_to_int64(row[15]);
611 bstrncpy(pdbr->LabelFormat, row[16]!=NULL?row[16]:"", sizeof(pdbr->LabelFormat));
615 sql_free_result(mdb);
619 Mmsg(mdb->cmd, "SELECT count(*) from Media WHERE PoolId=%s",
620 edit_int64(pdbr->PoolId, ed1));
621 NumVols = get_sql_record_max(jcr, mdb);
622 Dmsg2(400, "Actual NumVols=%d Pool NumVols=%d\n", NumVols, pdbr->NumVols);
623 if (NumVols != pdbr->NumVols) {
624 pdbr->NumVols = NumVols;
625 db_update_pool_record(jcr, mdb, pdbr);
628 Mmsg(mdb->errmsg, _("Pool record not found in Catalog.\n"));
635 * If the ClientId is non-zero, we get its record,
636 * otherwise, we search on the Client Name
638 * Returns: 0 on failure
641 int db_get_client_record(JCR *jcr, B_DB *mdb, CLIENT_DBR *cdbr)
648 if (cdbr->ClientId != 0) { /* find by id */
650 "SELECT ClientId,Name,Uname,AutoPrune,FileRetention,JobRetention "
651 "FROM Client WHERE Client.ClientId=%s",
652 edit_int64(cdbr->ClientId, ed1));
653 } else { /* find by name */
655 "SELECT ClientId,Name,Uname,AutoPrune,FileRetention,JobRetention "
656 "FROM Client WHERE Client.Name='%s'", cdbr->Name);
659 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
660 mdb->num_rows = sql_num_rows(mdb);
661 if (mdb->num_rows > 1) {
662 Mmsg1(mdb->errmsg, _("More than one Client!: %s\n"),
663 edit_uint64(mdb->num_rows, ed1));
664 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
665 } else if (mdb->num_rows == 1) {
666 if ((row = sql_fetch_row(mdb)) == NULL) {
667 Mmsg1(mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb));
668 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
670 cdbr->ClientId = str_to_int64(row[0]);
671 bstrncpy(cdbr->Name, row[1]!=NULL?row[1]:"", sizeof(cdbr->Name));
672 bstrncpy(cdbr->Uname, row[2]!=NULL?row[2]:"", sizeof(cdbr->Uname));
673 cdbr->AutoPrune = str_to_int64(row[3]);
674 cdbr->FileRetention = str_to_int64(row[4]);
675 cdbr->JobRetention = str_to_int64(row[5]);
679 Mmsg(mdb->errmsg, _("Client record not found in Catalog.\n"));
681 sql_free_result(mdb);
683 Mmsg(mdb->errmsg, _("Client record not found in Catalog.\n"));
692 * Returns: 0 on failure
695 int db_get_counter_record(JCR *jcr, B_DB *mdb, COUNTER_DBR *cr)
700 Mmsg(mdb->cmd, "SELECT MinValue,MaxValue,CurrentValue,WrapCounter "
701 "FROM Counters WHERE Counter='%s'", cr->Counter);
703 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
704 mdb->num_rows = sql_num_rows(mdb);
706 /* If more than one, report error, but return first row */
707 if (mdb->num_rows > 1) {
708 Mmsg1(mdb->errmsg, _("More than one Counter!: %d\n"), (int)(mdb->num_rows));
709 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
711 if (mdb->num_rows >= 1) {
712 if ((row = sql_fetch_row(mdb)) == NULL) {
713 Mmsg1(mdb->errmsg, _("error fetching Counter row: %s\n"), sql_strerror(mdb));
714 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
715 sql_free_result(mdb);
719 cr->MinValue = str_to_int64(row[0]);
720 cr->MaxValue = str_to_int64(row[1]);
721 cr->CurrentValue = str_to_int64(row[2]);
723 bstrncpy(cr->WrapCounter, row[3], sizeof(cr->WrapCounter));
725 cr->WrapCounter[0] = 0;
727 sql_free_result(mdb);
731 sql_free_result(mdb);
733 Mmsg(mdb->errmsg, _("Counter record: %s not found in Catalog.\n"), cr->Counter);
740 /* Get FileSet Record
741 * If the FileSetId is non-zero, we get its record,
742 * otherwise, we search on the name
744 * Returns: 0 on failure
747 int db_get_fileset_record(JCR *jcr, B_DB *mdb, FILESET_DBR *fsr)
754 if (fsr->FileSetId != 0) { /* find by id */
756 "SELECT FileSetId,FileSet,MD5,CreateTime FROM FileSet "
757 "WHERE FileSetId=%s",
758 edit_int64(fsr->FileSetId, ed1));
759 } else { /* find by name */
761 "SELECT FileSetId,FileSet,MD5,CreateTime FROM FileSet "
762 "WHERE FileSet='%s' ORDER BY CreateTime DESC LIMIT 1", fsr->FileSet);
765 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
766 mdb->num_rows = sql_num_rows(mdb);
767 if (mdb->num_rows > 1) {
769 Mmsg1(mdb->errmsg, _("Error got %s FileSets but expected only one!\n"),
770 edit_uint64(mdb->num_rows, ed1));
771 sql_data_seek(mdb, mdb->num_rows-1);
773 if ((row = sql_fetch_row(mdb)) == NULL) {
774 Mmsg1(mdb->errmsg, _("FileSet record \"%s\" not found.\n"), fsr->FileSet);
776 fsr->FileSetId = str_to_int64(row[0]);
777 bstrncpy(fsr->FileSet, row[1]!=NULL?row[1]:"", sizeof(fsr->FileSet));
778 bstrncpy(fsr->MD5, row[2]!=NULL?row[2]:"", sizeof(fsr->MD5));
779 bstrncpy(fsr->cCreateTime, row[3]!=NULL?row[3]:"", sizeof(fsr->cCreateTime));
780 stat = fsr->FileSetId;
782 sql_free_result(mdb);
784 Mmsg(mdb->errmsg, _("FileSet record not found in Catalog.\n"));
792 * Get the number of Media records
794 * Returns: -1 on failure
797 int db_get_num_media_records(JCR *jcr, B_DB *mdb)
802 Mmsg(mdb->cmd, "SELECT count(*) from Media");
803 stat = get_sql_record_max(jcr, mdb);
810 * This function returns a list of all the Media record ids for
812 * The caller must free ids if non-NULL.
814 * Returns false: on failure
817 bool db_get_media_ids(JCR *jcr, B_DB *mdb, uint32_t PoolId, int *num_ids, uint32_t *ids[])
827 Mmsg(mdb->cmd, "SELECT MediaId FROM Media WHERE PoolId=%s",
828 edit_int64(PoolId, ed1));
829 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
830 *num_ids = sql_num_rows(mdb);
832 id = (uint32_t *)malloc(*num_ids * sizeof(uint32_t));
833 while ((row = sql_fetch_row(mdb)) != NULL) {
834 id[i++] = str_to_uint64(row[0]);
838 sql_free_result(mdb);
841 Mmsg(mdb->errmsg, _("Media id select failed: ERR=%s\n"), sql_strerror(mdb));
842 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
852 * Returns: false: on failure
855 bool db_get_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr)
862 if (mr->MediaId == 0 && mr->VolumeName[0] == 0) {
863 Mmsg(mdb->cmd, "SELECT count(*) from Media");
864 mr->MediaId = get_sql_record_max(jcr, mdb);
868 if (mr->MediaId != 0) { /* find by id */
869 Mmsg(mdb->cmd, "SELECT MediaId,VolumeName,VolJobs,VolFiles,VolBlocks,"
870 "VolBytes,VolMounts,VolErrors,VolWrites,MaxVolBytes,VolCapacityBytes,"
871 "MediaType,VolStatus,PoolId,VolRetention,VolUseDuration,MaxVolJobs,"
872 "MaxVolFiles,Recycle,Slot,FirstWritten,LastWritten,InChanger,"
873 "EndFile,EndBlock,VolParts,LabelType,LabelDate,StorageId,"
874 "Enabled,LocationId,RecycleCount,InitialWrite,"
875 "ScratchPoolId,RecyclePoolId "
876 "FROM Media WHERE MediaId=%s",
877 edit_int64(mr->MediaId, ed1));
878 } else { /* find by name */
879 Mmsg(mdb->cmd, "SELECT MediaId,VolumeName,VolJobs,VolFiles,VolBlocks,"
880 "VolBytes,VolMounts,VolErrors,VolWrites,MaxVolBytes,VolCapacityBytes,"
881 "MediaType,VolStatus,PoolId,VolRetention,VolUseDuration,MaxVolJobs,"
882 "MaxVolFiles,Recycle,Slot,FirstWritten,LastWritten,InChanger,"
883 "EndFile,EndBlock,VolParts,LabelType,LabelDate,StorageId,"
884 "Enabled,LocationId,RecycleCount,InitialWrite,"
885 "ScratchPoolId,RecyclePoolId "
886 "FROM Media WHERE VolumeName='%s'", mr->VolumeName);
889 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
891 mdb->num_rows = sql_num_rows(mdb);
892 if (mdb->num_rows > 1) {
893 Mmsg1(mdb->errmsg, _("More than one Volume!: %s\n"),
894 edit_uint64(mdb->num_rows, ed1));
895 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
896 } else if (mdb->num_rows == 1) {
897 if ((row = sql_fetch_row(mdb)) == NULL) {
898 Mmsg1(mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb));
899 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
902 mr->MediaId = str_to_int64(row[0]);
903 bstrncpy(mr->VolumeName, row[1]!=NULL?row[1]:"", sizeof(mr->VolumeName));
904 mr->VolJobs = str_to_int64(row[2]);
905 mr->VolFiles = str_to_int64(row[3]);
906 mr->VolBlocks = str_to_int64(row[4]);
907 mr->VolBytes = str_to_uint64(row[5]);
908 mr->VolMounts = str_to_int64(row[6]);
909 mr->VolErrors = str_to_int64(row[7]);
910 mr->VolWrites = str_to_int64(row[8]);
911 mr->MaxVolBytes = str_to_uint64(row[9]);
912 mr->VolCapacityBytes = str_to_uint64(row[10]);
913 bstrncpy(mr->MediaType, row[11]!=NULL?row[11]:"", sizeof(mr->MediaType));
914 bstrncpy(mr->VolStatus, row[12]!=NULL?row[12]:"", sizeof(mr->VolStatus));
915 mr->PoolId = str_to_int64(row[13]);
916 mr->VolRetention = str_to_uint64(row[14]);
917 mr->VolUseDuration = str_to_uint64(row[15]);
918 mr->MaxVolJobs = str_to_int64(row[16]);
919 mr->MaxVolFiles = str_to_int64(row[17]);
920 mr->Recycle = str_to_int64(row[18]);
921 mr->Slot = str_to_int64(row[19]);
922 bstrncpy(mr->cFirstWritten, row[20]!=NULL?row[20]:"", sizeof(mr->cFirstWritten));
923 mr->FirstWritten = (time_t)str_to_utime(mr->cFirstWritten);
924 bstrncpy(mr->cLastWritten, row[21]!=NULL?row[21]:"", sizeof(mr->cLastWritten));
925 mr->LastWritten = (time_t)str_to_utime(mr->cLastWritten);
926 mr->InChanger = str_to_uint64(row[22]);
927 mr->EndFile = str_to_uint64(row[23]);
928 mr->EndBlock = str_to_uint64(row[24]);
929 mr->VolParts = str_to_int64(row[25]);
930 mr->LabelType = str_to_int64(row[26]);
931 bstrncpy(mr->cLabelDate, row[27]!=NULL?row[27]:"", sizeof(mr->cLabelDate));
932 mr->LabelDate = (time_t)str_to_utime(mr->cLabelDate);
933 mr->StorageId = str_to_int64(row[28]);
934 mr->Enabled = str_to_int64(row[29]);
935 mr->LocationId = str_to_int64(row[30]);
936 mr->RecycleCount = str_to_int64(row[31]);
937 bstrncpy(mr->cInitialWrite, row[32]!=NULL?row[32]:"", sizeof(mr->cInitialWrite));
938 mr->InitialWrite = (time_t)str_to_utime(mr->cInitialWrite);
939 mr->ScratchPoolId = str_to_int64(row[33]);
940 mr->RecyclePoolId = str_to_int64(row[34]);
945 if (mr->MediaId != 0) {
946 Mmsg1(mdb->errmsg, _("Media record MediaId=%s not found.\n"),
947 edit_int64(mr->MediaId, ed1));
949 Mmsg1(mdb->errmsg, _("Media record for Volume \"%s\" not found.\n"),
953 sql_free_result(mdb);
955 if (mr->MediaId != 0) {
956 Mmsg(mdb->errmsg, _("Media record for MediaId=%u not found in Catalog.\n"),
959 Mmsg(mdb->errmsg, _("Media record for Vol=%s not found in Catalog.\n"),
967 #endif /* HAVE_SQLITE3 || HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL*/