]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/cats/sql_list.c
A better fix for the WIN32_VSS bug that Kern discovered.
[bacula/bacula] / bacula / src / cats / sql_list.c
1 /*
2  * Bacula Catalog Database List records interface routines
3  *
4  *    Kern Sibbald, March 2000
5  *
6  *    Version $Id$
7  */
8 /*
9    Copyright (C) 2000-2006 Kern Sibbald
10
11    This program is free software; you can redistribute it and/or
12    modify it under the terms of the GNU General Public License
13    version 2 as amended with additional clauses defined in the
14    file LICENSE in the main source directory.
15
16    This program is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
19    the file LICENSE for additional details.
20
21  */
22
23 /* The following is necessary so that we do not include
24  * the dummy external definition of DB.
25  */
26 #define __SQL_C                       /* indicate that this is sql.c */
27
28 #include "bacula.h"
29 #include "cats.h"
30
31 #if    HAVE_SQLITE3 || HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL
32
33 /* -----------------------------------------------------------------------
34  *
35  *   Generic Routines (or almost generic)
36  *
37  * -----------------------------------------------------------------------
38  */
39
40 /*
41  * Submit general SQL query
42  */
43 int db_list_sql_query(JCR *jcr, B_DB *mdb, const char *query, DB_LIST_HANDLER *sendit,
44                       void *ctx, int verbose, e_list_type type)
45 {
46    db_lock(mdb);
47    if (sql_query(mdb, query) != 0) {
48       Mmsg(mdb->errmsg, _("Query failed: %s\n"), sql_strerror(mdb));
49       if (verbose) {
50          sendit(ctx, mdb->errmsg);
51       }
52       db_unlock(mdb);
53       return 0;
54    }
55
56    mdb->result = sql_store_result(mdb);
57
58    if (mdb->result) {
59       list_result(jcr, mdb, sendit, ctx, type);
60       sql_free_result(mdb);
61    }
62    db_unlock(mdb);
63    return 1;
64 }
65
66 void
67 db_list_pool_records(JCR *jcr, B_DB *mdb, POOL_DBR *pdbr, 
68                      DB_LIST_HANDLER *sendit, void *ctx, e_list_type type)
69 {
70    db_lock(mdb);
71    if (type == VERT_LIST) {
72       if (pdbr->Name[0] != 0) {
73          Mmsg(mdb->cmd, "SELECT PoolId,Name,NumVols,MaxVols,UseOnce,UseCatalog,"
74             "AcceptAnyVolume,VolRetention,VolUseDuration,MaxVolJobs,MaxVolBytes,"
75             "AutoPrune,Recycle,PoolType,LabelFormat,Enabled,ScratchPoolId,"
76             "RecyclePoolId,LabelType "
77             " FROM Pool WHERE Name='%s'", pdbr->Name);
78       } else {
79          Mmsg(mdb->cmd, "SELECT PoolId,Name,NumVols,MaxVols,UseOnce,UseCatalog,"
80             "AcceptAnyVolume,VolRetention,VolUseDuration,MaxVolJobs,MaxVolBytes,"
81             "AutoPrune,Recycle,PoolType,LabelFormat,Enabled,ScratchPoolId,"
82             "RecyclePoolId,LabelType "
83             " FROM Pool ORDER BY PoolId");
84       }
85    } else {
86       if (pdbr->Name[0] != 0) {
87          Mmsg(mdb->cmd, "SELECT PoolId,Name,NumVols,MaxVols,PoolType,LabelFormat "
88            "FROM Pool WHERE Name='%s'", pdbr->Name);
89       } else {
90          Mmsg(mdb->cmd, "SELECT PoolId,Name,NumVols,MaxVols,PoolType,LabelFormat "
91            "FROM Pool ORDER BY PoolId");
92       }
93    }
94
95    if (!QUERY_DB(jcr, mdb, mdb->cmd)) {
96       db_unlock(mdb);
97       return;
98    }
99
100    list_result(jcr, mdb, sendit, ctx, type);
101
102    sql_free_result(mdb);
103    db_unlock(mdb);
104 }
105
106 void
107 db_list_client_records(JCR *jcr, B_DB *mdb, DB_LIST_HANDLER *sendit, void *ctx, e_list_type type)
108 {
109    db_lock(mdb);
110    if (type == VERT_LIST) {
111       Mmsg(mdb->cmd, "SELECT ClientId,Name,Uname,AutoPrune,FileRetention,"
112          "JobRetention "
113          "FROM Client ORDER BY ClientId");
114    } else {
115       Mmsg(mdb->cmd, "SELECT ClientId,Name,FileRetention,JobRetention "
116          "FROM Client ORDER BY ClientId");
117    }
118
119    if (!QUERY_DB(jcr, mdb, mdb->cmd)) {
120       db_unlock(mdb);
121       return;
122    }
123
124    list_result(jcr, mdb, sendit, ctx, type);
125
126    sql_free_result(mdb);
127    db_unlock(mdb);
128 }
129
130
131 /*
132  * If VolumeName is non-zero, list the record for that Volume
133  *   otherwise, list the Volumes in the Pool specified by PoolId
134  */
135 void
136 db_list_media_records(JCR *jcr, B_DB *mdb, MEDIA_DBR *mdbr,
137                       DB_LIST_HANDLER *sendit, void *ctx, e_list_type type)
138 {
139    char ed1[50];
140    db_lock(mdb);
141    if (type == VERT_LIST) {
142       if (mdbr->VolumeName[0] != 0) {
143          Mmsg(mdb->cmd, "SELECT MediaId,VolumeName,Slot,PoolId,"
144             "MediaType,FirstWritten,LastWritten,LabelDate,VolJobs,"
145             "VolFiles,VolBlocks,VolMounts,VolBytes,VolErrors,VolWrites,"
146             "VolCapacityBytes,VolStatus,Enabled,Recycle,VolRetention,"
147             "VolUseDuration,MaxVolJobs,MaxVolFiles,MaxVolBytes,InChanger,"
148             "EndFile,EndBlock,VolParts,LabelType,StorageId,DeviceId,"
149             "LocationId,RecycleCount,InitialWrite,ScratchPoolId,RecyclePoolId, "
150             "Comment"
151             " FROM Media WHERE Media.VolumeName='%s'", mdbr->VolumeName);
152       } else {
153          Mmsg(mdb->cmd, "SELECT MediaId,VolumeName,Slot,PoolId,"
154             "MediaType,FirstWritten,LastWritten,LabelDate,VolJobs,"
155             "VolFiles,VolBlocks,VolMounts,VolBytes,VolErrors,VolWrites,"
156             "VolCapacityBytes,VolStatus,Enabled,Recycle,VolRetention,"
157             "VolUseDuration,MaxVolJobs,MaxVolFiles,MaxVolBytes,InChanger,"
158             "EndFile,EndBlock,VolParts,LabelType,StorageId,DeviceId,"
159             "LocationId,RecycleCount,InitialWrite,ScratchPoolId,RecyclePoolId, "
160             "Comment"
161             " FROM Media WHERE Media.PoolId=%s ORDER BY MediaId", 
162             edit_int64(mdbr->PoolId, ed1));
163       }
164    } else {
165       if (mdbr->VolumeName[0] != 0) {
166          Mmsg(mdb->cmd, "SELECT MediaId,VolumeName,VolStatus,Enabled,"
167             "VolBytes,VolFiles,VolRetention,Recycle,Slot,InChanger,MediaType,LastWritten "
168             "FROM Media WHERE Media.VolumeName='%s'", mdbr->VolumeName);
169       } else {
170          Mmsg(mdb->cmd, "SELECT MediaId,VolumeName,VolStatus,Enabled,"
171             "VolBytes,VolFiles,VolRetention,Recycle,Slot,InChanger,MediaType,LastWritten "
172             "FROM Media WHERE Media.PoolId=%s ORDER BY MediaId", 
173             edit_int64(mdbr->PoolId, ed1));
174       }
175    }
176
177    if (!QUERY_DB(jcr, mdb, mdb->cmd)) {
178       db_unlock(mdb);
179       return;
180    }
181
182    list_result(jcr, mdb, sendit, ctx, type);
183
184    sql_free_result(mdb);
185    db_unlock(mdb);
186 }
187
188 void db_list_jobmedia_records(JCR *jcr, B_DB *mdb, uint32_t JobId,
189                               DB_LIST_HANDLER *sendit, void *ctx, e_list_type type)
190 {
191    char ed1[50];
192    db_lock(mdb);
193    if (type == VERT_LIST) {
194       if (JobId > 0) {                   /* do by JobId */
195          Mmsg(mdb->cmd, "SELECT JobMediaId,JobId,Media.MediaId,Media.VolumeName,"
196             "FirstIndex,LastIndex,StartFile,JobMedia.EndFile,StartBlock,"
197             "JobMedia.EndBlock,Copy "
198             "FROM JobMedia,Media WHERE Media.MediaId=JobMedia.MediaId "
199             "AND JobMedia.JobId=%s", edit_int64(JobId, ed1));
200       } else {
201          Mmsg(mdb->cmd, "SELECT JobMediaId,JobId,Media.MediaId,Media.VolumeName,"
202             "FirstIndex,LastIndex,StartFile,JobMedia.EndFile,StartBlock,"
203             "JobMedia.EndBlock,Copy "
204             "FROM JobMedia,Media WHERE Media.MediaId=JobMedia.MediaId");
205       }
206
207    } else {
208       if (JobId > 0) {                   /* do by JobId */
209          Mmsg(mdb->cmd, "SELECT JobId,Media.VolumeName,FirstIndex,LastIndex "
210             "FROM JobMedia,Media WHERE Media.MediaId=JobMedia.MediaId "
211             "AND JobMedia.JobId=%s", edit_int64(JobId, ed1));
212       } else {
213          Mmsg(mdb->cmd, "SELECT JobId,Media.VolumeName,FirstIndex,LastIndex "
214             "FROM JobMedia,Media WHERE Media.MediaId=JobMedia.MediaId");
215       }
216    }
217    if (!QUERY_DB(jcr, mdb, mdb->cmd)) {
218       db_unlock(mdb);
219       return;
220    }
221
222    list_result(jcr, mdb, sendit, ctx, type);
223
224    sql_free_result(mdb);
225    db_unlock(mdb);
226 }
227
228
229
230 /*
231  * List Job record(s) that match JOB_DBR
232  *
233  *  Currently, we return all jobs or if jr->JobId is set,
234  *  only the job with the specified id.
235  */
236 void
237 db_list_job_records(JCR *jcr, B_DB *mdb, JOB_DBR *jr, DB_LIST_HANDLER *sendit,
238                     void *ctx, e_list_type type)
239 {
240    char ed1[50];
241    char limit[100];
242    db_lock(mdb);
243    if (jr->limit > 0) {
244       snprintf(limit, sizeof(limit), " LIMIT %d", jr->limit);
245    } else {
246       limit[0] = 0;
247    }
248    if (type == VERT_LIST) {
249       if (jr->JobId == 0 && jr->Job[0] == 0) {
250          Mmsg(mdb->cmd,
251             "SELECT JobId,Job,Job.Name,PurgedFiles,Type,Level,"
252             "Job.ClientId,Client.Name as ClientName,JobStatus,SchedTime,"
253             "StartTime,EndTime,RealEndTime,JobTDate,"
254             "VolSessionId,VolSessionTime,JobFiles,JobErrors,"
255             "JobMissingFiles,Job.PoolId,Pool.Name as PooLname,PriorJobId,"
256             "Job.FileSetId,FileSet.FileSet "
257             "FROM Job,Client,Pool,FileSet WHERE "
258             "Client.ClientId=Job.ClientId AND Pool.PoolId=Job.PoolId "
259             "AND FileSet.FileSetId=Job.FileSetId  ORDER BY StartTime%s", limit);
260       } else {                           /* single record */
261          Mmsg(mdb->cmd,
262             "SELECT JobId,Job,Job.Name,PurgedFiles,Type,Level,"
263             "Job.ClientId,Client.Name,JobStatus,SchedTime,"
264             "StartTime,EndTime,RealEndTime,JobTDate,"
265             "VolSessionId,VolSessionTime,JobFiles,JobErrors,"
266             "JobMissingFiles,Job.PoolId,Pool.Name as PooLname,PriorJobId,"
267             "Job.FileSetId,FileSet.FileSet "
268             "FROM Job,Client,Pool,FileSet WHERE Job.JobId=%s AND "
269             "Client.ClientId=Job.ClientId AND Pool.PoolId=Job.PoolId "
270             "AND FileSet.FileSetId=Job.FileSetId", 
271             edit_int64(jr->JobId, ed1));
272       }
273    } else {
274       if (jr->Name[0] != 0) {
275          Mmsg(mdb->cmd,
276             "SELECT JobId,Name,StartTime,Type,Level,JobFiles,JobBytes,JobStatus "
277             "FROM Job WHERE Name='%s' ORDER BY StartTime,JobId ASC", jr->Name);
278       } else if (jr->Job[0] != 0) {
279          Mmsg(mdb->cmd,
280             "SELECT JobId,Name,StartTime,Type,Level,JobFiles,JobBytes,JobStatus "
281             "FROM Job WHERE Job='%s' ORDER BY StartTime,JobId ASC", jr->Job);
282       } else if (jr->JobId != 0) {
283          Mmsg(mdb->cmd, 
284             "SELECT JobId,Name,StartTime,Type,Level,JobFiles,JobBytes,JobStatus "
285             "FROM Job WHERE JobId=%s", edit_int64(jr->JobId, ed1));
286       } else {                           /* all records */
287          Mmsg(mdb->cmd,
288            "SELECT JobId,Name,StartTime,Type,Level,JobFiles,JobBytes,JobStatus "
289            "FROM Job ORDER BY StartTime,JobId ASC%s", limit);
290       }
291    }
292    if (!QUERY_DB(jcr, mdb, mdb->cmd)) {
293       db_unlock(mdb);
294       return;
295    }
296    list_result(jcr, mdb, sendit, ctx, type);
297
298    sql_free_result(mdb);
299    db_unlock(mdb);
300 }
301
302 /*
303  * List Job totals
304  *
305  */
306 void
307 db_list_job_totals(JCR *jcr, B_DB *mdb, JOB_DBR *jr, DB_LIST_HANDLER *sendit, void *ctx)
308 {
309    db_lock(mdb);
310
311    /* List by Job */
312    Mmsg(mdb->cmd, "SELECT  count(*) AS Jobs,sum(JobFiles) "
313       "AS Files,sum(JobBytes) AS Bytes,Name AS Job FROM Job GROUP BY Name");
314
315    if (!QUERY_DB(jcr, mdb, mdb->cmd)) {
316       db_unlock(mdb);
317       return;
318    }
319
320    list_result(jcr, mdb, sendit, ctx, HORZ_LIST);
321
322    sql_free_result(mdb);
323
324    /* Do Grand Total */
325    Mmsg(mdb->cmd, "SELECT count(*) AS Jobs,sum(JobFiles) "
326         "AS Files,sum(JobBytes) As Bytes FROM Job");
327
328    if (!QUERY_DB(jcr, mdb, mdb->cmd)) {
329       db_unlock(mdb);
330       return;
331    }
332
333    list_result(jcr, mdb, sendit, ctx, HORZ_LIST);
334
335    sql_free_result(mdb);
336    db_unlock(mdb);
337 }
338
339 /*
340  * Stupid MySQL is NON-STANDARD !
341  */
342 #ifdef HAVE_MYSQL
343 #define FN "CONCAT(Path.Path,Filename.Name)"
344 #else
345 #define FN "Path.Path||Filename.Name"
346 #endif
347
348 void
349 db_list_files_for_job(JCR *jcr, B_DB *mdb, JobId_t jobid, DB_LIST_HANDLER *sendit, void *ctx)
350 {
351    char ed1[50];
352    db_lock(mdb);
353
354    Mmsg(mdb->cmd, "SELECT " FN " AS Filename FROM File,"
355 "Filename,Path WHERE File.JobId=%s AND Filename.FilenameId=File.FilenameId "
356 "AND Path.PathId=File.PathId",
357       edit_int64(jobid, ed1));
358
359    if (!QUERY_DB(jcr, mdb, mdb->cmd)) {
360       db_unlock(mdb);
361       return;
362    }
363
364    list_result(jcr, mdb, sendit, ctx, HORZ_LIST);
365
366    sql_free_result(mdb);
367    db_unlock(mdb);
368 }
369
370
371 #endif /* HAVE_SQLITE3 || HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL*/