]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/cats/sqlite.c
change all void *jcr into JCR *jcr
[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-2003 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, JCR *jcr, 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(JCR *jcr, char *db_name, char *db_user, char *db_password,
63                  char *db_address, int db_port, char *db_socket) 
64 {
65    B_DB *mdb;
66
67    P(mutex);                          /* lock DB queue */
68    /* Look to see if DB already open */
69    for (mdb=NULL; (mdb=(B_DB *)qnext(&db_list, &mdb->bq)); ) {
70       if (strcmp(mdb->db_name, db_name) == 0) {
71          Dmsg2(100, "DB REopen %d %s\n", mdb->ref_count, db_name);
72          mdb->ref_count++;
73          V(mutex);
74          return mdb;                  /* already open */
75       }
76    }
77    Dmsg0(100, "db_open first time\n");
78    mdb = (B_DB *) malloc(sizeof(B_DB));
79    memset(mdb, 0, sizeof(B_DB));
80    mdb->db_name = bstrdup(db_name);
81    mdb->have_insert_id = TRUE; 
82    mdb->errmsg = get_pool_memory(PM_EMSG); /* get error message buffer */
83    *mdb->errmsg = 0;
84    mdb->cmd = get_pool_memory(PM_EMSG);    /* get command buffer */
85    mdb->cached_path = get_pool_memory(PM_FNAME);
86    mdb->cached_path_id = 0;
87    mdb->ref_count = 1;
88    mdb->fname = get_pool_memory(PM_FNAME);
89    mdb->path = get_pool_memory(PM_FNAME);
90    mdb->esc_name = get_pool_memory(PM_FNAME);
91    qinsert(&db_list, &mdb->bq);            /* put db in list */
92    V(mutex);
93    return mdb;
94 }
95
96 /*
97  * Now actually open the database.  This can generate errors,
98  * which are returned in the errmsg
99  */
100 int
101 db_open_database(JCR *jcr, B_DB *mdb)
102 {
103    char *db_name;
104    int len;
105    struct stat statbuf;
106    int errstat;
107
108    P(mutex);
109    if (mdb->connected) {
110       V(mutex);
111       return 1;
112    }
113    mdb->connected = FALSE;
114
115    if ((errstat=rwl_init(&mdb->lock)) != 0) {
116       Mmsg1(&mdb->errmsg, _("Unable to initialize DB lock. ERR=%s\n"), 
117             strerror(errstat));
118       V(mutex);
119       return 0;
120    }
121
122    /* open the database */
123    len = strlen(working_directory) + strlen(mdb->db_name) + 5; 
124    db_name = (char *)malloc(len);
125    strcpy(db_name, working_directory);
126    strcat(db_name, "/");
127    strcat(db_name, mdb->db_name);
128    strcat(db_name, ".db");
129    if (stat(db_name, &statbuf) != 0) {
130       Mmsg1(&mdb->errmsg, _("Database %s does not exist, please create it.\n"), 
131          db_name);
132       free(db_name);
133       V(mutex);
134       return 0;
135    }
136    mdb->db = sqlite_open(
137         db_name,                      /* database name */
138         644,                          /* mode */
139         &mdb->sqlite_errmsg);         /* error message */
140
141    Dmsg0(50, "sqlite_open\n");
142   
143    if (mdb->db == NULL) {
144       Mmsg2(&mdb->errmsg, _("Unable to open Database=%s. ERR=%s\n"),
145          db_name, mdb->sqlite_errmsg ? mdb->sqlite_errmsg : _("unknown"));
146       free(db_name);
147       V(mutex);
148       return 0;
149    }
150    free(db_name);
151    if (!check_tables_version(jcr, mdb)) {
152       V(mutex);
153       return 0;
154    }
155
156    mdb->connected = TRUE;
157    V(mutex);
158    return 1;
159 }
160
161 void
162 db_close_database(JCR *jcr, B_DB *mdb)
163 {
164    P(mutex);
165    mdb->ref_count--;
166    if (mdb->ref_count == 0) {
167       qdchain(&mdb->bq);
168       if (mdb->connected && mdb->db) {
169          sqlite_close(mdb->db);
170       }
171       rwl_destroy(&mdb->lock);       
172       free_pool_memory(mdb->errmsg);
173       free_pool_memory(mdb->cmd);
174       free_pool_memory(mdb->cached_path);
175       free_pool_memory(mdb->fname);
176       free_pool_memory(mdb->path);
177       free_pool_memory(mdb->esc_name);
178       if (mdb->db_name) {
179          free(mdb->db_name);
180       }
181       free(mdb);
182    }
183    V(mutex);
184 }
185
186 /*
187  * Return the next unique index (auto-increment) for
188  * the given table.  Return 0 on error.
189  */
190 int db_next_index(JCR *jcr, B_DB *mdb, char *table, char *index)
191 {
192    SQL_ROW row;
193
194    db_lock(mdb);
195
196    Mmsg(&mdb->cmd,
197 "SELECT id FROM NextId WHERE TableName=\"%s\"", table);
198    if (!QUERY_DB(jcr, mdb, mdb->cmd)) {
199       Mmsg(&mdb->errmsg, _("next_index query error: ERR=%s\n"), sql_strerror(mdb));
200       db_unlock(mdb);
201       return 0;
202    }
203    if ((row = sql_fetch_row(mdb)) == NULL) {
204       Mmsg(&mdb->errmsg, _("Error fetching index: ERR=%s\n"), sql_strerror(mdb));
205       db_unlock(mdb);
206       return 0;
207    }
208    bstrncpy(index, row[0], 28);
209    sql_free_result(mdb);
210
211    Mmsg(&mdb->cmd,
212 "UPDATE NextId SET id=id+1 WHERE TableName=\"%s\"", table);
213    if (!QUERY_DB(jcr, mdb, mdb->cmd)) {
214       Mmsg(&mdb->errmsg, _("next_index update error: ERR=%s\n"), sql_strerror(mdb));
215       db_unlock(mdb);
216       return 0;
217    }
218    sql_free_result(mdb);
219
220    db_unlock(mdb);
221    return 1;
222 }   
223
224
225 /*
226  * Escape strings so that SQLite is happy
227  *
228  *   NOTE! len is the length of the old string. Your new
229  *         string must be long enough (max 2*old) to hold
230  *         the escaped output.
231  */
232 void
233 db_escape_string(char *snew, char *old, int len)
234 {
235    char *n, *o;
236
237    n = snew;
238    o = old;
239    while (len--) {
240       switch (*o) {
241       case '\'':
242          *n++ = '\'';
243          *n++ = '\'';
244          o++;
245          break;
246       case 0:
247          *n++ = '\\';
248          *n++ = 0;
249          o++;
250          break;
251       default:
252          *n++ = *o++;
253          break;
254       }
255    }
256    *n = 0;
257 }
258
259 struct rh_data {
260    DB_RESULT_HANDLER *result_handler;
261    void *ctx;
262 };
263
264 /*  
265  * Convert SQLite's callback into Bacula DB callback  
266  */
267 static int sqlite_result(void *arh_data, int num_fields, char **rows, char **col_names)
268 {
269    struct rh_data *rh_data = (struct rh_data *)arh_data;   
270
271    if (rh_data->result_handler) {
272       (*(rh_data->result_handler))(rh_data->ctx, num_fields, rows);
273    }
274    return 0;
275 }
276
277 /*
278  * Submit a general SQL command (cmd), and for each row returned,
279  *  the sqlite_handler is called with the ctx.
280  */
281 int db_sql_query(B_DB *mdb, char *query, DB_RESULT_HANDLER *result_handler, void *ctx)
282 {
283    struct rh_data rh_data;
284    int stat;
285
286    db_lock(mdb);
287    if (mdb->sqlite_errmsg) {
288       actuallyfree(mdb->sqlite_errmsg);
289       mdb->sqlite_errmsg = NULL;
290    }
291    rh_data.result_handler = result_handler;
292    rh_data.ctx = ctx;
293    stat = sqlite_exec(mdb->db, query, sqlite_result, (void *)&rh_data, &mdb->sqlite_errmsg);
294    if (stat != 0) {
295       Mmsg(&mdb->errmsg, _("Query failed: %s: ERR=%s\n"), query, sql_strerror(mdb));
296       db_unlock(mdb);
297       return 0;
298    }
299    db_unlock(mdb);
300    return 1;
301 }
302
303 /*
304  * Submit a sqlite query and retrieve all the data
305  */
306 int my_sqlite_query(B_DB *mdb, char *cmd) 
307 {
308    int stat;
309
310    if (mdb->sqlite_errmsg) {
311       actuallyfree(mdb->sqlite_errmsg);
312       mdb->sqlite_errmsg = NULL;
313    }
314    stat = sqlite_get_table(mdb->db, cmd, &mdb->result, &mdb->nrow, &mdb->ncolumn,
315             &mdb->sqlite_errmsg);
316    mdb->row = 0;                      /* row fetched */
317    return stat;
318 }
319
320 /* Fetch one row at a time */
321 SQL_ROW my_sqlite_fetch_row(B_DB *mdb)
322 {
323    if (mdb->row >= mdb->nrow) {
324       return NULL;
325    }
326    mdb->row++;
327    return &mdb->result[mdb->ncolumn * mdb->row];
328 }
329
330 void my_sqlite_free_table(B_DB *mdb)
331 {
332    unsigned int i;
333
334    if (mdb->fields_defined) {
335       for (i=0; i < sql_num_fields(mdb); i++) {
336          free(mdb->fields[i]);
337       }
338       free(mdb->fields);
339       mdb->fields_defined = FALSE;
340    }
341    sqlite_free_table(mdb->result);
342    mdb->nrow = mdb->ncolumn = 0; 
343 }
344
345 void my_sqlite_field_seek(B_DB *mdb, int field)
346 {
347    unsigned int i, j;
348    if (mdb->result == NULL) {
349       return;
350    }
351    /* On first call, set up the fields */
352    if (!mdb->fields_defined && sql_num_fields(mdb) > 0) {
353       mdb->fields = (SQL_FIELD **)malloc(sizeof(SQL_FIELD) * mdb->ncolumn);
354       for (i=0; i < sql_num_fields(mdb); i++) {
355          mdb->fields[i] = (SQL_FIELD *)malloc(sizeof(SQL_FIELD));
356          mdb->fields[i]->name = mdb->result[i];
357          mdb->fields[i]->length = strlen(mdb->fields[i]->name);
358          mdb->fields[i]->max_length = mdb->fields[i]->length;
359          for (j=1; j <= (unsigned)mdb->nrow; j++) {
360             uint32_t len;
361             if (mdb->result[i + mdb->ncolumn *j]) {
362                len = (uint32_t)strlen(mdb->result[i + mdb->ncolumn * j]);
363             } else {
364                len = 0;
365             }
366             if (len > mdb->fields[i]->max_length) {
367                mdb->fields[i]->max_length = len;
368             }
369          }
370          mdb->fields[i]->type = 0;
371          mdb->fields[i]->flags = 1;        /* not null */
372       }
373       mdb->fields_defined = TRUE;
374    }
375    if (field > (int)sql_num_fields(mdb)) {
376       field = (int)sql_num_fields(mdb);
377     }
378     mdb->field = field;
379
380 }
381
382 SQL_FIELD *my_sqlite_fetch_field(B_DB *mdb)
383 {
384    return mdb->fields[mdb->field++];
385 }
386
387 static void
388 list_dashes(B_DB *mdb, DB_LIST_HANDLER *send, void *ctx)
389 {
390    SQL_FIELD *field;
391    unsigned int i, j;
392
393    sql_field_seek(mdb, 0);
394    send(ctx, "+");
395    for (i = 0; i < sql_num_fields(mdb); i++) {
396       field = sql_fetch_field(mdb);
397       for (j = 0; j < field->max_length + 2; j++)
398               send(ctx, "-");
399       send(ctx, "+");
400    }
401    send(ctx, "\n");
402 }
403
404 /*
405  * If full_list is set, we list vertically, otherwise, we 
406  * list on one line horizontally.      
407  */
408 void
409 list_result(B_DB *mdb, DB_LIST_HANDLER *send, void *ctx, int full_list)
410 {
411    SQL_FIELD *field;
412    SQL_ROW row;
413    unsigned int i, col_len, max_len = 0;
414    char buf[2000], ewc[30];
415
416    if (mdb->result == NULL || mdb->nrow == 0) {
417       send(ctx, _("No results to list.\n"));
418       return;
419    }
420    /* determine column display widths */
421    sql_field_seek(mdb, 0);
422    for (i = 0; i < sql_num_fields(mdb); i++) {
423       field = sql_fetch_field(mdb);
424       col_len = strlen(field->name);
425       if (full_list) {
426          if (col_len > max_len) {
427             max_len = col_len;
428          }
429       } else {
430          if (IS_NUM(field->type) && field->max_length > 0) { /* fixup for commas */
431             field->max_length += (field->max_length - 1) / 3;
432          }
433          if (col_len < field->max_length) {
434             col_len = field->max_length;
435          }
436          if (col_len < 4 && !IS_NOT_NULL(field->flags)) {
437             col_len = 4;                 /* 4 = length of the word "NULL" */
438          }
439          field->max_length = col_len;    /* reset column info */
440       }
441    }
442
443    if (full_list) {
444       goto horizontal_list;
445    }
446
447    list_dashes(mdb, send, ctx);
448    send(ctx, "|");
449    sql_field_seek(mdb, 0);
450    for (i = 0; i < sql_num_fields(mdb); i++) {
451       field = sql_fetch_field(mdb);
452       bsnprintf(buf, sizeof(buf), " %-*s |", (int)field->max_length, field->name);
453       send(ctx, buf);
454    }
455    send(ctx, "\n");
456    list_dashes(mdb, send, ctx);
457
458    while ((row = sql_fetch_row(mdb)) != NULL) {
459       sql_field_seek(mdb, 0);
460       send(ctx, "|");
461       for (i = 0; i < sql_num_fields(mdb); i++) {
462          field = sql_fetch_field(mdb);
463          if (row[i] == NULL) {
464             bsnprintf(buf, sizeof(buf), " %-*s |", (int)field->max_length, "NULL");
465          } else if (IS_NUM(field->type)) {
466             bsnprintf(buf, sizeof(buf), " %*s |", (int)field->max_length,       
467                add_commas(row[i], ewc));
468          } else {
469             bsnprintf(buf, sizeof(buf), " %-*s |", (int)field->max_length, row[i]);
470          }
471          send(ctx, buf);
472       }
473       send(ctx, "\n");
474    }
475    list_dashes(mdb, send, ctx);
476    return;
477
478 horizontal_list:
479    
480    while ((row = sql_fetch_row(mdb)) != NULL) {
481       sql_field_seek(mdb, 0);
482       for (i = 0; i < sql_num_fields(mdb); i++) {
483          field = sql_fetch_field(mdb);
484          if (row[i] == NULL) {
485             bsnprintf(buf, sizeof(buf), " %*s: %s\n", max_len, field->name, "NULL");
486          } else if (IS_NUM(field->type)) {
487             bsnprintf(buf, sizeof(buf), " %*s: %s\n", max_len, field->name, 
488                add_commas(row[i], ewc));
489          } else {
490             bsnprintf(buf, sizeof(buf), " %*s: %s\n", max_len, field->name, row[i]);
491          }
492          send(ctx, buf);
493       }
494       send(ctx, "\n");
495    }
496    return;
497 }
498
499
500 #endif /* HAVE_SQLITE */