]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/cats/sqlite.c
bvfs: Restore should be ok with MySQL
[bacula/bacula] / bacula / src / cats / sqlite.c
index 1672f07502dbcebcd6c68d24cf97739d5b691bfc..bc2458a731f167b54595849bed63f973f2c11d69 100644 (file)
@@ -6,7 +6,7 @@
    The main author of Bacula is Kern Sibbald, with contributions from
    many others, a complete list can be found in the file AUTHORS.
    This program is Free Software; you can redistribute it and/or
-   modify it under the terms of version two of the GNU General Public
+   modify it under the terms of version three of the GNU Affero General Public
    License as published by the Free Software Foundation and included
    in the file LICENSE.
 
@@ -15,7 +15,7 @@
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    General Public License for more details.
 
-   You should have received a copy of the GNU General Public License
+   You should have received a copy of the GNU Affero General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
@@ -121,7 +121,6 @@ db_init_database(JCR *jcr, const char *db_name, const char *db_user, const char
    mdb = (B_DB *)malloc(sizeof(B_DB));
    memset(mdb, 0, sizeof(B_DB));
    mdb->db_name = bstrdup(db_name);
-   mdb->have_insert_id = true;
    mdb->errmsg = get_pool_memory(PM_EMSG); /* get error message buffer */
    *mdb->errmsg = 0;
    mdb->cmd = get_pool_memory(PM_EMSG);    /* get command buffer */
@@ -132,6 +131,7 @@ db_init_database(JCR *jcr, const char *db_name, const char *db_user, const char
    mdb->path = get_pool_memory(PM_FNAME);
    mdb->esc_name = get_pool_memory(PM_FNAME);
    mdb->esc_path = get_pool_memory(PM_FNAME);
+   mdb->esc_obj  = get_pool_memory(PM_FNAME);
    mdb->allow_transactions = mult_db_connections;
    db_list->append(mdb);
    V(mutex);
@@ -259,10 +259,15 @@ db_close_database(JCR *jcr, B_DB *mdb)
       free_pool_memory(mdb->path);
       free_pool_memory(mdb->esc_name);
       free_pool_memory(mdb->esc_path);
+      free_pool_memory(mdb->esc_obj);
       if (mdb->db_name) {
          free(mdb->db_name);
       }
       free(mdb);
+      if (db_list->size() == 0) {
+         delete db_list;
+         db_list = NULL;
+      }
    }
    V(mutex);
 }
@@ -270,10 +275,12 @@ db_close_database(JCR *jcr, B_DB *mdb)
 void db_check_backend_thread_safe()
 {
 #ifdef HAVE_BATCH_FILE_INSERT
+# ifdef HAVE_SQLITE3_THREADSAFE
    if (!sqlite3_threadsafe()) {
       Emsg0(M_ABORT, 0, _("SQLite3 client library must be thread-safe "
                           "when using BatchMode.\n"));
    }
+# endif
 #endif
 }
 
@@ -294,6 +301,60 @@ int db_next_index(JCR *jcr, B_DB *mdb, char *table, char *index)
    return 1;
 }
 
+/*
+ * Escape binary object so that SQLite is happy
+ * Memory is stored in B_DB struct, no need to free it
+ *
+ * TODO: this should be implemented  (escape \0)
+ */
+char *
+db_escape_object(JCR *jcr, B_DB *mdb, char *old, int len)
+{
+   char *n, *o;
+
+   n = mdb->esc_obj = check_pool_memory_size(mdb->esc_obj, len*2+1);
+   o = old;
+   while (len--) {
+      switch (*o) {
+      case '\'':
+         *n++ = '\'';
+         *n++ = '\'';
+         o++;
+         break;
+      case 0:
+         *n++ = '\\';
+         *n++ = 0;
+         o++;
+         break;
+      default:
+         *n++ = *o++;
+         break;
+      }
+   }
+   *n = 0;
+   return mdb->esc_obj;
+}
+
+/*
+ * Unescape binary object so that SQLIte is happy
+ *
+ * TODO: need to be implemented (escape \0)
+ */
+void
+db_unescape_object(JCR *jcr, B_DB *mdb, 
+                   char *from, int32_t expected_len, 
+                   POOLMEM **dest, int32_t *dest_len)
+{
+   if (!from) {
+      *dest[0] = 0;
+      *dest_len = 0;
+      return;
+   }
+   *dest = check_pool_memory_size(*dest, expected_len+1);
+   *dest_len = expected_len;
+   memcpy(*dest, from, expected_len);
+   (*dest)[expected_len]=0;
+}
 
 /*
  * Escape strings so that SQLite is happy
@@ -303,7 +364,7 @@ int db_next_index(JCR *jcr, B_DB *mdb, char *table, char *index)
  *         the escaped output.
  */
 void
-db_escape_string(JCR *jcr, B_DB *db, char *snew, char *old, int len)
+db_escape_string(JCR *jcr, B_DB *mdb, char *snew, char *old, int len)
 {
    char *n, *o;
 
@@ -448,6 +509,16 @@ void my_sqlite_field_seek(B_DB *mdb, int field)
       mdb->fields = (SQL_FIELD **)malloc(sizeof(SQL_FIELD) * mdb->ncolumn);
       for (i=0; i < sql_num_fields(mdb); i++) {
          mdb->fields[i] = (SQL_FIELD *)malloc(sizeof(SQL_FIELD));
+         /* ***FIXME***  it seems to me that this is wrong
+          *   fields has lots of items
+          */
+         if (mdb->result[i] == NULL) {
+            mdb->fields_defined = false;
+            free(mdb->fields);
+            mdb->fields = NULL;
+            mdb->field = 0;
+            return;
+         }
          mdb->fields[i]->name = mdb->result[i];
          mdb->fields[i]->length = cstrlen(mdb->fields[i]->name);
          mdb->fields[i]->max_length = mdb->fields[i]->length;
@@ -485,6 +556,29 @@ SQL_FIELD *my_sqlite_fetch_field(B_DB *mdb)
    }
 }
 
+uint64_t my_sqlite_insert_autokey_record(B_DB *mdb, const char *query, const char *table_name)
+{
+   /*
+    * First execute the insert query and then retrieve the currval.
+    */
+   if (my_sqlite_query(mdb, query)) {
+      return 0;
+   }
+
+   mdb->num_rows = sql_affected_rows(mdb);
+   if (mdb->num_rows != 1) {
+      return 0;
+   }
+
+   mdb->changes++;
+
+#ifdef HAVE_SQLITE3
+   return sqlite3_last_insert_rowid(mdb->db);
+#else
+   return sqlite_last_insert_rowid(mdb->db);
+#endif
+}
+
 #ifdef HAVE_BATCH_FILE_INSERT
 const char *my_sqlite_batch_lock_query = "BEGIN";
 const char *my_sqlite_batch_unlock_query = "COMMIT";