]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/cats/sql_get.c
kes Fix incorrect number of arguments in SQL statement in
[bacula/bacula] / bacula / src / cats / sql_get.c
1 /*
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
5  *        should be in find.c
6  *
7  *    Kern Sibbald, March 2000
8  *
9  *    Version $Id$
10  */
11
12 /*
13    Copyright (C) 2000-2006 Kern Sibbald
14
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.
19
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.
24
25  */
26
27
28 /* The following is necessary so that we do not include
29  * the dummy external definition of DB.
30  */
31 #define __SQL_C                       /* indicate that this is sql.c */
32
33 #include "bacula.h"
34 #include "cats.h"
35
36 #if    HAVE_SQLITE3 || HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL
37
38 /* -----------------------------------------------------------------------
39  *
40  *   Generic Routines (or almost generic)
41  *
42  * -----------------------------------------------------------------------
43  */
44
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);
49
50
51 /*
52  * Given a full filename (with path), look up the File record
53  * (with attributes) in the database.
54  *
55  *  Returns: 0 on failure
56  *           1 on success with the File record in FILE_DBR
57  */
58 int db_get_file_attributes_record(JCR *jcr, B_DB *mdb, char *fname, JOB_DBR *jr, FILE_DBR *fdbr)
59 {
60    int stat;
61    Dmsg1(100, "db_get_file_att_record fname=%s \n", fname);
62
63    db_lock(mdb);
64    split_path_and_file(jcr, mdb, fname);
65
66    fdbr->FilenameId = db_get_filename_record(jcr, mdb);
67
68    fdbr->PathId = db_get_path_record(jcr, mdb);
69
70    stat = db_get_file_record(jcr, mdb, jr, fdbr);
71
72    db_unlock(mdb);
73
74    return stat;
75 }
76
77
78 /*
79  * Get a File record
80  * Returns: 0 on failure
81  *          1 on success
82  *
83  *  DO NOT use Jmsg in this routine.
84  *
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.
88  */
89 static
90 int db_get_file_record(JCR *jcr, B_DB *mdb, JOB_DBR *jr, FILE_DBR *fdbr)
91 {
92    SQL_ROW row;
93    int stat = 0;
94    char ed1[50], ed2[50], ed3[50];
95
96    if (jcr->JobLevel == L_VERIFY_DISK_TO_CATALOG) {
97    Mmsg(mdb->cmd,
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));
105
106    } else {
107       Mmsg(mdb->cmd,
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));
113    }
114    Dmsg3(050, "Get_file_record JobId=%u FilenameId=%u PathId=%u\n",
115       fdbr->JobId, fdbr->FilenameId, fdbr->PathId);
116
117    Dmsg1(100, "Query=%s\n", mdb->cmd);
118
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"),
124             mdb->num_rows);
125       }
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));
129          } else {
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));
133             stat = 1;
134          }
135       } else {
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));
139       }
140       sql_free_result(mdb);
141    } else {
142       Mmsg(mdb->errmsg, _("File record not found in Catalog.\n"));
143    }
144    return stat;
145
146 }
147
148 /* Get Filename record
149  * Returns: 0 on failure
150  *          FilenameId on success
151  *
152  *   DO NOT use Jmsg in this routine (see notes for get_file_record)
153  */
154 static int db_get_filename_record(JCR *jcr, B_DB *mdb)
155 {
156    SQL_ROW row;
157    int FilenameId = 0;
158
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);
161
162    Mmsg(mdb->cmd, "SELECT FilenameId FROM Filename WHERE Name='%s'", mdb->esc_name);
163    if (QUERY_DB(jcr, mdb, mdb->cmd)) {
164       char ed1[30];
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);
170       }
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));
174          } else {
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);
179                FilenameId = 0;
180             }
181          }
182       } else {
183          Mmsg1(mdb->errmsg, _("Filename record: %s not found.\n"), mdb->fname);
184       }
185       sql_free_result(mdb);
186    } else {
187       Mmsg(mdb->errmsg, _("Filename record: %s not found in Catalog.\n"), mdb->fname);
188    }
189    return FilenameId;
190 }
191
192 /* Get path record
193  * Returns: 0 on failure
194  *          PathId on success
195  *
196  *   DO NOT use Jmsg in this routine (see notes for get_file_record)
197  */
198 static int db_get_path_record(JCR *jcr, B_DB *mdb)
199 {
200    SQL_ROW row;
201    uint32_t PathId = 0;
202
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);
205
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;
209    }
210
211    Mmsg(mdb->cmd, "SELECT PathId FROM Path WHERE Path='%s'", mdb->esc_name);
212
213    if (QUERY_DB(jcr, mdb, mdb->cmd)) {
214       char ed1[30];
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);
220       }
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));
225          } else {
226             PathId = str_to_int64(row[0]);
227             if (PathId <= 0) {
228                Mmsg2(mdb->errmsg, _("Get DB path record %s found bad record: %s\n"),
229                   mdb->cmd, edit_int64(PathId, ed1));
230                PathId = 0;
231             } else {
232                /* Cache path */
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);
237                }
238             }
239          }
240       } else {
241          Mmsg1(mdb->errmsg, _("Path record: %s not found.\n"), mdb->path);
242       }
243       sql_free_result(mdb);
244    } else {
245       Mmsg(mdb->errmsg, _("Path record: %s not found in Catalog.\n"), mdb->path);
246    }
247    return PathId;
248 }
249
250
251 /*
252  * Get Job record for given JobId or Job name
253  * Returns: false on failure
254  *          true  on success
255  */
256 bool db_get_job_record(JCR *jcr, B_DB *mdb, JOB_DBR *jr)
257 {
258    SQL_ROW row;
259    char ed1[50];
260
261    db_lock(mdb);
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,PriorJobId,RealEndTime "
266 "FROM Job WHERE Job='%s'", jr->Job);
267     } else {
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));
273     }
274
275    if (!QUERY_DB(jcr, mdb, mdb->cmd)) {
276       db_unlock(mdb);
277       return false;                   /* failed */
278    }
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);
282       db_unlock(mdb);
283       return false;                   /* failed */
284    }
285
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);
303
304    db_unlock(mdb);
305    return true;
306 }
307
308 /*
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.
315  *
316  *  Returns: number of volumes on success
317  */
318 int db_get_job_volume_names(JCR *jcr, B_DB *mdb, JobId_t JobId, POOLMEM **VolumeNames)
319 {
320    SQL_ROW row;
321    char ed1[50];
322    int stat = 0;
323    int i;
324
325    db_lock(mdb);
326    /* Get one entry per VolumeName, but "sort" by VolIndex */
327    Mmsg(mdb->cmd,
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));
332
333    Dmsg1(130, "VolNam=%s\n", mdb->cmd);
334    *VolumeNames[0] = 0;
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);
340          stat = 0;
341       } else {
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);
347                stat = 0;
348                break;
349             } else {
350                if (*VolumeNames[0] != 0) {
351                   pm_strcat(VolumeNames, "|");
352                }
353                pm_strcat(VolumeNames, row[0]);
354             }
355          }
356       }
357       sql_free_result(mdb);
358    } else {
359       Mmsg(mdb->errmsg, _("No Volume for JobId %d found in Catalog.\n"), JobId);
360    }
361    db_unlock(mdb);
362    return stat;
363 }
364
365 /*
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!)
370  *
371  *  Returns: number of volumes on success
372  */
373 int db_get_job_volume_parameters(JCR *jcr, B_DB *mdb, JobId_t JobId, VOL_PARAMS **VolParams)
374 {
375    SQL_ROW row;
376    char ed1[50];
377    int stat = 0;
378    int i;
379    VOL_PARAMS *Vols = NULL;
380
381    db_lock(mdb);
382    Mmsg(mdb->cmd,
383 "SELECT VolumeName,MediaType,FirstIndex,LastIndex,StartFile,"
384 "JobMedia.EndFile,StartBlock,JobMedia.EndBlock,Copy,"
385 "Slot,StorageId"
386 " FROM JobMedia,Media WHERE JobMedia.JobId=%s"
387 " AND JobMedia.MediaId=Media.MediaId ORDER BY VolIndex,JobMediaId",
388         edit_int64(JobId, ed1));
389
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);
396          stat = 0;
397       } else {
398          stat = mdb->num_rows;
399          DBId_t *SId;
400          if (stat > 0) {
401             *VolParams = Vols = (VOL_PARAMS *)malloc(stat * sizeof(VOL_PARAMS));
402             SId = (DBId_t *)malloc(stat * sizeof(DBId_t));
403          } else {
404             SId = NULL;
405          }
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);
410                stat = 0;
411                break;
412             } else {
413                DBId_t StorageId;
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;
426                SId[i] = StorageId;
427             }
428          }
429          for (i=0; i < stat; i++) {
430             if (SId[i] != 0) {
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);
436                   }
437                }
438             }
439          }
440       }
441       sql_free_result(mdb);
442    }
443    db_unlock(mdb);
444    return stat;
445 }
446
447
448
449 /*
450  * Get the number of pool records
451  *
452  * Returns: -1 on failure
453  *          number on success
454  */
455 int db_get_num_pool_records(JCR *jcr, B_DB *mdb)
456 {
457    int stat = 0;
458
459    db_lock(mdb);
460    Mmsg(mdb->cmd, "SELECT count(*) from Pool");
461    stat = get_sql_record_max(jcr, mdb);
462    db_unlock(mdb);
463    return stat;
464 }
465
466 /*
467  * This function returns a list of all the Pool record ids.
468  *  The caller must free ids if non-NULL.
469  *
470  *  Returns 0: on failure
471  *          1: on success
472  */
473 int db_get_pool_ids(JCR *jcr, B_DB *mdb, int *num_ids, uint32_t *ids[])
474 {
475    SQL_ROW row;
476    int stat = 0;
477    int i = 0;
478    uint32_t *id;
479
480    db_lock(mdb);
481    *ids = NULL;
482    Mmsg(mdb->cmd, "SELECT PoolId FROM Pool");
483    if (QUERY_DB(jcr, mdb, mdb->cmd)) {
484       *num_ids = sql_num_rows(mdb);
485       if (*num_ids > 0) {
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]);
489          }
490          *ids = id;
491       }
492       sql_free_result(mdb);
493       stat = 1;
494    } else {
495       Mmsg(mdb->errmsg, _("Pool id select failed: ERR=%s\n"), sql_strerror(mdb));
496       Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
497       stat = 0;
498    }
499    db_unlock(mdb);
500    return stat;
501 }
502
503 /*
504  * This function returns a list of all the Client record ids.
505  *  The caller must free ids if non-NULL.
506  *
507  *  Returns 0: on failure
508  *          1: on success
509  */
510 int db_get_client_ids(JCR *jcr, B_DB *mdb, int *num_ids, uint32_t *ids[])
511 {
512    SQL_ROW row;
513    int stat = 0;
514    int i = 0;
515    uint32_t *id;
516
517    db_lock(mdb);
518    *ids = NULL;
519    Mmsg(mdb->cmd, "SELECT ClientId FROM Client");
520    if (QUERY_DB(jcr, mdb, mdb->cmd)) {
521       *num_ids = sql_num_rows(mdb);
522       if (*num_ids > 0) {
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]);
526          }
527          *ids = id;
528       }
529       sql_free_result(mdb);
530       stat = 1;
531    } else {
532       Mmsg(mdb->errmsg, _("Client id select failed: ERR=%s\n"), sql_strerror(mdb));
533       Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
534       stat = 0;
535    }
536    db_unlock(mdb);
537    return stat;
538 }
539
540
541
542 /* Get Pool Record
543  * If the PoolId is non-zero, we get its record,
544  *  otherwise, we search on the PoolName
545  *
546  * Returns: false on failure
547  *          true on success
548  */
549 bool db_get_pool_record(JCR *jcr, B_DB *mdb, POOL_DBR *pdbr)
550 {
551    SQL_ROW row;
552    bool ok = false;
553    char ed1[50];
554
555    db_lock(mdb);
556    if (pdbr->PoolId != 0) {               /* find by id */
557       Mmsg(mdb->cmd,
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 */
563       Mmsg(mdb->cmd,
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'", 
567          pdbr->Name);
568    }
569
570    if (QUERY_DB(jcr, mdb, mdb->cmd)) {
571       mdb->num_rows = sql_num_rows(mdb);
572       if (mdb->num_rows > 1) {
573          char ed1[30];
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);
581          } else {
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));
599             ok = true;
600          }
601       }
602       sql_free_result(mdb);
603    }
604    if (ok) {
605       uint32_t NumVols;
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);
613       }
614    } else {
615       Mmsg(mdb->errmsg, _("Pool record not found in Catalog.\n"));
616    }
617    db_unlock(mdb);
618    return ok;
619 }
620
621 /* Get Client Record
622  * If the ClientId is non-zero, we get its record,
623  *  otherwise, we search on the Client Name
624  *
625  * Returns: 0 on failure
626  *          1 on success
627  */
628 int db_get_client_record(JCR *jcr, B_DB *mdb, CLIENT_DBR *cdbr)
629 {
630    SQL_ROW row;
631    int stat = 0;
632    char ed1[50];
633
634    db_lock(mdb);
635    if (cdbr->ClientId != 0) {               /* find by id */
636       Mmsg(mdb->cmd,
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 */
641       Mmsg(mdb->cmd,
642 "SELECT ClientId,Name,Uname,AutoPrune,FileRetention,JobRetention "
643 "FROM Client WHERE Client.Name='%s'", cdbr->Name);
644    }
645
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);
656          } else {
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]);
663             stat = 1;
664          }
665       } else {
666          Mmsg(mdb->errmsg, _("Client record not found in Catalog.\n"));
667       }
668       sql_free_result(mdb);
669    } else {
670       Mmsg(mdb->errmsg, _("Client record not found in Catalog.\n"));
671    }
672    db_unlock(mdb);
673    return stat;
674 }
675
676 /*
677  * Get Counter Record
678  *
679  * Returns: 0 on failure
680  *          1 on success
681  */
682 int db_get_counter_record(JCR *jcr, B_DB *mdb, COUNTER_DBR *cr)
683 {
684    SQL_ROW row;
685
686    db_lock(mdb);
687    Mmsg(mdb->cmd, "SELECT MinValue,MaxValue,CurrentValue,WrapCounter "
688       "FROM Counters WHERE Counter='%s'", cr->Counter);
689
690    if (QUERY_DB(jcr, mdb, mdb->cmd)) {
691       mdb->num_rows = sql_num_rows(mdb);
692
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);
697       }
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);
703             db_unlock(mdb);
704             return 0;
705          }
706          cr->MinValue = str_to_int64(row[0]);
707          cr->MaxValue = str_to_int64(row[1]);
708          cr->CurrentValue = str_to_int64(row[2]);
709          if (row[3]) {
710             bstrncpy(cr->WrapCounter, row[3], sizeof(cr->WrapCounter));
711          } else {
712             cr->WrapCounter[0] = 0;
713          }
714          sql_free_result(mdb);
715          db_unlock(mdb);
716          return 1;
717       }
718       sql_free_result(mdb);
719    } else {
720       Mmsg(mdb->errmsg, _("Counter record: %s not found in Catalog.\n"), cr->Counter);
721    }
722    db_unlock(mdb);
723    return 0;
724 }
725
726
727 /* Get FileSet Record
728  * If the FileSetId is non-zero, we get its record,
729  *  otherwise, we search on the name
730  *
731  * Returns: 0 on failure
732  *          id on success
733  */
734 int db_get_fileset_record(JCR *jcr, B_DB *mdb, FILESET_DBR *fsr)
735 {
736    SQL_ROW row;
737    int stat = 0;
738    char ed1[50];
739
740    db_lock(mdb);
741    if (fsr->FileSetId != 0) {               /* find by id */
742       Mmsg(mdb->cmd,
743            "SELECT FileSetId,FileSet,MD5,CreateTime FROM FileSet "
744            "WHERE FileSetId=%s", 
745            edit_int64(fsr->FileSetId, ed1));
746    } else {                           /* find by name */
747       Mmsg(mdb->cmd,
748            "SELECT FileSetId,FileSet,MD5,CreateTime FROM FileSet "
749            "WHERE FileSet='%s' ORDER BY CreateTime DESC LIMIT 1", fsr->FileSet);
750    }
751
752    if (QUERY_DB(jcr, mdb, mdb->cmd)) {
753       mdb->num_rows = sql_num_rows(mdb);
754       if (mdb->num_rows > 1) {
755          char ed1[30];
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);
759       }
760       if ((row = sql_fetch_row(mdb)) == NULL) {
761          Mmsg1(mdb->errmsg, _("FileSet record \"%s\" not found.\n"), fsr->FileSet);
762       } else {
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;
768       }
769       sql_free_result(mdb);
770    } else {
771       Mmsg(mdb->errmsg, _("FileSet record not found in Catalog.\n"));
772    }
773    db_unlock(mdb);
774    return stat;
775 }
776
777
778 /*
779  * Get the number of Media records
780  *
781  * Returns: -1 on failure
782  *          number on success
783  */
784 int db_get_num_media_records(JCR *jcr, B_DB *mdb)
785 {
786    int stat = 0;
787
788    db_lock(mdb);
789    Mmsg(mdb->cmd, "SELECT count(*) from Media");
790    stat = get_sql_record_max(jcr, mdb);
791    db_unlock(mdb);
792    return stat;
793 }
794
795
796 /*
797  * This function returns a list of all the Media record ids for
798  *     the current Pool.
799  *  The caller must free ids if non-NULL.
800  *
801  *  Returns false: on failure
802  *          true:  on success
803  */
804 bool db_get_media_ids(JCR *jcr, B_DB *mdb, uint32_t PoolId, int *num_ids, uint32_t *ids[])
805 {
806    SQL_ROW row;
807    int i = 0;
808    uint32_t *id;
809    char ed1[50];
810    bool ok = false;
811
812    db_lock(mdb);
813    *ids = NULL;
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);
818       if (*num_ids > 0) {
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]);
822          }
823          *ids = id;
824       }
825       sql_free_result(mdb);
826       ok = true;
827    } else {
828       Mmsg(mdb->errmsg, _("Media id select failed: ERR=%s\n"), sql_strerror(mdb));
829       Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
830       ok = false;
831    }
832    db_unlock(mdb);
833    return ok;
834 }
835
836
837 /* Get Media Record
838  *
839  * Returns: false: on failure
840  *          true:  on success
841  */
842 bool db_get_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr)
843 {
844    SQL_ROW row;
845    char ed1[50];
846    bool ok = false;
847
848    db_lock(mdb);
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);
852       db_unlock(mdb);
853       return true;
854    }
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);
874    }
875
876    if (QUERY_DB(jcr, mdb, mdb->cmd)) {
877       char ed1[50];
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);
887          } else {
888             /* return values */
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]);
928             
929             ok = true;
930          }
931       } else {
932          if (mr->MediaId != 0) {
933             Mmsg1(mdb->errmsg, _("Media record MediaId=%s not found.\n"), 
934                edit_int64(mr->MediaId, ed1));
935          } else {
936             Mmsg1(mdb->errmsg, _("Media record for Volume \"%s\" not found.\n"),
937                   mr->VolumeName);
938          }
939       }
940       sql_free_result(mdb);
941    } else {
942       if (mr->MediaId != 0) {
943          Mmsg(mdb->errmsg, _("Media record for MediaId=%u not found in Catalog.\n"),
944             mr->MediaId);
945        } else {
946          Mmsg(mdb->errmsg, _("Media record for Vol=%s not found in Catalog.\n"),
947             mr->VolumeName);
948    }   }
949    db_unlock(mdb);
950    return ok;
951 }
952
953
954 #endif /* HAVE_SQLITE3 || HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL*/