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 * Catalog DB header file 21 * 22 * Written by Kern E. Sibbald 23 * 24 * Anyone who accesses the database will need to include 25 * this file. 26 */ 27 28 #ifndef __CATS_H_ 29 #define __CATS_H_ 1 30 31 /* 32 Here is how database versions work. 33 34 While I am working on a new release with database changes, the 35 update scripts are in the src/cats directory under the names 36 update_xxx_tables.in. Most of the time, I make database updates 37 in one go and immediately update the version, but not always. If 38 there are going to be several updates as is the case with version 39 1.37, then I will often forgo changing the version until the last 40 update otherwise I will end up with too many versions and a lot 41 of confusion. 42 43 When I am pretty sure there will be no more updates, I will 44 change the version from 8 to 9 (in the present case), and when I 45 am 100% sure there will be no more changes, the update script 46 will be copied to the updatedb directory with the correct name 47 (in the present case 8 to 9). 48 */ 49 50 /* Current database version number for all drivers */ 51 #define BDB_VERSION 16 52 53 typedef void (DB_LIST_HANDLER)(void *, const char *); 54 typedef int (DB_RESULT_HANDLER)(void *, int, char **); 55 56 /* What kind of database we have */ 57 typedef enum { 58 SQL_TYPE_MYSQL = 0, 59 SQL_TYPE_POSTGRESQL = 1, 60 SQL_TYPE_SQLITE3 = 2, 61 SQL_TYPE_UNKNOWN = 99 62 } SQL_DBTYPE; 63 64 /* What kind of driver we have */ 65 typedef enum { 66 SQL_DRIVER_TYPE_MYSQL = 0, 67 SQL_DRIVER_TYPE_POSTGRESQL = 1, 68 SQL_DRIVER_TYPE_SQLITE3 = 2 69 } SQL_DRIVER; 70 71 72 /* ============================================================== 73 * 74 * What follows are definitions that are used "globally" for all 75 * the different SQL engines and both inside and external to the 76 * cats directory. 77 */ 78 79 #define faddr_t long 80 81 /* 82 * Generic definition of a sql_row. 83 */ 84 typedef char **SQL_ROW; 85 86 /* 87 * Generic definition of a a sql_field. 88 */ 89 typedef struct sql_field { 90 char *name; /* name of column */ 91 int max_length; /* max length */ 92 uint32_t type; /* type */ 93 uint32_t flags; /* flags */ 94 } SQL_FIELD; 95 96 97 /* 98 * Structure used when calling db_get_query_ids() 99 * allows the subroutine to return a list of ids. 100 */ 101 class dbid_list : public SMARTALLOC { 102 public: 103 DBId_t *DBId; /* array of DBIds */ 104 char *PurgedFiles; /* Array of PurgedFile flags */ 105 int num_ids; /* num of ids actually stored */ 106 int max_ids; /* size of id array */ 107 int num_seen; /* number of ids processed */ 108 int tot_ids; /* total to process */ 109 110 dbid_list(); /* in sql.c */ 111 ~dbid_list(); /* in sql.c */ 112 }; 113 114 /* Job information passed to create job record and update 115 * job record at end of job. Note, although this record 116 * contains all the fields found in the Job database record, 117 * it also contains fields found in the JobMedia record. 118 */ 119 /* Job record */ 120 struct JOB_DBR { 121 JobId_t JobId; 122 char Job[MAX_NAME_LENGTH]; /* Job unique name */ 123 char Name[MAX_NAME_LENGTH]; /* Job base name */ 124 char PriorJob[MAX_NAME_LENGTH]; /* PriorJob name if any */ 125 int JobType; /* actually char(1) */ 126 int JobLevel; /* actually char(1) */ 127 int JobStatus; /* actually char(1) */ 128 DBId_t ClientId; /* Id of client */ 129 DBId_t PoolId; /* Id of pool */ 130 DBId_t FileSetId; /* Id of FileSet */ 131 DBId_t PriorJobId; /* Id of migrated (prior) job */ 132 time_t SchedTime; /* Time job scheduled */ 133 time_t StartTime; /* Job start time */ 134 time_t EndTime; /* Job termination time of orig job */ 135 time_t RealEndTime; /* Job termination time of this job */ 136 utime_t JobTDate; /* Backup time/date in seconds */ 137 uint32_t VolSessionId; 138 uint32_t VolSessionTime; 139 uint32_t JobFiles; 140 uint32_t JobErrors; 141 uint32_t JobMissingFiles; 142 uint64_t JobBytes; 143 uint64_t ReadBytes; 144 int PurgedFiles; 145 int HasBase; 146 147 /* Note, FirstIndex, LastIndex, Start/End File and Block 148 * are only used in the JobMedia record. 149 */ 150 uint32_t FirstIndex; /* First index this Volume */ 151 uint32_t LastIndex; /* Last index this Volume */ 152 uint32_t StartFile; 153 uint32_t EndFile; 154 uint32_t StartBlock; 155 uint32_t EndBlock; 156 157 char cSchedTime[MAX_TIME_LENGTH]; 158 char cStartTime[MAX_TIME_LENGTH]; 159 char cEndTime[MAX_TIME_LENGTH]; 160 char cRealEndTime[MAX_TIME_LENGTH]; 161 /* Extra stuff not in DB */ 162 int order; /* 0 ASC, 1 DESC */ 163 int limit; /* limit records to display */ 164 faddr_t rec_addr; 165 int32_t FileIndex; /* added during Verify */ 166 167 int CorrNbJob; /* used by dbd_get_job_statistics() */ 168 int CorrJobBytes; /* used by dbd_get_job_statistics() */ 169 int CorrJobFiles; /* used by dbd_get_job_statistics() */ 170 }; 171 172 /* Job Media information used to create the media records 173 * for each Volume used for the job. 174 */ 175 /* JobMedia record */ 176 struct JOBMEDIA_DBR { 177 DBId_t JobMediaId; /* record id */ 178 JobId_t JobId; /* JobId */ 179 DBId_t MediaId; /* MediaId */ 180 uint32_t FirstIndex; /* First index this Volume */ 181 uint32_t LastIndex; /* Last index this Volume */ 182 uint32_t StartFile; /* File for start of data */ 183 uint32_t EndFile; /* End file on Volume */ 184 uint32_t StartBlock; /* start block on tape */ 185 uint32_t EndBlock; /* last block */ 186 uint32_t VolIndex; /* Volume seqence no. */ 187 }; 188 189 190 /* Volume Parameter structure */ 191 struct VOL_PARAMS { 192 char VolumeName[MAX_NAME_LENGTH]; /* Volume name */ 193 char MediaType[MAX_NAME_LENGTH]; /* Media Type */ 194 char Storage[MAX_NAME_LENGTH]; /* Storage name */ 195 uint32_t VolIndex; /* Volume seqence no. */ 196 uint32_t FirstIndex; /* First index this Volume */ 197 uint32_t LastIndex; /* Last index this Volume */ 198 int32_t Slot; /* Slot */ 199 uint64_t StartAddr; /* Start address */ 200 uint64_t EndAddr; /* End address */ 201 int32_t InChanger; /* InChanger flag */ 202 }; 203 204 205 /* Attributes record -- NOT same as in database because 206 * in general, this "record" creates multiple database 207 * records (e.g. pathname, filename, fileattributes). 208 */ 209 struct ATTR_DBR { 210 char *fname; /* full path & filename */ 211 char *link; /* link if any */ 212 char *attr; /* attributes statp */ 213 int32_t FileIndex; 214 uint32_t Stream; 215 uint32_t FileType; 216 uint32_t DeltaSeq; 217 JobId_t JobId; 218 DBId_t ClientId; 219 DBId_t PathId; 220 DBId_t FilenameId; 221 FileId_t FileId; 222 char *Digest; 223 int DigestType; 224 }; 225 226 struct ROBJECT_DBR { 227 char *object_name; 228 char *object; 229 char *plugin_name; 230 char *JobIds; 231 uint32_t object_len; 232 uint32_t object_full_len; 233 uint32_t object_index; 234 int32_t object_compression; 235 int32_t FileIndex; 236 uint32_t Stream; 237 uint32_t FileType; 238 JobId_t JobId; 239 DBId_t RestoreObjectId; 240 }; 241 242 243 /* File record -- same format as database */ 244 struct FILE_DBR { 245 FileId_t FileId; 246 int32_t FileIndex; 247 int32_t FileIndex2; 248 JobId_t JobId; 249 DBId_t FilenameId; 250 DBId_t PathId; 251 JobId_t MarkId; 252 uint32_t DeltaSeq; 253 char LStat[256]; 254 char Digest[BASE64_SIZE(CRYPTO_DIGEST_MAX_SIZE)]; 255 int DigestType; /* NO_SIG/MD5_SIG/SHA1_SIG */ 256 }; 257 258 /* Pool record -- same format as database */ 259 class POOL_DBR { 260 public: 261 /* 262 * Do not turn on constructor until all bmemset on POOL_DBR removed 263 * 264 * POOL_DBR() { bmemset(this, 0, sizeof(POOL_DBR)); }; 265 * ~POOL_DBR() { }; 266 */ 267 DBId_t PoolId; 268 char Name[MAX_NAME_LENGTH]; /* Pool name */ 269 uint32_t NumVols; /* total number of volumes */ 270 uint32_t MaxVols; /* max allowed volumes */ 271 int32_t LabelType; /* Bacula/ANSI/IBM */ 272 int32_t UseOnce; /* set to use once only */ 273 int32_t UseCatalog; /* set to use catalog */ 274 int32_t AcceptAnyVolume; /* set to accept any volume sequence */ 275 int32_t AutoPrune; /* set to prune automatically */ 276 int32_t Recycle; /* default Vol recycle flag */ 277 uint32_t ActionOnPurge; /* action on purge, e.g. truncate the disk volume */ 278 utime_t VolRetention; /* retention period in seconds */ 279 utime_t CacheRetention; /* cache retention period in seconds */ 280 utime_t VolUseDuration; /* time in secs volume can be used */ 281 uint32_t MaxVolJobs; /* Max Jobs on Volume */ 282 uint32_t MaxVolFiles; /* Max files on Volume */ 283 uint64_t MaxVolBytes; /* Max bytes on Volume */ 284 DBId_t RecyclePoolId; /* RecyclePool destination when media is purged */ 285 DBId_t ScratchPoolId; /* ScratchPool source when media is needed */ 286 char PoolType[MAX_NAME_LENGTH]; 287 char LabelFormat[MAX_NAME_LENGTH]; 288 /* Extra stuff not in DB */ 289 faddr_t rec_addr; 290 }; 291 292 class DEVICE_DBR { 293 public: 294 DBId_t DeviceId; 295 char Name[MAX_NAME_LENGTH]; /* Device name */ 296 DBId_t MediaTypeId; /* MediaType */ 297 DBId_t StorageId; /* Storage id if autochanger */ 298 uint32_t DevMounts; /* Number of times mounted */ 299 uint32_t DevErrors; /* Number of read/write errors */ 300 uint64_t DevReadBytes; /* Number of bytes read */ 301 uint64_t DevWriteBytes; /* Number of bytew written */ 302 uint64_t DevReadTime; /* time spent reading volume */ 303 uint64_t DevWriteTime; /* time spent writing volume */ 304 uint64_t DevReadTimeSincCleaning; /* read time since cleaning */ 305 uint64_t DevWriteTimeSincCleaning; /* write time since cleaning */ 306 time_t CleaningDate; /* time last cleaned */ 307 utime_t CleaningPeriod; /* time between cleanings */ 308 }; 309 310 class STORAGE_DBR { 311 public: 312 DBId_t StorageId; 313 char Name[MAX_NAME_LENGTH]; /* Device name */ 314 int AutoChanger; /* Set if autochanger */ 315 316 /* Not in database */ 317 bool created; /* set if created by db_create ... */ 318 }; 319 320 class MEDIATYPE_DBR { 321 public: 322 DBId_t MediaTypeId; 323 char MediaType[MAX_NAME_LENGTH]; /* MediaType string */ 324 int ReadOnly; /* Set if read-only */ 325 }; 326 327 /* Media record -- same as the database */ 328 class MEDIA_DBR { 329 public: MEDIA_DBR()330 MEDIA_DBR() { memset(this, 0, sizeof(MEDIA_DBR)); }; ~MEDIA_DBR()331 ~MEDIA_DBR() { }; clear()332 void clear() { memset(this, 0, sizeof(MEDIA_DBR)); }; copy(MEDIA_DBR * omr)333 void copy(MEDIA_DBR *omr) { memcpy(this, omr, sizeof(MEDIA_DBR)); sid_group = NULL; }; 334 335 DBId_t MediaId; /* Unique volume id */ 336 char VolumeName[MAX_NAME_LENGTH]; /* Volume name */ 337 char MediaType[MAX_NAME_LENGTH]; /* Media type */ 338 DBId_t PoolId; /* Pool id */ 339 time_t FirstWritten; /* Time Volume first written this usage */ 340 time_t LastWritten; /* Time Volume last written */ 341 time_t LabelDate; /* Date/Time Volume labeled */ 342 time_t InitialWrite; /* Date/Time Volume first written */ 343 int32_t LabelType; /* Label (Bacula/ANSI/IBM) */ 344 uint32_t VolJobs; /* number of jobs on this medium */ 345 uint32_t VolFiles; /* Number of files */ 346 uint32_t VolBlocks; /* Number of blocks */ 347 uint32_t VolParts; /* Number of cache parts */ 348 uint32_t VolCloudParts; /* Number of cloud parts */ 349 uint32_t VolMounts; /* Number of times mounted */ 350 uint32_t VolErrors; /* Number of read/write errors */ 351 uint64_t VolWrites; /* Number of writes */ 352 uint64_t VolReads; /* Number of reads */ 353 uint64_t VolBytes; /* Number of bytes written */ 354 uint64_t VolABytes; /* Size of aligned volume */ 355 uint64_t VolHoleBytes; /* The size of Holes */ 356 uint32_t VolHoles; /* Number of holes */ 357 uint32_t VolType; /* Device type of where Volume labeled */ 358 uint64_t MaxVolBytes; /* Max bytes to write to Volume */ 359 uint64_t VolCapacityBytes; /* capacity estimate */ 360 uint64_t LastPartBytes; /* Bytes in last part */ 361 uint64_t VolReadTime; /* time spent reading volume */ 362 uint64_t VolWriteTime; /* time spent writing volume */ 363 utime_t VolRetention; /* Volume retention in seconds */ 364 utime_t CacheRetention; /* Cache retention period in second */ 365 utime_t VolUseDuration; /* time in secs volume can be used */ 366 uint32_t ActionOnPurge; /* action on purge, e.g. truncate the disk volume */ 367 uint32_t MaxVolJobs; /* Max Jobs on Volume */ 368 uint32_t MaxVolFiles; /* Max files on Volume */ 369 int32_t Recycle; /* recycle yes/no */ 370 int32_t Slot; /* slot in changer */ 371 int32_t Enabled; /* 0=disabled, 1=enabled, 2=archived */ 372 int32_t InChanger; /* Volume currently in changer */ 373 DBId_t StorageId; /* Storage record Id */ 374 uint32_t EndFile; /* Last file on volume */ 375 uint32_t EndBlock; /* Last block on volume */ 376 uint32_t RecycleCount; /* Number of times recycled */ 377 char VolStatus[20]; /* Volume status */ 378 DBId_t DeviceId; /* Device where Vol last written */ 379 DBId_t LocationId; /* Where Volume is -- user defined */ 380 DBId_t ScratchPoolId; /* Where to move if scratch */ 381 DBId_t RecyclePoolId; /* Where to move when recycled */ 382 /* Extra stuff not in DB */ 383 faddr_t rec_addr; /* found record address */ 384 /* Since the database returns times as strings, this is how we pass 385 * them back. 386 */ 387 char cFirstWritten[MAX_TIME_LENGTH]; /* FirstWritten returned from DB */ 388 char cLastWritten[MAX_TIME_LENGTH]; /* LastWritten returned from DB */ 389 char cLabelDate[MAX_TIME_LENGTH]; /* LabelData returned from DB */ 390 char cInitialWrite[MAX_TIME_LENGTH]; /* InitialWrite returned from DB */ 391 char *exclude_list; /* Optionnal exclude list for db_find_next_volume() */ 392 char *sid_group; /* Storageid group string */ 393 char sid[30]; /* edited StorageId */ 394 bool set_first_written; 395 bool set_label_date; 396 }; 397 398 /* Client record -- same as the database */ 399 struct CLIENT_DBR { 400 DBId_t ClientId; /* Unique Client id */ 401 int AutoPrune; 402 utime_t FileRetention; 403 utime_t JobRetention; 404 char Name[MAX_NAME_LENGTH]; /* Client name */ 405 char Uname[256]; /* Uname for client */ 406 }; 407 408 /* Counter record as in database */ 409 struct COUNTER_DBR { 410 char Counter[MAX_NAME_LENGTH]; 411 int32_t MinValue; 412 int32_t MaxValue; 413 int32_t CurrentValue; 414 char WrapCounter[MAX_NAME_LENGTH]; 415 }; 416 417 418 /* FileSet record -- same as the database */ 419 struct FILESET_DBR { 420 DBId_t FileSetId; /* Unique FileSet id */ 421 char FileSet[MAX_NAME_LENGTH]; /* FileSet name */ 422 char MD5[50]; /* MD5 signature of include/exclude */ 423 time_t CreateTime; /* date created */ 424 /* 425 * This is where we return CreateTime 426 */ 427 char cCreateTime[MAX_TIME_LENGTH]; /* CreateTime as returned from DB */ 428 /* Not in DB but returned by db_create_fileset() */ 429 bool created; /* set when record newly created */ 430 }; 431 432 class SNAPSHOT_DBR { 433 public: SNAPSHOT_DBR()434 SNAPSHOT_DBR() { 435 memset(this, 0, sizeof(SNAPSHOT_DBR)); 436 }; ~SNAPSHOT_DBR()437 ~SNAPSHOT_DBR() { 438 reset(); 439 }; debug(int level)440 void debug(int level) { 441 Dmsg8(DT_SNAPSHOT|level, 442 "Snapshot %s:\n" 443 " Volume: %s\n" 444 " Device: %s\n" 445 " Id: %d\n" 446 " FileSet: %s\n" 447 " CreateDate: %s\n" 448 " Client: %s\n" 449 " Type: %s\n", 450 Name, NPRT(Volume), NPRT(Device), SnapshotId, 451 FileSet, CreateDate, Client, Type); 452 }; as_arg(POOLMEM ** out)453 char *as_arg(POOLMEM **out) { 454 bash_spaces(Name); 455 bash_spaces(Type); 456 457 if (Volume) { 458 bash_spaces(Volume); 459 } 460 if (Device) { 461 bash_spaces(Device); 462 } 463 464 Mmsg(out, "name=%s volume=%s device=%s tdate=%d type=%s", 465 Name, NPRTB(Volume), NPRTB(Device), CreateTDate, Type); 466 467 unbash_spaces(Name); 468 unbash_spaces(Type); 469 if (Volume) { 470 unbash_spaces(Volume); 471 } 472 if (Device) { 473 unbash_spaces(Device); 474 } 475 return *out; 476 }; reset()477 void reset() { 478 if (need_to_free) { 479 if (Volume) { 480 free(Volume); 481 } 482 if (Device) { 483 free(Device); 484 } 485 if (errmsg) { 486 free(errmsg); 487 } 488 errmsg = Volume = Device = NULL; 489 } 490 need_to_free = false; 491 }; 492 bool need_to_free; /* Need to free the internal memory */ 493 /* Used when searching snapshots */ 494 char created_after[MAX_TIME_LENGTH]; 495 char created_before[MAX_TIME_LENGTH]; 496 bool expired; /* Look for CreateTDate > (NOW - Retention) */ 497 bool sorted_client; /* Results sorted by Client, SnapshotId */ 498 int status; /* Status of the snapshot */ 499 500 DBId_t SnapshotId; /* Unique Snapshot ID */ 501 DBId_t JobId; /* Related JobId */ 502 DBId_t FileSetId; /* FileSetId if any */ 503 DBId_t ClientId; /* From which client this snapshot comes */ 504 char Name[MAX_NAME_LENGTH]; /* Snapshot Name */ 505 char FileSet[MAX_NAME_LENGTH];/* FileSet name if any */ 506 char Client[MAX_NAME_LENGTH]; /* Client name */ 507 char Type[MAX_NAME_LENGTH]; /* zfs, btrfs, lvm, netapp, */ 508 char Comment[MAX_NAME_LENGTH];/* Comment */ 509 char CreateDate[MAX_TIME_LENGTH]; /* Create date as string */ 510 time_t CreateTDate; /* Create TDate (in sec, since epoch) */ 511 char *Volume; /* Volume taken in snapshot */ 512 char *Device; /* Device, Pool, Directory, ... */ 513 char *errmsg; /* Error associated with a snapshot */ 514 utime_t Retention; /* Number of second before pruning the snapshot */ 515 uint64_t Size; /* Snapshot Size */ 516 }; 517 518 /* Call back context for getting a 32/64 bit value from the database */ 519 class db_int64_ctx { 520 public: 521 int64_t value; /* value returned */ 522 int count; /* number of values seen */ 523 db_int64_ctx()524 db_int64_ctx() : value(0), count(0) {}; ~db_int64_ctx()525 ~db_int64_ctx() {}; 526 private: 527 db_int64_ctx(const db_int64_ctx&); /* prohibit pass by value */ 528 db_int64_ctx &operator=(const db_int64_ctx&); /* prohibit class assignment */ 529 }; 530 531 /* Call back context for getting a list of comma separated strings from the 532 * database 533 */ 534 class db_list_ctx { 535 public: 536 POOLMEM *list; /* list */ 537 int count; /* number of values seen */ 538 db_list_ctx()539 db_list_ctx() { list = get_pool_memory(PM_FNAME); reset(); } ~db_list_ctx()540 ~db_list_ctx() { free_pool_memory(list); list = NULL; } reset()541 void reset() { *list = 0; count = 0;} add(const db_list_ctx & str)542 void add(const db_list_ctx &str) { 543 if (str.count > 0) { 544 if (*list) { 545 pm_strcat(list, ","); 546 } 547 pm_strcat(list, str.list); 548 count += str.count; 549 } 550 } add(const char * str)551 void add(const char *str) { 552 if (count > 0) { 553 pm_strcat(list, ","); 554 } 555 pm_strcat(list, str); 556 count++; 557 } 558 private: 559 db_list_ctx(const db_list_ctx&); /* prohibit pass by value */ 560 db_list_ctx &operator=(const db_list_ctx&); /* prohibit class assignment */ 561 }; 562 563 /* sql_query flags */ 564 #define QF_STORE_RESULT 0x01 565 566 /* sql_list.c */ 567 enum e_list_type { 568 HORZ_LIST, /* list */ 569 VERT_LIST, /* llist */ 570 ARG_LIST, /* key1=v1 key2=v2 key3=v3 */ 571 FAILED_JOBS, 572 INCOMPLETE_JOBS 573 }; 574 575 #include "bdb.h" 576 #include "protos.h" 577 #include "jcr.h" 578 #include "sql_cmds.h" 579 580 581 /* Object used in db_list_xxx function */ 582 class LIST_CTX { 583 public: 584 char line[256]; /* Used to print last dash line */ 585 int32_t num_rows; 586 587 e_list_type type; /* Vertical/Horizontal */ 588 DB_LIST_HANDLER *send; /* send data back */ 589 bool once; /* Used to print header one time */ 590 void *ctx; /* send() user argument */ 591 BDB *mdb; 592 JCR *jcr; 593 empty()594 void empty() { 595 once = false; 596 line[0] = '\0'; 597 } 598 send_dashes()599 void send_dashes() { 600 if (*line) { 601 send(ctx, line); 602 } 603 } 604 LIST_CTX(JCR * j,BDB * m,DB_LIST_HANDLER * h,void * c,e_list_type t)605 LIST_CTX(JCR *j, BDB *m, DB_LIST_HANDLER *h, void *c, e_list_type t) { 606 line[0] = '\0'; 607 once = false; 608 num_rows = 0; 609 type = t; 610 send = h; 611 ctx = c; 612 jcr = j; 613 mdb = m; 614 } 615 }; 616 617 /* Functions exported by sql.c for use within the cats directory. */ 618 int list_result(void *vctx, int cols, char **row); 619 int list_result(JCR *jcr, BDB *mdb, DB_LIST_HANDLER *send, void *ctx, e_list_type type); 620 int get_sql_record_max(JCR *jcr, BDB *mdb); 621 void list_dashes(BDB *mdb, DB_LIST_HANDLER *send, void *ctx); 622 623 void print_dashes(BDB *mdb); 624 void print_result(BDB *mdb); 625 int QueryDB(const char *file, int line, JCR *jcr, BDB *db, char *select_cmd); 626 int InsertDB(const char *file, int line, JCR *jcr, BDB *db, char *select_cmd); 627 int DeleteDB(const char *file, int line, JCR *jcr, BDB *db, char *delete_cmd); 628 void split_path_and_file(JCR *jcr, BDB *mdb, const char *fname); 629 630 #endif /* __CATS_H_ */ 631