2 Bacula® - The Network Backup Solution
4 Copyright (C) 2000-2007 Free Software Foundation Europe e.V.
6 The main author of Bacula is Kern Sibbald, with contributions from
7 many others, a complete list can be found in the file AUTHORS.
8 This program is Free Software; you can redistribute it and/or
9 modify it under the terms of version two of the GNU General Public
10 License as published by the Free Software Foundation plus additions
11 that are listed in the file LICENSE.
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 Bacula® is a registered trademark of John Walker.
24 The licensor of Bacula is the Free Software Foundation Europe
25 (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26 Switzerland, email:ftf@fsfeurope.org.
29 * Bacula Catalog Database Get record interface routines
30 * Note, these routines generally get a record by id or
31 * by name. If more logic is involved, the routine
34 * Kern Sibbald, March 2000
40 /* The following is necessary so that we do not include
41 * the dummy external definition of DB.
43 #define __SQL_C /* indicate that this is sql.c */
48 #if HAVE_SQLITE3 || HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL
50 /* -----------------------------------------------------------------------
52 * Generic Routines (or almost generic)
54 * -----------------------------------------------------------------------
57 /* Forward referenced functions */
58 static int db_get_file_record(JCR *jcr, B_DB *mdb, JOB_DBR *jr, FILE_DBR *fdbr);
59 static int db_get_filename_record(JCR *jcr, B_DB *mdb);
60 static int db_get_path_record(JCR *jcr, B_DB *mdb);
64 * Given a full filename (with path), look up the File record
65 * (with attributes) in the database.
67 * Returns: 0 on failure
68 * 1 on success with the File record in FILE_DBR
70 int db_get_file_attributes_record(JCR *jcr, B_DB *mdb, char *fname, JOB_DBR *jr, FILE_DBR *fdbr)
73 Dmsg1(100, "db_get_file_att_record fname=%s \n", fname);
76 split_path_and_file(jcr, mdb, fname);
78 fdbr->FilenameId = db_get_filename_record(jcr, mdb);
80 fdbr->PathId = db_get_path_record(jcr, mdb);
82 stat = db_get_file_record(jcr, mdb, jr, fdbr);
92 * Returns: 0 on failure
95 * DO NOT use Jmsg in this routine.
97 * Note in this routine, we do not use Jmsg because it may be
98 * called to get attributes of a non-existent file, which is
99 * "normal" if a new file is found during Verify.
102 int db_get_file_record(JCR *jcr, B_DB *mdb, JOB_DBR *jr, FILE_DBR *fdbr)
106 char ed1[50], ed2[50], ed3[50];
108 if (jcr->JobLevel == L_VERIFY_DISK_TO_CATALOG) {
110 "SELECT FileId, LStat, MD5 FROM File,Job WHERE "
111 "File.JobId=Job.JobId AND File.PathId=%s AND "
112 "File.FilenameId=%s AND Job.Type='B' AND Job.JobSTATUS='T' AND "
113 "ClientId=%s ORDER BY StartTime DESC LIMIT 1",
114 edit_int64(fdbr->PathId, ed1),
115 edit_int64(fdbr->FilenameId, ed2),
116 edit_int64(jr->ClientId,ed3));
120 "SELECT FileId, LStat, MD5 FROM File WHERE File.JobId=%s AND File.PathId=%s AND "
121 "File.FilenameId=%s",
122 edit_int64(fdbr->JobId, ed1),
123 edit_int64(fdbr->PathId, ed2),
124 edit_int64(fdbr->FilenameId,ed3));
126 Dmsg3(050, "Get_file_record JobId=%u FilenameId=%u PathId=%u\n",
127 fdbr->JobId, fdbr->FilenameId, fdbr->PathId);
129 Dmsg1(100, "Query=%s\n", mdb->cmd);
131 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
132 mdb->num_rows = sql_num_rows(mdb);
133 Dmsg1(050, "get_file_record num_rows=%d\n", (int)mdb->num_rows);
134 if (mdb->num_rows > 1) {
135 Mmsg1(mdb->errmsg, _("get_file_record want 1 got rows=%d\n"),
138 if (mdb->num_rows >= 1) {
139 if ((row = sql_fetch_row(mdb)) == NULL) {
140 Mmsg1(mdb->errmsg, _("Error fetching row: %s\n"), sql_strerror(mdb));
142 fdbr->FileId = (FileId_t)str_to_int64(row[0]);
143 bstrncpy(fdbr->LStat, row[1], sizeof(fdbr->LStat));
144 bstrncpy(fdbr->Digest, row[2], sizeof(fdbr->Digest));
148 Mmsg2(mdb->errmsg, _("File record for PathId=%s FilenameId=%s not found.\n"),
149 edit_int64(fdbr->PathId, ed1),
150 edit_int64(fdbr->FilenameId, ed2));
152 sql_free_result(mdb);
154 Mmsg(mdb->errmsg, _("File record not found in Catalog.\n"));
160 /* Get Filename record
161 * Returns: 0 on failure
162 * FilenameId on success
164 * DO NOT use Jmsg in this routine (see notes for get_file_record)
166 static int db_get_filename_record(JCR *jcr, B_DB *mdb)
171 mdb->esc_name = check_pool_memory_size(mdb->esc_name, 2*mdb->fnl+2);
172 db_escape_string(mdb->esc_name, mdb->fname, mdb->fnl);
174 Mmsg(mdb->cmd, "SELECT FilenameId FROM Filename WHERE Name='%s'", mdb->esc_name);
175 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
177 mdb->num_rows = sql_num_rows(mdb);
178 if (mdb->num_rows > 1) {
179 Mmsg2(mdb->errmsg, _("More than one Filename!: %s for file: %s\n"),
180 edit_uint64(mdb->num_rows, ed1), mdb->fname);
181 Jmsg(jcr, M_WARNING, 0, "%s", mdb->errmsg);
183 if (mdb->num_rows >= 1) {
184 if ((row = sql_fetch_row(mdb)) == NULL) {
185 Mmsg1(mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb));
187 FilenameId = str_to_int64(row[0]);
188 if (FilenameId <= 0) {
189 Mmsg2(mdb->errmsg, _("Get DB Filename record %s found bad record: %d\n"),
190 mdb->cmd, FilenameId);
195 Mmsg1(mdb->errmsg, _("Filename record: %s not found.\n"), mdb->fname);
197 sql_free_result(mdb);
199 Mmsg(mdb->errmsg, _("Filename record: %s not found in Catalog.\n"), mdb->fname);
205 * Returns: 0 on failure
208 * DO NOT use Jmsg in this routine (see notes for get_file_record)
210 static int db_get_path_record(JCR *jcr, B_DB *mdb)
215 mdb->esc_name = check_pool_memory_size(mdb->esc_name, 2*mdb->pnl+2);
216 db_escape_string(mdb->esc_name, mdb->path, mdb->pnl);
218 if (mdb->cached_path_id != 0 && mdb->cached_path_len == mdb->pnl &&
219 strcmp(mdb->cached_path, mdb->path) == 0) {
220 return mdb->cached_path_id;
223 Mmsg(mdb->cmd, "SELECT PathId FROM Path WHERE Path='%s'", mdb->esc_name);
225 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
227 mdb->num_rows = sql_num_rows(mdb);
228 if (mdb->num_rows > 1) {
229 Mmsg2(mdb->errmsg, _("More than one Path!: %s for path: %s\n"),
230 edit_uint64(mdb->num_rows, ed1), mdb->path);
231 Jmsg(jcr, M_WARNING, 0, "%s", mdb->errmsg);
233 /* Even if there are multiple paths, take the first one */
234 if (mdb->num_rows >= 1) {
235 if ((row = sql_fetch_row(mdb)) == NULL) {
236 Mmsg1(mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb));
238 PathId = str_to_int64(row[0]);
240 Mmsg2(mdb->errmsg, _("Get DB path record %s found bad record: %s\n"),
241 mdb->cmd, edit_int64(PathId, ed1));
245 if (PathId != mdb->cached_path_id) {
246 mdb->cached_path_id = PathId;
247 mdb->cached_path_len = mdb->pnl;
248 pm_strcpy(mdb->cached_path, mdb->path);
253 Mmsg1(mdb->errmsg, _("Path record: %s not found.\n"), mdb->path);
255 sql_free_result(mdb);
257 Mmsg(mdb->errmsg, _("Path record: %s not found in Catalog.\n"), mdb->path);
264 * Get Job record for given JobId or Job name
265 * Returns: false on failure
268 bool db_get_job_record(JCR *jcr, B_DB *mdb, JOB_DBR *jr)
274 if (jr->JobId == 0) {
275 Mmsg(mdb->cmd, "SELECT VolSessionId,VolSessionTime,"
276 "PoolId,StartTime,EndTime,JobFiles,JobBytes,JobTDate,Job,JobStatus,"
277 "Type,Level,ClientId,Name,PriorJobId,RealEndTime,JobId,FileSetId "
278 "FROM Job WHERE Job='%s'", jr->Job);
280 Mmsg(mdb->cmd, "SELECT VolSessionId,VolSessionTime,"
281 "PoolId,StartTime,EndTime,JobFiles,JobBytes,JobTDate,Job,JobStatus,"
282 "Type,Level,ClientId,Name,PriorJobId,RealEndTime,JobId,FileSetId "
283 "FROM Job WHERE JobId=%s",
284 edit_int64(jr->JobId, ed1));
287 if (!QUERY_DB(jcr, mdb, mdb->cmd)) {
289 return false; /* failed */
291 if ((row = sql_fetch_row(mdb)) == NULL) {
292 Mmsg1(mdb->errmsg, _("No Job found for JobId %s\n"), edit_int64(jr->JobId, ed1));
293 sql_free_result(mdb);
295 return false; /* failed */
298 jr->VolSessionId = str_to_uint64(row[0]);
299 jr->VolSessionTime = str_to_uint64(row[1]);
300 jr->PoolId = str_to_int64(row[2]);
301 bstrncpy(jr->cStartTime, row[3]!=NULL?row[3]:"", sizeof(jr->cStartTime));
302 bstrncpy(jr->cEndTime, row[4]!=NULL?row[4]:"", sizeof(jr->cEndTime));
303 jr->JobFiles = str_to_int64(row[5]);
304 jr->JobBytes = str_to_int64(row[6]);
305 jr->JobTDate = str_to_int64(row[7]);
306 bstrncpy(jr->Job, row[8]!=NULL?row[8]:"", sizeof(jr->Job));
307 jr->JobStatus = (int)*row[9];
308 jr->JobType = (int)*row[10];
309 jr->JobLevel = (int)*row[11];
310 jr->ClientId = str_to_uint64(row[12]!=NULL?row[12]:(char *)"");
311 bstrncpy(jr->Name, row[13]!=NULL?row[13]:"", sizeof(jr->Name));
312 jr->PriorJobId = str_to_uint64(row[14]!=NULL?row[14]:(char *)"");
313 bstrncpy(jr->cRealEndTime, row[15]!=NULL?row[15]:"", sizeof(jr->cRealEndTime));
314 if (jr->JobId == 0) {
315 jr->JobId = str_to_int64(row[16]);
317 jr->FileSetId = str_to_int64(row[17]);
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));
420 for (i=0; i < stat; i++) {
421 if ((row = sql_fetch_row(mdb)) == NULL) {
422 Mmsg2(mdb->errmsg, _("Error fetching row %d: ERR=%s\n"), i, sql_strerror(mdb));
423 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
428 bstrncpy(Vols[i].VolumeName, row[0], MAX_NAME_LENGTH);
429 bstrncpy(Vols[i].MediaType, row[1], MAX_NAME_LENGTH);
430 Vols[i].FirstIndex = str_to_uint64(row[2]);
431 Vols[i].LastIndex = str_to_uint64(row[3]);
432 Vols[i].StartFile = str_to_uint64(row[4]);
433 Vols[i].EndFile = str_to_uint64(row[5]);
434 Vols[i].StartBlock = str_to_uint64(row[6]);
435 Vols[i].EndBlock = str_to_uint64(row[7]);
436 // Vols[i].Copy = str_to_uint64(row[8]);
437 Vols[i].Slot = str_to_uint64(row[9]);
438 StorageId = str_to_uint64(row[10]);
439 Vols[i].Storage[0] = 0;
443 for (i=0; i < stat; i++) {
445 Mmsg(mdb->cmd, "SELECT Name from Storage WHERE StorageId=%s",
446 edit_int64(SId[i], ed1));
447 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
448 if ((row = sql_fetch_row(mdb)) != NULL) {
449 bstrncpy(Vols[i].Storage, row[0], MAX_NAME_LENGTH);
458 sql_free_result(mdb);
467 * Get the number of pool records
469 * Returns: -1 on failure
472 int db_get_num_pool_records(JCR *jcr, B_DB *mdb)
477 Mmsg(mdb->cmd, "SELECT count(*) from Pool");
478 stat = get_sql_record_max(jcr, mdb);
484 * This function returns a list of all the Pool record ids.
485 * The caller must free ids if non-NULL.
487 * Returns 0: on failure
490 int db_get_pool_ids(JCR *jcr, B_DB *mdb, int *num_ids, uint32_t *ids[])
499 Mmsg(mdb->cmd, "SELECT PoolId FROM Pool");
500 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
501 *num_ids = sql_num_rows(mdb);
503 id = (uint32_t *)malloc(*num_ids * sizeof(uint32_t));
504 while ((row = sql_fetch_row(mdb)) != NULL) {
505 id[i++] = str_to_uint64(row[0]);
509 sql_free_result(mdb);
512 Mmsg(mdb->errmsg, _("Pool id select failed: ERR=%s\n"), sql_strerror(mdb));
513 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
521 * This function returns a list of all the Client record ids.
522 * The caller must free ids if non-NULL.
524 * Returns 0: on failure
527 int db_get_client_ids(JCR *jcr, B_DB *mdb, int *num_ids, uint32_t *ids[])
536 Mmsg(mdb->cmd, "SELECT ClientId FROM Client");
537 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
538 *num_ids = sql_num_rows(mdb);
540 id = (uint32_t *)malloc(*num_ids * sizeof(uint32_t));
541 while ((row = sql_fetch_row(mdb)) != NULL) {
542 id[i++] = str_to_uint64(row[0]);
546 sql_free_result(mdb);
549 Mmsg(mdb->errmsg, _("Client id select failed: ERR=%s\n"), sql_strerror(mdb));
550 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
560 * If the PoolId is non-zero, we get its record,
561 * otherwise, we search on the PoolName
563 * Returns: false on failure
566 bool db_get_pool_record(JCR *jcr, B_DB *mdb, POOL_DBR *pdbr)
573 if (pdbr->PoolId != 0) { /* find by id */
575 "SELECT PoolId,Name,NumVols,MaxVols,UseOnce,UseCatalog,AcceptAnyVolume,"
576 "AutoPrune,Recycle,VolRetention,VolUseDuration,MaxVolJobs,MaxVolFiles,"
577 "MaxVolBytes,PoolType,LabelType,LabelFormat,RecyclePoolId FROM Pool WHERE Pool.PoolId=%s",
578 edit_int64(pdbr->PoolId, ed1));
579 } else { /* find by name */
581 "SELECT PoolId,Name,NumVols,MaxVols,UseOnce,UseCatalog,AcceptAnyVolume,"
582 "AutoPrune,Recycle,VolRetention,VolUseDuration,MaxVolJobs,MaxVolFiles,"
583 "MaxVolBytes,PoolType,LabelType,LabelFormat,RecyclePoolId FROM Pool WHERE Pool.Name='%s'",
587 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
588 mdb->num_rows = sql_num_rows(mdb);
589 if (mdb->num_rows > 1) {
591 Mmsg1(mdb->errmsg, _("More than one Pool!: %s\n"),
592 edit_uint64(mdb->num_rows, ed1));
593 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
594 } else if (mdb->num_rows == 1) {
595 if ((row = sql_fetch_row(mdb)) == NULL) {
596 Mmsg1(mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb));
597 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
599 pdbr->PoolId = str_to_int64(row[0]);
600 bstrncpy(pdbr->Name, row[1]!=NULL?row[1]:"", sizeof(pdbr->Name));
601 pdbr->NumVols = str_to_int64(row[2]);
602 pdbr->MaxVols = str_to_int64(row[3]);
603 pdbr->UseOnce = str_to_int64(row[4]);
604 pdbr->UseCatalog = str_to_int64(row[5]);
605 pdbr->AcceptAnyVolume = str_to_int64(row[6]);
606 pdbr->AutoPrune = str_to_int64(row[7]);
607 pdbr->Recycle = str_to_int64(row[8]);
608 pdbr->VolRetention = str_to_int64(row[9]);
609 pdbr->VolUseDuration = str_to_int64(row[10]);
610 pdbr->MaxVolJobs = str_to_int64(row[11]);
611 pdbr->MaxVolFiles = str_to_int64(row[12]);
612 pdbr->MaxVolBytes = str_to_uint64(row[13]);
613 bstrncpy(pdbr->PoolType, row[14]!=NULL?row[14]:"", sizeof(pdbr->PoolType));
614 pdbr->LabelType = str_to_int64(row[15]);
615 bstrncpy(pdbr->LabelFormat, row[16]!=NULL?row[16]:"", sizeof(pdbr->LabelFormat));
616 pdbr->RecyclePoolId = str_to_int64(row[17]);
620 sql_free_result(mdb);
624 Mmsg(mdb->cmd, "SELECT count(*) from Media WHERE PoolId=%s",
625 edit_int64(pdbr->PoolId, ed1));
626 NumVols = get_sql_record_max(jcr, mdb);
627 Dmsg2(400, "Actual NumVols=%d Pool NumVols=%d\n", NumVols, pdbr->NumVols);
628 if (NumVols != pdbr->NumVols) {
629 pdbr->NumVols = NumVols;
630 db_update_pool_record(jcr, mdb, pdbr);
633 Mmsg(mdb->errmsg, _("Pool record not found in Catalog.\n"));
640 * If the ClientId is non-zero, we get its record,
641 * otherwise, we search on the Client Name
643 * Returns: 0 on failure
646 int db_get_client_record(JCR *jcr, B_DB *mdb, CLIENT_DBR *cdbr)
653 if (cdbr->ClientId != 0) { /* find by id */
655 "SELECT ClientId,Name,Uname,AutoPrune,FileRetention,JobRetention "
656 "FROM Client WHERE Client.ClientId=%s",
657 edit_int64(cdbr->ClientId, ed1));
658 } else { /* find by name */
660 "SELECT ClientId,Name,Uname,AutoPrune,FileRetention,JobRetention "
661 "FROM Client WHERE Client.Name='%s'", cdbr->Name);
664 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
665 mdb->num_rows = sql_num_rows(mdb);
666 if (mdb->num_rows > 1) {
667 Mmsg1(mdb->errmsg, _("More than one Client!: %s\n"),
668 edit_uint64(mdb->num_rows, ed1));
669 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
670 } else if (mdb->num_rows == 1) {
671 if ((row = sql_fetch_row(mdb)) == NULL) {
672 Mmsg1(mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb));
673 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
675 cdbr->ClientId = str_to_int64(row[0]);
676 bstrncpy(cdbr->Name, row[1]!=NULL?row[1]:"", sizeof(cdbr->Name));
677 bstrncpy(cdbr->Uname, row[2]!=NULL?row[2]:"", sizeof(cdbr->Uname));
678 cdbr->AutoPrune = str_to_int64(row[3]);
679 cdbr->FileRetention = str_to_int64(row[4]);
680 cdbr->JobRetention = str_to_int64(row[5]);
684 Mmsg(mdb->errmsg, _("Client record not found in Catalog.\n"));
686 sql_free_result(mdb);
688 Mmsg(mdb->errmsg, _("Client record not found in Catalog.\n"));
697 * Returns: 0 on failure
700 int db_get_counter_record(JCR *jcr, B_DB *mdb, COUNTER_DBR *cr)
705 Mmsg(mdb->cmd, "SELECT MinValue,MaxValue,CurrentValue,WrapCounter "
706 "FROM Counters WHERE Counter='%s'", cr->Counter);
708 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
709 mdb->num_rows = sql_num_rows(mdb);
711 /* If more than one, report error, but return first row */
712 if (mdb->num_rows > 1) {
713 Mmsg1(mdb->errmsg, _("More than one Counter!: %d\n"), (int)(mdb->num_rows));
714 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
716 if (mdb->num_rows >= 1) {
717 if ((row = sql_fetch_row(mdb)) == NULL) {
718 Mmsg1(mdb->errmsg, _("error fetching Counter row: %s\n"), sql_strerror(mdb));
719 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
720 sql_free_result(mdb);
724 cr->MinValue = str_to_int64(row[0]);
725 cr->MaxValue = str_to_int64(row[1]);
726 cr->CurrentValue = str_to_int64(row[2]);
728 bstrncpy(cr->WrapCounter, row[3], sizeof(cr->WrapCounter));
730 cr->WrapCounter[0] = 0;
732 sql_free_result(mdb);
736 sql_free_result(mdb);
738 Mmsg(mdb->errmsg, _("Counter record: %s not found in Catalog.\n"), cr->Counter);
745 /* Get FileSet Record
746 * If the FileSetId is non-zero, we get its record,
747 * otherwise, we search on the name
749 * Returns: 0 on failure
752 int db_get_fileset_record(JCR *jcr, B_DB *mdb, FILESET_DBR *fsr)
759 if (fsr->FileSetId != 0) { /* find by id */
761 "SELECT FileSetId,FileSet,MD5,CreateTime FROM FileSet "
762 "WHERE FileSetId=%s",
763 edit_int64(fsr->FileSetId, ed1));
764 } else { /* find by name */
766 "SELECT FileSetId,FileSet,MD5,CreateTime FROM FileSet "
767 "WHERE FileSet='%s' ORDER BY CreateTime DESC LIMIT 1", fsr->FileSet);
770 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
771 mdb->num_rows = sql_num_rows(mdb);
772 if (mdb->num_rows > 1) {
774 Mmsg1(mdb->errmsg, _("Error got %s FileSets but expected only one!\n"),
775 edit_uint64(mdb->num_rows, ed1));
776 sql_data_seek(mdb, mdb->num_rows-1);
778 if ((row = sql_fetch_row(mdb)) == NULL) {
779 Mmsg1(mdb->errmsg, _("FileSet record \"%s\" not found.\n"), fsr->FileSet);
781 fsr->FileSetId = str_to_int64(row[0]);
782 bstrncpy(fsr->FileSet, row[1]!=NULL?row[1]:"", sizeof(fsr->FileSet));
783 bstrncpy(fsr->MD5, row[2]!=NULL?row[2]:"", sizeof(fsr->MD5));
784 bstrncpy(fsr->cCreateTime, row[3]!=NULL?row[3]:"", sizeof(fsr->cCreateTime));
785 stat = fsr->FileSetId;
787 sql_free_result(mdb);
789 Mmsg(mdb->errmsg, _("FileSet record not found in Catalog.\n"));
797 * Get the number of Media records
799 * Returns: -1 on failure
802 int db_get_num_media_records(JCR *jcr, B_DB *mdb)
807 Mmsg(mdb->cmd, "SELECT count(*) from Media");
808 stat = get_sql_record_max(jcr, mdb);
815 * This function returns a list of all the Media record ids for
816 * the current Pool with the correct Media Type.
817 * The caller must free ids if non-NULL.
819 * Returns false: on failure
822 bool db_get_media_ids(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr, int *num_ids, uint32_t *ids[])
832 Mmsg(mdb->cmd, "SELECT DISTINCT MediaId FROM Media WHERE PoolId=%s "
833 " AND MediaType='%s'",
834 edit_int64(mr->PoolId, ed1), mr->MediaType);
835 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
836 *num_ids = sql_num_rows(mdb);
838 id = (uint32_t *)malloc(*num_ids * sizeof(uint32_t));
839 while ((row = sql_fetch_row(mdb)) != NULL) {
840 id[i++] = str_to_uint64(row[0]);
844 sql_free_result(mdb);
847 Mmsg(mdb->errmsg, _("Media id select failed: ERR=%s\n"), sql_strerror(mdb));
848 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
858 * Returns: false: on failure
861 bool db_get_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr)
868 if (mr->MediaId == 0 && mr->VolumeName[0] == 0) {
869 Mmsg(mdb->cmd, "SELECT count(*) from Media");
870 mr->MediaId = get_sql_record_max(jcr, mdb);
874 if (mr->MediaId != 0) { /* find by id */
875 Mmsg(mdb->cmd, "SELECT MediaId,VolumeName,VolJobs,VolFiles,VolBlocks,"
876 "VolBytes,VolMounts,VolErrors,VolWrites,MaxVolBytes,VolCapacityBytes,"
877 "MediaType,VolStatus,PoolId,VolRetention,VolUseDuration,MaxVolJobs,"
878 "MaxVolFiles,Recycle,Slot,FirstWritten,LastWritten,InChanger,"
879 "EndFile,EndBlock,VolParts,LabelType,LabelDate,StorageId,"
880 "Enabled,LocationId,RecycleCount,InitialWrite,"
881 "ScratchPoolId,RecyclePoolId,VolReadTime,VolWriteTime "
882 "FROM Media WHERE MediaId=%s",
883 edit_int64(mr->MediaId, ed1));
884 } else { /* find by name */
885 Mmsg(mdb->cmd, "SELECT MediaId,VolumeName,VolJobs,VolFiles,VolBlocks,"
886 "VolBytes,VolMounts,VolErrors,VolWrites,MaxVolBytes,VolCapacityBytes,"
887 "MediaType,VolStatus,PoolId,VolRetention,VolUseDuration,MaxVolJobs,"
888 "MaxVolFiles,Recycle,Slot,FirstWritten,LastWritten,InChanger,"
889 "EndFile,EndBlock,VolParts,LabelType,LabelDate,StorageId,"
890 "Enabled,LocationId,RecycleCount,InitialWrite,"
891 "ScratchPoolId,RecyclePoolId,VolReadTime,VolWriteTime "
892 "FROM Media WHERE VolumeName='%s'", mr->VolumeName);
895 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
897 mdb->num_rows = sql_num_rows(mdb);
898 if (mdb->num_rows > 1) {
899 Mmsg1(mdb->errmsg, _("More than one Volume!: %s\n"),
900 edit_uint64(mdb->num_rows, ed1));
901 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
902 } else if (mdb->num_rows == 1) {
903 if ((row = sql_fetch_row(mdb)) == NULL) {
904 Mmsg1(mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb));
905 Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
908 mr->MediaId = str_to_int64(row[0]);
909 bstrncpy(mr->VolumeName, row[1]!=NULL?row[1]:"", sizeof(mr->VolumeName));
910 mr->VolJobs = str_to_int64(row[2]);
911 mr->VolFiles = str_to_int64(row[3]);
912 mr->VolBlocks = str_to_int64(row[4]);
913 mr->VolBytes = str_to_uint64(row[5]);
914 mr->VolMounts = str_to_int64(row[6]);
915 mr->VolErrors = str_to_int64(row[7]);
916 mr->VolWrites = str_to_int64(row[8]);
917 mr->MaxVolBytes = str_to_uint64(row[9]);
918 mr->VolCapacityBytes = str_to_uint64(row[10]);
919 bstrncpy(mr->MediaType, row[11]!=NULL?row[11]:"", sizeof(mr->MediaType));
920 bstrncpy(mr->VolStatus, row[12]!=NULL?row[12]:"", sizeof(mr->VolStatus));
921 mr->PoolId = str_to_int64(row[13]);
922 mr->VolRetention = str_to_uint64(row[14]);
923 mr->VolUseDuration = str_to_uint64(row[15]);
924 mr->MaxVolJobs = str_to_int64(row[16]);
925 mr->MaxVolFiles = str_to_int64(row[17]);
926 mr->Recycle = str_to_int64(row[18]);
927 mr->Slot = str_to_int64(row[19]);
928 bstrncpy(mr->cFirstWritten, row[20]!=NULL?row[20]:"", sizeof(mr->cFirstWritten));
929 mr->FirstWritten = (time_t)str_to_utime(mr->cFirstWritten);
930 bstrncpy(mr->cLastWritten, row[21]!=NULL?row[21]:"", sizeof(mr->cLastWritten));
931 mr->LastWritten = (time_t)str_to_utime(mr->cLastWritten);
932 mr->InChanger = str_to_uint64(row[22]);
933 mr->EndFile = str_to_uint64(row[23]);
934 mr->EndBlock = str_to_uint64(row[24]);
935 mr->VolParts = str_to_int64(row[25]);
936 mr->LabelType = str_to_int64(row[26]);
937 bstrncpy(mr->cLabelDate, row[27]!=NULL?row[27]:"", sizeof(mr->cLabelDate));
938 mr->LabelDate = (time_t)str_to_utime(mr->cLabelDate);
939 mr->StorageId = str_to_int64(row[28]);
940 mr->Enabled = str_to_int64(row[29]);
941 mr->LocationId = str_to_int64(row[30]);
942 mr->RecycleCount = str_to_int64(row[31]);
943 bstrncpy(mr->cInitialWrite, row[32]!=NULL?row[32]:"", sizeof(mr->cInitialWrite));
944 mr->InitialWrite = (time_t)str_to_utime(mr->cInitialWrite);
945 mr->ScratchPoolId = str_to_int64(row[33]);
946 mr->RecyclePoolId = str_to_int64(row[34]);
947 mr->VolReadTime = str_to_int64(row[35]);
948 mr->VolWriteTime = str_to_int64(row[36]);
953 if (mr->MediaId != 0) {
954 Mmsg1(mdb->errmsg, _("Media record MediaId=%s not found.\n"),
955 edit_int64(mr->MediaId, ed1));
957 Mmsg1(mdb->errmsg, _("Media record for Volume \"%s\" not found.\n"),
961 sql_free_result(mdb);
963 if (mr->MediaId != 0) {
964 Mmsg(mdb->errmsg, _("Media record for MediaId=%u not found in Catalog.\n"),
967 Mmsg(mdb->errmsg, _("Media record for Vol=%s not found in Catalog.\n"),
975 #endif /* HAVE_SQLITE3 || HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL*/