]> git.sur5r.net Git - bacula/bacula/commitdiff
Allow using sql_fetch_field() in db_sql_query() callback for SQLite
authorEric Bollengier <eric@eb.homelinux.org>
Sun, 6 Feb 2011 08:21:44 +0000 (09:21 +0100)
committerKern Sibbald <kern@sibbald.com>
Sat, 20 Apr 2013 12:40:00 +0000 (14:40 +0200)
bacula/src/cats/bdb_sqlite.h
bacula/src/cats/sqlite.c

index c03e02e685217977bac0685ce9c58e2e8f9bb251..7226b357d7c761b4f48b3ae90bacc21b4383fae8 100644 (file)
 class B_DB_SQLITE: public B_DB_PRIV {
 private:
    struct sqlite3 *m_db_handle;
-   char **m_result;
+   char **m_result;             /* sql_store_results() and sql_query() */
+   char **m_col_names;          /* used to access fields when using db_sql_query() */
    char *m_sqlite_errmsg;
+   SQL_FIELD m_sql_field;       /* used when using db_sql_query() and sql_fetch_field() */
 
 public:
    B_DB_SQLITE(JCR *jcr, const char *db_driver, const char *db_name,
@@ -42,6 +44,13 @@ public:
                bool mult_db_connections, bool disable_batch_insert);
    ~B_DB_SQLITE();
 
+   /* Used internaly by sqlite.c to access fields in db_sql_query() */
+   void set_column_names(char **res, int nb) { 
+      m_col_names = res; 
+      m_num_fields = nb;
+      m_field_number = 0;
+   }
+
    /* low level operations */
    bool db_open_database(JCR *jcr);
    void db_close_database(JCR *jcr);
index cd64546d9b4c6c11d50f3b5f4612293b094c1263..4850f7a6ade7f57bc8a2c583ba0fe5051bbc7c1d 100644 (file)
@@ -404,8 +404,10 @@ void B_DB_SQLITE::db_end_transaction(JCR *jcr)
 }
 
 struct rh_data {
+   B_DB_SQLITE *mdb;
    DB_RESULT_HANDLER *result_handler;
    void *ctx;
+   bool initialized;
 };
 
 /*
@@ -415,9 +417,17 @@ static int sqlite_sqlite_result(void *arh_data, int num_fields, char **rows, cha
 {
    struct rh_data *rh_data = (struct rh_data *)arh_data;
 
+   /* The db_sql_query doesn't have access to m_results, so if we wan't to get
+    * fields information, we need to use col_names
+    */
+   if (!rh_data->initialized) {
+      rh_data->mdb->set_column_names(col_names, num_fields);
+      rh_data->initialized = true;
+   }
    if (rh_data->result_handler) {
       (*(rh_data->result_handler))(rh_data->ctx, num_fields, rows);
    }
+   
    return 0;
 }
 
@@ -438,15 +448,23 @@ bool B_DB_SQLITE::db_sql_query(const char *query, DB_RESULT_HANDLER *result_hand
       sqlite3_free(m_sqlite_errmsg);
       m_sqlite_errmsg = NULL;
    }
-   rh_data.result_handler = result_handler;
+   sql_free_result();
+
    rh_data.ctx = ctx;
-   stat = sqlite3_exec(m_db_handle, query, sqlite_sqlite_result, (void *)&rh_data, &m_sqlite_errmsg);
+   rh_data.mdb = this;
+   rh_data.initialized = false;
+   rh_data.result_handler = result_handler;
+
+   stat = sqlite3_exec(m_db_handle, query, sqlite_sqlite_result,
+                       (void *)&rh_data, &m_sqlite_errmsg);
+   
    if (stat != SQLITE_OK) {
       Mmsg(errmsg, _("Query failed: %s: ERR=%s\n"), query, sql_strerror());
       Dmsg0(500, "db_sql_query finished\n");
       goto bail_out;
    }
    Dmsg0(500, "db_sql_query finished\n");
+   sql_free_result();
    retval = true;
 
 bail_out:
@@ -497,6 +515,7 @@ void B_DB_SQLITE::sql_free_result(void)
       sqlite3_free_table(m_result);
       m_result = NULL;
    }
+   m_col_names = NULL;
    m_num_rows = m_num_fields = 0;
    db_unlock(this);
 }
@@ -554,6 +573,26 @@ SQL_FIELD *B_DB_SQLITE::sql_fetch_field(void)
 {
    int i, j, len;
 
+   /* We are in the middle of a db_sql_query and we want to get fields info */
+   if (m_col_names != NULL) {
+      if (m_num_fields > m_field_number) {
+         m_sql_field.name = m_col_names[m_field_number];
+         /* We don't have the maximum field length, so we can use 80 as
+          * estimation.
+          */
+         len = MAX(cstrlen(m_sql_field.name), 80/m_num_fields);
+         m_sql_field.max_length = len;
+
+         m_field_number++;
+         m_sql_field.type = 0;  /* not numeric */
+         m_sql_field.flags = 1; /* not null */
+         return &m_sql_field;
+      } else {                  /* too much fetch_field() */
+         return NULL;
+      }
+   }
+
+   /* We are after a sql_query() that stores the result in m_results */
    if (!m_fields || m_fields_size < m_num_fields) {
       if (m_fields) {
          free(m_fields);