2 * Bacula Catalog Database Delete record interface routines
4 * Kern Sibbald, December 2000
6 * Version $Id: sql_delete.c 7380 2008-07-14 10:42:59Z kerns $
9 Bacula® - The Network Backup Solution
11 Copyright (C) 2000-2006 Free Software Foundation Europe e.V.
13 The main author of Bacula is Kern Sibbald, with contributions from
14 many others, a complete list can be found in the file AUTHORS.
15 This program is Free Software; you can redistribute it and/or
16 modify it under the terms of version three of the GNU Affero General Public
17 License as published by the Free Software Foundation and included
20 This program is distributed in the hope that it will be useful, but
21 WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 General Public License for more details.
25 You should have received a copy of the GNU Affero General Public License
26 along with this program; if not, write to the Free Software
27 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
30 Bacula® is a registered trademark of Kern Sibbald.
31 The licensor of Bacula is the Free Software Foundation Europe
32 (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
33 Switzerland, email:ftf@fsfeurope.org.
36 /* *****FIXME**** fix fixed length of select_cmd[] and insert_cmd[] */
40 #if HAVE_SQLITE3 || HAVE_MYSQL || HAVE_POSTGRESQL || HAVE_INGRES || HAVE_DBI
46 /* -----------------------------------------------------------------------
48 * Generic Routines (or almost generic)
50 * -----------------------------------------------------------------------
54 * Delete Pool record, must also delete all associated
59 * PoolId = number of Pools deleted (should be 1)
60 * NumVols = number of Media records deleted
63 db_delete_pool_record(JCR *jcr, B_DB *mdb, POOL_DBR *pr)
67 char esc[MAX_ESCAPE_NAME_LENGTH];
70 mdb->db_escape_string(jcr, esc, pr->Name, strlen(pr->Name));
71 Mmsg(mdb->cmd, "SELECT PoolId FROM Pool WHERE Name='%s'", esc);
72 Dmsg1(10, "selectpool: %s\n", mdb->cmd);
74 pr->PoolId = pr->NumVols = 0;
76 if (QUERY_DB(jcr, mdb, mdb->cmd)) {
78 num_rows = sql_num_rows(mdb);
80 Mmsg(mdb->errmsg, _("No pool record %s exists\n"), pr->Name);
84 } else if (num_rows != 1) {
85 Mmsg(mdb->errmsg, _("Expecting one pool record, got %d\n"), num_rows);
90 if ((row = sql_fetch_row(mdb)) == NULL) {
91 Mmsg1(&mdb->errmsg, _("Error fetching row %s\n"), sql_strerror(mdb));
95 pr->PoolId = str_to_int64(row[0]);
99 /* Delete Media owned by this pool */
101 "DELETE FROM Media WHERE Media.PoolId = %d", pr->PoolId);
103 pr->NumVols = DELETE_DB(jcr, mdb, mdb->cmd);
104 Dmsg1(200, "Deleted %d Media records\n", pr->NumVols);
108 "DELETE FROM Pool WHERE Pool.PoolId = %d", pr->PoolId);
109 pr->PoolId = DELETE_DB(jcr, mdb, mdb->cmd);
110 Dmsg1(200, "Deleted %d Pool records\n", pr->PoolId);
116 #define MAX_DEL_LIST_LEN 1000000
120 int num_ids; /* ids stored */
121 int max_ids; /* size of array */
122 int num_del; /* number deleted */
123 int tot_ids; /* total to process */
127 * Called here to make in memory list of JobIds to be
128 * deleted. The in memory list will then be transversed
129 * to issue the SQL DELETE commands. Note, the list
130 * is allowed to get to MAX_DEL_LIST_LEN to limit the
131 * maximum malloc'ed memory.
133 static int delete_handler(void *ctx, int num_fields, char **row)
135 struct s_del_ctx *del = (struct s_del_ctx *)ctx;
137 if (del->num_ids == MAX_DEL_LIST_LEN) {
140 if (del->num_ids == del->max_ids) {
141 del->max_ids = (del->max_ids * 3) / 2;
142 del->JobId = (JobId_t *)brealloc(del->JobId, sizeof(JobId_t) *
145 del->JobId[del->num_ids++] = (JobId_t)str_to_int64(row[0]);
151 * This routine will purge (delete) all records
152 * associated with a particular Volume. It will
153 * not delete the media record itself.
154 * TODO: This function is broken and it doesn't purge
155 * File, BaseFiles, Log, ...
156 * We call it from relabel and delete volume=, both ensure
157 * that the volume is properly purged.
159 static int do_media_purge(B_DB *mdb, MEDIA_DBR *mr)
161 POOLMEM *query = get_pool_memory(PM_MESSAGE);
162 struct s_del_ctx del;
170 Mmsg(mdb->cmd, "SELECT JobId from JobMedia WHERE MediaId=%d", mr->MediaId);
171 del.max_ids = mr->VolJobs;
172 if (del.max_ids < 100) {
174 } else if (del.max_ids > MAX_DEL_LIST_LEN) {
175 del.max_ids = MAX_DEL_LIST_LEN;
177 del.JobId = (JobId_t *)malloc(sizeof(JobId_t) * del.max_ids);
178 db_sql_query(mdb, mdb->cmd, delete_handler, (void *)&del);
180 for (i=0; i < del.num_ids; i++) {
181 Dmsg1(400, "Delete JobId=%d\n", del.JobId[i]);
182 Mmsg(query, "DELETE FROM Job WHERE JobId=%s", edit_int64(del.JobId[i], ed1));
183 db_sql_query(mdb, query, NULL, (void *)NULL);
184 Mmsg(query, "DELETE FROM File WHERE JobId=%s", edit_int64(del.JobId[i], ed1));
185 db_sql_query(mdb, query, NULL, (void *)NULL);
186 Mmsg(query, "DELETE FROM JobMedia WHERE JobId=%s", edit_int64(del.JobId[i], ed1));
187 db_sql_query(mdb, query, NULL, (void *)NULL);
190 free_pool_memory(query);
194 /* Delete Media record and all records that
195 * are associated with it.
197 int db_delete_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr)
200 if (mr->MediaId == 0 && !db_get_media_record(jcr, mdb, mr)) {
204 /* Do purge if not already purged */
205 if (strcmp(mr->VolStatus, "Purged") != 0) {
206 /* Delete associated records */
207 do_media_purge(mdb, mr);
210 Mmsg(mdb->cmd, "DELETE FROM Media WHERE MediaId=%d", mr->MediaId);
211 db_sql_query(mdb, mdb->cmd, NULL, (void *)NULL);
217 * Purge all records associated with a
218 * media record. This does not delete the
219 * media record itself. But the media status
220 * is changed to "Purged".
222 int db_purge_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr)
225 if (mr->MediaId == 0 && !db_get_media_record(jcr, mdb, mr)) {
229 /* Delete associated records */
230 do_media_purge(mdb, mr); /* Note, always purge */
232 /* Mark Volume as purged */
233 strcpy(mr->VolStatus, "Purged");
234 if (!db_update_media_record(jcr, mdb, mr)) {
244 #endif /* HAVE_SQLITE3 || HAVE_MYSQL || HAVE_POSTGRESQL || HAVE_INGRES */