]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/cats/sql_get.c
o initial add
[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 /* Imported subroutines */
52 extern void print_result(B_DB *mdb);
53 extern int QueryDB(const char *file, int line, JCR *jcr, B_DB *db, char *select_cmd);
54 extern void split_path_and_file(JCR *jcr, B_DB *mdb, const char *fname);
55
56
57
58 /*
59  * Given a full filename (with path), look up the File record
60  * (with attributes) in the database.
61  *
62  *  Returns: 0 on failure
63  *           1 on success with the File record in FILE_DBR
64  */
65 int db_get_file_attributes_record(JCR *jcr, B_DB *mdb, char *fname, JOB_DBR *jr, FILE_DBR *fdbr)
66 {
67    int stat;
68    Dmsg1(100, "db_get_file_att_record fname=%s \n", fname);
69
70    db_lock(mdb);
71    split_path_and_file(jcr, mdb, fname);
72
73    fdbr->FilenameId = db_get_filename_record(jcr, mdb);
74
75    fdbr->PathId = db_get_path_record(jcr, mdb);
76
77    stat = db_get_file_record(jcr, mdb, jr, fdbr);
78
79    db_unlock(mdb);
80
81    return stat;
82 }
83
84
85 /*
86  * Get a File record
87  * Returns: 0 on failure
88  *          1 on success
89  *
90  *  DO NOT use Jmsg in this routine.
91  *
92  *  Note in this routine, we do not use Jmsg because it may be
93  *    called to get attributes of a non-existent file, which is
94  *    "normal" if a new file is found during Verify.
95  */
96 static
97 int db_get_file_record(JCR *jcr, B_DB *mdb, JOB_DBR *jr, FILE_DBR *fdbr)
98 {
99    SQL_ROW row;
100    int stat = 0;
101    char ed1[50], ed2[50], ed3[50];
102
103    if (jcr->JobLevel == L_VERIFY_DISK_TO_CATALOG) {
104    Mmsg(mdb->cmd,
105 "SELECT FileId, LStat, MD5 FROM File,Job WHERE "
106 "File.JobId=Job.JobId AND File.PathId=%s AND "
107 "File.FilenameId=%s AND Job.Type='B' AND Job.JobSTATUS='T' AND "
108 "ClientId=%s ORDER BY StartTime DESC LIMIT 1",
109       edit_int64(fdbr->PathId, ed1), 
110       edit_int64(fdbr->FilenameId, ed2), 
111       edit_int64(jr->ClientId,ed3));
112
113    } else {
114       Mmsg(mdb->cmd,
115 "SELECT FileId, LStat, MD5 FROM File WHERE File.JobId=%s AND File.PathId=%s AND "
116 "File.FilenameId=%s", 
117       edit_int64(fdbr->JobId, ed1), 
118       edit_int64(fdbr->PathId, ed2), 
119       edit_int64(fdbr->FilenameId,ed3));
120    }
121    Dmsg3(050, "Get_file_record JobId=%u FilenameId=%u PathId=%u\n",
122       fdbr->JobId, fdbr->FilenameId, fdbr->PathId);
123
124    Dmsg1(100, "Query=%s\n", mdb->cmd);
125
126    if (QUERY_DB(jcr, mdb, mdb->cmd)) {
127       mdb->num_rows = sql_num_rows(mdb);
128       Dmsg1(050, "get_file_record num_rows=%d\n", (int)mdb->num_rows);
129       if (mdb->num_rows > 1) {
130          Mmsg1(mdb->errmsg, _("get_file_record want 1 got rows=%d\n"),
131             mdb->num_rows);
132       }
133       if (mdb->num_rows >= 1) {
134          if ((row = sql_fetch_row(mdb)) == NULL) {
135             Mmsg1(mdb->errmsg, _("Error fetching row: %s\n"), sql_strerror(mdb));
136          } else {
137             fdbr->FileId = (FileId_t)str_to_int64(row[0]);
138             bstrncpy(fdbr->LStat, row[1], sizeof(fdbr->LStat));
139             bstrncpy(fdbr->Digest, row[2], sizeof(fdbr->Digest));
140             stat = 1;
141          }
142       } else {
143          Mmsg2(mdb->errmsg, _("File record for PathId=%s FilenameId=%s not found.\n"),
144             edit_int64(fdbr->PathId, ed1), 
145             edit_int64(fdbr->FilenameId, ed2));
146       }
147       sql_free_result(mdb);
148    } else {
149       Mmsg(mdb->errmsg, _("File record not found in Catalog.\n"));
150    }
151    return stat;
152
153 }
154
155 /* Get Filename record
156  * Returns: 0 on failure
157  *          FilenameId on success
158  *
159  *   DO NOT use Jmsg in this routine (see notes for get_file_record)
160  */
161 static int db_get_filename_record(JCR *jcr, B_DB *mdb)
162 {
163    SQL_ROW row;
164    int FilenameId = 0;
165
166    mdb->esc_name = check_pool_memory_size(mdb->esc_name, 2*mdb->fnl+2);
167    db_escape_string(mdb->esc_name, mdb->fname, mdb->fnl);
168
169    Mmsg(mdb->cmd, "SELECT FilenameId FROM Filename WHERE Name='%s'", mdb->esc_name);
170    if (QUERY_DB(jcr, mdb, mdb->cmd)) {
171       char ed1[30];
172       mdb->num_rows = sql_num_rows(mdb);
173       if (mdb->num_rows > 1) {
174          Mmsg2(mdb->errmsg, _("More than one Filename!: %s for file: %s\n"),
175             edit_uint64(mdb->num_rows, ed1), mdb->fname);
176          Jmsg(jcr, M_WARNING, 0, "%s", mdb->errmsg);
177       }
178       if (mdb->num_rows >= 1) {
179          if ((row = sql_fetch_row(mdb)) == NULL) {
180             Mmsg1(mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb));
181          } else {
182             FilenameId = str_to_int64(row[0]);
183             if (FilenameId <= 0) {
184                Mmsg2(mdb->errmsg, _("Get DB Filename record %s found bad record: %d\n"),
185                   mdb->cmd, FilenameId);
186                FilenameId = 0;
187             }
188          }
189       } else {
190          Mmsg1(mdb->errmsg, _("Filename record: %s not found.\n"), mdb->fname);
191       }
192       sql_free_result(mdb);
193    } else {
194       Mmsg(mdb->errmsg, _("Filename record: %s not found in Catalog.\n"), mdb->fname);
195    }
196    return FilenameId;
197 }
198
199 /* Get path record
200  * Returns: 0 on failure
201  *          PathId on success
202  *
203  *   DO NOT use Jmsg in this routine (see notes for get_file_record)
204  */
205 static int db_get_path_record(JCR *jcr, B_DB *mdb)
206 {
207    SQL_ROW row;
208    uint32_t PathId = 0;
209
210    mdb->esc_name = check_pool_memory_size(mdb->esc_name, 2*mdb->pnl+2);
211    db_escape_string(mdb->esc_name, mdb->path, mdb->pnl);
212
213    if (mdb->cached_path_id != 0 && mdb->cached_path_len == mdb->pnl &&
214        strcmp(mdb->cached_path, mdb->path) == 0) {
215       return mdb->cached_path_id;
216    }
217
218    Mmsg(mdb->cmd, "SELECT PathId FROM Path WHERE Path='%s'", mdb->esc_name);
219
220    if (QUERY_DB(jcr, mdb, mdb->cmd)) {
221       char ed1[30];
222       mdb->num_rows = sql_num_rows(mdb);
223       if (mdb->num_rows > 1) {
224          Mmsg2(mdb->errmsg, _("More than one Path!: %s for path: %s\n"),
225             edit_uint64(mdb->num_rows, ed1), mdb->path);
226          Jmsg(jcr, M_WARNING, 0, "%s", mdb->errmsg);
227       }
228       /* Even if there are multiple paths, take the first one */
229       if (mdb->num_rows >= 1) {
230          if ((row = sql_fetch_row(mdb)) == NULL) {
231             Mmsg1(mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb));
232          } else {
233             PathId = str_to_int64(row[0]);
234             if (PathId <= 0) {
235                Mmsg2(mdb->errmsg, _("Get DB path record %s found bad record: %s\n"),
236                   mdb->cmd, edit_int64(PathId, ed1));
237                PathId = 0;
238             } else {
239                /* Cache path */
240                if (PathId != mdb->cached_path_id) {
241                   mdb->cached_path_id = PathId;
242                   mdb->cached_path_len = mdb->pnl;
243                   pm_strcpy(mdb->cached_path, mdb->path);
244                }
245             }
246          }
247       } else {
248          Mmsg1(mdb->errmsg, _("Path record: %s not found.\n"), mdb->path);
249       }
250       sql_free_result(mdb);
251    } else {
252       Mmsg(mdb->errmsg, _("Path record: %s not found in Catalog.\n"), mdb->path);
253    }
254    return PathId;
255 }
256
257
258 /*
259  * Get Job record for given JobId or Job name
260  * Returns: false on failure
261  *          true  on success
262  */
263 bool db_get_job_record(JCR *jcr, B_DB *mdb, JOB_DBR *jr)
264 {
265    SQL_ROW row;
266    char ed1[50];
267
268    db_lock(mdb);
269    if (jr->JobId == 0) {
270       Mmsg(mdb->cmd, "SELECT VolSessionId,VolSessionTime,"
271 "PoolId,StartTime,EndTime,JobFiles,JobBytes,JobTDate,Job,JobStatus,"
272 "Type,Level,ClientId,Name "
273 "FROM Job WHERE Job='%s'", jr->Job);
274     } else {
275       Mmsg(mdb->cmd, "SELECT VolSessionId,VolSessionTime,"
276 "PoolId,StartTime,EndTime,JobFiles,JobBytes,JobTDate,Job,JobStatus,"
277 "Type,Level,ClientId,Name "
278 "FROM Job WHERE JobId=%s", 
279           edit_int64(jr->JobId, ed1));
280     }
281
282    if (!QUERY_DB(jcr, mdb, mdb->cmd)) {
283       db_unlock(mdb);
284       return false;                   /* failed */
285    }
286    if ((row = sql_fetch_row(mdb)) == NULL) {
287       Mmsg1(mdb->errmsg, _("No Job found for JobId %s\n"), edit_int64(jr->JobId, ed1));
288       sql_free_result(mdb);
289       db_unlock(mdb);
290       return false;                   /* failed */
291    }
292
293    jr->VolSessionId = str_to_uint64(row[0]);
294    jr->VolSessionTime = str_to_uint64(row[1]);
295    jr->PoolId = str_to_int64(row[2]);
296    bstrncpy(jr->cStartTime, row[3]!=NULL?row[3]:"", sizeof(jr->cStartTime));
297    bstrncpy(jr->cEndTime, row[4]!=NULL?row[4]:"", sizeof(jr->cEndTime));
298    jr->JobFiles = str_to_int64(row[5]);
299    jr->JobBytes = str_to_int64(row[6]);
300    jr->JobTDate = str_to_int64(row[7]);
301    bstrncpy(jr->Job, row[8]!=NULL?row[8]:"", sizeof(jr->Job));
302    jr->JobStatus = (int)*row[9];
303    jr->JobType = (int)*row[10];
304    jr->JobLevel = (int)*row[11];
305    jr->ClientId = str_to_uint64(row[12]!=NULL?row[12]:(char *)"");
306    bstrncpy(jr->Name, row[13]!=NULL?row[13]:"", sizeof(jr->Name));
307    sql_free_result(mdb);
308
309    db_unlock(mdb);
310    return true;
311 }
312
313 /*
314  * Get MAC record for given JobId
315  * Returns: false on failure
316  *          true  on success
317  */
318 bool db_get_mac_record(JCR *jcr, B_DB *mdb, MAC_DBR *mr)
319 {
320    SQL_ROW row;
321    char ed1[50];
322
323    db_lock(mdb);
324    Mmsg(mdb->cmd, "SELECT OriginalJobId,JobType,JobLevel,"
325 "SchedTime,StartTime,EndTime,JobTDate"
326 "FROM MAC WHERE JobId=%s", 
327       edit_int64(mr->JobId, ed1));
328
329    if (!QUERY_DB(jcr, mdb, mdb->cmd)) {
330       db_unlock(mdb);
331       return 0;                       /* failed */
332    }
333    if ((row = sql_fetch_row(mdb)) == NULL) {
334       Mmsg1(mdb->errmsg, _("No MAC record found for JobId %s\n"), ed1);
335       sql_free_result(mdb);
336       db_unlock(mdb);
337       return false;                   /* failed */
338    }
339
340    mr->OriginalJobId = str_to_int64(row[0]);
341    mr->JobType = (int)*row[1];
342    mr->JobLevel = (int)*row[2];
343    bstrncpy(mr->cSchedTime, row[3]!=NULL?row[3]:"", sizeof(mr->cSchedTime));
344    bstrncpy(mr->cStartTime, row[4]!=NULL?row[4]:"", sizeof(mr->cStartTime));
345    bstrncpy(mr->cEndTime, row[5]!=NULL?row[5]:"", sizeof(mr->cEndTime));
346    mr->JobTDate = str_to_int64(row[6]);
347    sql_free_result(mdb);
348
349    db_unlock(mdb);
350    return 1;
351 }
352
353
354 /*
355  * Find VolumeNames for a given JobId
356  *  Returns: 0 on error or no Volumes found
357  *           number of volumes on success
358  *              Volumes are concatenated in VolumeNames
359  *              separated by a vertical bar (|) in the order
360  *              that they were written.
361  *
362  *  Returns: number of volumes on success
363  */
364 int db_get_job_volume_names(JCR *jcr, B_DB *mdb, JobId_t JobId, POOLMEM **VolumeNames)
365 {
366    SQL_ROW row;
367    char ed1[50];
368    int stat = 0;
369    int i;
370
371    db_lock(mdb);
372    /* Get one entry per VolumeName, but "sort" by VolIndex */
373    Mmsg(mdb->cmd,
374         "SELECT VolumeName,MAX(VolIndex) FROM JobMedia,Media WHERE "
375         "JobMedia.JobId=%s AND JobMedia.MediaId=Media.MediaId "
376         "GROUP BY VolumeName "
377         "ORDER BY 2 ASC", edit_int64(JobId,ed1));
378
379    Dmsg1(130, "VolNam=%s\n", mdb->cmd);
380    *VolumeNames[0] = 0;
381    if (QUERY_DB(jcr, mdb, mdb->cmd)) {
382       mdb->num_rows = sql_num_rows(mdb);
383       Dmsg1(130, "Num rows=%d\n", mdb->num_rows);
384       if (mdb->num_rows <= 0) {
385          Mmsg1(mdb->errmsg, _("No volumes found for JobId=%d\n"), JobId);
386          stat = 0;
387       } else {
388          stat = mdb->num_rows;
389          for (i=0; i < stat; i++) {
390             if ((row = sql_fetch_row(mdb)) == NULL) {
391                Mmsg2(mdb->errmsg, _("Error fetching row %d: ERR=%s\n"), i, sql_strerror(mdb));
392                Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
393                stat = 0;
394                break;
395             } else {
396                if (*VolumeNames[0] != 0) {
397                   pm_strcat(VolumeNames, "|");
398                }
399                pm_strcat(VolumeNames, row[0]);
400             }
401          }
402       }
403       sql_free_result(mdb);
404    } else {
405       Mmsg(mdb->errmsg, _("No Volume for JobId %d found in Catalog.\n"), JobId);
406    }
407    db_unlock(mdb);
408    return stat;
409 }
410
411 /*
412  * Find Volume parameters for a give JobId
413  *  Returns: 0 on error or no Volumes found
414  *           number of volumes on success
415  *           List of Volumes and start/end file/blocks (malloced structure!)
416  *
417  *  Returns: number of volumes on success
418  */
419 int db_get_job_volume_parameters(JCR *jcr, B_DB *mdb, JobId_t JobId, VOL_PARAMS **VolParams)
420 {
421    SQL_ROW row;
422    char ed1[50];
423    int stat = 0;
424    int i;
425    VOL_PARAMS *Vols = NULL;
426
427    db_lock(mdb);
428    Mmsg(mdb->cmd,
429 "SELECT VolumeName,MediaType,FirstIndex,LastIndex,StartFile,"
430 "JobMedia.EndFile,StartBlock,JobMedia.EndBlock,Copy,Stripe,"
431 "Slot,StorageId"
432 " FROM JobMedia,Media WHERE JobMedia.JobId=%s"
433 " AND JobMedia.MediaId=Media.MediaId ORDER BY VolIndex,JobMediaId",
434         edit_int64(JobId, ed1));
435
436    Dmsg1(130, "VolNam=%s\n", mdb->cmd);
437    if (QUERY_DB(jcr, mdb, mdb->cmd)) {
438       mdb->num_rows = sql_num_rows(mdb);
439       Dmsg1(200, "Num rows=%d\n", mdb->num_rows);
440       if (mdb->num_rows <= 0) {
441          Mmsg1(mdb->errmsg, _("No volumes found for JobId=%d\n"), JobId);
442          stat = 0;
443       } else {
444          stat = mdb->num_rows;
445          DBId_t *SId;
446          if (stat > 0) {
447             *VolParams = Vols = (VOL_PARAMS *)malloc(stat * sizeof(VOL_PARAMS));
448             SId = (DBId_t *)malloc(stat * sizeof(DBId_t));
449          }
450          for (i=0; i < stat; i++) {
451             if ((row = sql_fetch_row(mdb)) == NULL) {
452                Mmsg2(mdb->errmsg, _("Error fetching row %d: ERR=%s\n"), i, sql_strerror(mdb));
453                Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
454                stat = 0;
455                break;
456             } else {
457                DBId_t StorageId;
458                bstrncpy(Vols[i].VolumeName, row[0], MAX_NAME_LENGTH);
459                bstrncpy(Vols[i].MediaType, row[1], MAX_NAME_LENGTH);
460                Vols[i].FirstIndex = str_to_uint64(row[2]);
461                Vols[i].LastIndex = str_to_uint64(row[3]);
462                Vols[i].StartFile = str_to_uint64(row[4]);
463                Vols[i].EndFile = str_to_uint64(row[5]);
464                Vols[i].StartBlock = str_to_uint64(row[6]);
465                Vols[i].EndBlock = str_to_uint64(row[7]);
466 //             Vols[i].Copy = str_to_uint64(row[8]);
467 //             Vols[i].Stripe = str_to_uint64(row[9]);
468                Vols[i].Slot = str_to_uint64(row[10]);
469                StorageId = str_to_uint64(row[11]);
470                Vols[i].Storage[0] = 0;
471                SId[i] = StorageId;
472             }
473          }
474          for (i=0; i < stat; i++) {
475             if (SId[i] != 0) {
476                Mmsg(mdb->cmd, "SELECT Name from Storage WHERE StorageId=%s",
477                   edit_int64(SId[i], ed1));
478                if (QUERY_DB(jcr, mdb, mdb->cmd)) {
479                   if ((row = sql_fetch_row(mdb)) != NULL) {
480                      bstrncpy(Vols[i].Storage, row[0], MAX_NAME_LENGTH);
481                   }
482                }
483             }
484          }
485       }
486       sql_free_result(mdb);
487    }
488    db_unlock(mdb);
489    return stat;
490 }
491
492
493
494 /*
495  * Get the number of pool records
496  *
497  * Returns: -1 on failure
498  *          number on success
499  */
500 int db_get_num_pool_records(JCR *jcr, B_DB *mdb)
501 {
502    int stat = 0;
503
504    db_lock(mdb);
505    Mmsg(mdb->cmd, "SELECT count(*) from Pool");
506    stat = get_sql_record_max(jcr, mdb);
507    db_unlock(mdb);
508    return stat;
509 }
510
511 /*
512  * This function returns a list of all the Pool record ids.
513  *  The caller must free ids if non-NULL.
514  *
515  *  Returns 0: on failure
516  *          1: on success
517  */
518 int db_get_pool_ids(JCR *jcr, B_DB *mdb, int *num_ids, uint32_t *ids[])
519 {
520    SQL_ROW row;
521    int stat = 0;
522    int i = 0;
523    uint32_t *id;
524
525    db_lock(mdb);
526    *ids = NULL;
527    Mmsg(mdb->cmd, "SELECT PoolId FROM Pool");
528    if (QUERY_DB(jcr, mdb, mdb->cmd)) {
529       *num_ids = sql_num_rows(mdb);
530       if (*num_ids > 0) {
531          id = (uint32_t *)malloc(*num_ids * sizeof(uint32_t));
532          while ((row = sql_fetch_row(mdb)) != NULL) {
533             id[i++] = str_to_uint64(row[0]);
534          }
535          *ids = id;
536       }
537       sql_free_result(mdb);
538       stat = 1;
539    } else {
540       Mmsg(mdb->errmsg, _("Pool id select failed: ERR=%s\n"), sql_strerror(mdb));
541       Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
542       stat = 0;
543    }
544    db_unlock(mdb);
545    return stat;
546 }
547
548 /*
549  * This function returns a list of all the Client record ids.
550  *  The caller must free ids if non-NULL.
551  *
552  *  Returns 0: on failure
553  *          1: on success
554  */
555 int db_get_client_ids(JCR *jcr, B_DB *mdb, int *num_ids, uint32_t *ids[])
556 {
557    SQL_ROW row;
558    int stat = 0;
559    int i = 0;
560    uint32_t *id;
561
562    db_lock(mdb);
563    *ids = NULL;
564    Mmsg(mdb->cmd, "SELECT ClientId FROM Client");
565    if (QUERY_DB(jcr, mdb, mdb->cmd)) {
566       *num_ids = sql_num_rows(mdb);
567       if (*num_ids > 0) {
568          id = (uint32_t *)malloc(*num_ids * sizeof(uint32_t));
569          while ((row = sql_fetch_row(mdb)) != NULL) {
570             id[i++] = str_to_uint64(row[0]);
571          }
572          *ids = id;
573       }
574       sql_free_result(mdb);
575       stat = 1;
576    } else {
577       Mmsg(mdb->errmsg, _("Client id select failed: ERR=%s\n"), sql_strerror(mdb));
578       Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
579       stat = 0;
580    }
581    db_unlock(mdb);
582    return stat;
583 }
584
585
586
587 /* Get Pool Record
588  * If the PoolId is non-zero, we get its record,
589  *  otherwise, we search on the PoolName
590  *
591  * Returns: false on failure
592  *          true on success
593  */
594 bool db_get_pool_record(JCR *jcr, B_DB *mdb, POOL_DBR *pdbr)
595 {
596    SQL_ROW row;
597    bool ok = false;
598    char ed1[50];
599
600    db_lock(mdb);
601    if (pdbr->PoolId != 0) {               /* find by id */
602       Mmsg(mdb->cmd,
603 "SELECT PoolId,Name,NumVols,MaxVols,UseOnce,UseCatalog,AcceptAnyVolume,"
604 "AutoPrune,Recycle,VolRetention,VolUseDuration,MaxVolJobs,MaxVolFiles,"
605 "MaxVolBytes,PoolType,LabelType,LabelFormat FROM Pool WHERE Pool.PoolId=%s", 
606          edit_int64(pdbr->PoolId, ed1));
607    } else {                           /* find by name */
608       Mmsg(mdb->cmd,
609 "SELECT PoolId,Name,NumVols,MaxVols,UseOnce,UseCatalog,AcceptAnyVolume,"
610 "AutoPrune,Recycle,VolRetention,VolUseDuration,MaxVolJobs,MaxVolFiles,"
611 "MaxVolBytes,PoolType,LabelType,LabelFormat FROM Pool WHERE Pool.Name='%s'", 
612          pdbr->Name);
613    }
614
615    if (QUERY_DB(jcr, mdb, mdb->cmd)) {
616       mdb->num_rows = sql_num_rows(mdb);
617       if (mdb->num_rows > 1) {
618          char ed1[30];
619          Mmsg1(mdb->errmsg, _("More than one Pool!: %s\n"),
620             edit_uint64(mdb->num_rows, ed1));
621          Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
622       } else if (mdb->num_rows == 1) {
623          if ((row = sql_fetch_row(mdb)) == NULL) {
624             Mmsg1(mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb));
625             Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
626          } else {
627             pdbr->PoolId = str_to_int64(row[0]);
628             bstrncpy(pdbr->Name, row[1]!=NULL?row[1]:"", sizeof(pdbr->Name));
629             pdbr->NumVols = str_to_int64(row[2]);
630             pdbr->MaxVols = str_to_int64(row[3]);
631             pdbr->UseOnce = str_to_int64(row[4]);
632             pdbr->UseCatalog = str_to_int64(row[5]);
633             pdbr->AcceptAnyVolume = str_to_int64(row[6]);
634             pdbr->AutoPrune = str_to_int64(row[7]);
635             pdbr->Recycle = str_to_int64(row[8]);
636             pdbr->VolRetention = str_to_int64(row[9]);
637             pdbr->VolUseDuration = str_to_int64(row[10]);
638             pdbr->MaxVolJobs = str_to_int64(row[11]);
639             pdbr->MaxVolFiles = str_to_int64(row[12]);
640             pdbr->MaxVolBytes = str_to_uint64(row[13]);
641             bstrncpy(pdbr->PoolType, row[14]!=NULL?row[14]:"", sizeof(pdbr->PoolType));
642             pdbr->LabelType = str_to_int64(row[15]);
643             bstrncpy(pdbr->LabelFormat, row[16]!=NULL?row[16]:"", sizeof(pdbr->LabelFormat));
644             ok = true;
645          }
646       }
647       sql_free_result(mdb);
648    }
649    if (ok) {
650       uint32_t NumVols;
651       Mmsg(mdb->cmd, "SELECT count(*) from Media WHERE PoolId=%s",
652          edit_int64(pdbr->PoolId, ed1));
653       NumVols = get_sql_record_max(jcr, mdb);
654       Dmsg2(400, "Actual NumVols=%d Pool NumVols=%d\n", NumVols, pdbr->NumVols);
655       if (NumVols != pdbr->NumVols) {
656          pdbr->NumVols = NumVols;
657          db_update_pool_record(jcr, mdb, pdbr);
658       }
659    } else {
660       Mmsg(mdb->errmsg, _("Pool record not found in Catalog.\n"));
661    }
662    db_unlock(mdb);
663    return ok;
664 }
665
666 /* Get Client Record
667  * If the ClientId is non-zero, we get its record,
668  *  otherwise, we search on the Client Name
669  *
670  * Returns: 0 on failure
671  *          1 on success
672  */
673 int db_get_client_record(JCR *jcr, B_DB *mdb, CLIENT_DBR *cdbr)
674 {
675    SQL_ROW row;
676    int stat = 0;
677    char ed1[50];
678
679    db_lock(mdb);
680    if (cdbr->ClientId != 0) {               /* find by id */
681       Mmsg(mdb->cmd,
682 "SELECT ClientId,Name,Uname,AutoPrune,FileRetention,JobRetention "
683 "FROM Client WHERE Client.ClientId=%s", 
684         edit_int64(cdbr->ClientId, ed1));
685    } else {                           /* find by name */
686       Mmsg(mdb->cmd,
687 "SELECT ClientId,Name,Uname,AutoPrune,FileRetention,JobRetention "
688 "FROM Client WHERE Client.Name='%s'", cdbr->Name);
689    }
690
691    if (QUERY_DB(jcr, mdb, mdb->cmd)) {
692       mdb->num_rows = sql_num_rows(mdb);
693       if (mdb->num_rows > 1) {
694          Mmsg1(mdb->errmsg, _("More than one Client!: %s\n"),
695             edit_uint64(mdb->num_rows, ed1));
696          Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
697       } else if (mdb->num_rows == 1) {
698          if ((row = sql_fetch_row(mdb)) == NULL) {
699             Mmsg1(mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb));
700             Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
701          } else {
702             cdbr->ClientId = str_to_int64(row[0]);
703             bstrncpy(cdbr->Name, row[1]!=NULL?row[1]:"", sizeof(cdbr->Name));
704             bstrncpy(cdbr->Uname, row[2]!=NULL?row[2]:"", sizeof(cdbr->Uname));
705             cdbr->AutoPrune = str_to_int64(row[3]);
706             cdbr->FileRetention = str_to_int64(row[4]);
707             cdbr->JobRetention = str_to_int64(row[5]);
708             stat = 1;
709          }
710       } else {
711          Mmsg(mdb->errmsg, _("Client record not found in Catalog.\n"));
712       }
713       sql_free_result(mdb);
714    } else {
715       Mmsg(mdb->errmsg, _("Client record not found in Catalog.\n"));
716    }
717    db_unlock(mdb);
718    return stat;
719 }
720
721 /*
722  * Get Counter Record
723  *
724  * Returns: 0 on failure
725  *          1 on success
726  */
727 int db_get_counter_record(JCR *jcr, B_DB *mdb, COUNTER_DBR *cr)
728 {
729    SQL_ROW row;
730
731    db_lock(mdb);
732    Mmsg(mdb->cmd, "SELECT MinValue,MaxValue,CurrentValue,WrapCounter "
733       "FROM Counters WHERE Counter='%s'", cr->Counter);
734
735    if (QUERY_DB(jcr, mdb, mdb->cmd)) {
736       mdb->num_rows = sql_num_rows(mdb);
737
738       /* If more than one, report error, but return first row */
739       if (mdb->num_rows > 1) {
740          Mmsg1(mdb->errmsg, _("More than one Counter!: %d\n"), (int)(mdb->num_rows));
741          Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
742       }
743       if (mdb->num_rows >= 1) {
744          if ((row = sql_fetch_row(mdb)) == NULL) {
745             Mmsg1(mdb->errmsg, _("error fetching Counter row: %s\n"), sql_strerror(mdb));
746             Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
747             sql_free_result(mdb);
748             db_unlock(mdb);
749             return 0;
750          }
751          cr->MinValue = str_to_int64(row[0]);
752          cr->MaxValue = str_to_int64(row[1]);
753          cr->CurrentValue = str_to_int64(row[2]);
754          if (row[3]) {
755             bstrncpy(cr->WrapCounter, row[3], sizeof(cr->WrapCounter));
756          } else {
757             cr->WrapCounter[0] = 0;
758          }
759          sql_free_result(mdb);
760          db_unlock(mdb);
761          return 1;
762       }
763       sql_free_result(mdb);
764    } else {
765       Mmsg(mdb->errmsg, _("Counter record: %s not found in Catalog.\n"), cr->Counter);
766    }
767    db_unlock(mdb);
768    return 0;
769 }
770
771
772 /* Get FileSet Record
773  * If the FileSetId is non-zero, we get its record,
774  *  otherwise, we search on the name
775  *
776  * Returns: 0 on failure
777  *          id on success
778  */
779 int db_get_fileset_record(JCR *jcr, B_DB *mdb, FILESET_DBR *fsr)
780 {
781    SQL_ROW row;
782    int stat = 0;
783    char ed1[50];
784
785    db_lock(mdb);
786    if (fsr->FileSetId != 0) {               /* find by id */
787       Mmsg(mdb->cmd,
788            "SELECT FileSetId,FileSet,MD5,CreateTime FROM FileSet "
789            "WHERE FileSetId=%s", 
790            edit_int64(fsr->FileSetId, ed1));
791    } else {                           /* find by name */
792       Mmsg(mdb->cmd,
793            "SELECT FileSetId,FileSet,MD5,CreateTime FROM FileSet "
794            "WHERE FileSet='%s' ORDER BY CreateTime DESC LIMIT 1", fsr->FileSet);
795    }
796
797    if (QUERY_DB(jcr, mdb, mdb->cmd)) {
798       mdb->num_rows = sql_num_rows(mdb);
799       if (mdb->num_rows > 1) {
800          char ed1[30];
801          Mmsg1(mdb->errmsg, _("Error got %s FileSets but expected only one!\n"),
802             edit_uint64(mdb->num_rows, ed1));
803          sql_data_seek(mdb, mdb->num_rows-1);
804       }
805       if ((row = sql_fetch_row(mdb)) == NULL) {
806          Mmsg1(mdb->errmsg, _("FileSet record \"%s\" not found.\n"), fsr->FileSet);
807       } else {
808          fsr->FileSetId = str_to_int64(row[0]);
809          bstrncpy(fsr->FileSet, row[1]!=NULL?row[1]:"", sizeof(fsr->FileSet));
810          bstrncpy(fsr->MD5, row[2]!=NULL?row[2]:"", sizeof(fsr->MD5));
811          bstrncpy(fsr->cCreateTime, row[3]!=NULL?row[3]:"", sizeof(fsr->cCreateTime));
812          stat = fsr->FileSetId;
813       }
814       sql_free_result(mdb);
815    } else {
816       Mmsg(mdb->errmsg, _("FileSet record not found in Catalog.\n"));
817    }
818    db_unlock(mdb);
819    return stat;
820 }
821
822
823 /*
824  * Get the number of Media records
825  *
826  * Returns: -1 on failure
827  *          number on success
828  */
829 int db_get_num_media_records(JCR *jcr, B_DB *mdb)
830 {
831    int stat = 0;
832
833    db_lock(mdb);
834    Mmsg(mdb->cmd, "SELECT count(*) from Media");
835    stat = get_sql_record_max(jcr, mdb);
836    db_unlock(mdb);
837    return stat;
838 }
839
840
841 /*
842  * This function returns a list of all the Media record ids for
843  *     the current Pool.
844  *  The caller must free ids if non-NULL.
845  *
846  *  Returns false: on failure
847  *          true:  on success
848  */
849 bool db_get_media_ids(JCR *jcr, B_DB *mdb, uint32_t PoolId, int *num_ids, uint32_t *ids[])
850 {
851    SQL_ROW row;
852    int i = 0;
853    uint32_t *id;
854    char ed1[50];
855    bool ok = false;
856
857    db_lock(mdb);
858    *ids = NULL;
859    Mmsg(mdb->cmd, "SELECT MediaId FROM Media WHERE PoolId=%s", 
860        edit_int64(PoolId, ed1));
861    if (QUERY_DB(jcr, mdb, mdb->cmd)) {
862       *num_ids = sql_num_rows(mdb);
863       if (*num_ids > 0) {
864          id = (uint32_t *)malloc(*num_ids * sizeof(uint32_t));
865          while ((row = sql_fetch_row(mdb)) != NULL) {
866             id[i++] = str_to_uint64(row[0]);
867          }
868          *ids = id;
869       }
870       sql_free_result(mdb);
871       ok = true;
872    } else {
873       Mmsg(mdb->errmsg, _("Media id select failed: ERR=%s\n"), sql_strerror(mdb));
874       Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
875       ok = false;
876    }
877    db_unlock(mdb);
878    return ok;
879 }
880
881
882 /* Get Media Record
883  *
884  * Returns: false: on failure
885  *          true:  on success
886  */
887 bool db_get_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr)
888 {
889    SQL_ROW row;
890    char ed1[50];
891    bool ok = false;
892
893    db_lock(mdb);
894    if (mr->MediaId == 0 && mr->VolumeName[0] == 0) {
895       Mmsg(mdb->cmd, "SELECT count(*) from Media");
896       mr->MediaId = get_sql_record_max(jcr, mdb);
897       db_unlock(mdb);
898       return true;
899    }
900    if (mr->MediaId != 0) {               /* find by id */
901       Mmsg(mdb->cmd, "SELECT MediaId,VolumeName,VolJobs,VolFiles,VolBlocks,"
902          "VolBytes,VolMounts,VolErrors,VolWrites,MaxVolBytes,VolCapacityBytes,"
903          "MediaType,VolStatus,PoolId,VolRetention,VolUseDuration,MaxVolJobs,"
904          "MaxVolFiles,Recycle,Slot,FirstWritten,LastWritten,InChanger,"
905          "EndFile,EndBlock,VolParts,LabelType,LabelDate,StorageId "
906          "FROM Media WHERE MediaId=%s", 
907          edit_int64(mr->MediaId, ed1));
908    } else {                           /* find by name */
909       Mmsg(mdb->cmd, "SELECT MediaId,VolumeName,VolJobs,VolFiles,VolBlocks,"
910          "VolBytes,VolMounts,VolErrors,VolWrites,MaxVolBytes,VolCapacityBytes,"
911          "MediaType,VolStatus,PoolId,VolRetention,VolUseDuration,MaxVolJobs,"
912          "MaxVolFiles,Recycle,Slot,FirstWritten,LastWritten,InChanger,"
913          "EndFile,EndBlock,VolParts,LabelType,LabelDate,StorageId "
914          "FROM Media WHERE VolumeName='%s'", mr->VolumeName);
915    }
916
917    if (QUERY_DB(jcr, mdb, mdb->cmd)) {
918       char ed1[50];
919       mdb->num_rows = sql_num_rows(mdb);
920       if (mdb->num_rows > 1) {
921          Mmsg1(mdb->errmsg, _("More than one Volume!: %s\n"),
922             edit_uint64(mdb->num_rows, ed1));
923          Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
924       } else if (mdb->num_rows == 1) {
925          if ((row = sql_fetch_row(mdb)) == NULL) {
926             Mmsg1(mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb));
927             Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
928          } else {
929             /* return values */
930             mr->MediaId = str_to_int64(row[0]);
931             bstrncpy(mr->VolumeName, row[1]!=NULL?row[1]:"", sizeof(mr->VolumeName));
932             mr->VolJobs = str_to_int64(row[2]);
933             mr->VolFiles = str_to_int64(row[3]);
934             mr->VolBlocks = str_to_int64(row[4]);
935             mr->VolBytes = str_to_uint64(row[5]);
936             mr->VolMounts = str_to_int64(row[6]);
937             mr->VolErrors = str_to_int64(row[7]);
938             mr->VolWrites = str_to_int64(row[8]);
939             mr->MaxVolBytes = str_to_uint64(row[9]);
940             mr->VolCapacityBytes = str_to_uint64(row[10]);
941             bstrncpy(mr->MediaType, row[11]!=NULL?row[11]:"", sizeof(mr->MediaType));
942             bstrncpy(mr->VolStatus, row[12]!=NULL?row[12]:"", sizeof(mr->VolStatus));
943             mr->PoolId = str_to_int64(row[13]);
944             mr->VolRetention = str_to_uint64(row[14]);
945             mr->VolUseDuration = str_to_uint64(row[15]);
946             mr->MaxVolJobs = str_to_int64(row[16]);
947             mr->MaxVolFiles = str_to_int64(row[17]);
948             mr->Recycle = str_to_int64(row[18]);
949             mr->Slot = str_to_int64(row[19]);
950             bstrncpy(mr->cFirstWritten, row[20]!=NULL?row[20]:"", sizeof(mr->cFirstWritten));
951             mr->FirstWritten = (time_t)str_to_utime(mr->cFirstWritten);
952             bstrncpy(mr->cLastWritten, row[21]!=NULL?row[21]:"", sizeof(mr->cLastWritten));
953             mr->LastWritten = (time_t)str_to_utime(mr->cLastWritten);
954             mr->InChanger = str_to_uint64(row[22]);
955             mr->EndFile = str_to_uint64(row[23]);
956             mr->EndBlock = str_to_uint64(row[24]);
957             mr->VolParts = str_to_int64(row[25]);
958             mr->LabelType = str_to_int64(row[26]);
959             bstrncpy(mr->cLabelDate, row[27]!=NULL?row[27]:"", sizeof(mr->cLabelDate));
960             mr->LabelDate = (time_t)str_to_utime(mr->cLabelDate);
961             mr->StorageId = str_to_int64(row[28]);
962             ok = true;
963          }
964       } else {
965          if (mr->MediaId != 0) {
966             Mmsg1(mdb->errmsg, _("Media record MediaId=%s not found.\n"), 
967                edit_int64(mr->MediaId, ed1));
968          } else {
969             Mmsg1(mdb->errmsg, _("Media record for Volume \"%s\" not found.\n"),
970                   mr->VolumeName);
971          }
972       }
973       sql_free_result(mdb);
974    } else {
975       if (mr->MediaId != 0) {
976          Mmsg(mdb->errmsg, _("Media record for MediaId=%u not found in Catalog.\n"),
977             mr->MediaId);
978        } else {
979          Mmsg(mdb->errmsg, _("Media record for Vol=%s not found in Catalog.\n"),
980             mr->VolumeName);
981    }   }
982    db_unlock(mdb);
983    return ok;
984 }
985
986
987 #endif /* HAVE_SQLITE3 || HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL*/