]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/cats/sql_delete.c
Use db_escape_string() in all db_xxx functions
[bacula/bacula] / bacula / src / cats / sql_delete.c
1 /*
2  * Bacula Catalog Database Delete record interface routines
3  *
4  *    Kern Sibbald, December 2000
5  *
6  *    Version $Id: sql_delete.c 7380 2008-07-14 10:42:59Z kerns $
7  */
8 /*
9    Bacula® - The Network Backup Solution
10
11    Copyright (C) 2000-2006 Free Software Foundation Europe e.V.
12
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
18    in the file LICENSE.
19
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.
24
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
28    02110-1301, USA.
29
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.
34 */
35
36 /* *****FIXME**** fix fixed length of select_cmd[] and insert_cmd[] */
37
38 #include "bacula.h"
39
40
41 #if HAVE_SQLITE3 || HAVE_MYSQL || HAVE_POSTGRESQL || HAVE_INGRES || HAVE_DBI
42
43 #include "cats.h"
44 #include "bdb_priv.h"
45 #include "sql_glue.h"
46
47 /* -----------------------------------------------------------------------
48  *
49  *   Generic Routines (or almost generic)
50  *
51  * -----------------------------------------------------------------------
52  */
53
54 /*
55  * Delete Pool record, must also delete all associated
56  *  Media records.
57  *
58  *  Returns: 0 on error
59  *           1 on success
60  *           PoolId = number of Pools deleted (should be 1)
61  *           NumVols = number of Media records deleted
62  */
63 int
64 db_delete_pool_record(JCR *jcr, B_DB *mdb, POOL_DBR *pr)
65 {
66    SQL_ROW row;
67    int num_rows;
68    char esc[MAX_ESCAPE_NAME_LENGTH];
69
70    db_lock(mdb);
71    mdb->db_escape_string(jcr, esc, pr->Name, strlen(pr->Name));
72    Mmsg(mdb->cmd, "SELECT PoolId FROM Pool WHERE Name='%s'", esc);
73    Dmsg1(10, "selectpool: %s\n", mdb->cmd);
74
75    pr->PoolId = pr->NumVols = 0;
76
77    if (QUERY_DB(jcr, mdb, mdb->cmd)) {
78
79       num_rows = sql_num_rows(mdb);
80       if (num_rows == 0) {
81          Mmsg(mdb->errmsg, _("No pool record %s exists\n"), pr->Name);
82          sql_free_result(mdb);
83          db_unlock(mdb);
84          return 0;
85       } else if (num_rows != 1) {
86          Mmsg(mdb->errmsg, _("Expecting one pool record, got %d\n"), num_rows);
87          sql_free_result(mdb);
88          db_unlock(mdb);
89          return 0;
90       }
91       if ((row = sql_fetch_row(mdb)) == NULL) {
92          Mmsg1(&mdb->errmsg, _("Error fetching row %s\n"), sql_strerror(mdb));
93          db_unlock(mdb);
94          return 0;
95       }
96       pr->PoolId = str_to_int64(row[0]);
97       sql_free_result(mdb);
98    }
99
100    /* Delete Media owned by this pool */
101    Mmsg(mdb->cmd,
102 "DELETE FROM Media WHERE Media.PoolId = %d", pr->PoolId);
103
104    pr->NumVols = DELETE_DB(jcr, mdb, mdb->cmd);
105    Dmsg1(200, "Deleted %d Media records\n", pr->NumVols);
106
107    /* Delete Pool */
108    Mmsg(mdb->cmd,
109 "DELETE FROM Pool WHERE Pool.PoolId = %d", pr->PoolId);
110    pr->PoolId = DELETE_DB(jcr, mdb, mdb->cmd);
111    Dmsg1(200, "Deleted %d Pool records\n", pr->PoolId);
112
113    db_unlock(mdb);
114    return 1;
115 }
116
117 #define MAX_DEL_LIST_LEN 1000000
118
119 struct s_del_ctx {
120    JobId_t *JobId;
121    int num_ids;                       /* ids stored */
122    int max_ids;                       /* size of array */
123    int num_del;                       /* number deleted */
124    int tot_ids;                       /* total to process */
125 };
126
127 /*
128  * Called here to make in memory list of JobIds to be
129  *  deleted. The in memory list will then be transversed
130  *  to issue the SQL DELETE commands.  Note, the list
131  *  is allowed to get to MAX_DEL_LIST_LEN to limit the
132  *  maximum malloc'ed memory.
133  */
134 static int delete_handler(void *ctx, int num_fields, char **row)
135 {
136    struct s_del_ctx *del = (struct s_del_ctx *)ctx;
137
138    if (del->num_ids == MAX_DEL_LIST_LEN) {
139       return 1;
140    }
141    if (del->num_ids == del->max_ids) {
142       del->max_ids = (del->max_ids * 3) / 2;
143       del->JobId = (JobId_t *)brealloc(del->JobId, sizeof(JobId_t) *
144          del->max_ids);
145    }
146    del->JobId[del->num_ids++] = (JobId_t)str_to_int64(row[0]);
147    return 0;
148 }
149
150
151 /*
152  * This routine will purge (delete) all records
153  * associated with a particular Volume. It will
154  * not delete the media record itself.
155  * TODO: This function is broken and it doesn't purge
156  *       File, BaseFiles, Log, ...
157  *       We call it from relabel and delete volume=, both ensure
158  *       that the volume is properly purged.
159  */
160 static int do_media_purge(B_DB *mdb, MEDIA_DBR *mr)
161 {
162    POOLMEM *query = get_pool_memory(PM_MESSAGE);
163    struct s_del_ctx del;
164    char ed1[50];
165    int i;
166
167    del.num_ids = 0;
168    del.tot_ids = 0;
169    del.num_del = 0;
170    del.max_ids = 0;
171    Mmsg(mdb->cmd, "SELECT JobId from JobMedia WHERE MediaId=%d", mr->MediaId);
172    del.max_ids = mr->VolJobs;
173    if (del.max_ids < 100) {
174       del.max_ids = 100;
175    } else if (del.max_ids > MAX_DEL_LIST_LEN) {
176       del.max_ids = MAX_DEL_LIST_LEN;
177    }
178    del.JobId = (JobId_t *)malloc(sizeof(JobId_t) * del.max_ids);
179    db_sql_query(mdb, mdb->cmd, delete_handler, (void *)&del);
180
181    for (i=0; i < del.num_ids; i++) {
182       Dmsg1(400, "Delete JobId=%d\n", del.JobId[i]);
183       Mmsg(query, "DELETE FROM Job WHERE JobId=%s", edit_int64(del.JobId[i], ed1));
184       db_sql_query(mdb, query, NULL, (void *)NULL);
185       Mmsg(query, "DELETE FROM File WHERE JobId=%s", edit_int64(del.JobId[i], ed1));
186       db_sql_query(mdb, query, NULL, (void *)NULL);
187       Mmsg(query, "DELETE FROM JobMedia WHERE JobId=%s", edit_int64(del.JobId[i], ed1));
188       db_sql_query(mdb, query, NULL, (void *)NULL);
189    }
190    free(del.JobId);
191    free_pool_memory(query);
192    return 1;
193 }
194
195 /* Delete Media record and all records that
196  * are associated with it.
197  */
198 int db_delete_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr)
199 {
200    db_lock(mdb);
201    if (mr->MediaId == 0 && !db_get_media_record(jcr, mdb, mr)) {
202       db_unlock(mdb);
203       return 0;
204    }
205    /* Do purge if not already purged */
206    if (strcmp(mr->VolStatus, "Purged") != 0) {
207       /* Delete associated records */
208       do_media_purge(mdb, mr);
209    }
210
211    Mmsg(mdb->cmd, "DELETE FROM Media WHERE MediaId=%d", mr->MediaId);
212    db_sql_query(mdb, mdb->cmd, NULL, (void *)NULL);
213    db_unlock(mdb);
214    return 1;
215 }
216
217 /*
218  * Purge all records associated with a
219  * media record. This does not delete the
220  * media record itself. But the media status
221  * is changed to "Purged".
222  */
223 int db_purge_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr)
224 {
225    db_lock(mdb);
226    if (mr->MediaId == 0 && !db_get_media_record(jcr, mdb, mr)) {
227       db_unlock(mdb);
228       return 0;
229    }
230    /* Delete associated records */
231    do_media_purge(mdb, mr);           /* Note, always purge */
232
233    /* Mark Volume as purged */
234    strcpy(mr->VolStatus, "Purged");
235    if (!db_update_media_record(jcr, mdb, mr)) {
236       db_unlock(mdb);
237       return 0;
238    }
239
240    db_unlock(mdb);
241    return 1;
242 }
243
244
245 #endif /* HAVE_SQLITE3 || HAVE_MYSQL || HAVE_POSTGRESQL || HAVE_INGRES */