]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/cats/sql_get.c
Fix verify
[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, 2001, 2002 Kern Sibbald and John Walker
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 as
17    published by the Free Software Foundation; either version 2 of
18    the License, or (at your option) any later version.
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 GNU
23    General Public License for more details.
24
25    You should have received a copy of the GNU General Public
26    License along with this program; if not, write to the Free
27    Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
28    MA 02111-1307, USA.
29
30  */
31
32 /* *****FIXME**** fix fixed length of select_cmd[] and insert_cmd[] */
33
34 /* The following is necessary so that we do not include
35  * the dummy external definition of DB.
36  */
37 #define __SQL_C                       /* indicate that this is sql.c */
38
39 #include "bacula.h"
40 #include "cats.h"
41
42 #if    HAVE_MYSQL || HAVE_SQLITE
43
44 /* -----------------------------------------------------------------------
45  *
46  *   Generic Routines (or almost generic)
47  *
48  * -----------------------------------------------------------------------
49  */
50
51 /* Forward referenced functions */
52 static int db_get_file_record(B_DB *mdb, FILE_DBR *fdbr);
53 static int db_get_filename_record(B_DB *mdb, char *fname);
54 static int db_get_path_record(B_DB *mdb, char *path);
55
56
57 /* Imported subroutines */
58 extern void print_result(B_DB *mdb);
59 extern int QueryDB(char *file, int line, B_DB *db, char *select_cmd);
60
61
62 /*
63  * Given a full filename (with path), look up the File record
64  * (with attributes) in the database.
65  *
66  *  Returns: 0 on failure
67  *           1 on success with the File record in FILE_DBR
68  */
69 int db_get_file_attributes_record(B_DB *mdb, char *fname, FILE_DBR *fdbr)
70 {
71    int fnl, pnl;
72    char *l, *p;
73    uint64_t id;
74    char file[MAXSTRING];
75    char spath[MAXSTRING];
76    char buf[MAXSTRING];
77    Dmsg1(20, "Enter get_file_from_catalog fname=%s \n", fname);
78
79    /* Find path without the filename */
80    for (p=l=fname; *p; p++) {
81       if (*p == '/') {
82          l = p;
83       }
84    }
85    if (*l == '/') {
86       l++;
87    }
88
89    fnl = p - l;
90    strcpy(file, l);
91
92    pnl = l - fname;    
93    strncpy(spath, fname, pnl);
94    spath[l-fname] = 0;
95
96    if (pnl == 0) {
97       return 0;
98    }
99
100    strip_trailing_junk(spath);
101    Dmsg1(50, "spath=%s\n", spath);
102
103    strip_trailing_junk(file);
104    Dmsg1(50, "file=%s\n", file);
105
106    db_escape_string(buf, file, fnl);
107    fdbr->FilenameId = db_get_filename_record(mdb, buf);
108    Dmsg1(50, "db_get_filename_record FilenameId=%d\n", fdbr->FilenameId);
109
110    db_escape_string(buf, spath, pnl);
111    fdbr->PathId = db_get_path_record(mdb, buf);
112    Dmsg2(50, "db_get_path_record PathId=%d path=%s\n", fdbr->PathId, buf);
113
114    id = db_get_file_record(mdb, fdbr);
115
116    return id;
117 }
118
119  
120
121 /* Get a File record   
122  * Returns: 0 on failure
123  *          1 on success
124  */
125 static
126 int db_get_file_record(B_DB *mdb, FILE_DBR *fdbr)
127 {
128    SQL_ROW row;
129    int stat = 0;
130
131    db_lock(mdb);
132    Mmsg(&mdb->cmd, 
133 "SELECT FileId, LStat, MD5 from File where File.JobId=%d and File.PathId=%d and \
134 File.FilenameId=%d", fdbr->JobId, fdbr->PathId, fdbr->FilenameId);
135
136    Dmsg3(050, "Get_file_record JobId=%d FilenameId=%d PathId=%d\n",
137       fdbr->JobId, fdbr->FilenameId, fdbr->PathId);
138       
139    Dmsg1(100, "Query=%s\n", mdb->cmd);
140
141    if (QUERY_DB(mdb, mdb->cmd)) {
142
143       mdb->num_rows = sql_num_rows(mdb);
144       Dmsg1(050, "get_file_record num_rows=%d\n", (int)mdb->num_rows);
145
146       /* 
147        * Note, we can find more than one File record with the same
148        *  filename if the file is linked.   ????????
149        */
150       if (mdb->num_rows > 1) {
151          Emsg1(M_WARNING, 0, _("get_file_record want 1 got rows=%d\n"), mdb->num_rows);
152          Emsg1(M_ERROR, 0, "%s", mdb->cmd);
153       }
154       if (mdb->num_rows >= 1) {
155          if ((row = sql_fetch_row(mdb)) == NULL) {
156             Mmsg1(&mdb->errmsg, "Error fetching row: %s\n", sql_strerror(mdb));
157          } else {
158             fdbr->FileId = (FileId_t)strtod(row[0], NULL);
159             strncpy(fdbr->LStat, row[1], sizeof(fdbr->LStat));
160             fdbr->LStat[sizeof(fdbr->LStat)] = 0;
161             strncpy(fdbr->MD5, row[2], sizeof(fdbr->MD5));
162             fdbr->MD5[sizeof(fdbr->MD5)] = 0;
163             stat = 1;
164          }
165       }
166       sql_free_result(mdb);
167    }
168    db_unlock(mdb);
169    return stat;
170
171 }
172
173 /* Get Filename record   
174  * Returns: 0 on failure
175  *          FilenameId on success
176  */
177 static int db_get_filename_record(B_DB *mdb, char *fname) 
178 {
179    SQL_ROW row;
180    int FilenameId = 0;
181
182    if (*fname == 0) {
183       Mmsg0(&mdb->errmsg, _("Null name given to db_get_filename_record\n"));
184       Emsg0(M_ABORT, 0, mdb->errmsg);
185    }
186
187    db_lock(mdb);
188    Mmsg(&mdb->cmd, "SELECT FilenameId FROM Filename WHERE Name=\"%s\"", fname);
189    if (QUERY_DB(mdb, mdb->cmd)) {
190
191       mdb->num_rows = sql_num_rows(mdb);
192
193       if (mdb->num_rows > 1) {
194          Mmsg1(&mdb->errmsg, _("More than one Filename!: %d\n"), (int)(mdb->num_rows));
195          Emsg1(M_WARNING, 0, _("get_filename_record want 1 got rows=%d\n"), mdb->num_rows);
196          Emsg1(M_ERROR, 0, "%s", mdb->errmsg);
197       }
198       if (mdb->num_rows >= 1) {
199          if ((row = sql_fetch_row(mdb)) == NULL) {
200             Mmsg1(&mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb));
201             Emsg1(M_ERROR, 0, "%s", mdb->errmsg);
202          } else {
203             FilenameId = atoi(row[0]);
204             if (FilenameId <= 0) {
205                Mmsg2(&mdb->errmsg, _("Get DB Filename record %s found bad record: %d\n"),
206                   mdb->cmd, FilenameId); 
207                Emsg1(M_ERROR, 0, "%s", mdb->errmsg);
208                FilenameId = 0;
209             }
210          }
211       }
212       sql_free_result(mdb);
213    }
214    db_unlock(mdb);
215    return FilenameId;
216 }
217
218 /* Get path record   
219  * Returns: 0 on failure
220  *          PathId on success
221  */
222 static int db_get_path_record(B_DB *mdb, char *path)
223 {
224    SQL_ROW row;
225    uint32_t PathId = 0;
226
227    if (*path == 0) {
228       Emsg0(M_ABORT, 0, _("Null path given to db_get_path_record\n"));
229    }
230
231    db_lock(mdb);
232
233    if (mdb->cached_path_id != 0 && strcmp(mdb->cached_path, path) == 0) {
234       db_unlock(mdb);
235       return mdb->cached_path_id;
236    }          
237
238    Mmsg(&mdb->cmd, "SELECT PathId FROM Path WHERE Path=\"%s\"", path);
239
240    if (QUERY_DB(mdb, mdb->cmd)) {
241       char ed1[30];
242       mdb->num_rows = sql_num_rows(mdb);
243
244       if (mdb->num_rows > 1) {
245          Mmsg1(&mdb->errmsg, _("More than one Path!: %s\n"), 
246             edit_uint64(mdb->num_rows, ed1));
247       } else if (mdb->num_rows == 1) {
248          if ((row = sql_fetch_row(mdb)) == NULL) {
249             Mmsg1(&mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb));
250          } else {
251             PathId = atoi(row[0]);
252             if (PathId <= 0) {
253                Mmsg2(&mdb->errmsg, _("Get DB path record %s found bad record: %d\n"),
254                   mdb->cmd, PathId); 
255                PathId = 0;
256             } else {
257                /* Cache path */
258                if (PathId != mdb->cached_path_id) {
259                   mdb->cached_path_id = PathId;
260                   mdb->cached_path = check_pool_memory_size(mdb->cached_path,
261                      strlen(path)+1);
262                   strcpy(mdb->cached_path, path);
263                }
264             }
265          }
266       }
267       sql_free_result(mdb);
268    }
269    db_unlock(mdb);
270    return PathId;
271 }
272
273
274 /* 
275  * Get Job record for given JobId or Job name
276  * Returns: 0 on failure
277  *          1 on success
278  */
279 int db_get_job_record(B_DB *mdb, JOB_DBR *jr)
280 {
281    SQL_ROW row;
282
283    db_lock(mdb);
284    if (jr->JobId == 0) {
285       Mmsg(&mdb->cmd, "SELECT VolSessionId, VolSessionTime, \
286 PoolId, StartTime, EndTime, JobFiles, JobBytes, JobTDate, Job \
287 FROM Job WHERE Job=\"%s\"", jr->Job);
288     } else {
289       Mmsg(&mdb->cmd, "SELECT VolSessionId, VolSessionTime, \
290 PoolId, StartTime, EndTime, JobFiles, JobBytes, JobTDate, Job \
291 FROM Job WHERE JobId=%d", jr->JobId);
292     }
293
294    if (!QUERY_DB(mdb, mdb->cmd)) {
295       db_unlock(mdb);
296       return 0;                       /* failed */
297    }
298    if ((row = sql_fetch_row(mdb)) == NULL) {
299       Mmsg1(&mdb->errmsg, _("No Job found for JobId %d\n"), jr->JobId);
300       sql_free_result(mdb);
301       db_unlock(mdb);
302       return 0;                       /* failed */
303    }
304
305    jr->VolSessionId = atol(row[0]);
306    jr->VolSessionTime = atol(row[1]);
307    jr->PoolId = atoi(row[2]);
308    strcpy(jr->cStartTime, row[3]);
309    strcpy(jr->cEndTime, row[4]);
310    jr->JobFiles = atol(row[5]);
311    jr->JobBytes = (uint64_t)strtod(row[6], NULL);
312    jr->JobTDate = (btime_t)strtod(row[7], NULL);
313    strcpy(jr->Job, row[8]);
314    sql_free_result(mdb);
315
316    db_unlock(mdb);
317    return 1;
318 }
319
320 /*
321  * Find VolumeNames for a give JobId
322  *  Returns: 0 on error or no Volumes found
323  *           number of volumes on success
324  *              Volumes are concatenated in VolumeNames
325  *              separated by a vertical bar (|).
326  */
327 int db_get_job_volume_names(B_DB *mdb, uint32_t JobId, char *VolumeNames)
328 {
329    SQL_ROW row;
330    int stat = 0;
331    int i;
332
333    db_lock(mdb);
334    Mmsg(&mdb->cmd, 
335 "SELECT VolumeName FROM JobMedia,Media WHERE JobMedia.JobId=%d \
336 AND JobMedia.MediaId=Media.MediaId", JobId);
337
338    Dmsg1(130, "VolNam=%s\n", mdb->cmd);
339    VolumeNames[0] = 0;
340    if (QUERY_DB(mdb, mdb->cmd)) {
341       mdb->num_rows = sql_num_rows(mdb);
342       Dmsg1(130, "Num rows=%d\n", mdb->num_rows);
343       if (mdb->num_rows <= 0) {
344          Mmsg1(&mdb->errmsg, _("No volumes found for JobId=%d"), JobId);
345          stat = 0;
346       } else {
347          stat = mdb->num_rows;
348          for (i=0; i < stat; i++) {
349             if ((row = sql_fetch_row(mdb)) == NULL) {
350                Mmsg2(&mdb->errmsg, _("Error fetching row %d: ERR=%s\n"), i, sql_strerror(mdb));
351                stat = 0;
352                break;
353             } else {
354                if (VolumeNames[0] != 0) {
355                   strcat(VolumeNames, "|");
356                }
357                strcat(VolumeNames, row[0]);
358             }
359          }
360       }
361       sql_free_result(mdb);
362    }
363    db_unlock(mdb);
364    return stat;
365 }
366
367
368 /* 
369  * Get the number of pool records
370  *
371  * Returns: -1 on failure
372  *          number on success
373  */
374 int db_get_num_pool_records(B_DB *mdb)
375 {
376    int stat = 0;
377
378    db_lock(mdb);
379    Mmsg(&mdb->cmd, "SELECT count(*) from Pool");
380    stat = get_sql_record_max(mdb);
381    db_unlock(mdb);
382    return stat;
383 }
384
385 /*
386  * This function returns a list of all the Pool record ids.
387  *  The caller must free ids if non-NULL.
388  *
389  *  Returns 0: on failure
390  *          1: on success
391  */
392 int db_get_pool_ids(B_DB *mdb, int *num_ids, uint32_t *ids[])
393 {
394    SQL_ROW row;
395    int stat = 0;
396    int i = 0;
397    uint32_t *id;
398
399    db_lock(mdb);
400    *ids = NULL;
401    Mmsg(&mdb->cmd, "SELECT PoolId FROM Pool");
402    if (QUERY_DB(mdb, mdb->cmd)) {
403       *num_ids = sql_num_rows(mdb);
404       if (*num_ids > 0) {
405          id = (uint32_t *)malloc(*num_ids * sizeof(uint32_t));
406          while ((row = sql_fetch_row(mdb)) != NULL) {
407             id[i++] = (uint32_t)atoi(row[0]);
408          }
409          *ids = id;
410       }
411       sql_free_result(mdb);
412       stat = 1;
413    } else {
414       Mmsg(&mdb->errmsg, _("Pool id select failed: ERR=%s\n"), sql_strerror(mdb));
415       stat = 0;
416    }
417    db_unlock(mdb);
418    return stat;
419 }
420
421
422 /* Get Pool Record   
423  * If the PoolId is non-zero, we get its record,
424  *  otherwise, we search on the PoolName
425  *
426  * Returns: 0 on failure
427  *          id on success 
428  */
429 int db_get_pool_record(B_DB *mdb, POOL_DBR *pdbr)
430 {
431    SQL_ROW row;
432    int stat = 0;
433
434    db_lock(mdb);
435    if (pdbr->PoolId != 0) {               /* find by id */
436       Mmsg(&mdb->cmd, 
437 "SELECT PoolId, Name, NumVols, MaxVols, UseOnce, UseCatalog, AcceptAnyVolume, \
438 AutoPrune, Recycle, VolRetention, \
439 PoolType, LabelFormat FROM Pool WHERE Pool.PoolId=%d", pdbr->PoolId);
440    } else {                           /* find by name */
441       Mmsg(&mdb->cmd, 
442 "SELECT PoolId, Name, NumVols, MaxVols, UseOnce, UseCatalog, AcceptAnyVolume, \
443 AutoPrune, Recycle, VolRetention, \
444 PoolType, LabelFormat FROM Pool WHERE Pool.Name=\"%s\"", pdbr->Name);
445    }  
446
447    if (QUERY_DB(mdb, mdb->cmd)) {
448       mdb->num_rows = sql_num_rows(mdb);
449       if (mdb->num_rows > 1) {
450          char ed1[30];
451          Mmsg1(&mdb->errmsg, _("More than one Pool!: %s\n"), 
452             edit_uint64(mdb->num_rows, ed1));
453       } else if (mdb->num_rows == 1) {
454          if ((row = sql_fetch_row(mdb)) == NULL) {
455             Mmsg1(&mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb));
456          } else {
457             pdbr->PoolId = atoi(row[0]);
458             strcpy(pdbr->Name, row[1]);
459             pdbr->NumVols = atoi(row[2]);
460             pdbr->MaxVols = atoi(row[3]);
461             pdbr->UseOnce = atoi(row[4]);
462             pdbr->UseCatalog = atoi(row[5]);
463             pdbr->AcceptAnyVolume = atoi(row[6]);
464             pdbr->AutoPrune = atoi(row[7]);
465             pdbr->Recycle = atoi(row[8]);
466             pdbr->VolRetention = (btime_t)strtod(row[9], NULL);
467             strcpy(pdbr->PoolType, row[10]);
468             if (row[11]) {
469                strcpy(pdbr->LabelFormat, row[11]);
470             } else {
471                pdbr->LabelFormat[0] = 0;
472             }
473             stat = pdbr->PoolId;
474          }
475       }
476       sql_free_result(mdb);
477    }
478    db_unlock(mdb);
479    return stat;
480 }
481
482
483 /* 
484  * Get the number of Media records
485  *
486  * Returns: -1 on failure
487  *          number on success
488  */
489 int db_get_num_media_records(B_DB *mdb)
490 {
491    int stat = 0;
492
493    db_lock(mdb);
494    Mmsg(&mdb->cmd, "SELECT count(*) from Media");
495    stat = get_sql_record_max(mdb);
496    db_unlock(mdb);
497    return stat;
498 }
499
500
501 /*
502  * This function returns a list of all the Media record ids.
503  *  The caller must free ids if non-NULL.
504  *
505  *  Returns 0: on failure
506  *          1: on success
507  */
508 int db_get_media_ids(B_DB *mdb, int *num_ids, uint32_t *ids[])
509 {
510    SQL_ROW row;
511    int stat = 0;
512    int i = 0;
513    uint32_t *id;
514
515    db_lock(mdb);
516    *ids = NULL;
517    Mmsg(&mdb->cmd, "SELECT MediaId FROM Media");
518    if (QUERY_DB(mdb, mdb->cmd)) {
519       *num_ids = sql_num_rows(mdb);
520       if (*num_ids > 0) {
521          id = (uint32_t *)malloc(*num_ids * sizeof(uint32_t));
522          while ((row = sql_fetch_row(mdb)) != NULL) {
523             id[i++] = (uint32_t)atoi(row[0]);
524          }
525          *ids = id;
526       }
527       sql_free_result(mdb);
528       stat = 1;
529    } else {
530       Mmsg(&mdb->errmsg, _("Media id select failed: ERR=%s\n"), sql_strerror(mdb));
531       stat = 0;
532    }
533    db_unlock(mdb);
534    return stat;
535 }
536
537
538 /* Get Media Record   
539  *
540  * Returns: 0 on failure
541  *          id on success 
542  */
543 int db_get_media_record(B_DB *mdb, MEDIA_DBR *mr)
544 {
545    SQL_ROW row;
546    int stat = 0;
547
548    db_lock(mdb);
549    if (mr->MediaId == 0 && mr->VolumeName[0] == 0) {
550       Mmsg(&mdb->cmd, "SELECT count(*) from Media");
551       mr->MediaId = get_sql_record_max(mdb);
552       db_unlock(mdb);
553       return 1;
554    }
555    if (mr->MediaId != 0) {               /* find by id */
556       Mmsg(&mdb->cmd, "SELECT MediaId,VolumeName,VolJobs,VolFiles,VolBlocks,\
557 VolBytes,VolMounts,VolErrors,VolWrites,VolMaxBytes,VolCapacityBytes,\
558 MediaType,VolStatus,PoolId,VolRetention,Recycle \
559 FROM Media WHERE MediaId=%d", mr->MediaId);
560    } else {                           /* find by name */
561       Mmsg(&mdb->cmd, "SELECT MediaId,VolumeName,VolJobs,VolFiles,VolBlocks,\
562 VolBytes,VolMounts,VolErrors,VolWrites,VolMaxBytes,VolCapacityBytes,\
563 MediaType,VolStatus,PoolId,VolRetention,Recycle \
564 FROM Media WHERE VolumeName=\"%s\"", mr->VolumeName);
565    }  
566
567    if (QUERY_DB(mdb, mdb->cmd)) {
568       mdb->num_rows = sql_num_rows(mdb);
569       if (mdb->num_rows > 1) {
570          char ed1[30];
571          Mmsg1(&mdb->errmsg, _("More than one Volume!: %s\n"), 
572             edit_uint64(mdb->num_rows, ed1));
573       } else if (mdb->num_rows == 1) {
574          if ((row = sql_fetch_row(mdb)) == NULL) {
575             Mmsg1(&mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb));
576          } else {
577             /* return values */
578             mr->MediaId = atoi(row[0]);
579             strcpy(mr->VolumeName, row[1]);
580             mr->VolJobs = atoi(row[2]);
581             mr->VolFiles = atoi(row[3]);
582             mr->VolBlocks = atoi(row[4]);
583             mr->VolBytes = (uint64_t)strtod(row[5], NULL);
584             mr->VolMounts = atoi(row[6]);
585             mr->VolErrors = atoi(row[7]);
586             mr->VolWrites = atoi(row[8]);
587             mr->VolMaxBytes = (uint64_t)strtod(row[9], NULL);
588             mr->VolCapacityBytes = (uint64_t)strtod(row[10], NULL);
589             strcpy(mr->MediaType, row[11]);
590             strcpy(mr->VolStatus, row[12]);
591             mr->PoolId = atoi(row[13]);
592             mr->VolRetention = (btime_t)strtod(row[14], NULL);
593             mr->Recycle = atoi(row[15]);
594             stat = mr->MediaId;
595          }
596       } else {
597          Mmsg0(&mdb->errmsg, _("Media record not found.\n"));
598       }
599       sql_free_result(mdb);
600    }
601    db_unlock(mdb);
602    return stat;
603 }
604
605
606 #endif /* HAVE_MYSQL || HAVE_SQLITE */