2 * Bacula Catalog Database Delete record interface routines
4 * Kern Sibbald, December 2000
10 Copyright (C) 2000-2006 Kern Sibbald
12 This program is free software; you can redistribute it and/or
13 modify it under the terms of the GNU General Public License
14 version 2 as amended with additional clauses defined in the
15 file LICENSE in the main source directory.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 the file LICENSE for additional details.
24 /* *****FIXME**** fix fixed length of select_cmd[] and insert_cmd[] */
26 /* The following is necessary so that we do not include
27 * the dummy external definition of DB.
29 #define __SQL_C /* indicate that this is sql.c */
35 #if HAVE_SQLITE3 || HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL
36 /* -----------------------------------------------------------------------
38 * Generic Routines (or almost generic)
40 * -----------------------------------------------------------------------
43 /* Imported subroutines */
44 extern void print_dashes(B_DB *mdb);
45 extern void print_result(B_DB *mdb);
46 extern int QueryDB(const char *file, int line, JCR *jcr, B_DB *db, char *select_cmd);
47 extern int DeleteDB(const char *file, int line, JCR *jcr, B_DB *db, char *delete_cmd);
50 * Delete Pool record, must also delete all associated
55 * PoolId = number of Pools deleted (should be 1)
56 * NumVols = number of Media records deleted
59 db_delete_pool_record(JCR *jcr, B_DB *mdb, POOL_DBR *pr)
64 Mmsg(mdb->cmd, "SELECT PoolId FROM Pool WHERE Name='%s'", pr->Name);
65 Dmsg1(10, "selectpool: %s\n", mdb->cmd);
67 pr->PoolId = pr->NumVols = 0;
69 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
71 mdb->num_rows = sql_num_rows(mdb);
73 if (mdb->num_rows == 0) {
74 Mmsg(mdb->errmsg, _("No pool record %s exists\n"), pr->Name);
78 } else if (mdb->num_rows != 1) {
79 Mmsg(mdb->errmsg, _("Expecting one pool record, got %d\n"), mdb->num_rows);
84 if ((row = sql_fetch_row(mdb)) == NULL) {
85 Mmsg1(&mdb->errmsg, _("Error fetching row %s\n"), sql_strerror(mdb));
89 pr->PoolId = str_to_int64(row[0]);
93 /* Delete Media owned by this pool */
95 "DELETE FROM Media WHERE Media.PoolId = %d", pr->PoolId);
97 pr->NumVols = DELETE_DB(jcr, mdb, mdb->cmd);
98 Dmsg1(200, "Deleted %d Media records\n", pr->NumVols);
102 "DELETE FROM Pool WHERE Pool.PoolId = %d", pr->PoolId);
103 pr->PoolId = DELETE_DB(jcr, mdb, mdb->cmd);
104 Dmsg1(200, "Deleted %d Pool records\n", pr->PoolId);
110 #define MAX_DEL_LIST_LEN 1000000
114 int num_ids; /* ids stored */
115 int max_ids; /* size of array */
116 int num_del; /* number deleted */
117 int tot_ids; /* total to process */
121 * Called here to make in memory list of JobIds to be
122 * deleted. The in memory list will then be transversed
123 * to issue the SQL DELETE commands. Note, the list
124 * is allowed to get to MAX_DEL_LIST_LEN to limit the
125 * maximum malloc'ed memory.
127 static int delete_handler(void *ctx, int num_fields, char **row)
129 struct s_del_ctx *del = (struct s_del_ctx *)ctx;
131 if (del->num_ids == MAX_DEL_LIST_LEN) {
134 if (del->num_ids == del->max_ids) {
135 del->max_ids = (del->max_ids * 3) / 2;
136 del->JobId = (JobId_t *)brealloc(del->JobId, sizeof(JobId_t) *
139 del->JobId[del->num_ids++] = (JobId_t)str_to_int64(row[0]);
145 * This routine will purge (delete) all records
146 * associated with a particular Volume. It will
147 * not delete the media record itself.
149 static int do_media_purge(B_DB *mdb, MEDIA_DBR *mr)
151 POOLMEM *query = get_pool_memory(PM_MESSAGE);
152 struct s_del_ctx del;
160 Mmsg(mdb->cmd, "SELECT JobId from JobMedia WHERE MediaId=%d", mr->MediaId);
161 del.max_ids = mr->VolJobs;
162 if (del.max_ids < 100) {
164 } else if (del.max_ids > MAX_DEL_LIST_LEN) {
165 del.max_ids = MAX_DEL_LIST_LEN;
167 del.JobId = (JobId_t *)malloc(sizeof(JobId_t) * del.max_ids);
168 db_sql_query(mdb, mdb->cmd, delete_handler, (void *)&del);
170 for (i=0; i < del.num_ids; i++) {
171 Dmsg1(400, "Delete JobId=%d\n", del.JobId[i]);
172 Mmsg(query, "DELETE FROM Job WHERE JobId=%s", edit_int64(del.JobId[i], ed1));
173 db_sql_query(mdb, query, NULL, (void *)NULL);
174 Mmsg(query, "DELETE FROM File WHERE JobId=%s", edit_int64(del.JobId[i], ed1));
175 db_sql_query(mdb, query, NULL, (void *)NULL);
176 Mmsg(query, "DELETE FROM JobMedia WHERE JobId=%s", edit_int64(del.JobId[i], ed1));
177 db_sql_query(mdb, query, NULL, (void *)NULL);
180 free_pool_memory(query);
184 /* Delete Media record and all records that
185 * are associated with it.
187 int db_delete_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr)
190 if (mr->MediaId == 0 && !db_get_media_record(jcr, mdb, mr)) {
194 /* Do purge if not already purged */
195 if (strcmp(mr->VolStatus, "Purged") != 0) {
196 /* Delete associated records */
197 do_media_purge(mdb, mr);
200 Mmsg(mdb->cmd, "DELETE FROM Media WHERE MediaId=%d", mr->MediaId);
201 db_sql_query(mdb, mdb->cmd, NULL, (void *)NULL);
207 * Purge all records associated with a
208 * media record. This does not delete the
209 * media record itself. But the media status
210 * is changed to "Purged".
212 int db_purge_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr)
215 if (mr->MediaId == 0 && !db_get_media_record(jcr, mdb, mr)) {
219 /* Delete associated records */
220 do_media_purge(mdb, mr); /* Note, always purge */
222 /* Mark Volume as purged */
223 strcpy(mr->VolStatus, "Purged");
224 if (!db_update_media_record(jcr, mdb, mr)) {
234 #endif /* HAVE_SQLITE3 || HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL*/