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