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 * -----------------------------------------------------------------------
44 * Delete Pool record, must also delete all associated
49 * PoolId = number of Pools deleted (should be 1)
50 * NumVols = number of Media records deleted
53 db_delete_pool_record(JCR *jcr, B_DB *mdb, POOL_DBR *pr)
58 Mmsg(mdb->cmd, "SELECT PoolId FROM Pool WHERE Name='%s'", pr->Name);
59 Dmsg1(10, "selectpool: %s\n", mdb->cmd);
61 pr->PoolId = pr->NumVols = 0;
63 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
65 mdb->num_rows = sql_num_rows(mdb);
67 if (mdb->num_rows == 0) {
68 Mmsg(mdb->errmsg, _("No pool record %s exists\n"), pr->Name);
72 } else if (mdb->num_rows != 1) {
73 Mmsg(mdb->errmsg, _("Expecting one pool record, got %d\n"), mdb->num_rows);
78 if ((row = sql_fetch_row(mdb)) == NULL) {
79 Mmsg1(&mdb->errmsg, _("Error fetching row %s\n"), sql_strerror(mdb));
83 pr->PoolId = str_to_int64(row[0]);
87 /* Delete Media owned by this pool */
89 "DELETE FROM Media WHERE Media.PoolId = %d", pr->PoolId);
91 pr->NumVols = DELETE_DB(jcr, mdb, mdb->cmd);
92 Dmsg1(200, "Deleted %d Media records\n", pr->NumVols);
96 "DELETE FROM Pool WHERE Pool.PoolId = %d", pr->PoolId);
97 pr->PoolId = DELETE_DB(jcr, mdb, mdb->cmd);
98 Dmsg1(200, "Deleted %d Pool records\n", pr->PoolId);
104 #define MAX_DEL_LIST_LEN 1000000
108 int num_ids; /* ids stored */
109 int max_ids; /* size of array */
110 int num_del; /* number deleted */
111 int tot_ids; /* total to process */
115 * Called here to make in memory list of JobIds to be
116 * deleted. The in memory list will then be transversed
117 * to issue the SQL DELETE commands. Note, the list
118 * is allowed to get to MAX_DEL_LIST_LEN to limit the
119 * maximum malloc'ed memory.
121 static int delete_handler(void *ctx, int num_fields, char **row)
123 struct s_del_ctx *del = (struct s_del_ctx *)ctx;
125 if (del->num_ids == MAX_DEL_LIST_LEN) {
128 if (del->num_ids == del->max_ids) {
129 del->max_ids = (del->max_ids * 3) / 2;
130 del->JobId = (JobId_t *)brealloc(del->JobId, sizeof(JobId_t) *
133 del->JobId[del->num_ids++] = (JobId_t)str_to_int64(row[0]);
139 * This routine will purge (delete) all records
140 * associated with a particular Volume. It will
141 * not delete the media record itself.
143 static int do_media_purge(B_DB *mdb, MEDIA_DBR *mr)
145 POOLMEM *query = get_pool_memory(PM_MESSAGE);
146 struct s_del_ctx del;
154 Mmsg(mdb->cmd, "SELECT JobId from JobMedia WHERE MediaId=%d", mr->MediaId);
155 del.max_ids = mr->VolJobs;
156 if (del.max_ids < 100) {
158 } else if (del.max_ids > MAX_DEL_LIST_LEN) {
159 del.max_ids = MAX_DEL_LIST_LEN;
161 del.JobId = (JobId_t *)malloc(sizeof(JobId_t) * del.max_ids);
162 db_sql_query(mdb, mdb->cmd, delete_handler, (void *)&del);
164 for (i=0; i < del.num_ids; i++) {
165 Dmsg1(400, "Delete JobId=%d\n", del.JobId[i]);
166 Mmsg(query, "DELETE FROM Job WHERE JobId=%s", edit_int64(del.JobId[i], ed1));
167 db_sql_query(mdb, query, NULL, (void *)NULL);
168 Mmsg(query, "DELETE FROM File WHERE JobId=%s", edit_int64(del.JobId[i], ed1));
169 db_sql_query(mdb, query, NULL, (void *)NULL);
170 Mmsg(query, "DELETE FROM JobMedia WHERE JobId=%s", edit_int64(del.JobId[i], ed1));
171 db_sql_query(mdb, query, NULL, (void *)NULL);
174 free_pool_memory(query);
178 /* Delete Media record and all records that
179 * are associated with it.
181 int db_delete_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr)
184 if (mr->MediaId == 0 && !db_get_media_record(jcr, mdb, mr)) {
188 /* Do purge if not already purged */
189 if (strcmp(mr->VolStatus, "Purged") != 0) {
190 /* Delete associated records */
191 do_media_purge(mdb, mr);
194 Mmsg(mdb->cmd, "DELETE FROM Media WHERE MediaId=%d", mr->MediaId);
195 db_sql_query(mdb, mdb->cmd, NULL, (void *)NULL);
201 * Purge all records associated with a
202 * media record. This does not delete the
203 * media record itself. But the media status
204 * is changed to "Purged".
206 int db_purge_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr)
209 if (mr->MediaId == 0 && !db_get_media_record(jcr, mdb, mr)) {
213 /* Delete associated records */
214 do_media_purge(mdb, mr); /* Note, always purge */
216 /* Mark Volume as purged */
217 strcpy(mr->VolStatus, "Purged");
218 if (!db_update_media_record(jcr, mdb, mr)) {
228 #endif /* HAVE_SQLITE3 || HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL*/