]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/cats/sql_get.c
c0e27e54e6051ee5cceb27540c404467d32af7d8
[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       char ed1[30];
236       mdb->num_rows = sql_num_rows(mdb);
237
238       if (mdb->num_rows > 1) {
239          Mmsg1(&mdb->errmsg, _("More than one Path!: %s\n"), 
240             edit_uint64(mdb->num_rows, ed1));
241          Emsg0(M_FATAL, 0, mdb->errmsg);
242       } else if (mdb->num_rows == 1) {
243          if ((row = sql_fetch_row(mdb)) == NULL) {
244             Mmsg1(&mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb));
245             Emsg0(M_FATAL, 0, mdb->errmsg);
246          }
247          PathId = atoi(row[0]);
248          if (PathId != cached_id) {
249             cached_id = PathId;
250             strcpy(cached_path, path);
251          }
252          sql_free_result(mdb);
253          V(mdb->mutex);
254          return PathId;
255       }
256
257       sql_free_result(mdb);
258    }
259    V(mdb->mutex);
260    return 0;                          /* failed */
261 }
262
263
264 /* 
265  * Get Job record for given JobId or Job name
266  * Returns: 0 on failure
267  *          1 on success
268  */
269 int db_get_job_record(B_DB *mdb, JOB_DBR *jr)
270 {
271    SQL_ROW row;
272
273    P(mdb->mutex);
274    if (jr->JobId == 0) {
275       Mmsg(&mdb->cmd, "SELECT VolSessionId, VolSessionTime, \
276 PoolId, StartTime, EndTime, JobFiles, JobBytes, Job \
277 FROM Job WHERE Job=\"%s\"", jr->Job);
278     } else {
279       Mmsg(&mdb->cmd, "SELECT VolSessionId, VolSessionTime, \
280 PoolId, StartTime, EndTime, JobFiles, JobBytes, Job \
281 FROM Job WHERE JobId=%d", jr->JobId);
282     }
283
284    if (!QUERY_DB(mdb, mdb->cmd)) {
285       V(mdb->mutex);
286       return 0;                       /* failed */
287    }
288    if ((row = sql_fetch_row(mdb)) == NULL) {
289       Mmsg1(&mdb->errmsg, _("No Job found for JobId %d\n"), jr->JobId);
290       sql_free_result(mdb);
291       V(mdb->mutex);
292       return 0;                       /* failed */
293    }
294
295    jr->VolSessionId = atol(row[0]);
296    jr->VolSessionTime = atol(row[1]);
297    jr->PoolId = atoi(row[2]);
298    strcpy(jr->cStartTime, row[3]);
299    strcpy(jr->cEndTime, row[4]);
300    jr->JobFiles = atol(row[5]);
301    jr->JobBytes = (uint64_t)strtod(row[6], NULL);
302    strcpy(jr->Job, row[7]);
303    sql_free_result(mdb);
304
305    V(mdb->mutex);
306    return 1;
307 }
308
309 /*
310  * Find VolumeNames for a give JobId
311  *  Returns: 0 on error or no Volumes found
312  *           number of volumes on success
313  *              Volumes are concatenated in VolumeNames
314  *              separated by a vertical bar (|).
315  */
316 int db_get_job_volume_names(B_DB *mdb, uint32_t JobId, char *VolumeNames)
317 {
318    SQL_ROW row;
319    int stat = 0;
320    int i;
321
322    P(mdb->mutex);
323    Mmsg(&mdb->cmd, 
324 "SELECT VolumeName FROM JobMedia,Media WHERE JobMedia.JobId=%d \
325 AND JobMedia.MediaId=Media.MediaId", JobId);
326
327    Dmsg1(130, "VolNam=%s\n", mdb->cmd);
328    VolumeNames[0] = 0;
329    if (QUERY_DB(mdb, mdb->cmd)) {
330       mdb->num_rows = sql_num_rows(mdb);
331       Dmsg1(130, "Num rows=%d\n", mdb->num_rows);
332       if (mdb->num_rows <= 0) {
333          Mmsg1(&mdb->errmsg, _("No volumes found for JobId=%d"), JobId);
334          stat = 0;
335       } else {
336          stat = mdb->num_rows;
337          for (i=0; i < stat; i++) {
338             if ((row = sql_fetch_row(mdb)) == NULL) {
339                Mmsg2(&mdb->errmsg, _("Error fetching row %d: ERR=%s\n"), i, sql_strerror(mdb));
340                stat = 0;
341                break;
342             } else {
343                if (VolumeNames[0] != 0) {
344                   strcat(VolumeNames, "|");
345                }
346                strcat(VolumeNames, row[0]);
347             }
348          }
349       }
350       sql_free_result(mdb);
351    }
352    V(mdb->mutex);
353    return stat;
354 }
355
356
357 /* 
358  * Get the number of pool records
359  *
360  * Returns: -1 on failure
361  *          number on success
362  */
363 int db_get_num_pool_records(B_DB *mdb)
364 {
365    int stat = 0;
366
367    P(mdb->mutex);
368    Mmsg(&mdb->cmd, "SELECT count(*) from Pool");
369    stat = get_sql_record_max(mdb);
370    V(mdb->mutex);
371    return stat;
372 }
373
374 /*
375  * This function returns a list of all the Pool record ids.
376  *  The caller must free ids if non-NULL.
377  *
378  *  Returns 0: on failure
379  *          1: on success
380  */
381 int db_get_pool_ids(B_DB *mdb, int *num_ids, uint32_t *ids[])
382 {
383    SQL_ROW row;
384    int stat = 0;
385    int i = 0;
386    uint32_t *id;
387
388    P(mdb->mutex);
389    *ids = NULL;
390    Mmsg(&mdb->cmd, "SELECT PoolId FROM Pool");
391    if (QUERY_DB(mdb, mdb->cmd)) {
392       *num_ids = sql_num_rows(mdb);
393       if (*num_ids > 0) {
394          id = (uint32_t *)malloc(*num_ids * sizeof(uint32_t));
395          while ((row = sql_fetch_row(mdb)) != NULL) {
396             id[i++] = (uint32_t)atoi(row[0]);
397          }
398          *ids = id;
399       }
400       sql_free_result(mdb);
401       stat = 1;
402    } else {
403       Mmsg(&mdb->errmsg, _("Pool id select failed: ERR=%s\n"), sql_strerror(mdb));
404       stat = 0;
405    }
406    V(mdb->mutex);
407    return stat;
408 }
409
410
411 /* Get Pool Record   
412  * If the PoolId is non-zero, we get its record,
413  *  otherwise, we search on the PoolName
414  *
415  * Returns: 0 on failure
416  *          id on success 
417  */
418 int db_get_pool_record(B_DB *mdb, POOL_DBR *pdbr)
419 {
420    SQL_ROW row;
421    int stat = 0;
422
423    P(mdb->mutex);
424    if (pdbr->PoolId != 0) {               /* find by id */
425       Mmsg(&mdb->cmd, 
426 "SELECT PoolId, Name, NumVols, MaxVols, UseOnce, UseCatalog, AcceptAnyVolume, \
427 PoolType, LabelFormat FROM Pool WHERE Pool.PoolId=%d", pdbr->PoolId);
428    } else {                           /* find by name */
429       Mmsg(&mdb->cmd, 
430 "SELECT PoolId, Name, NumVols, MaxVols, UseOnce, UseCatalog, AcceptAnyVolume, \
431 PoolType, LabelFormat FROM Pool WHERE Pool.Name=\"%s\"", pdbr->Name);
432    }  
433
434    if (QUERY_DB(mdb, mdb->cmd)) {
435       mdb->num_rows = sql_num_rows(mdb);
436       if (mdb->num_rows > 1) {
437          char ed1[30];
438          Mmsg1(&mdb->errmsg, _("More than one Pool!: %s\n"), 
439             edit_uint64(mdb->num_rows, ed1));
440          Emsg0(M_ERROR, 0, mdb->errmsg);
441       } else if (mdb->num_rows == 1) {
442          if ((row = sql_fetch_row(mdb)) == NULL) {
443             Mmsg1(&mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb));
444             Emsg0(M_ERROR, 0, mdb->errmsg);
445          } else {
446             pdbr->PoolId = atoi(row[0]);
447             strcpy(pdbr->Name, row[1]);
448             pdbr->NumVols = atoi(row[2]);
449             pdbr->MaxVols = atoi(row[3]);
450             pdbr->UseOnce = atoi(row[4]);
451             pdbr->UseCatalog = atoi(row[5]);
452             pdbr->AcceptAnyVolume = atoi(row[6]);
453             strcpy(pdbr->PoolType, row[7]);
454             if (row[8]) {
455                strcpy(pdbr->LabelFormat, row[8]);
456             } else {
457                pdbr->LabelFormat[0] = 0;
458             }
459             stat = pdbr->PoolId;
460          }
461       }
462       sql_free_result(mdb);
463    }
464    V(mdb->mutex);
465    return stat;
466 }
467
468
469 /* 
470  * Get the number of Media records
471  *
472  * Returns: -1 on failure
473  *          number on success
474  */
475 int db_get_num_media_records(B_DB *mdb)
476 {
477    int stat = 0;
478
479    P(mdb->mutex);
480    Mmsg(&mdb->cmd, "SELECT count(*) from Media");
481    stat = get_sql_record_max(mdb);
482    V(mdb->mutex);
483    return stat;
484 }
485
486
487 /*
488  * This function returns a list of all the Media record ids.
489  *  The caller must free ids if non-NULL.
490  *
491  *  Returns 0: on failure
492  *          1: on success
493  */
494 int db_get_media_ids(B_DB *mdb, int *num_ids, uint32_t *ids[])
495 {
496    SQL_ROW row;
497    int stat = 0;
498    int i = 0;
499    uint32_t *id;
500
501    P(mdb->mutex);
502    *ids = NULL;
503    Mmsg(&mdb->cmd, "SELECT MediaId FROM Media");
504    if (QUERY_DB(mdb, mdb->cmd)) {
505       *num_ids = sql_num_rows(mdb);
506       if (*num_ids > 0) {
507          id = (uint32_t *)malloc(*num_ids * sizeof(uint32_t));
508          while ((row = sql_fetch_row(mdb)) != NULL) {
509             id[i++] = (uint32_t)atoi(row[0]);
510          }
511          *ids = id;
512       }
513       sql_free_result(mdb);
514       stat = 1;
515    } else {
516       Mmsg(&mdb->errmsg, _("Media id select failed: ERR=%s\n"), sql_strerror(mdb));
517       stat = 0;
518    }
519    V(mdb->mutex);
520    return stat;
521 }
522
523
524 /* Get Media Record   
525  *
526  * Returns: 0 on failure
527  *          id on success 
528  */
529 int db_get_media_record(B_DB *mdb, MEDIA_DBR *mr)
530 {
531    SQL_ROW row;
532    int stat = 0;
533
534    P(mdb->mutex);
535    if (mr->MediaId == 0 && mr->VolumeName[0] == 0) {
536       Mmsg(&mdb->cmd, "SELECT count(*) from Media");
537       mr->MediaId = get_sql_record_max(mdb);
538       V(mdb->mutex);
539       return 1;
540    }
541    if (mr->MediaId != 0) {               /* find by id */
542       Mmsg(&mdb->cmd, "SELECT MediaId,VolumeName,VolJobs,VolFiles,VolBlocks,\
543 VolBytes,VolMounts,VolErrors,VolWrites,VolMaxBytes,VolCapacityBytes,\
544 MediaType,VolStatus,PoolId \
545 FROM Media WHERE MediaId=%d", mr->MediaId);
546    } else {                           /* find by name */
547       Mmsg(&mdb->cmd, "SELECT MediaId,VolumeName,VolJobs,VolFiles,VolBlocks,\
548 VolBytes,VolMounts,VolErrors,VolWrites,VolMaxBytes,VolCapacityBytes,\
549 MediaType,VolStatus,PoolId \
550 FROM Media WHERE VolumeName=\"%s\"", mr->VolumeName);
551    }  
552
553    if (QUERY_DB(mdb, mdb->cmd)) {
554       mdb->num_rows = sql_num_rows(mdb);
555       if (mdb->num_rows > 1) {
556          char ed1[30];
557          Mmsg1(&mdb->errmsg, _("More than one Volume!: %s\n"), 
558             edit_uint64(mdb->num_rows, ed1));
559          Emsg0(M_ERROR, 0, mdb->errmsg);
560       } else if (mdb->num_rows == 1) {
561          if ((row = sql_fetch_row(mdb)) == NULL) {
562             Mmsg1(&mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb));
563             Emsg0(M_ERROR, 0, mdb->errmsg);
564          } else {
565             /* return values */
566             mr->MediaId = atoi(row[0]);
567             strcpy(mr->VolumeName, row[1]);
568             mr->VolJobs = atoi(row[2]);
569             mr->VolFiles = atoi(row[3]);
570             mr->VolBlocks = atoi(row[4]);
571             mr->VolBytes = (uint64_t)strtod(row[5], NULL);
572             mr->VolMounts = atoi(row[6]);
573             mr->VolErrors = atoi(row[7]);
574             mr->VolWrites = atoi(row[8]);
575             mr->VolMaxBytes = (uint64_t)strtod(row[9], NULL);
576             mr->VolCapacityBytes = (uint64_t)strtod(row[10], NULL);
577             strcpy(mr->MediaType, row[11]);
578             strcpy(mr->VolStatus, row[12]);
579             mr->PoolId = atoi(row[13]);
580             stat = mr->MediaId;
581          }
582       } else {
583          Mmsg0(&mdb->errmsg, _("Media record not found.\n"));
584       }
585       sql_free_result(mdb);
586    }
587    V(mdb->mutex);
588    return stat;
589 }
590
591
592 #endif /* HAVE_MYSQL || HAVE_SQLITE */