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