2 * Bacula Catalog Database Delete record interface routines
4 * Kern Sibbald, December 2000
10 Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker
12 This program is free software; you can redistribute it and/or
13 modify it under the terms of the GNU General Public License as
14 published by the Free Software Foundation; either version 2 of
15 the License, or (at your option) any later version.
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 GNU
20 General Public License for more details.
22 You should have received a copy of the GNU General Public
23 License along with this program; if not, write to the Free
24 Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
29 /* *****FIXME**** fix fixed length of select_cmd[] and insert_cmd[] */
31 /* The following is necessary so that we do not include
32 * the dummy external definition of DB.
34 #define __SQL_C /* indicate that this is sql.c */
40 #if HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL
41 /* -----------------------------------------------------------------------
43 * Generic Routines (or almost generic)
45 * -----------------------------------------------------------------------
48 /* Imported subroutines */
49 extern void print_dashes(B_DB *mdb);
50 extern void print_result(B_DB *mdb);
51 extern int QueryDB(char *file, int line, JCR *jcr, B_DB *db, char *select_cmd);
52 extern int DeleteDB(char *file, int line, JCR *jcr, B_DB *db, char *delete_cmd);
55 * Delete Pool record, must also delete all associated
60 * PoolId = number of Pools deleted (should be 1)
61 * NumVols = number of Media records deleted
64 db_delete_pool_record(JCR *jcr, B_DB *mdb, POOL_DBR *pr)
69 Mmsg(&mdb->cmd, "SELECT PoolId FROM Pool WHERE Name='%s'", pr->Name);
70 Dmsg1(10, "selectpool: %s\n", mdb->cmd);
72 pr->PoolId = pr->NumVols = 0;
74 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
76 mdb->num_rows = sql_num_rows(mdb);
78 if (mdb->num_rows == 0) {
79 Mmsg(&mdb->errmsg, _("No pool record %s exists\n"), pr->Name);
83 } else if (mdb->num_rows != 1) {
84 Mmsg(&mdb->errmsg, _("Expecting one pool record, got %d\n"), mdb->num_rows);
89 if ((row = sql_fetch_row(mdb)) == NULL) {
90 Mmsg1(&mdb->errmsg, _("Error fetching row %s\n"), sql_strerror(mdb));
94 pr->PoolId = atoi(row[0]);
98 /* Delete Media owned by this pool */
100 "DELETE FROM Media WHERE Media.PoolId = %d", pr->PoolId);
102 pr->NumVols = DELETE_DB(jcr, mdb, mdb->cmd);
103 Dmsg1(200, "Deleted %d Media records\n", pr->NumVols);
107 "DELETE FROM Pool WHERE Pool.PoolId = %d", pr->PoolId);
108 pr->PoolId = DELETE_DB(jcr, mdb, mdb->cmd);
109 Dmsg1(200, "Deleted %d Pool records\n", pr->PoolId);
115 #define MAX_DEL_LIST_LEN 1000000
119 int num_ids; /* ids stored */
120 int max_ids; /* size of array */
121 int num_del; /* number deleted */
122 int tot_ids; /* total to process */
126 * Called here to make in memory list of JobIds to be
127 * deleted. The in memory list will then be transversed
128 * to issue the SQL DELETE commands. Note, the list
129 * is allowed to get to MAX_DEL_LIST_LEN to limit the
130 * maximum malloc'ed memory.
132 static int delete_handler(void *ctx, int num_fields, char **row)
134 struct s_del_ctx *del = (struct s_del_ctx *)ctx;
136 if (del->num_ids == MAX_DEL_LIST_LEN) {
139 if (del->num_ids == del->max_ids) {
140 del->max_ids = (del->max_ids * 3) / 2;
141 del->JobId = (JobId_t *)brealloc(del->JobId, sizeof(JobId_t) *
144 del->JobId[del->num_ids++] = (JobId_t)str_to_int64(row[0]);
150 * This routine will purge (delete) all records
151 * associated with a particular Volume. It will
152 * not delete the media record itself.
154 static int do_media_purge(B_DB *mdb, MEDIA_DBR *mr)
156 POOLMEM *query = get_pool_memory(PM_MESSAGE);
157 struct s_del_ctx del;
164 Mmsg(&mdb->cmd, "SELECT JobId from JobMedia WHERE MediaId=%d", mr->MediaId);
165 del.max_ids = mr->VolJobs;
166 if (del.max_ids < 100) {
168 } else if (del.max_ids > MAX_DEL_LIST_LEN) {
169 del.max_ids = MAX_DEL_LIST_LEN;
171 del.JobId = (JobId_t *)malloc(sizeof(JobId_t) * del.max_ids);
172 db_sql_query(mdb, mdb->cmd, delete_handler, (void *)&del);
174 for (i=0; i < del.num_ids; i++) {
175 Dmsg1(400, "Delete JobId=%d\n", del.JobId[i]);
176 Mmsg(&query, "DELETE FROM Job WHERE JobId=%u", del.JobId[i]);
177 db_sql_query(mdb, query, NULL, (void *)NULL);
178 Mmsg(&query, "DELETE FROM File WHERE JobId=%u", del.JobId[i]);
179 db_sql_query(mdb, query, NULL, (void *)NULL);
180 Mmsg(&query, "DELETE FROM JobMedia WHERE JobId=%u", del.JobId[i]);
181 db_sql_query(mdb, query, NULL, (void *)NULL);
184 free_pool_memory(query);
188 /* Delete Media record and all records that
189 * are associated with it.
191 int db_delete_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr)
194 if (mr->MediaId == 0 && !db_get_media_record(jcr, mdb, mr)) {
198 /* Do purge if not already purged */
199 if (strcmp(mr->VolStatus, "Purged") != 0) {
200 /* Delete associated records */
201 do_media_purge(mdb, mr);
204 Mmsg(&mdb->cmd, "DELETE FROM Media WHERE MediaId=%d", mr->MediaId);
205 db_sql_query(mdb, mdb->cmd, NULL, (void *)NULL);
211 * Purge all records associated with a
212 * media record. This does not delete the
213 * media record itself. But the media status
214 * is changed to "Purged".
216 int db_purge_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr)
219 if (mr->MediaId == 0 && !db_get_media_record(jcr, mdb, mr)) {
223 /* Delete associated records */
224 do_media_purge(mdb, mr); /* Note, always purge */
226 /* Mark Volume as purged */
227 strcpy(mr->VolStatus, "Purged");
228 if (!db_update_media_record(jcr, mdb, mr)) {
238 #endif /* HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL */