1 /*
2 Bacula(R) - The Network Backup Solution
3
4 Copyright (C) 2000-2020 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 */
bdb_list_sql_query(JCR * jcr,const char * query,DB_LIST_HANDLER * sendit,void * ctx,int verbose,e_list_type type)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
bdb_list_pool_records(JCR * jcr,POOL_DBR * pdbr,DB_LIST_HANDLER * sendit,void * ctx,e_list_type type)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
bdb_list_client_records(JCR * jcr,DB_LIST_HANDLER * sendit,void * ctx,e_list_type type)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 */
bdb_list_restore_objects(JCR * jcr,ROBJECT_DBR * rr,DB_LIST_HANDLER * sendit,void * ctx,e_list_type type)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 */
bdb_list_media_records(JCR * jcr,MEDIA_DBR * mdbr,DB_LIST_HANDLER * sendit,void * ctx,e_list_type type)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
bdb_list_jobmedia_records(JCR * jcr,uint32_t JobId,DB_LIST_HANDLER * sendit,void * ctx,e_list_type type)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
bdb_list_copies_records(JCR * jcr,uint32_t limit,char * JobIds,DB_LIST_HANDLER * sendit,void * ctx,e_list_type type)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
bdb_list_joblog_records(JCR * jcr,uint32_t JobId,DB_LIST_HANDLER * sendit,void * ctx,e_list_type type)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 * List Job record(s) that match JOB_DBR
410 *
411 * Currently, we return all jobs or if jr->JobId is set,
412 * only the job with the specified id.
413 */
bdb_list_job_records(JCR * jcr,JOB_DBR * jr,DB_LIST_HANDLER * sendit,void * ctx,e_list_type type)414 alist *BDB::bdb_list_job_records(JCR *jcr, JOB_DBR *jr, DB_LIST_HANDLER *sendit,
415 void *ctx, e_list_type type)
416 {
417 char ed1[50];
418 char limit[50];
419 char esc[MAX_ESCAPE_NAME_LENGTH];
420 alist *list = NULL;
421 POOLMEM *where = get_pool_memory(PM_MESSAGE);
422 POOLMEM *tmp = get_pool_memory(PM_MESSAGE);
423 const char *order = "ASC";
424 *where = 0;
425
426 bdb_lock();
427 if (jr->order == 1) {
428 order = "DESC";
429 }
430 if (jr->limit > 0) {
431 snprintf(limit, sizeof(limit), " LIMIT %d", jr->limit);
432 } else {
433 limit[0] = 0;
434 }
435 if (jr->Name[0]) {
436 bdb_escape_string(jcr, esc, jr->Name, strlen(jr->Name));
437 Mmsg(tmp, " Job.Name='%s' ", esc);
438 append_filter(where, tmp);
439
440 } else if (jr->JobId != 0) {
441 Mmsg(tmp, " Job.JobId=%s ", edit_int64(jr->JobId, ed1));
442 append_filter(where, tmp);
443
444 } else if (jr->Job[0] != 0) {
445 bdb_escape_string(jcr, esc, jr->Job, strlen(jr->Job));
446 Mmsg(tmp, " Job.Job='%s' ", esc);
447 append_filter(where, tmp);
448 }
449
450 if (type == INCOMPLETE_JOBS && jr->JobStatus == JS_FatalError) {
451 Mmsg(tmp, " Job.JobStatus IN ('E', 'f') ");
452 append_filter(where, tmp);
453
454 } else if (jr->JobStatus) {
455 Mmsg(tmp, " Job.JobStatus='%c' ", jr->JobStatus);
456 append_filter(where, tmp);
457 }
458
459 if (jr->JobType) {
460 Mmsg(tmp, " Job.Type='%c' ", jr->JobType);
461 append_filter(where, tmp);
462 }
463
464 if (jr->JobErrors > 0) {
465 Mmsg(tmp, " Job.JobErrors > 0 ");
466 append_filter(where, tmp);
467 }
468
469 if (jr->ClientId > 0) {
470 Mmsg(tmp, " Job.ClientId=%s ", edit_int64(jr->ClientId, ed1));
471 append_filter(where, tmp);
472 }
473
474 switch (type) {
475 case VERT_LIST:
476 Mmsg(cmd,
477 "SELECT JobId,Job,Job.Name,PurgedFiles,Type,Level,"
478 "Job.ClientId,Client.Name as ClientName,JobStatus,SchedTime,"
479 "StartTime,EndTime,RealEndTime,JobTDate,"
480 "VolSessionId,VolSessionTime,JobFiles,JobBytes,ReadBytes,JobErrors,"
481 "JobMissingFiles,Job.PoolId,Pool.Name as PoolName,PriorJobId,"
482 "Job.FileSetId,FileSet.FileSet,Job.HasBase,Job.HasCache,Job.Comment "
483 "FROM Job JOIN Client USING (ClientId) LEFT JOIN Pool USING (PoolId) "
484 "LEFT JOIN FileSet USING (FileSetId) %s "
485 "ORDER BY StartTime %s %s", where, order, limit);
486 break;
487 case HORZ_LIST:
488 Mmsg(cmd,
489 "SELECT JobId,Name,StartTime,Type,Level,JobFiles,JobBytes,JobStatus "
490 "FROM Job %s ORDER BY StartTime %s,JobId %s %s", where, order, order, limit);
491 break;
492 case INCOMPLETE_JOBS:
493 Mmsg(cmd,
494 "SELECT JobId,Name,StartTime,Type,Level,JobFiles,JobBytes,JobStatus "
495 "FROM Job %s ORDER BY StartTime %s,JobId %s %s",
496 where, order, order, limit);
497 break;
498 default:
499 break;
500 }
501
502 free_pool_memory(tmp);
503 free_pool_memory(where);
504
505 Dmsg1(100, "SQL: %s\n", cmd);
506 if (!QueryDB(jcr, cmd)) {
507 bdb_unlock();
508 return NULL;
509 }
510 if (type == INCOMPLETE_JOBS) {
511 SQL_ROW row;
512 list = New(alist(10));
513 sql_data_seek(0);
514 for (int i=0; (row=sql_fetch_row()) != NULL; i++) {
515 list->append(bstrdup(row[0]));
516 }
517 }
518 sql_data_seek(0);
519 list_result(jcr, this, sendit, ctx, type);
520 sql_free_result();
521 bdb_unlock();
522 return list;
523 }
524
525 /*
526 * List Job totals
527 *
528 */
bdb_list_job_totals(JCR * jcr,JOB_DBR * jr,DB_LIST_HANDLER * sendit,void * ctx)529 void BDB::bdb_list_job_totals(JCR *jcr, JOB_DBR *jr, DB_LIST_HANDLER *sendit, void *ctx)
530 {
531 bdb_lock();
532
533 /* List by Job */
534 Mmsg(cmd, "SELECT count(*) AS Jobs,sum(JobFiles) "
535 "AS Files,sum(JobBytes) AS Bytes,Name AS Job FROM Job GROUP BY Name");
536
537 if (!QueryDB(jcr, cmd)) {
538 bdb_unlock();
539 return;
540 }
541
542 list_result(jcr, this, sendit, ctx, HORZ_LIST);
543
544 sql_free_result();
545
546 /* Do Grand Total */
547 Mmsg(cmd, "SELECT count(*) AS Jobs,sum(JobFiles) "
548 "AS Files,sum(JobBytes) As Bytes FROM Job");
549
550 if (!QueryDB(jcr, cmd)) {
551 bdb_unlock();
552 return;
553 }
554
555 list_result(jcr, this, sendit, ctx, HORZ_LIST);
556
557 sql_free_result();
558 bdb_unlock();
559 }
560
561 /* List all file records from a job
562 * "deleted" values are described just below
563 */
bdb_list_files_for_job(JCR * jcr,JobId_t jobid,int deleted,DB_LIST_HANDLER * sendit,void * ctx)564 void BDB::bdb_list_files_for_job(JCR *jcr, JobId_t jobid, int deleted, DB_LIST_HANDLER *sendit, void *ctx)
565 {
566 char ed1[50];
567 const char *opt;
568 LIST_CTX lctx(jcr, this, sendit, ctx, HORZ_LIST);
569
570 switch (deleted) {
571 case 0: /* Show only actual files */
572 opt = " AND FileIndex > 0 ";
573 break;
574 case 1: /* Show only deleted files */
575 opt = " AND FileIndex <= 0 ";
576 break;
577 default: /* Show everything */
578 opt = "";
579 break;
580 }
581
582 bdb_lock();
583
584 /*
585 * MySQL is different with no || operator
586 */
587 if (bdb_get_type_index() == SQL_TYPE_MYSQL) {
588 Mmsg(cmd, "SELECT CONCAT(Path.Path,Filename.Name) AS Filename "
589 "FROM (SELECT PathId, FilenameId FROM File WHERE JobId=%s %s "
590 "UNION ALL "
591 "SELECT PathId, FilenameId "
592 "FROM BaseFiles JOIN File "
593 "ON (BaseFiles.FileId = File.FileId) "
594 "WHERE BaseFiles.JobId = %s"
595 ") AS F, Filename,Path "
596 "WHERE Filename.FilenameId=F.FilenameId "
597 "AND Path.PathId=F.PathId",
598 edit_int64(jobid, ed1), opt, ed1);
599 } else {
600 Mmsg(cmd, "SELECT Path.Path||Filename.Name AS Filename "
601 "FROM (SELECT PathId, FilenameId FROM File WHERE JobId=%s %s "
602 "UNION ALL "
603 "SELECT PathId, FilenameId "
604 "FROM BaseFiles JOIN File "
605 "ON (BaseFiles.FileId = File.FileId) "
606 "WHERE BaseFiles.JobId = %s"
607 ") AS F, Filename,Path "
608 "WHERE Filename.FilenameId=F.FilenameId "
609 "AND Path.PathId=F.PathId",
610 edit_int64(jobid, ed1), opt, ed1);
611 }
612 Dmsg1(100, "q=%s\n", cmd);
613 if (!bdb_big_sql_query(cmd, list_result, &lctx)) {
614 bdb_unlock();
615 return;
616 }
617
618 lctx.send_dashes();
619
620 sql_free_result();
621 bdb_unlock();
622 }
623
bdb_list_base_files_for_job(JCR * jcr,JobId_t jobid,DB_LIST_HANDLER * sendit,void * ctx)624 void BDB::bdb_list_base_files_for_job(JCR *jcr, JobId_t jobid, DB_LIST_HANDLER *sendit, void *ctx)
625 {
626 char ed1[50];
627 LIST_CTX lctx(jcr, this, sendit, ctx, HORZ_LIST);
628
629 bdb_lock();
630
631 /*
632 * Stupid MySQL is NON-STANDARD !
633 */
634 if (bdb_get_type_index() == SQL_TYPE_MYSQL) {
635 Mmsg(cmd, "SELECT CONCAT(Path.Path,Filename.Name) AS Filename "
636 "FROM BaseFiles, File, Filename, Path "
637 "WHERE BaseFiles.JobId=%s AND BaseFiles.BaseJobId = File.JobId "
638 "AND BaseFiles.FileId = File.FileId "
639 "AND Filename.FilenameId=File.FilenameId "
640 "AND Path.PathId=File.PathId",
641 edit_int64(jobid, ed1));
642 } else {
643 Mmsg(cmd, "SELECT Path.Path||Filename.Name AS Filename "
644 "FROM BaseFiles, File, Filename, Path "
645 "WHERE BaseFiles.JobId=%s AND BaseFiles.BaseJobId = File.JobId "
646 "AND BaseFiles.FileId = File.FileId "
647 "AND Filename.FilenameId=File.FilenameId "
648 "AND Path.PathId=File.PathId",
649 edit_int64(jobid, ed1));
650 }
651
652 if (!bdb_big_sql_query(cmd, list_result, &lctx)) {
653 bdb_unlock();
654 return;
655 }
656
657 lctx.send_dashes();
658
659 sql_free_result();
660 bdb_unlock();
661 }
662
bdb_list_snapshot_records(JCR * jcr,SNAPSHOT_DBR * sdbr,DB_LIST_HANDLER * sendit,void * ctx,e_list_type type)663 void BDB::bdb_list_snapshot_records(JCR *jcr, SNAPSHOT_DBR *sdbr,
664 DB_LIST_HANDLER *sendit, void *ctx, e_list_type type)
665 {
666 POOLMEM *filter = get_pool_memory(PM_MESSAGE);
667 POOLMEM *tmp = get_pool_memory(PM_MESSAGE);
668 POOLMEM *esc = get_pool_memory(PM_MESSAGE);
669 char ed1[50];
670
671 bdb_lock();
672 *filter = 0;
673
674 if (sdbr->Name[0]) {
675 bdb_escape_string(jcr, esc, sdbr->Name, strlen(sdbr->Name));
676 Mmsg(tmp, "Name='%s'", esc);
677 append_filter(filter, tmp);
678 }
679 if (sdbr->SnapshotId > 0) {
680 Mmsg(tmp, "Snapshot.SnapshotId=%d", sdbr->SnapshotId);
681 append_filter(filter, tmp);
682 }
683 if (sdbr->ClientId > 0) {
684 Mmsg(tmp, "Snapshot.ClientId=%d", sdbr->ClientId);
685 append_filter(filter, tmp);
686 }
687 if (sdbr->JobId > 0) {
688 Mmsg(tmp, "Snapshot.JobId=%d", sdbr->JobId);
689 append_filter(filter, tmp);
690 }
691 if (*sdbr->Client) {
692 bdb_escape_string(jcr, esc, sdbr->Client, strlen(sdbr->Client));
693 Mmsg(tmp, "Client.Name='%s'", esc);
694 append_filter(filter, tmp);
695 }
696 if (sdbr->Device && *(sdbr->Device)) {
697 esc = check_pool_memory_size(esc, strlen(sdbr->Device) * 2 + 1);
698 bdb_escape_string(jcr, esc, sdbr->Device, strlen(sdbr->Device));
699 Mmsg(tmp, "Device='%s'", esc);
700 append_filter(filter, tmp);
701 }
702 if (*sdbr->Type) {
703 bdb_escape_string(jcr, esc, sdbr->Type, strlen(sdbr->Type));
704 Mmsg(tmp, "Type='%s'", esc);
705 append_filter(filter, tmp);
706 }
707 if (*sdbr->created_before) {
708 bdb_escape_string(jcr, esc, sdbr->created_before, strlen(sdbr->created_before));
709 Mmsg(tmp, "CreateDate <= '%s'", esc);
710 append_filter(filter, tmp);
711 }
712 if (*sdbr->created_after) {
713 bdb_escape_string(jcr, esc, sdbr->created_after, strlen(sdbr->created_after));
714 Mmsg(tmp, "CreateDate >= '%s'", esc);
715 append_filter(filter, tmp);
716 }
717 if (sdbr->expired) {
718 Mmsg(tmp, "CreateTDate < (%s - Retention)", edit_int64(time(NULL), ed1));
719 append_filter(filter, tmp);
720 }
721 if (*sdbr->CreateDate) {
722 bdb_escape_string(jcr, esc, sdbr->CreateDate, strlen(sdbr->CreateDate));
723 Mmsg(tmp, "CreateDate = '%s'", esc);
724 append_filter(filter, tmp);
725 }
726
727 if (sdbr->sorted_client) {
728 pm_strcat(filter, " ORDER BY Client.Name, SnapshotId DESC");
729
730 } else {
731 pm_strcat(filter, " ORDER BY SnapshotId DESC");
732 }
733
734 if (type == VERT_LIST || type == ARG_LIST) {
735 Mmsg(cmd, "SELECT SnapshotId, Snapshot.Name, CreateDate, Client.Name AS Client, "
736 "FileSet.FileSet AS FileSet, JobId, Volume, Device, Type, Retention, Comment "
737 "FROM Snapshot JOIN Client USING (ClientId) LEFT JOIN FileSet USING (FileSetId) %s", filter);
738
739 } else if (type == HORZ_LIST) {
740 Mmsg(cmd, "SELECT SnapshotId, Snapshot.Name, CreateDate, Client.Name AS Client, "
741 "Device, Type "
742 "FROM Snapshot JOIN Client USING (ClientId) %s", filter);
743 }
744
745 if (!QueryDB(jcr, cmd)) {
746 goto bail_out;
747 }
748
749 list_result(jcr, this, sendit, ctx, type);
750
751 bail_out:
752 sql_free_result();
753 bdb_unlock();
754
755 free_pool_memory(filter);
756 free_pool_memory(esc);
757 free_pool_memory(tmp);
758 }
759
760 #endif /* HAVE_SQLITE3 || HAVE_MYSQL || HAVE_POSTGRESQL */
761