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