]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/cats/sql_list.c
Add more debug in src/cats/bvfs.c
[bacula/bacula] / bacula / src / cats / sql_list.c
1 /*
2    Bacula(R) - The Network Backup Solution
3
4    Copyright (C) 2000-2016 Kern Sibbald
5
6    The original author of Bacula is Kern Sibbald, with contributions
7    from many others, a complete list can be found in the file AUTHORS.
8
9    You may use this file and others of this release according to the
10    license defined in the LICENSE file, which includes the Affero General
11    Public License, v3.0 ("AGPLv3") and some additional permissions and
12    terms pursuant to its AGPLv3 Section 7.
13
14    This notice must be preserved when any source code is 
15    conveyed and/or propagated.
16
17    Bacula(R) is a registered trademark of Kern Sibbald.
18 */
19 /*
20  * Bacula Catalog Database List records interface routines
21  *
22  *    Written by Kern Sibbald, March 2000
23  *
24  */
25
26 #include  "bacula.h"
27
28 #if HAVE_SQLITE3 || HAVE_MYSQL || HAVE_POSTGRESQL
29
30 #include  "cats.h"
31
32 /* -----------------------------------------------------------------------
33  *
34  *   Generic Routines (or almost generic)
35  *
36  * -----------------------------------------------------------------------
37  */
38
39 #define append_filter(buf, sql)  \
40    do {                          \
41       if (*buf) {                \
42          pm_strcat(buf, " AND ");\
43       } else {                   \
44          pm_strcpy(buf, " WHERE ");\
45       }                          \
46       pm_strcat(buf, sql);       \
47    } while (0)
48
49 /*
50  * Submit general SQL query
51  */
52 int BDB::bdb_list_sql_query(JCR *jcr, const char *query, DB_LIST_HANDLER *sendit,
53                       void *ctx, int verbose, e_list_type type)
54 {
55    bdb_lock();
56    if (!sql_query(query, QF_STORE_RESULT)) {
57       Mmsg(errmsg, _("Query failed: %s\n"), sql_strerror());
58       if (verbose) {
59          sendit(ctx, errmsg);
60       }
61       bdb_unlock();
62       return 0;
63    }
64
65    list_result(jcr,this, sendit, ctx, type);
66    sql_free_result();
67    bdb_unlock();
68    return 1;
69 }
70
71 void BDB::bdb_list_pool_records(JCR *jcr, POOL_DBR *pdbr,
72                      DB_LIST_HANDLER *sendit, void *ctx, e_list_type type)
73 {
74    char esc[MAX_ESCAPE_NAME_LENGTH];
75
76    bdb_lock();
77    bdb_escape_string(jcr, esc, pdbr->Name, strlen(pdbr->Name));
78
79    if (type == VERT_LIST) {
80       if (pdbr->Name[0] != 0) {
81          Mmsg(cmd, "SELECT PoolId,Name,NumVols,MaxVols,UseOnce,UseCatalog,"
82             "AcceptAnyVolume,VolRetention,VolUseDuration,MaxVolJobs,MaxVolBytes,"
83             "AutoPrune,Recycle,PoolType,LabelFormat,Enabled,ScratchPoolId,"
84             "RecyclePoolId,LabelType,ActionOnPurge,CacheRetention "
85             " FROM Pool WHERE Name='%s'", esc);
86       } else {
87          Mmsg(cmd, "SELECT PoolId,Name,NumVols,MaxVols,UseOnce,UseCatalog,"
88             "AcceptAnyVolume,VolRetention,VolUseDuration,MaxVolJobs,MaxVolBytes,"
89             "AutoPrune,Recycle,PoolType,LabelFormat,Enabled,ScratchPoolId,"
90             "RecyclePoolId,LabelType,ActionOnPurge,CacheRetention "
91             " FROM Pool ORDER BY PoolId");
92       }
93    } else {
94       if (pdbr->Name[0] != 0) {
95          Mmsg(cmd, "SELECT PoolId,Name,NumVols,MaxVols,MaxVolBytes,VolRetention,Enabled,PoolType,LabelFormat "
96            "FROM Pool WHERE Name='%s'", esc);
97       } else {
98          Mmsg(cmd, "SELECT PoolId,Name,NumVols,MaxVols,MaxVolBytes,VolRetention,Enabled,PoolType,LabelFormat "
99            "FROM Pool ORDER BY PoolId");
100       }
101    }
102
103    if (!QueryDB(jcr, cmd)) {
104       bdb_unlock();
105       return;
106    }
107
108    list_result(jcr, this, sendit, ctx, type);
109
110    sql_free_result();
111    bdb_unlock();
112 }
113
114 void BDB::bdb_list_client_records(JCR *jcr, DB_LIST_HANDLER *sendit, void *ctx, e_list_type type)
115 {
116    bdb_lock();
117    if (type == VERT_LIST) {
118       Mmsg(cmd, "SELECT ClientId,Name,Uname,AutoPrune,FileRetention,"
119          "JobRetention "
120          "FROM Client ORDER BY ClientId");
121    } else {
122       Mmsg(cmd, "SELECT ClientId,Name,FileRetention,JobRetention "
123          "FROM Client ORDER BY ClientId");
124    }
125
126    if (!QueryDB(jcr, cmd)) {
127       bdb_unlock();
128       return;
129    }
130
131    list_result(jcr, this, sendit, ctx, type);
132
133    sql_free_result();
134    bdb_unlock();
135 }
136
137 /*
138  * List restore objects
139  *
140  * JobId | JobIds: List RestoreObjects for specific Job(s)
141  * It is possible to specify the ObjectType using FileType field.
142  */
143 void BDB::bdb_list_restore_objects(JCR *jcr, ROBJECT_DBR *rr, DB_LIST_HANDLER *sendit, void *ctx, e_list_type type)
144 {
145    POOL_MEM filter;
146    char  ed1[50];
147    char *jobid;
148
149    if (rr->JobIds && is_a_number_list(rr->JobIds)) {
150       jobid = rr->JobIds;
151
152    } else if (rr->JobId) {
153       jobid = edit_int64(rr->JobId, ed1);
154
155    } else {
156       return;
157    }
158
159    if (rr->FileType > 0) {
160       Mmsg(filter, "AND ObjectType = %d ", rr->FileType);
161    }
162
163    bdb_lock();
164    if (type == VERT_LIST) {
165       Mmsg(cmd, "SELECT JobId, RestoreObjectId, ObjectName, "
166            "PluginName, ObjectType "
167            "FROM RestoreObject JOIN Job USING (JobId) WHERE JobId IN (%s) %s "
168            "ORDER BY JobTDate ASC, RestoreObjectId",
169            jobid, filter.c_str());
170    } else {
171       Mmsg(cmd, "SELECT JobId, RestoreObjectId, ObjectName, "
172            "PluginName, ObjectType, ObjectLength "
173            "FROM RestoreObject JOIN Job USING (JobId) WHERE JobId IN (%s) %s "
174            "ORDER BY JobTDate ASC, RestoreObjectId",
175            jobid, filter.c_str());
176    }
177
178    if (!QueryDB(jcr, cmd)) {
179       bdb_unlock();
180       return;
181    }
182
183    list_result(jcr, this, sendit, ctx, type);
184
185    sql_free_result();
186    bdb_unlock();
187 }
188
189 /*
190  * If VolumeName is non-zero, list the record for that Volume
191  *   otherwise, list the Volumes in the Pool specified by PoolId
192  */
193 void BDB::bdb_list_media_records(JCR *jcr, MEDIA_DBR *mdbr,
194                       DB_LIST_HANDLER *sendit, void *ctx, e_list_type type)
195 {
196    char ed1[50];
197    char esc[MAX_ESCAPE_NAME_LENGTH];
198    const char *expiresin = expires_in[bdb_get_type_index()];
199
200    bdb_lock();
201    bdb_escape_string(jcr, esc, mdbr->VolumeName, strlen(mdbr->VolumeName));
202    const char *join = "";
203    const char *where = "";
204
205    if (type == VERT_LIST) {
206       if (mdbr->VolumeName[0] != 0) {
207          Mmsg(cmd, "SELECT MediaId,VolumeName,Slot,PoolId,"
208             "MediaType,MediaTypeId,FirstWritten,LastWritten,LabelDate,VolJobs,"
209             "VolFiles,VolBlocks,VolParts,VolCloudParts,Media.CacheRetention,VolMounts,VolBytes,"
210             "VolABytes,VolAPadding,"
211             "VolHoleBytes,VolHoles,LastPartBytes,VolErrors,VolWrites,"
212             "VolCapacityBytes,VolStatus,Media.Enabled,Media.Recycle,Media.VolRetention,"
213             "Media.VolUseDuration,Media.MaxVolJobs,Media.MaxVolFiles,Media.MaxVolBytes,InChanger,"
214             "EndFile,EndBlock,VolType,Media.LabelType,StorageId,DeviceId,"
215             "MediaAddressing,VolReadTime,VolWriteTime,"
216             "LocationId,RecycleCount,InitialWrite,Media.ScratchPoolId,Media.RecyclePoolId, "
217             "Media.ActionOnPurge,%s AS ExpiresIn, Comment"
218            " FROM Media %s WHERE Media.VolumeName='%s' %s",
219               expiresin,
220               join,
221               esc,
222               where
223             );
224       } else {
225          Mmsg(cmd, "SELECT MediaId,VolumeName,Slot,PoolId,"
226             "MediaType,MediaTypeId,FirstWritten,LastWritten,LabelDate,VolJobs,"
227             "VolFiles,VolBlocks,VolParts,VolCloudParts,Media.CacheRetention,VolMounts,VolBytes,"
228             "VolABytes,VolAPadding,"
229             "VolHoleBytes,VolHoles,LastPartBytes,VolErrors,VolWrites,"
230             "VolCapacityBytes,VolStatus,Media.Enabled,Media.Recycle,Media.VolRetention,"
231             "Media.VolUseDuration,Media.MaxVolJobs,Media.MaxVolFiles,Media.MaxVolBytes,InChanger,"
232             "EndFile,EndBlock,VolType,Media.LabelType,StorageId,DeviceId,"
233             "MediaAddressing,VolReadTime,VolWriteTime,"
234             "LocationId,RecycleCount,InitialWrite,Media.ScratchPoolId,Media.RecyclePoolId, "
235             "Media.ActionOnPurge,%s AS ExpiresIn, Comment"
236             " FROM Media %s WHERE Media.PoolId=%s %s ORDER BY MediaId",
237               expiresin,
238               join,
239               edit_int64(mdbr->PoolId, ed1),
240               where
241             );
242       }
243    } else {
244       if (mdbr->VolumeName[0] != 0) {
245          Mmsg(cmd, "SELECT MediaId,VolumeName,VolStatus,Media.Enabled,"
246             "VolBytes,VolFiles,Media.VolRetention,Media.Recycle,Slot,InChanger,MediaType,VolType,"
247               "VolParts,%s AS ExpiresIn "
248               "FROM Media %s WHERE Media.VolumeName='%s' %s",
249               expiresin,
250               join,
251               esc,
252               where
253             );
254       } else {
255          Mmsg(cmd, "SELECT MediaId,VolumeName,VolStatus,Media.Enabled,"
256             "VolBytes,VolFiles,Media.VolRetention,Media.Recycle,Slot,InChanger,MediaType,VolType,"
257             "VolParts,LastWritten,%s AS ExpiresIn "
258             "FROM Media %s WHERE Media.PoolId=%s %s ORDER BY MediaId",
259               expiresin,
260               join,
261               edit_int64(mdbr->PoolId, ed1),
262               where
263             );
264       }
265    }
266    Dmsg1(DT_SQL|50, "q=%s\n", cmd);
267    if (!QueryDB(jcr, cmd)) {
268       bdb_unlock();
269       return;
270    }
271
272    list_result(jcr, this, sendit, ctx, type);
273
274    sql_free_result();
275    bdb_unlock();
276 }
277
278 void BDB::bdb_list_jobmedia_records(JCR *jcr, uint32_t JobId,
279                               DB_LIST_HANDLER *sendit, void *ctx, e_list_type type)
280 {
281    char ed1[50];
282
283    bdb_lock();
284    const char *join = "";
285    const char *where = "";
286
287    if (type == VERT_LIST) {
288       if (JobId > 0) {                   /* do by JobId */
289          Mmsg(cmd, "SELECT JobMediaId,JobId,Media.MediaId,Media.VolumeName,"
290             "FirstIndex,LastIndex,StartFile,JobMedia.EndFile,StartBlock,"
291             "JobMedia.EndBlock "
292             "FROM JobMedia JOIN Media USING (MediaId) %s "
293             "WHERE JobMedia.JobId=%s %s",
294               join,
295               edit_int64(JobId, ed1),
296               where);
297       } else {
298          Mmsg(cmd, "SELECT JobMediaId,JobId,Media.MediaId,Media.VolumeName,"
299             "FirstIndex,LastIndex,StartFile,JobMedia.EndFile,StartBlock,"
300             "JobMedia.EndBlock "
301             "FROM JobMedia JOIN Media USING (MediaId) %s %s",
302               join,
303               where);
304       }
305
306    } else {
307       if (JobId > 0) {                   /* do by JobId */
308          Mmsg(cmd, "SELECT JobId,Media.VolumeName,FirstIndex,LastIndex "
309             "FROM JobMedia JOIN Media USING (MediaId) %s WHERE "
310             "JobMedia.JobId=%s %s",
311               join,
312               edit_int64(JobId, ed1),
313               where);
314       } else {
315          Mmsg(cmd, "SELECT JobId,Media.VolumeName,FirstIndex,LastIndex "
316               "FROM JobMedia JOIN Media USING (MediaId) %s %s",
317               join,
318               where);
319       }
320    }
321    Dmsg1(DT_SQL|50, "q=%s\n", cmd);
322
323    if (!QueryDB(jcr, cmd)) {
324       bdb_unlock();
325       return;
326    }
327
328    list_result(jcr, this, sendit, ctx, type);
329
330    sql_free_result();
331    bdb_unlock();
332 }
333
334
335 void BDB::bdb_list_copies_records(JCR *jcr, uint32_t limit, char *JobIds,
336                             DB_LIST_HANDLER *sendit, void *ctx, e_list_type type)
337 {
338    POOL_MEM str_limit(PM_MESSAGE);
339    POOL_MEM str_jobids(PM_MESSAGE);
340
341    if (limit > 0) {
342       Mmsg(str_limit, " LIMIT %d", limit);
343    }
344
345    if (JobIds && JobIds[0]) {
346       Mmsg(str_jobids, " AND (Job.PriorJobId IN (%s) OR Job.JobId IN (%s)) ",
347            JobIds, JobIds);
348    }
349
350    bdb_lock();
351    Mmsg(cmd,
352    "SELECT DISTINCT Job.PriorJobId AS JobId, Job.Job, "
353                    "Job.JobId AS CopyJobId, Media.MediaType "
354      "FROM Job "
355      "JOIN JobMedia USING (JobId) "
356      "JOIN Media    USING (MediaId) "
357     "WHERE Job.Type = '%c' %s ORDER BY Job.PriorJobId DESC %s",
358         (char) JT_JOB_COPY, str_jobids.c_str(), str_limit.c_str());
359
360    if (!QueryDB(jcr, cmd)) {
361       goto bail_out;
362    }
363
364    if (sql_num_rows()) {
365       if (JobIds && JobIds[0]) {
366          sendit(ctx, _("These JobIds have copies as follows:\n"));
367       } else {
368          sendit(ctx, _("The catalog contains copies as follows:\n"));
369       }
370
371       list_result(jcr, this, sendit, ctx, type);
372    }
373
374    sql_free_result();
375
376 bail_out:
377    bdb_unlock();
378 }
379
380 void BDB::bdb_list_joblog_records(JCR *jcr, uint32_t JobId,
381                               DB_LIST_HANDLER *sendit, void *ctx, e_list_type type)
382 {
383    char ed1[50];
384  
385    if (JobId <= 0) {
386       return;
387    }
388    bdb_lock();
389    if (type == VERT_LIST) {
390       Mmsg(cmd, "SELECT Time,LogText FROM Log "
391            "WHERE Log.JobId=%s ORDER BY LogId ASC", edit_int64(JobId, ed1));
392    } else {
393       Mmsg(cmd, "SELECT LogText FROM Log "
394            "WHERE Log.JobId=%s ORDER BY LogId ASC", edit_int64(JobId, ed1));
395    }
396    if (!QueryDB(jcr, cmd)) {
397       goto bail_out;
398    }
399
400    list_result(jcr, this, sendit, ctx, type);
401
402    sql_free_result();
403
404 bail_out:
405    bdb_unlock();
406 }
407
408
409 /*
410  * List Job record(s) that match JOB_DBR
411  *
412  *  Currently, we return all jobs or if jr->JobId is set,
413  *  only the job with the specified id.
414  */
415 alist *BDB::bdb_list_job_records(JCR *jcr, JOB_DBR *jr, DB_LIST_HANDLER *sendit,
416                     void *ctx, e_list_type type)
417 {
418    char ed1[50];
419    char limit[50];
420    char esc[MAX_ESCAPE_NAME_LENGTH];
421    alist *list = NULL;
422    POOLMEM *where  = get_pool_memory(PM_MESSAGE);
423    POOLMEM *tmp    = get_pool_memory(PM_MESSAGE);
424    const char *order = "ASC";
425    *where = 0;
426
427    bdb_lock();
428    if (jr->order == 1) {
429       order = "DESC";
430    }
431    if (jr->limit > 0) {
432       snprintf(limit, sizeof(limit), " LIMIT %d", jr->limit);
433    } else {
434       limit[0] = 0;
435    }
436    if (jr->Name[0]) {
437       bdb_escape_string(jcr, esc, jr->Name, strlen(jr->Name));
438       Mmsg(tmp, " Job.Name='%s' ", esc);
439       append_filter(where, tmp);
440
441    } else if (jr->JobId != 0) {
442       Mmsg(tmp, " Job.JobId=%s ", edit_int64(jr->JobId, ed1));
443       append_filter(where, tmp);
444
445    } else if (jr->Job[0] != 0) {
446       bdb_escape_string(jcr, esc, jr->Job, strlen(jr->Job));
447       Mmsg(tmp, " Job.Job='%s' ", esc);
448       append_filter(where, tmp);
449    }
450
451    if (type == INCOMPLETE_JOBS && jr->JobStatus == JS_FatalError) {
452       Mmsg(tmp, " Job.JobStatus IN ('E', 'f') ");
453       append_filter(where, tmp);
454
455    } else if (jr->JobStatus) {
456       Mmsg(tmp, " Job.JobStatus='%c' ", jr->JobStatus);
457       append_filter(where, tmp);
458    }
459
460    if (jr->JobType) {
461       Mmsg(tmp, " Job.Type='%c' ", jr->JobType);
462       append_filter(where, tmp);
463    }
464
465    if (jr->JobErrors > 0) {
466       Mmsg(tmp, " Job.JobErrors > 0 ");
467       append_filter(where, tmp);
468    }
469
470    if (jr->ClientId > 0) {
471       Mmsg(tmp, " Job.ClientId=%s ", edit_int64(jr->ClientId, ed1));
472       append_filter(where, tmp);
473    }
474
475    switch (type) {
476    case VERT_LIST:
477       Mmsg(cmd,
478            "SELECT JobId,Job,Job.Name,PurgedFiles,Type,Level,"
479            "Job.ClientId,Client.Name as ClientName,JobStatus,SchedTime,"
480            "StartTime,EndTime,RealEndTime,JobTDate,"
481            "VolSessionId,VolSessionTime,JobFiles,JobBytes,ReadBytes,JobErrors,"
482            "JobMissingFiles,Job.PoolId,Pool.Name as PoolName,PriorJobId,"
483            "Job.FileSetId,FileSet.FileSet,Job.HasBase,Job.HasCache,Job.Comment "
484            "FROM Job JOIN Client USING (ClientId) LEFT JOIN Pool USING (PoolId) "
485            "LEFT JOIN FileSet USING (FileSetId) %s "
486            "ORDER BY StartTime %s %s", where, order, limit);
487       break;
488    case HORZ_LIST:
489       Mmsg(cmd,
490            "SELECT JobId,Name,StartTime,Type,Level,JobFiles,JobBytes,JobStatus "
491            "FROM Job %s ORDER BY StartTime %s,JobId %s %s", where, order, order, limit);
492       break;
493    case INCOMPLETE_JOBS:
494       Mmsg(cmd,
495            "SELECT JobId,Name,StartTime,Type,Level,JobFiles,JobBytes,JobStatus "
496              "FROM Job %s ORDER BY StartTime %s,JobId %s %s",
497            where, order, order, limit);
498       break;
499    default:
500       break;
501    }
502
503    free_pool_memory(tmp);
504    free_pool_memory(where);
505
506    Dmsg1(100, "SQL: %s\n", cmd);
507    if (!QueryDB(jcr, cmd)) {
508       bdb_unlock();
509       return NULL;
510    }
511    if (type == INCOMPLETE_JOBS) {
512       SQL_ROW row;
513       list = New(alist(10));
514       sql_data_seek(0);
515       for (int i=0; (row=sql_fetch_row()) != NULL; i++) {
516          list->append(bstrdup(row[0]));
517       }
518    }
519    sql_data_seek(0);
520    list_result(jcr, this, sendit, ctx, type);
521    sql_free_result();
522    bdb_unlock();
523    return list;
524 }
525
526 /*
527  * List Job totals
528  *
529  */
530 void BDB::bdb_list_job_totals(JCR *jcr, JOB_DBR *jr, DB_LIST_HANDLER *sendit, void *ctx)
531 {
532    bdb_lock();
533
534    /* List by Job */
535    Mmsg(cmd, "SELECT  count(*) AS Jobs,sum(JobFiles) "
536       "AS Files,sum(JobBytes) AS Bytes,Name AS Job FROM Job GROUP BY Name");
537
538    if (!QueryDB(jcr, cmd)) {
539       bdb_unlock();
540       return;
541    }
542
543    list_result(jcr, this, sendit, ctx, HORZ_LIST);
544
545    sql_free_result();
546
547    /* Do Grand Total */
548    Mmsg(cmd, "SELECT count(*) AS Jobs,sum(JobFiles) "
549         "AS Files,sum(JobBytes) As Bytes FROM Job");
550
551    if (!QueryDB(jcr, cmd)) {
552       bdb_unlock();
553       return;
554    }
555
556    list_result(jcr, this, sendit, ctx, HORZ_LIST);
557
558    sql_free_result();
559    bdb_unlock();
560 }
561
562 /* List all file records from a job
563  * "deleted" values are described just below
564  */
565 void BDB::bdb_list_files_for_job(JCR *jcr, JobId_t jobid, int deleted, DB_LIST_HANDLER *sendit, void *ctx)
566 {
567    char ed1[50];
568    const char *opt;
569    LIST_CTX lctx(jcr, this, sendit, ctx, HORZ_LIST);
570
571    switch (deleted) {
572    case 0:                      /* Show only actual files */
573       opt = " AND FileIndex <> 0 ";
574       break;
575    case 1:                      /* Show only deleted files */
576       opt = " AND FileIndex = 0 ";
577       break;
578    default:                     /* Show everything */
579       opt = "";
580       break;
581    }
582
583    bdb_lock();
584
585    /*
586     * Stupid MySQL is NON-STANDARD !
587     */
588    if (bdb_get_type_index() == SQL_TYPE_MYSQL) {
589       Mmsg(cmd, "SELECT CONCAT(Path.Path,Filename.Name) AS Filename "
590            "FROM (SELECT PathId, FilenameId FROM File WHERE JobId=%s %s "
591                   "UNION ALL "
592                  "SELECT PathId, FilenameId "
593                    "FROM BaseFiles JOIN File "
594                          "ON (BaseFiles.FileId = File.FileId) "
595                   "WHERE BaseFiles.JobId = %s"
596            ") AS F, Filename,Path "
597            "WHERE Filename.FilenameId=F.FilenameId "
598            "AND Path.PathId=F.PathId",
599            edit_int64(jobid, ed1), opt, ed1);
600    } else {
601       Mmsg(cmd, "SELECT Path.Path||Filename.Name AS Filename "
602            "FROM (SELECT PathId, FilenameId FROM File WHERE JobId=%s %s "
603                   "UNION ALL "
604                  "SELECT PathId, FilenameId "
605                    "FROM BaseFiles JOIN File "
606                          "ON (BaseFiles.FileId = File.FileId) "
607                   "WHERE BaseFiles.JobId = %s"
608            ") AS F, Filename,Path "
609            "WHERE Filename.FilenameId=F.FilenameId "
610            "AND Path.PathId=F.PathId",
611            edit_int64(jobid, ed1), opt, ed1);
612    }
613    Dmsg1(100, "q=%s\n", cmd);
614    if (!bdb_big_sql_query(cmd, list_result, &lctx)) {
615        bdb_unlock();
616        return;
617    }
618
619    lctx.send_dashes();
620
621    sql_free_result();
622    bdb_unlock();
623 }
624
625 void BDB::bdb_list_base_files_for_job(JCR *jcr, JobId_t jobid, DB_LIST_HANDLER *sendit, void *ctx)
626 {
627    char ed1[50];
628    LIST_CTX lctx(jcr, this, sendit, ctx, HORZ_LIST);
629
630    bdb_lock();
631
632    /*
633     * Stupid MySQL is NON-STANDARD !
634     */
635    if (bdb_get_type_index() == SQL_TYPE_MYSQL) {
636       Mmsg(cmd, "SELECT CONCAT(Path.Path,Filename.Name) AS Filename "
637            "FROM BaseFiles, File, Filename, Path "
638            "WHERE BaseFiles.JobId=%s AND BaseFiles.BaseJobId = File.JobId "
639            "AND BaseFiles.FileId = File.FileId "
640            "AND Filename.FilenameId=File.FilenameId "
641            "AND Path.PathId=File.PathId",
642          edit_int64(jobid, ed1));
643    } else {
644       Mmsg(cmd, "SELECT Path.Path||Filename.Name AS Filename "
645            "FROM BaseFiles, File, Filename, Path "
646            "WHERE BaseFiles.JobId=%s AND BaseFiles.BaseJobId = File.JobId "
647            "AND BaseFiles.FileId = File.FileId "
648            "AND Filename.FilenameId=File.FilenameId "
649            "AND Path.PathId=File.PathId",
650            edit_int64(jobid, ed1));
651    }
652
653    if (!bdb_big_sql_query(cmd, list_result, &lctx)) {
654        bdb_unlock();
655        return;
656    }
657
658    lctx.send_dashes();
659
660    sql_free_result();
661    bdb_unlock();
662 }
663
664 void BDB::bdb_list_snapshot_records(JCR *jcr, SNAPSHOT_DBR *sdbr,
665               DB_LIST_HANDLER *sendit, void *ctx, e_list_type type)
666 {
667    POOLMEM *filter = get_pool_memory(PM_MESSAGE);
668    POOLMEM *tmp    = get_pool_memory(PM_MESSAGE);
669    POOLMEM *esc    = get_pool_memory(PM_MESSAGE);
670    char ed1[50];
671
672    bdb_lock();
673    *filter = 0;
674
675    if (sdbr->Name[0]) {
676       bdb_escape_string(jcr, esc, sdbr->Name, strlen(sdbr->Name));
677       Mmsg(tmp, "Name='%s'", esc);
678       append_filter(filter, tmp);
679    }
680    if (sdbr->SnapshotId > 0) {
681       Mmsg(tmp, "Snapshot.SnapshotId=%d", sdbr->SnapshotId);
682       append_filter(filter, tmp);
683    }
684    if (sdbr->ClientId > 0) {
685       Mmsg(tmp, "Snapshot.ClientId=%d", sdbr->ClientId);
686       append_filter(filter, tmp);
687    }
688    if (sdbr->JobId > 0) {
689       Mmsg(tmp, "Snapshot.JobId=%d", sdbr->JobId);
690       append_filter(filter, tmp);
691    }
692    if (*sdbr->Client) {
693       bdb_escape_string(jcr, esc, sdbr->Client, strlen(sdbr->Client));
694       Mmsg(tmp, "Client.Name='%s'", esc);
695       append_filter(filter, tmp);
696    }
697    if (sdbr->Device && *(sdbr->Device)) {
698       esc = check_pool_memory_size(esc, strlen(sdbr->Device) * 2 + 1);
699       bdb_escape_string(jcr, esc, sdbr->Device, strlen(sdbr->Device));
700       Mmsg(tmp, "Device='%s'", esc);
701       append_filter(filter, tmp);
702    }
703    if (*sdbr->Type) {
704       bdb_escape_string(jcr, esc, sdbr->Type, strlen(sdbr->Type));
705       Mmsg(tmp, "Type='%s'", esc);
706       append_filter(filter, tmp);
707    }
708    if (*sdbr->created_before) {
709       bdb_escape_string(jcr, esc, sdbr->created_before, strlen(sdbr->created_before));
710       Mmsg(tmp, "CreateDate <= '%s'", esc);
711       append_filter(filter, tmp);
712    }
713    if (*sdbr->created_after) {
714       bdb_escape_string(jcr, esc, sdbr->created_after, strlen(sdbr->created_after));
715       Mmsg(tmp, "CreateDate >= '%s'", esc);
716       append_filter(filter, tmp);
717    }
718    if (sdbr->expired) {
719       Mmsg(tmp, "CreateTDate < (%s - Retention)", edit_int64(time(NULL), ed1));
720       append_filter(filter, tmp);
721    }
722    if (*sdbr->CreateDate) {
723       bdb_escape_string(jcr, esc, sdbr->CreateDate, strlen(sdbr->CreateDate));
724       Mmsg(tmp, "CreateDate = '%s'", esc);
725       append_filter(filter, tmp);
726    }
727
728    if (sdbr->sorted_client) {
729       pm_strcat(filter, " ORDER BY Client.Name, SnapshotId DESC");
730
731    } else {
732       pm_strcat(filter, " ORDER BY SnapshotId DESC");
733    }
734
735    if (type == VERT_LIST || type == ARG_LIST) {
736       Mmsg(cmd, "SELECT SnapshotId, Snapshot.Name, CreateDate, Client.Name AS Client, "
737            "FileSet.FileSet AS FileSet, JobId, Volume, Device, Type, Retention, Comment "
738            "FROM Snapshot JOIN Client USING (ClientId) LEFT JOIN FileSet USING (FileSetId) %s", filter);
739
740    } else if (type == HORZ_LIST) {
741       Mmsg(cmd, "SELECT SnapshotId, Snapshot.Name, CreateDate, Client.Name AS Client, "
742            "Device, Type "
743            "FROM Snapshot JOIN Client USING (ClientId) %s", filter);
744    }
745
746    if (!QueryDB(jcr, cmd)) {
747       goto bail_out;
748    }
749
750    list_result(jcr, this, sendit, ctx, type);
751
752 bail_out:
753    sql_free_result();
754    bdb_unlock();
755
756    free_pool_memory(filter);
757    free_pool_memory(esc);
758    free_pool_memory(tmp);
759 }
760
761 #endif /* HAVE_SQLITE3 || HAVE_MYSQL || HAVE_POSTGRESQL */