esc_obj = get_pool_memory(PM_FNAME);
m_allow_transactions = mult_db_connections;
+ /* At this time, when mult_db_connections == true, this is for
+ * specific console command such as bvfs or batch mode, and we don't
+ * want to share a batch mode or bvfs. In the future, we can change
+ * the creation function to add this parameter.
+ */
+ m_dedicated = mult_db_connections;
+
/*
* Initialize the private members.
*/
{
db_end_transaction(jcr);
P(mutex);
- sql_free_result();
m_ref_count--;
if (m_ref_count == 0) {
+ sql_free_result();
db_list->remove(this);
if (m_connected && m_db_handle) {
sqlite3_close(m_db_handle);
*/
char *B_DB_SQLITE::db_escape_object(JCR *jcr, char *old, int len)
{
- char *n, *o;
+ int l;
+ int max = len*2; /* TODO: too big, should be *4/3 */
+
+ esc_obj = check_pool_memory_size(esc_obj, max);
+ l = bin_to_base64(esc_obj, max, old, len, true);
+ esc_obj[l] = 0;
+ ASSERT(l < max); /* TODO: add check for l */
- n = esc_obj = check_pool_memory_size(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 esc_obj;
}
*
* TODO: need to be implemented (escape \0)
*/
+
void B_DB_SQLITE::db_unescape_object(JCR *jcr, char *from, int32_t expected_len,
POOLMEM **dest, int32_t *dest_len)
{
return;
}
*dest = check_pool_memory_size(*dest, expected_len+1);
+ base64_to_bin(*dest, expected_len+1, from, strlen(from));
*dest_len = expected_len;
- memcpy(*dest, from, expected_len);
(*dest)[expected_len]=0;
}
}
struct rh_data {
+ B_DB_SQLITE *mdb;
DB_RESULT_HANDLER *result_handler;
void *ctx;
+ bool initialized;
};
/*
* Convert SQLite's callback into Bacula DB callback
*/
-static int sqlite_sqlite_result(void *arh_data, int num_fields, char **rows, char **col_names)
+static int sqlite_result_handler(void *arh_data, int num_fields, char **rows, char **col_names)
{
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;
}
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_result_handler,
+ (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:
Dmsg1(500, "sql_query starts with '%s'\n", query);
- if (m_result) {
- sql_free_result();
- }
+ sql_free_result();
if (m_sqlite_errmsg) {
sqlite3_free(m_sqlite_errmsg);
m_sqlite_errmsg = NULL;
sqlite3_free_table(m_result);
m_result = NULL;
}
+ m_col_names = NULL;
m_num_rows = m_num_fields = 0;
db_unlock(this);
}
{
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);
"Name blob,"
"LStat tinyblob,"
"MD5 tinyblob,"
- "MarkId integer)");
+ "DeltaSeq integer)");
db_unlock(this);
return retval;
*/
bool B_DB_SQLITE::sql_batch_insert(JCR *jcr, ATTR_DBR *ar)
{
- size_t len;
const char *digest;
char ed1[50];
digest = ar->Digest;
}
- len = Mmsg(cmd, "INSERT INTO batch VALUES "
- "(%u,%s,'%s','%s','%s','%s',%u)",
- ar->FileIndex, edit_int64(ar->JobId,ed1), esc_path,
- esc_name, ar->attr, digest, ar->DeltaSeq);
+ Mmsg(cmd, "INSERT INTO batch VALUES "
+ "(%u,%s,'%s','%s','%s','%s',%u)",
+ ar->FileIndex, edit_int64(ar->JobId,ed1), esc_path,
+ esc_name, ar->attr, digest, ar->DeltaSeq);
return sql_query(cmd);
}