1 /*
2 BAREOS® - Backup Archiving REcovery Open Sourced
3
4 Copyright (C) 2000-2012 Free Software Foundation Europe e.V.
5 Copyright (C) 2011-2016 Planets Communications B.V.
6 Copyright (C) 2013-2019 Bareos GmbH & Co. KG
7
8 This program is Free Software; you can redistribute it and/or
9 modify it under the terms of version three of the GNU Affero 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 Affero General Public License for more details.
17
18 You should have received a copy of the GNU Affero 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 /*
24 * Kern Sibbald, March 2000
25 */
26 /**
27 * @file
28 * BAREOS Catalog Database Update record interface routines
29 */
30
31 #include "include/bareos.h"
32
33 #if HAVE_SQLITE3 || HAVE_MYSQL || HAVE_POSTGRESQL || HAVE_INGRES || HAVE_DBI
34
35 # include "cats.h"
36 # include "lib/edit.h"
37
38 /* -----------------------------------------------------------------------
39 *
40 * Generic Routines (or almost generic)
41 *
42 * -----------------------------------------------------------------------
43 */
44
45 /* -----------------------------------------------------------------------
46 *
47 * Generic Routines (or almost generic)
48 *
49 * -----------------------------------------------------------------------
50 */
51 /* Update the attributes record by adding the file digest */
AddDigestToFileRecord(JobControlRecord * jcr,FileId_t FileId,char * digest,int type)52 bool BareosDb::AddDigestToFileRecord(JobControlRecord* jcr,
53 FileId_t FileId,
54 char* digest,
55 int type)
56 {
57 bool retval;
58 char ed1[50];
59 int len = strlen(digest);
60
61 DbLock(this);
62 esc_name = CheckPoolMemorySize(esc_name, len * 2 + 1);
63 EscapeString(jcr, esc_name, digest, len);
64 Mmsg(cmd, "UPDATE File SET MD5='%s' WHERE FileId=%s", esc_name,
65 edit_int64(FileId, ed1));
66 retval = UPDATE_DB(jcr, cmd);
67 DbUnlock(this);
68
69 return retval;
70 }
71
72 /* Mark the file record as being visited during database
73 * verify compare. Stuff JobId into the MarkId field
74 */
MarkFileRecord(JobControlRecord * jcr,FileId_t FileId,JobId_t JobId)75 bool BareosDb::MarkFileRecord(JobControlRecord* jcr,
76 FileId_t FileId,
77 JobId_t JobId)
78 {
79 bool retval;
80 char ed1[50], ed2[50];
81
82 DbLock(this);
83 Mmsg(cmd, "UPDATE File SET MarkId=%s WHERE FileId=%s", edit_int64(JobId, ed1),
84 edit_int64(FileId, ed2));
85 retval = UPDATE_DB(jcr, cmd);
86 DbUnlock(this);
87
88 return retval;
89 }
90
91 /**
92 * Update the Job record at start of Job
93 *
94 * Returns: false on failure
95 * true on success
96 */
UpdateJobStartRecord(JobControlRecord * jcr,JobDbRecord * jr)97 bool BareosDb::UpdateJobStartRecord(JobControlRecord* jcr, JobDbRecord* jr)
98 {
99 char dt[MAX_TIME_LENGTH];
100 time_t stime;
101 btime_t JobTDate;
102 bool retval;
103 char ed1[50], ed2[50], ed3[50], ed4[50], ed5[50];
104
105 stime = jr->StartTime;
106 bstrutime(dt, sizeof(dt), stime);
107 JobTDate = (btime_t)stime;
108
109 DbLock(this);
110 Mmsg(cmd,
111 "UPDATE Job SET JobStatus='%c',Level='%c',StartTime='%s',"
112 "ClientId=%s,JobTDate=%s,PoolId=%s,FileSetId=%s WHERE JobId=%s",
113 (char)(jcr->JobStatus), (char)(jr->JobLevel), dt,
114 edit_int64(jr->ClientId, ed1), edit_uint64(JobTDate, ed2),
115 edit_int64(jr->PoolId, ed3), edit_int64(jr->FileSetId, ed4),
116 edit_int64(jr->JobId, ed5));
117
118 retval = UPDATE_DB(jcr, cmd);
119 changes = 0;
120 DbUnlock(this);
121 return retval;
122 }
123
124 /**
125 * Update Long term statistics with all jobs that were run before age seconds
126 */
UpdateStats(JobControlRecord * jcr,utime_t age)127 int BareosDb::UpdateStats(JobControlRecord* jcr, utime_t age)
128 {
129 char ed1[30];
130 int rows;
131 utime_t now = (utime_t)time(NULL);
132
133 DbLock(this);
134
135 edit_uint64(now - age, ed1);
136 FillQuery(SQL_QUERY::fill_jobhisto, ed1);
137 if (QUERY_DB(jcr, cmd)) {
138 rows = SqlAffectedRows();
139 } else {
140 rows = -1;
141 }
142
143 DbUnlock(this);
144 return rows;
145 }
146
147 /**
148 * Update the Job record at end of Job
149 *
150 * Returns: false on failure
151 * true on success
152 */
UpdateJobEndRecord(JobControlRecord * jcr,JobDbRecord * jr)153 bool BareosDb::UpdateJobEndRecord(JobControlRecord* jcr, JobDbRecord* jr)
154 {
155 bool retval;
156 char dt[MAX_TIME_LENGTH];
157 char rdt[MAX_TIME_LENGTH];
158 time_t ttime;
159 char ed1[30], ed2[30], ed3[50], ed4[50];
160 btime_t JobTDate;
161 char PriorJobId[50];
162
163 if (jr->PriorJobId) {
164 bstrncpy(PriorJobId, edit_int64(jr->PriorJobId, ed1), sizeof(PriorJobId));
165 } else {
166 bstrncpy(PriorJobId, "0", sizeof(PriorJobId));
167 }
168
169 ttime = jr->EndTime;
170 bstrutime(dt, sizeof(dt), ttime);
171
172 if (jr->RealEndTime < jr->EndTime) { jr->RealEndTime = jr->EndTime; }
173 ttime = jr->RealEndTime;
174 bstrutime(rdt, sizeof(rdt), ttime);
175
176 JobTDate = ttime;
177
178 DbLock(this);
179 Mmsg(
180 cmd,
181 "UPDATE Job SET JobStatus='%c',Level='%c',EndTime='%s',"
182 "ClientId=%u,JobBytes=%s,ReadBytes=%s,JobFiles=%u,JobErrors=%u,"
183 "VolSessionId=%u,"
184 "VolSessionTime=%u,PoolId=%u,FileSetId=%u,JobTDate=%s,"
185 "RealEndTime='%s',PriorJobId=%s,HasBase=%u,PurgedFiles=%u WHERE JobId=%s",
186 (char)(jr->JobStatus), (char)(jr->JobLevel), dt, jr->ClientId,
187 edit_uint64(jr->JobBytes, ed1), edit_uint64(jr->ReadBytes, ed4),
188 jr->JobFiles, jr->JobErrors, jr->VolSessionId, jr->VolSessionTime,
189 jr->PoolId, jr->FileSetId, edit_uint64(JobTDate, ed2), rdt, PriorJobId,
190 jr->HasBase, jr->PurgedFiles, edit_int64(jr->JobId, ed3));
191
192 retval = UPDATE_DB(jcr, cmd);
193
194 DbUnlock(this);
195 return retval;
196 }
197
198 /**
199 * Update Client record
200 * Returns: false on failure
201 * true on success
202 */
UpdateClientRecord(JobControlRecord * jcr,ClientDbRecord * cr)203 bool BareosDb::UpdateClientRecord(JobControlRecord* jcr, ClientDbRecord* cr)
204 {
205 bool retval = false;
206 char ed1[50], ed2[50];
207 char esc_clientname[MAX_ESCAPE_NAME_LENGTH];
208 char esc_uname[MAX_ESCAPE_NAME_LENGTH];
209 ClientDbRecord tcr;
210
211 DbLock(this);
212 tcr = *cr;
213 if (!CreateClientRecord(jcr, &tcr)) { goto bail_out; }
214
215 EscapeString(jcr, esc_clientname, cr->Name, strlen(cr->Name));
216 EscapeString(jcr, esc_uname, cr->Uname, strlen(cr->Uname));
217 Mmsg(cmd,
218 "UPDATE Client SET AutoPrune=%d,FileRetention=%s,JobRetention=%s,"
219 "Uname='%s' WHERE Name='%s'",
220 cr->AutoPrune, edit_uint64(cr->FileRetention, ed1),
221 edit_uint64(cr->JobRetention, ed2), esc_uname, esc_clientname);
222
223 retval = UPDATE_DB(jcr, cmd);
224
225 bail_out:
226 DbUnlock(this);
227 return retval;
228 }
229
230 /**
231 * Update Counters record
232 * Returns: false on failure
233 * true on success
234 */
UpdateCounterRecord(JobControlRecord * jcr,CounterDbRecord * cr)235 bool BareosDb::UpdateCounterRecord(JobControlRecord* jcr, CounterDbRecord* cr)
236 {
237 bool retval;
238 char esc[MAX_ESCAPE_NAME_LENGTH];
239
240 DbLock(this);
241
242 EscapeString(jcr, esc, cr->Counter, strlen(cr->Counter));
243 FillQuery(SQL_QUERY::update_counter_values, cr->MinValue, cr->MaxValue,
244 cr->CurrentValue, cr->WrapCounter, esc);
245 retval = UPDATE_DB(jcr, cmd);
246
247 DbUnlock(this);
248 return retval;
249 }
250
UpdatePoolRecord(JobControlRecord * jcr,PoolDbRecord * pr)251 bool BareosDb::UpdatePoolRecord(JobControlRecord* jcr, PoolDbRecord* pr)
252 {
253 bool retval;
254 char ed1[50], ed2[50], ed3[50], ed4[50], ed5[50], ed6[50];
255 char esc[MAX_ESCAPE_NAME_LENGTH];
256
257 DbLock(this);
258 EscapeString(jcr, esc, pr->LabelFormat, strlen(pr->LabelFormat));
259
260 Mmsg(cmd, "SELECT count(*) from Media WHERE PoolId=%s",
261 edit_int64(pr->PoolId, ed4));
262 pr->NumVols = GetSqlRecordMax(jcr);
263 Dmsg1(400, "NumVols=%d\n", pr->NumVols);
264
265 Mmsg(cmd,
266 "UPDATE Pool SET NumVols=%u,MaxVols=%u,UseOnce=%d,UseCatalog=%d,"
267 "AcceptAnyVolume=%d,VolRetention='%s',VolUseDuration='%s',"
268 "MaxVolJobs=%u,MaxVolFiles=%u,MaxVolBytes=%s,Recycle=%d,"
269 "AutoPrune=%d,LabelType=%d,LabelFormat='%s',RecyclePoolId=%s,"
270 "ScratchPoolId=%s,ActionOnPurge=%d,MinBlockSize=%d,MaxBlockSize=%d "
271 "WHERE PoolId=%s",
272 pr->NumVols, pr->MaxVols, pr->UseOnce, pr->UseCatalog,
273 pr->AcceptAnyVolume, edit_uint64(pr->VolRetention, ed1),
274 edit_uint64(pr->VolUseDuration, ed2), pr->MaxVolJobs, pr->MaxVolFiles,
275 edit_uint64(pr->MaxVolBytes, ed3), pr->Recycle, pr->AutoPrune,
276 pr->LabelType, esc, edit_int64(pr->RecyclePoolId, ed5),
277 edit_int64(pr->ScratchPoolId, ed6), pr->ActionOnPurge, pr->MinBlocksize,
278 pr->MaxBlocksize, ed4);
279 retval = UPDATE_DB(jcr, cmd);
280 DbUnlock(this);
281 return retval;
282 }
283
UpdateStorageRecord(JobControlRecord * jcr,StorageDbRecord * sr)284 bool BareosDb::UpdateStorageRecord(JobControlRecord* jcr, StorageDbRecord* sr)
285 {
286 bool retval;
287 char ed1[50];
288
289 DbLock(this);
290 Mmsg(cmd, "UPDATE Storage SET AutoChanger=%d WHERE StorageId=%s",
291 sr->AutoChanger, edit_int64(sr->StorageId, ed1));
292
293 retval = UPDATE_DB(jcr, cmd);
294 DbUnlock(this);
295 return retval;
296 }
297
298
299 /**
300 * Update the Media Record at end of Session
301 *
302 * Returns: false on failure
303 * true on success
304 */
UpdateMediaRecord(JobControlRecord * jcr,MediaDbRecord * mr)305 bool BareosDb::UpdateMediaRecord(JobControlRecord* jcr, MediaDbRecord* mr)
306 {
307 bool retval;
308 char dt[MAX_TIME_LENGTH];
309 time_t ttime;
310 char ed1[50], ed2[50], ed3[50], ed4[50];
311 char ed5[50], ed6[50], ed7[50], ed8[50];
312 char ed9[50], ed10[50], ed11[50];
313 char esc_medianame[MAX_ESCAPE_NAME_LENGTH];
314 char esc_status[MAX_ESCAPE_NAME_LENGTH];
315
316 Dmsg1(100, "update_media: FirstWritten=%d\n", mr->FirstWritten);
317 DbLock(this);
318 EscapeString(jcr, esc_medianame, mr->VolumeName, strlen(mr->VolumeName));
319 EscapeString(jcr, esc_status, mr->VolStatus, strlen(mr->VolStatus));
320
321 if (mr->set_first_written) {
322 Dmsg1(400, "Set FirstWritten Vol=%s\n", mr->VolumeName);
323 ttime = mr->FirstWritten;
324 bstrutime(dt, sizeof(dt), ttime);
325 Mmsg(cmd,
326 "UPDATE Media SET FirstWritten='%s'"
327 " WHERE VolumeName='%s'",
328 dt, esc_medianame);
329 retval = UPDATE_DB(jcr, cmd);
330 Dmsg1(400, "Firstwritten=%d\n", mr->FirstWritten);
331 }
332
333 /* Label just done? */
334 if (mr->set_label_date) {
335 ttime = mr->LabelDate;
336 if (ttime == 0) { ttime = time(NULL); }
337 bstrutime(dt, sizeof(dt), ttime);
338 Mmsg(cmd,
339 "UPDATE Media SET LabelDate='%s' "
340 "WHERE VolumeName='%s'",
341 dt, esc_medianame);
342 UPDATE_DB(jcr, cmd);
343 }
344
345 if (mr->LastWritten != 0) {
346 ttime = mr->LastWritten;
347 bstrutime(dt, sizeof(dt), ttime);
348 Mmsg(cmd,
349 "UPDATE Media Set LastWritten='%s' "
350 "WHERE VolumeName='%s'",
351 dt, esc_medianame);
352 UPDATE_DB(jcr, cmd);
353 }
354
355 Mmsg(cmd,
356 "UPDATE Media SET VolJobs=%u,"
357 "VolFiles=%u,VolBlocks=%u,VolBytes=%s,VolMounts=%u,VolErrors=%u,"
358 "VolWrites=%u,MaxVolBytes=%s,VolStatus='%s',"
359 "Slot=%d,InChanger=%d,VolReadTime=%s,VolWriteTime=%s,"
360 "LabelType=%d,StorageId=%s,PoolId=%s,VolRetention=%s,VolUseDuration=%s,"
361 "MaxVolJobs=%d,MaxVolFiles=%d,Enabled=%d,LocationId=%s,"
362 "ScratchPoolId=%s,RecyclePoolId=%s,RecycleCount=%d,Recycle=%d,"
363 "ActionOnPurge=%d,"
364 "MinBlocksize=%u,MaxBlocksize=%u"
365 " WHERE VolumeName='%s'",
366 mr->VolJobs, mr->VolFiles, mr->VolBlocks, edit_uint64(mr->VolBytes, ed1),
367 mr->VolMounts, mr->VolErrors, mr->VolWrites,
368 edit_uint64(mr->MaxVolBytes, ed2), esc_status, mr->Slot, mr->InChanger,
369 edit_int64(mr->VolReadTime, ed3), edit_int64(mr->VolWriteTime, ed4),
370 mr->LabelType, edit_int64(mr->StorageId, ed5),
371 edit_int64(mr->PoolId, ed6), edit_uint64(mr->VolRetention, ed7),
372 edit_uint64(mr->VolUseDuration, ed8), mr->MaxVolJobs, mr->MaxVolFiles,
373 mr->Enabled, edit_uint64(mr->LocationId, ed9),
374 edit_uint64(mr->ScratchPoolId, ed10),
375 edit_uint64(mr->RecyclePoolId, ed11), mr->RecycleCount, mr->Recycle,
376 mr->ActionOnPurge, mr->MinBlocksize, mr->MaxBlocksize, esc_medianame);
377
378 Dmsg1(400, "%s\n", cmd);
379
380 retval = UPDATE_DB(jcr, cmd);
381
382 /*
383 * Make sure InChanger is 0 for any record having the same Slot
384 */
385 MakeInchangerUnique(jcr, mr);
386
387 DbUnlock(this);
388
389 return retval;
390 }
391
392 /**
393 * Update the Media Record Default values from Pool
394 *
395 * Returns: false on failure
396 * true on success
397 */
UpdateMediaDefaults(JobControlRecord * jcr,MediaDbRecord * mr)398 bool BareosDb::UpdateMediaDefaults(JobControlRecord* jcr, MediaDbRecord* mr)
399 {
400 bool retval;
401 char ed1[50], ed2[50], ed3[50], ed4[50], ed5[50];
402 char esc[MAX_ESCAPE_NAME_LENGTH];
403
404 DbLock(this);
405 if (mr->VolumeName[0]) {
406 EscapeString(jcr, esc, mr->VolumeName, strlen(mr->VolumeName));
407 Mmsg(cmd,
408 "UPDATE Media SET "
409 "ActionOnPurge=%d,Recycle=%d,VolRetention=%s,VolUseDuration=%s,"
410 "MaxVolJobs=%u,MaxVolFiles=%u,MaxVolBytes=%s,RecyclePoolId=%s,"
411 "MinBlocksize=%d,MaxBlocksize=%d"
412 " WHERE VolumeName='%s'",
413 mr->ActionOnPurge, mr->Recycle, edit_uint64(mr->VolRetention, ed1),
414 edit_uint64(mr->VolUseDuration, ed2), mr->MaxVolJobs, mr->MaxVolFiles,
415 edit_uint64(mr->MaxVolBytes, ed3), edit_uint64(mr->RecyclePoolId, ed4),
416 mr->MinBlocksize, mr->MaxBlocksize, esc);
417 } else {
418 Mmsg(cmd,
419 "UPDATE Media SET "
420 "ActionOnPurge=%d,Recycle=%d,VolRetention=%s,VolUseDuration=%s,"
421 "MaxVolJobs=%u,MaxVolFiles=%u,MaxVolBytes=%s,RecyclePoolId=%s,"
422 "MinBlocksize=%d,MaxBlocksize=%d"
423 " WHERE PoolId=%s",
424 mr->ActionOnPurge, mr->Recycle, edit_uint64(mr->VolRetention, ed1),
425 edit_uint64(mr->VolUseDuration, ed2), mr->MaxVolJobs, mr->MaxVolFiles,
426 edit_uint64(mr->MaxVolBytes, ed3), edit_int64(mr->RecyclePoolId, ed4),
427 mr->MinBlocksize, mr->MaxBlocksize, edit_int64(mr->PoolId, ed5));
428 }
429
430 Dmsg1(400, "%s\n", cmd);
431
432 retval = UPDATE_DB(jcr, cmd);
433
434 DbUnlock(this);
435 return retval;
436 }
437
438
439 /**
440 * If we have a non-zero InChanger, ensure that no other Media
441 * record has InChanger set on the same Slot.
442 *
443 * This routine assumes the database is already locked.
444 */
MakeInchangerUnique(JobControlRecord * jcr,MediaDbRecord * mr)445 void BareosDb::MakeInchangerUnique(JobControlRecord* jcr, MediaDbRecord* mr)
446 {
447 char ed1[50], ed2[50];
448 char esc[MAX_ESCAPE_NAME_LENGTH];
449 if (mr->InChanger != 0 && mr->Slot != 0 && mr->StorageId != 0) {
450 if (mr->MediaId != 0) {
451 Mmsg(cmd,
452 "UPDATE Media SET InChanger=0, Slot=0 WHERE "
453 "Slot=%d AND StorageId=%s AND MediaId!=%s",
454 mr->Slot, edit_int64(mr->StorageId, ed1),
455 edit_int64(mr->MediaId, ed2));
456
457 } else if (*mr->VolumeName) {
458 EscapeString(jcr, esc, mr->VolumeName, strlen(mr->VolumeName));
459 Mmsg(cmd,
460 "UPDATE Media SET InChanger=0, Slot=0 WHERE "
461 "Slot=%d AND StorageId=%s AND VolumeName!='%s'",
462 mr->Slot, edit_int64(mr->StorageId, ed1), esc);
463
464 } else { /* used by ua_label to reset all volume with this slot */
465 Mmsg(cmd,
466 "UPDATE Media SET InChanger=0, Slot=0 WHERE "
467 "Slot=%d AND StorageId=%s",
468 mr->Slot, edit_int64(mr->StorageId, ed1), mr->VolumeName);
469 }
470 Dmsg1(100, "%s\n", cmd);
471 UPDATE_DB_NO_AFR(jcr, cmd);
472 }
473 }
474
475 /**
476 * Update Quota record
477 *
478 * Returns: false on failure
479 * true on success
480 */
UpdateQuotaGracetime(JobControlRecord * jcr,JobDbRecord * jr)481 bool BareosDb::UpdateQuotaGracetime(JobControlRecord* jcr, JobDbRecord* jr)
482 {
483 bool retval;
484 char ed1[50], ed2[50];
485 time_t now = time(NULL);
486
487 DbLock(this);
488
489 Mmsg(cmd, "UPDATE Quota SET GraceTime=%s WHERE ClientId='%s'",
490 edit_uint64(now, ed1), edit_uint64(jr->ClientId, ed2));
491
492 retval = UPDATE_DB(jcr, cmd);
493
494 DbUnlock(this);
495
496 return retval;
497 }
498
499 /**
500 * Update Quota Softlimit
501 *
502 * Returns: false on failure
503 * true on success
504 */
UpdateQuotaSoftlimit(JobControlRecord * jcr,JobDbRecord * jr)505 bool BareosDb::UpdateQuotaSoftlimit(JobControlRecord* jcr, JobDbRecord* jr)
506 {
507 bool retval;
508 char ed1[50], ed2[50];
509
510 DbLock(this);
511
512 Mmsg(cmd, "UPDATE Quota SET QuotaLimit=%s WHERE ClientId='%s'",
513 edit_uint64((jr->JobSumTotalBytes + jr->JobBytes), ed1),
514 edit_uint64(jr->ClientId, ed2));
515
516 retval = UPDATE_DB(jcr, cmd);
517
518 DbUnlock(this);
519
520 return retval;
521 }
522
523 /**
524 * Reset Quota Gracetime
525 *
526 * Returns: false on failure
527 * true on success
528 */
ResetQuotaRecord(JobControlRecord * jcr,ClientDbRecord * cr)529 bool BareosDb::ResetQuotaRecord(JobControlRecord* jcr, ClientDbRecord* cr)
530 {
531 bool retval;
532 char ed1[50];
533
534 DbLock(this);
535
536 Mmsg(cmd,
537 "UPDATE Quota SET GraceTime='0', QuotaLimit='0' WHERE ClientId='%s'",
538 edit_uint64(cr->ClientId, ed1));
539
540 retval = UPDATE_DB(jcr, cmd);
541
542 DbUnlock(this);
543
544 return retval;
545 }
546
547 /**
548 * Update NDMP level mapping
549 *
550 * Returns: false on failure
551 * true on success
552 */
UpdateNdmpLevelMapping(JobControlRecord * jcr,JobDbRecord * jr,char * filesystem,int level)553 bool BareosDb::UpdateNdmpLevelMapping(JobControlRecord* jcr,
554 JobDbRecord* jr,
555 char* filesystem,
556 int level)
557 {
558 bool retval;
559 char ed1[50], ed2[50], ed3[50];
560
561 DbLock(this);
562
563 esc_name = CheckPoolMemorySize(esc_name, strlen(filesystem) * 2 + 1);
564 EscapeString(jcr, esc_name, filesystem, strlen(filesystem));
565
566 Mmsg(cmd,
567 "UPDATE NDMPLevelMap SET DumpLevel='%s' WHERE "
568 "ClientId='%s' AND FileSetId='%s' AND FileSystem='%s'",
569 edit_uint64(level, ed1), edit_uint64(jr->ClientId, ed2),
570 edit_uint64(jr->FileSetId, ed3), esc_name);
571
572 retval = UPDATE_DB(jcr, cmd);
573
574 DbUnlock(this);
575
576 return retval;
577 }
578 #endif /* HAVE_SQLITE3 || HAVE_MYSQL || HAVE_POSTGRESQL || HAVE_INGRES || \
579 HAVE_DBI */
580