]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/cats/sqlite.c
Verify cleanups + eliminate unwanted messages
[bacula/bacula] / bacula / src / cats / sqlite.c
1 /*
2  * Bacula Catalog Database routines specific to SQLite
3  *
4  *    Kern Sibbald, January 2002
5  *
6  *    Version $Id$
7  */
8
9 /*
10    Copyright (C) 2002 Kern Sibbald and John Walker
11
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.
16
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.
21
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,
25    MA 02111-1307, USA.
26
27  */
28
29
30 /* The following is necessary so that we do not include
31  * the dummy external definition of DB.
32  */
33 #define __SQL_C                       /* indicate that this is sql.c */
34
35 #include "bacula.h"
36 #include "cats.h"
37
38 #ifdef HAVE_SQLITE
39
40 /* -----------------------------------------------------------------------
41  *
42  *    SQLite dependent defines and subroutines
43  *
44  * -----------------------------------------------------------------------
45  */
46
47 extern char *working_directory;
48
49 /* List of open databases */
50 static BQUEUE db_list = {&db_list, &db_list};
51
52 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
53
54 int QueryDB(char *file, int line, B_DB *db, char *select_cmd);
55
56
57 /*
58  * Initialize database data structure. In principal this should
59  * never have errors, or it is really fatal.
60  */
61 B_DB *
62 db_init_database(void *jcr, char *db_name, char *db_user, char *db_password)
63 {
64    B_DB *mdb;
65
66    P(mutex);                          /* lock DB queue */
67    /* Look to see if DB already open */
68    for (mdb=NULL; (mdb=(B_DB *)qnext(&db_list, &mdb->bq)); ) {
69       if (strcmp(mdb->db_name, db_name) == 0) {
70          Dmsg2(100, "DB REopen %d %s\n", mdb->ref_count, db_name);
71          mdb->ref_count++;
72          V(mutex);
73          return mdb;                  /* already open */
74       }
75    }
76    Dmsg0(100, "db_open first time\n");
77    mdb = (B_DB *) malloc(sizeof(B_DB));
78    memset(mdb, 0, sizeof(B_DB));
79    mdb->db_name = bstrdup(db_name);
80    mdb->have_insert_id = TRUE; 
81    mdb->errmsg = get_pool_memory(PM_EMSG); /* get error message buffer */
82    *mdb->errmsg = 0;
83    mdb->cmd = get_pool_memory(PM_EMSG);    /* get command buffer */
84    mdb->cached_path = get_pool_memory(PM_FNAME);
85    mdb->cached_path_id = 0;
86    mdb->ref_count = 1;
87    qinsert(&db_list, &mdb->bq);            /* put db in list */
88    mdb->jcr = jcr;
89    V(mutex);
90    return mdb;
91 }
92
93 /*
94  * Now actually open the database.  This can generate errors,
95  * which are returned in the errmsg
96  */
97 int
98 db_open_database(B_DB *mdb)
99 {
100    char *db_name;
101    int len;
102    struct stat statbuf;
103    int errstat;
104
105    P(mutex);
106    if (mdb->connected) {
107       V(mutex);
108       return 1;
109    }
110    mdb->connected = FALSE;
111
112    if ((errstat=rwl_init(&mdb->lock)) != 0) {
113       Mmsg1(&mdb->errmsg, _("Unable to initialize DB lock. ERR=%s\n"), 
114             strerror(errstat));
115       V(mutex);
116       return 0;
117    }
118
119    /* open the database */
120    len = strlen(working_directory) + strlen(mdb->db_name) + 5; 
121    db_name = (char *)malloc(len);
122    strcpy(db_name, working_directory);
123    strcat(db_name, "/");
124    strcat(db_name, mdb->db_name);
125    strcat(db_name, ".db");
126    if (stat(db_name, &statbuf) != 0) {
127       Mmsg1(&mdb->errmsg, _("Database %s does not exist, please create it.\n"), 
128          db_name);
129       free(db_name);
130       V(mutex);
131       return 0;
132    }
133    mdb->db = sqlite_open(
134         db_name,                      /* database name */
135         644,                          /* mode */
136         &mdb->sqlite_errmsg);         /* error message */
137
138    Dmsg0(50, "sqlite_open\n");
139   
140    if (mdb->db == NULL) {
141       Mmsg2(&mdb->errmsg, _("Unable to open Database=%s. ERR=%s\n"),
142          db_name, mdb->sqlite_errmsg ? mdb->sqlite_errmsg : _("unknown"));
143       free(db_name);
144       V(mutex);
145       return 0;
146    }
147    free(db_name);
148    if (!check_tables_version(mdb)) {
149       V(mutex);
150       return 0;
151    }
152
153    mdb->connected = TRUE;
154    V(mutex);
155    return 1;
156 }
157
158 void
159 db_close_database(B_DB *mdb)
160 {
161    P(mutex);
162    mdb->ref_count--;
163    if (mdb->ref_count == 0) {
164       qdchain(&mdb->bq);
165       if (mdb->connected && mdb->db) {
166          sqlite_close(mdb->db);
167       }
168       rwl_destroy(&mdb->lock);       
169       free_pool_memory(mdb->errmsg);
170       free_pool_memory(mdb->cmd);
171       free_pool_memory(mdb->cached_path);
172       if (mdb->db_name) {
173          free(mdb->db_name);
174       }
175       free(mdb);
176    }
177    V(mutex);
178 }
179
180 /*
181  * Return the next unique index (auto-increment) for
182  * the given table.  Return 0 on error.
183  */
184 int db_next_index(B_DB *mdb, char *table, char *index)
185 {
186    SQL_ROW row;
187
188    db_lock(mdb);
189
190    Mmsg(&mdb->cmd,
191 "SELECT id FROM NextId WHERE TableName=\"%s\"", table);
192    if (!QUERY_DB(mdb, mdb->cmd)) {
193       Mmsg(&mdb->errmsg, _("next_index query error: ERR=%s\n"), sql_strerror(mdb));
194       db_unlock(mdb);
195       return 0;
196    }
197    if ((row = sql_fetch_row(mdb)) == NULL) {
198       Mmsg(&mdb->errmsg, _("Error fetching index: ERR=%s\n"), sql_strerror(mdb));
199       db_unlock(mdb);
200       return 0;
201    }
202    strncpy(index, row[0], 28);
203    index[28] = 0;
204    sql_free_result(mdb);
205
206    Mmsg(&mdb->cmd,
207 "UPDATE NextId SET id=id+1 WHERE TableName=\"%s\"", table);
208    if (!QUERY_DB(mdb, mdb->cmd)) {
209       Mmsg(&mdb->errmsg, _("next_index update error: ERR=%s\n"), sql_strerror(mdb));
210       db_unlock(mdb);
211       return 0;
212    }
213    sql_free_result(mdb);
214
215    db_unlock(mdb);
216    return 1;
217 }   
218
219
220
221 void
222 db_escape_string(char *snew, char *old, int len)
223 {
224    char *n, *o;
225
226    n = snew;
227    o = old;
228    while (len--) {
229       switch (*o) {
230       case '\'':
231          *n++ = '\'';
232          *n++ = '\'';
233          o++;
234          break;
235       case 0:
236          *n++ = '\\';
237          *n++ = 0;
238          o++;
239          break;
240       default:
241          *n++ = *o++;
242          break;
243       }
244    }
245    *n = 0;
246 }
247
248 struct rh_data {
249    DB_RESULT_HANDLER *result_handler;
250    void *ctx;
251 };
252
253 /*  
254  * Convert SQLite's callback into Bacula DB callback  
255  */
256 static int sqlite_result(void *arh_data, int num_fields, char **rows, char **col_names)
257 {
258    struct rh_data *rh_data = (struct rh_data *)arh_data;   
259
260    if (rh_data->result_handler) {
261       (*(rh_data->result_handler))(rh_data->ctx, num_fields, rows);
262    }
263    return 0;
264 }
265
266 /*
267  * Submit a general SQL command (cmd), and for each row returned,
268  *  the sqlite_handler is called with the ctx.
269  */
270 int db_sql_query(B_DB *mdb, char *query, DB_RESULT_HANDLER *result_handler, void *ctx)
271 {
272    struct rh_data rh_data;
273    int stat;
274
275    db_lock(mdb);
276    if (mdb->sqlite_errmsg) {
277       actuallyfree(mdb->sqlite_errmsg);
278       mdb->sqlite_errmsg = NULL;
279    }
280    rh_data.result_handler = result_handler;
281    rh_data.ctx = ctx;
282    stat = sqlite_exec(mdb->db, query, sqlite_result, (void *)&rh_data, &mdb->sqlite_errmsg);
283    if (stat != 0) {
284       Mmsg(&mdb->errmsg, _("Query failed: %s: ERR=%s\n"), query, sql_strerror(mdb));
285       db_unlock(mdb);
286       return 0;
287    }
288    db_unlock(mdb);
289    return 1;
290 }
291
292 /*
293  * Submit a sqlite query and retrieve all the data
294  */
295 int my_sqlite_query(B_DB *mdb, char *cmd) 
296 {
297    int stat;
298
299    if (mdb->sqlite_errmsg) {
300       actuallyfree(mdb->sqlite_errmsg);
301       mdb->sqlite_errmsg = NULL;
302    }
303    stat = sqlite_get_table(mdb->db, cmd, &mdb->result, &mdb->nrow, &mdb->ncolumn,
304             &mdb->sqlite_errmsg);
305    mdb->row = 0;                      /* row fetched */
306    return stat;
307 }
308
309 /* Fetch one row at a time */
310 SQL_ROW my_sqlite_fetch_row(B_DB *mdb)
311 {
312    if (mdb->row >= mdb->nrow) {
313       return NULL;
314    }
315    mdb->row++;
316    return &mdb->result[mdb->ncolumn * mdb->row];
317 }
318
319 void my_sqlite_free_table(B_DB *mdb)
320 {
321    unsigned int i;
322
323    if (mdb->fields_defined) {
324       for (i=0; i < sql_num_fields(mdb); i++) {
325          free(mdb->fields[i]);
326       }
327       free(mdb->fields);
328       mdb->fields_defined = FALSE;
329    }
330    sqlite_free_table(mdb->result);
331    mdb->nrow = mdb->ncolumn = 0; 
332 }
333
334 void my_sqlite_field_seek(B_DB *mdb, int field)
335 {
336    unsigned int i, j;
337    if (mdb->result == NULL) {
338       return;
339    }
340    /* On first call, set up the fields */
341    if (!mdb->fields_defined && sql_num_fields(mdb) > 0) {
342       mdb->fields = (SQL_FIELD **)malloc(sizeof(SQL_FIELD) * mdb->ncolumn);
343       for (i=0; i < sql_num_fields(mdb); i++) {
344          mdb->fields[i] = (SQL_FIELD *)malloc(sizeof(SQL_FIELD));
345          mdb->fields[i]->name = mdb->result[i];
346          mdb->fields[i]->length = strlen(mdb->fields[i]->name);
347          mdb->fields[i]->max_length = mdb->fields[i]->length;
348          for (j=1; j <= (unsigned)mdb->nrow; j++) {
349             uint32_t len;
350             if (mdb->result[i + mdb->ncolumn *j]) {
351                len = (uint32_t)strlen(mdb->result[i + mdb->ncolumn * j]);
352             } else {
353                len = 0;
354             }
355             if (len > mdb->fields[i]->max_length) {
356                mdb->fields[i]->max_length = len;
357             }
358          }
359          mdb->fields[i]->type = 0;
360          mdb->fields[i]->flags = 1;        /* not null */
361       }
362       mdb->fields_defined = TRUE;
363    }
364    if (field > (int)sql_num_fields(mdb)) {
365       field = (int)sql_num_fields(mdb);
366     }
367     mdb->field = field;
368
369 }
370
371 SQL_FIELD *my_sqlite_fetch_field(B_DB *mdb)
372 {
373    return mdb->fields[mdb->field++];
374 }
375
376 static void
377 list_dashes(B_DB *mdb, DB_LIST_HANDLER *send, void *ctx)
378 {
379    SQL_FIELD *field;
380    unsigned int i, j;
381
382    sql_field_seek(mdb, 0);
383    send(ctx, "+");
384    for (i = 0; i < sql_num_fields(mdb); i++) {
385       field = sql_fetch_field(mdb);
386       for (j = 0; j < field->max_length + 2; j++)
387               send(ctx, "-");
388       send(ctx, "+");
389    }
390    send(ctx, "\n");
391 }
392
393 void
394 list_result(B_DB *mdb, DB_LIST_HANDLER *send, void *ctx)
395 {
396    SQL_FIELD *field;
397    SQL_ROW row;
398    unsigned int i, col_len;
399    char buf[2000], ewc[30];
400
401    if (mdb->result == NULL || mdb->nrow == 0) {
402       send(ctx, _("No results to list.\n"));
403       return;
404    }
405    /* determine column display widths */
406    sql_field_seek(mdb, 0);
407    for (i = 0; i < sql_num_fields(mdb); i++) {
408       field = sql_fetch_field(mdb);
409       if (IS_NUM(field->type) && field->max_length > 0) { /* fixup for commas */
410          field->max_length += (field->max_length - 1) / 3;
411       }
412       col_len = strlen(field->name);
413       if (col_len < field->max_length)
414               col_len = field->max_length;
415       if (col_len < 4 && !IS_NOT_NULL(field->flags))
416               col_len = 4;    /* 4 = length of the word "NULL" */
417       field->max_length = col_len;    /* reset column info */
418    }
419
420    list_dashes(mdb, send, ctx);
421    send(ctx, "|");
422    sql_field_seek(mdb, 0);
423    for (i = 0; i < sql_num_fields(mdb); i++) {
424       field = sql_fetch_field(mdb);
425       sprintf(buf, " %-*s |", field->max_length, field->name);
426       send(ctx, buf);
427    }
428    send(ctx, "\n");
429    list_dashes(mdb, send, ctx);
430
431    while ((row = sql_fetch_row(mdb)) != NULL) {
432       sql_field_seek(mdb, 0);
433       send(ctx, "|");
434       for (i = 0; i < sql_num_fields(mdb); i++) {
435          field = sql_fetch_field(mdb);
436          if (row[i] == NULL) {
437             sprintf(buf, " %-*s |", field->max_length, "NULL");
438          } else if (IS_NUM(field->type)) {
439             sprintf(buf, " %*s |", field->max_length,       
440                add_commas(row[i], ewc));
441          } else {
442             sprintf(buf, " %-*s |", field->max_length, row[i]);
443          }
444          send(ctx, buf);
445       }
446       send(ctx, "\n");
447    }
448    list_dashes(mdb, send, ctx);
449 }
450
451
452 #endif /* HAVE_SQLITE */