#include <glib.h>
#include <sqlite3.h>
#include <sys/types.h>
#include <unistd.h>
#include <liberutils/er_error.h>
#include "ermetadb_log.h"
#include "ermetadb.h"
#include "ermetadb_error.h"
#include "ermetadb_private.h"
#include "metadata_table.h"
#include "metadata_table_private.h"
#include "sqlite3_wrapper.h"
Go to the source code of this file.
Defines | |
#define | LOGGING_ON 0 |
#define | UNUSED(x) (void)(x) |
Functions | |
static void | sql3_finalize_statements (GPtrArray *statements) |
Release compiled sql statements. | |
static int | sql3_prepare_statements (sqlite3 *db, const char *sql, GPtrArray **statements) |
Parse sql string and compile into byte code. | |
static void | bind_single_statement (void *p1, void *p2) |
int | sql3_bind_parameters (GPtrArray *statements, const metadata_table *parameters) |
Bind positional parameters to a set of compiled sql statements Assumes no parameters are currently bound to this statement Assumes TEXT and BLOB parameters unchanged until statements have executed. | |
static metadata_table * | create_result_table (sqlite3_stmt *stmt) |
static int | execute_single_statement (sqlite3_stmt *stmt, metadata_table **result_table) |
static int | sql3_execute_statements (sqlite3 *db, const GPtrArray *statements, metadata_table **result_table) |
Parse sql string and compile into byte code. | |
int | sql3_execute_query (sqlite3 *db, const char *sql, const metadata_table *parameters, metadata_table **result_table) |
Execute sql query. A convenience wrapper around sql3_prepare_statements(), sql3_execute_statements(), sql3_finalize_statements() for queries that have no parameters. | |
static int | begin_transaction (erMetadb thiz, const gboolean is_readonly) |
int | sql3_begin_transaction (erMetadb thiz) |
Start a database transaction. Transactions may be nested, as long as the calls to sql3_begin_transaction() and sql3_begin_transaction_readonly() are balanced with calls to sql3_commit_or_rollback. | |
int | sql3_begin_transaction_readonly (erMetadb thiz) |
Start a read-only database transaction. Transactions may be nested, as long as the calls to sql3_begin_transaction() and sql3_begin_transaction_readonly() are balanced with calls to sql3_commit_or_rollback. | |
int | sql3_commit_or_rollback (erMetadb thiz, int err) |
Commit or rollback a database transaction Transactions may be nested, as long as the calls to sql3_begin_transaction() are balanced with calls to sql3_commit_or_rollback. Superfluous calls to sql3_commit_or_rollback are allowed. | |
int | sql3_strcase_compare (void *user_data, int left_len, const void *left_void, int right_len, const void *right_void) |
Compare function to be used in custom collation sequence See documentation on sqlite3_create_collation() for details. | |
Variables | |
static const int | BEGIN_MAX_RETRIES = 20 |
static const int | BEGIN_RETRY_MS = 250 |
static const int | COMMIT_MAX_RETRIES = 30 |
static const int | COMMIT_RETRY_MS = 100 |
static const int | STEP_MAX_RETRIES = 10 |
static const int | STEP_RETRY_MS = 100 |
#define LOGGING_ON 0 |
Copyright (C) 2008 iRex Technologies B.V. All rights reserved.
Definition at line 41 of file sqlite3_wrapper.c.
#define UNUSED | ( | x | ) | (void)(x) |
Definition at line 50 of file sqlite3_wrapper.c.
static int begin_transaction | ( | erMetadb | thiz, | |
const gboolean | is_readonly | |||
) | [static] |
Definition at line 511 of file sqlite3_wrapper.c.
References BEGIN_MAX_RETRIES, BEGIN_RETRY_MS, ER_INVALID_PARAMETER, ER_OK, ER_READONLY, ERMETADB_DATABASE_BUSY, ERMETADB_FAIL, ERRORPRINTF, LOGPRINTF, QUERYPRINTF, and WARNPRINTF.
Referenced by sql3_begin_transaction(), and sql3_begin_transaction_readonly().
00512 { 00513 int ret = ER_OK; 00514 int rc; 00515 const char *sql = NULL; 00516 char *errmsg = NULL; 00517 int retries_left = BEGIN_MAX_RETRIES; 00518 gboolean done = FALSE; 00519 00520 g_assert(thiz && thiz->database); 00521 g_assert(thiz->transaction_nesting < 100); 00522 00523 sqlite3 *db = thiz->database; 00524 00525 LOGPRINTF( "entry: db [%p] is_readonly [%d] [%d] transaction_nesting [%d]", 00526 db, 00527 is_readonly, 00528 thiz->is_transaction_readonly, 00529 thiz->transaction_nesting ); 00530 00531 g_return_val_if_fail(db, ER_INVALID_PARAMETER); 00532 00533 00534 // start a transaction, acquire write lock 00535 if (thiz->transaction_nesting == 0) 00536 { 00537 thiz->is_transaction_readonly = is_readonly; 00538 thiz->do_force_rollback = FALSE; 00539 00540 // repeat while database locked 00541 if ( is_readonly ) 00542 { 00543 sql = "BEGIN DEFERRED;"; 00544 } 00545 else 00546 { 00547 sql = "BEGIN IMMEDIATE;"; 00548 } 00549 QUERYPRINTF("sql [%s]", sql); 00550 while (!done) 00551 { 00552 rc = sqlite3_exec(db, sql, NULL, NULL, &errmsg); 00553 if (rc == SQLITE_OK) 00554 { 00555 // database lock obtained: increase transaction nesting level 00556 thiz->transaction_nesting++; 00557 done = TRUE; 00558 00559 } 00560 else if ( rc == SQLITE_BUSY 00561 && --retries_left >= 0 ) 00562 { 00563 // database locked: wait a while then try again 00564 WARNPRINTF("pid [%ld] waiting for database lock", (long)getpid()); 00565 usleep(BEGIN_RETRY_MS * 1000); 00566 } 00567 else 00568 { 00569 ERRORPRINTF("pid [%ld] cannot begin transaction, error [%d] [%s]", (long)getpid(), rc, errmsg); 00570 switch (rc) 00571 { 00572 case SQLITE_BUSY: 00573 ret = ERMETADB_DATABASE_BUSY; 00574 break; 00575 case SQLITE_READONLY: 00576 ret = ER_READONLY; 00577 break; 00578 default: 00579 ret = ERMETADB_FAIL; 00580 } 00581 done = TRUE; 00582 } 00583 00584 // free error message, if any 00585 sqlite3_free(errmsg); 00586 errmsg = NULL; 00587 } 00588 } 00589 else 00590 { 00591 // transaction in progress: check read-only status 00592 if ( is_readonly == thiz->is_transaction_readonly ) 00593 { 00594 // same is_readonly: ok 00595 thiz->transaction_nesting++; 00596 } 00597 else if ( is_readonly ) 00598 { 00599 // read-only begin on writable transaction: ok 00600 thiz->transaction_nesting++; 00601 } 00602 else 00603 { 00604 // error: read-only transaction cannot be promoted to writable 00605 ret = ER_READONLY; 00606 } 00607 } 00608 00609 if (ret != ER_OK) WARNPRINTF("cannot begin transaction. ret [%d]", ret); 00610 return ret; 00611 }
static void bind_single_statement | ( | void * | p1, | |
void * | p2 | |||
) | [static] |
Definition at line 185 of file sqlite3_wrapper.c.
References ER_OK, ERRORPRINTF, LOGPRINTF, METADATA_BLOB, METADATA_DOUBLE, METADATA_INT64, METADATA_NULL, metadata_table_get_cell(), METADATA_TEXT, metadata_cell::type, metadata_cell::v_blob, metadata_cell::v_double, metadata_cell::v_int64, metadata_cell::v_text, and metadata_cell::value.
Referenced by sql3_bind_parameters().
00186 { 00187 sqlite3_stmt *stmt = (sqlite3_stmt*) p1; 00188 const metadata_table *parameters = (const metadata_table*) p2; 00189 00190 LOGPRINTF("entry: stmt [%p]", stmt); 00191 00192 // get #parameters in statement 00193 int n_parms = sqlite3_bind_parameter_count(stmt); 00194 00195 // bind parameters 00196 GString *parm_name = g_string_new(""); 00197 int parm_idx; 00198 const metadata_cell *parm = NULL; 00199 for (parm_idx = 0 ; parm_idx < n_parms ; parm_idx++) 00200 { 00201 // get parameter name 00202 g_string_printf(parm_name, "?%d", parm_idx + 1); 00203 00204 // find parameter value 00205 metadata_cell_type parm_type = METADATA_NULL; 00206 if (parameters) 00207 { 00208 parm = metadata_table_get_cell(parameters, parm_idx); 00209 if (parm) 00210 { 00211 parm_type = parm->type; 00212 } 00213 } 00214 00215 int rc; 00216 // bind parameter 00217 switch (parm_type) 00218 { 00219 case METADATA_INT64: 00220 rc = sqlite3_bind_int64(stmt, parm_idx + 1, parm->value.v_int64); 00221 break; 00222 case METADATA_DOUBLE: 00223 rc = sqlite3_bind_double(stmt, parm_idx + 1, parm->value.v_double); 00224 break; 00225 case METADATA_TEXT: 00226 rc = sqlite3_bind_text(stmt, parm_idx + 1, parm->value.v_text->str, -1, SQLITE_STATIC); 00227 break; 00228 case METADATA_BLOB: 00229 rc = sqlite3_bind_blob(stmt, parm_idx + 1, parm->value.v_blob.data, parm->value.v_blob.len, SQLITE_STATIC); 00230 break; 00231 default: 00232 rc = sqlite3_bind_null(stmt, parm_idx + 1); 00233 } 00234 if (rc != ER_OK) 00235 { 00236 ERRORPRINTF("sqlite3_bind_xx returns [%d] on stmt [%p]", rc, stmt); 00237 sqlite3_bind_null(stmt, parm_idx + 1); 00238 } 00239 } 00240 00241 g_string_free(parm_name, TRUE); 00242 }
static metadata_table* create_result_table | ( | sqlite3_stmt * | stmt | ) | [static] |
Definition at line 272 of file sqlite3_wrapper.c.
References ERRORPRINTF, LOGPRINTF, metadata_table_add_column(), metadata_table_new(), and name.
Referenced by execute_single_statement().
00273 { 00274 metadata_table *result = metadata_table_new(); 00275 g_assert(result); 00276 00277 // add columns to result table 00278 int n_col = sqlite3_column_count(stmt); 00279 int col; 00280 for (col = 0 ; col < n_col ; col++) 00281 { 00282 const char* name = sqlite3_column_name(stmt, col); 00283 if (name == NULL) 00284 { 00285 ERRORPRINTF("sqlite3_column returns NULL"); 00286 } 00287 LOGPRINTF("column [%d] name [%s]", col, name); 00288 metadata_table_add_column(result, name); 00289 } 00290 return result; 00291 }
static int execute_single_statement | ( | sqlite3_stmt * | stmt, | |
metadata_table ** | result_table | |||
) | [static] |
Definition at line 295 of file sqlite3_wrapper.c.
References create_result_table(), ER_OK, ERMETADB_FAIL, ERRORPRINTF, metadata_table_dump, metadata_table_free, metadata_table_n_columns, metadata_table_n_rows, metadata_table_set_value(), STEP_MAX_RETRIES, and STEP_RETRY_MS.
Referenced by sql3_execute_statements().
00296 { 00297 int ret = ER_OK; 00298 00299 // repeat step while new rows are delivered 00300 metadata_table *result = NULL; 00301 int retries_left = STEP_MAX_RETRIES; 00302 gboolean done = FALSE; 00303 while (!done) 00304 { 00305 int step_rc = sqlite3_step(stmt); 00306 switch (step_rc) 00307 { 00308 case SQLITE_ROW: 00309 { 00310 if (result == NULL) result = create_result_table(stmt); 00311 00312 // read column values into result table 00313 int n_row = metadata_table_n_rows(result); 00314 int n_col = metadata_table_n_columns(result); 00315 int idx = n_row * n_col; 00316 int col; 00317 for (col = 0 ; col < n_col && ret == ER_OK ; col++) 00318 { 00319 sqlite3_value *value = sqlite3_column_value(stmt, col); 00320 int rc = metadata_table_set_value(result, idx, value); 00321 if (rc != ER_OK) 00322 { 00323 ret = rc; 00324 done = TRUE; 00325 } 00326 idx++; 00327 } 00328 retries_left = STEP_MAX_RETRIES; 00329 break; 00330 } 00331 case SQLITE_DONE: 00332 done = TRUE; 00333 break; 00334 00335 case SQLITE_BUSY: 00336 if (--retries_left >= 0) 00337 { 00338 // wait a while, then try again 00339 usleep(STEP_RETRY_MS * 1000); 00340 break; 00341 } 00342 else 00343 { 00344 // no more retries: error 00345 ; // FALLTHROUGH to case default 00346 } 00347 00348 default: 00349 ERRORPRINTF("sqlite3_step reports error [%d]", step_rc); 00350 ret = ERMETADB_FAIL; 00351 done = TRUE; 00352 } 00353 } 00354 00355 if (result) 00356 { 00357 // report the result 00358 if (*result_table) 00359 { 00360 ERRORPRINTF( "Not allowed to have SQL statements produce multiple result sets.\n" 00361 "Second result set discarded:" ); 00362 metadata_table_dump(result); 00363 metadata_table_free(result); 00364 ret = ERMETADB_FAIL; 00365 } 00366 else 00367 { 00368 *result_table = result; 00369 } 00370 } 00371 00372 return ret; 00373 }
int sql3_begin_transaction | ( | erMetadb | thiz | ) |
Start a database transaction. Transactions may be nested, as long as the calls to sql3_begin_transaction() and sql3_begin_transaction_readonly() are balanced with calls to sql3_commit_or_rollback.
---------------------------------------------------------------------------
Name : sql3_begin_transaction
[in] | thiz | - erMetadb object on which to start a transaction |
--------------------------------------------------------------------------
Definition at line 614 of file sqlite3_wrapper.c.
References begin_transaction().
Referenced by add_filename(), ermetadb_begin_transaction(), ermetadb_global_remove_folder(), ermetadb_local_create_annotation(), ermetadb_local_remove_application_data(), ermetadb_local_set_annotation(), ermetadb_local_set_application_data(), local_delete_all_data_for_id(), open_sql_database(), and set_file_metadata_impl().
00615 { 00616 return begin_transaction(thiz, FALSE); 00617 }
int sql3_begin_transaction_readonly | ( | erMetadb | thiz | ) |
Start a read-only database transaction. Transactions may be nested, as long as the calls to sql3_begin_transaction() and sql3_begin_transaction_readonly() are balanced with calls to sql3_commit_or_rollback.
---------------------------------------------------------------------------
Name : sql3_begin_transaction_readonly
[in] | thiz | - erMetadb object on which to start a transaction |
--------------------------------------------------------------------------
Definition at line 620 of file sqlite3_wrapper.c.
References begin_transaction().
Referenced by ermetadb_begin_transaction_readonly(), ermetadb_global_get_file(), ermetadb_local_get_annotations(), ermetadb_local_get_application_data(), ermetadb_local_select_annotations(), and open_sql_database().
00621 { 00622 return begin_transaction(thiz, TRUE); 00623 }
int sql3_bind_parameters | ( | GPtrArray * | statements, | |
const metadata_table * | parameters | |||
) |
Bind positional parameters to a set of compiled sql statements Assumes no parameters are currently bound to this statement Assumes TEXT and BLOB parameters unchanged until statements have executed.
---------------------------------------------------------------------------
Name : sql3_bind_parameters
[in/out] | statements - GPtrArray with compiled statements | |
[in] | parameters | - metadata_table with parameters (value), or NULL table must have exactly one row |
--------------------------------------------------------------------------
Definition at line 260 of file sqlite3_wrapper.c.
References bind_single_statement(), ER_INVALID_PARAMETER, and ER_OK.
Referenced by sql3_execute_query().
00261 { 00262 g_return_val_if_fail( statements , ER_INVALID_PARAMETER); 00263 g_return_val_if_fail((statements->len > 0), ER_INVALID_PARAMETER); 00264 00265 metadata_table *parms = (metadata_table*) parameters; // const_cast 00266 g_ptr_array_foreach(statements, bind_single_statement, parms); 00267 00268 return ER_OK; 00269 }
int sql3_commit_or_rollback | ( | erMetadb | thiz, | |
int | err | |||
) |
Commit or rollback a database transaction Transactions may be nested, as long as the calls to sql3_begin_transaction() are balanced with calls to sql3_commit_or_rollback. Superfluous calls to sql3_commit_or_rollback are allowed.
---------------------------------------------------------------------------
Name : sql3_commit_or_rollback
[in] | thiz | - erMetadb object on which to end a transaction |
[in] | err | - ER_OK or error code |
--------------------------------------------------------------------------
Definition at line 626 of file sqlite3_wrapper.c.
References BEGIN_RETRY_MS, COMMIT_MAX_RETRIES, ER_OK, ERMETADB_DATABASE_BUSY, ERMETADB_FAIL, ERRORPRINTF, LOGPRINTF, QUERYPRINTF, and WARNPRINTF.
Referenced by add_filename(), ermetadb_close(), ermetadb_end_transaction(), ermetadb_global_get_file(), ermetadb_global_remove_folder(), ermetadb_global_rename_file(), ermetadb_local_create_annotation(), ermetadb_local_get_annotations(), ermetadb_local_get_application_data(), ermetadb_local_remove_application_data(), ermetadb_local_select_annotations(), ermetadb_local_set_annotation(), ermetadb_local_set_application_data(), local_delete_all_data_for_id(), open_sql_database(), and set_file_metadata_impl().
00627 { 00628 g_assert(thiz && thiz->database); 00629 00630 LOGPRINTF( "entry: err [%d] is_readonly [%d] transaction_nesting [%d]", 00631 err, 00632 thiz->is_transaction_readonly, 00633 thiz->transaction_nesting ); 00634 00635 // decide whether to commit or rollback 00636 if (err != ER_OK) thiz->do_force_rollback = TRUE; 00637 00638 // never turn an error code into a good one 00639 int ret = err; 00640 if (thiz->transaction_nesting > 0) 00641 { 00642 // decrease transaction nesting level 00643 thiz->transaction_nesting--; 00644 00645 if (thiz->transaction_nesting == 0) 00646 { 00647 const char *sql = NULL; 00648 // decide commit or rollback ... 00649 if ( err == ER_OK && thiz->do_force_rollback == FALSE ) 00650 { 00651 // ok: commit changes to database 00652 sql = "COMMIT;"; 00653 } 00654 else 00655 { 00656 // error: rollback and return original error code 00657 sql = "ROLLBACK;"; 00658 } 00659 QUERYPRINTF("sql [%s]", sql); 00660 00661 // ... and execute it 00662 gboolean done = FALSE; 00663 int retries_left = COMMIT_MAX_RETRIES; 00664 while (!done) 00665 { 00666 char *errmsg = NULL; 00667 int rc = sqlite3_exec(thiz->database, sql, NULL, NULL, &errmsg); 00668 if (rc == SQLITE_OK) 00669 { 00670 // transaction ended 00671 done = TRUE; 00672 } 00673 else if ( rc == SQLITE_BUSY && --retries_left >= 0 ) 00674 { 00675 // database locked: wait a while then try again 00676 WARNPRINTF("pid [%ld] waiting for database lock, sql [%s]", (long)getpid(), sql); 00677 usleep(BEGIN_RETRY_MS * 1000); 00678 } 00679 else 00680 { 00681 ERRORPRINTF("cannot end transaction, sql [%s] error [%d] [%s]", sql, rc, errmsg); 00682 if (rc == SQLITE_BUSY) 00683 { 00684 ret = ERMETADB_DATABASE_BUSY; 00685 } 00686 else 00687 { 00688 ret = ERMETADB_FAIL; 00689 } 00690 done = TRUE; 00691 } 00692 00693 // free error message, if any 00694 sqlite3_free(errmsg); 00695 errmsg = NULL; 00696 } 00697 } 00698 } 00699 00700 LOGPRINTF("leave: ret [%d]", ret); 00701 return ret; 00702 }
int sql3_execute_query | ( | sqlite3 * | db, | |
const char * | sql, | |||
const metadata_table * | parameters, | |||
metadata_table ** | result_table | |||
) |
Execute sql query. A convenience wrapper around sql3_prepare_statements(), sql3_execute_statements(), sql3_finalize_statements() for queries that have no parameters.
File Name : sqlite3_wrapper.h
Description: Wrapper layer around the sqlite3 C API Copyright (C) 2008 iRex Technologies B.V. All rights reserved.---------------------------------------------------------------------------
Name : sql3_execute_query
[in] | db | - sqlite database object |
[in] | sql | - SQL statement(s) as text |
[in] | parameters | - metadata_table with parameters (value), or NULL table must have exactly one row |
[in] | result_table | - location to store metadata_table holding query results, or NULL when caller is not interested in query results |
[out] | result_table | - metadata_table holding query results, or NULL when no results First row holds column names and cell values, other rows hold cell values only. |
--------------------------------------------------------------------------
Definition at line 453 of file sqlite3_wrapper.c.
References ER_INVALID_PARAMETER, ER_OK, ERRORPRINTF, metadata_table_dump, metadata_table_free, QUERYPRINTF, sql3_bind_parameters(), sql3_execute_statements(), sql3_finalize_statements(), and sql3_prepare_statements().
Referenced by add_file_ids(), add_filename(), check_database_version(), check_global_database_columns(), check_global_database_tables(), convert_database_01_06(), convert_database_05_06(), delete_entry(), ermetadb_global_get_file(), ermetadb_global_remove_folder(), ermetadb_global_rename_file(), ermetadb_global_select_all(), ermetadb_global_update_size(), ermetadb_global_update_title(), ermetadb_local_create_annotation(), ermetadb_local_get_annotations(), ermetadb_local_get_application_data(), ermetadb_local_remove_annotation(), ermetadb_local_remove_application_data(), ermetadb_local_select_annotations(), ermetadb_local_set_application_data(), find_or_create_filename(), get_global_id(), get_local_id(), global_select_common(), local_delete_all_annotations(), local_delete_all_application_data(), local_delete_entry(), open_sql_database(), set_annotation_impl(), set_file_metadata_impl(), and update_version_number().
00454 { 00455 QUERYPRINTF("entry: sql [%s]", sql); 00456 metadata_table_dump(parameters); 00457 00458 g_return_val_if_fail( db , ER_INVALID_PARAMETER); 00459 g_return_val_if_fail( sql , ER_INVALID_PARAMETER); 00460 g_return_val_if_fail(( result_table == NULL 00461 || *result_table == NULL), ER_INVALID_PARAMETER); 00462 00463 int ret = ER_OK; 00464 GPtrArray *statements = NULL; 00465 int rc = sql3_prepare_statements(db, sql, &statements); 00466 if (rc != ER_OK) 00467 { 00468 ERRORPRINTF("sql3_prepare_statements returns [%d] sql [%s]", rc, sql); 00469 ret = rc; 00470 } 00471 00472 if (ret == ER_OK && parameters) 00473 { 00474 rc = sql3_bind_parameters(statements, parameters); 00475 if (rc != ER_OK) 00476 { 00477 ERRORPRINTF("sql3_bind_parameters returns [%d] sql [%s]", rc, sql); 00478 ret = rc; 00479 } 00480 } 00481 00482 metadata_table *result = NULL; 00483 if (ret == ER_OK) 00484 { 00485 rc = sql3_execute_statements(db, statements, &result); 00486 if (rc != ER_OK) 00487 { 00488 ERRORPRINTF("sql3_execute_statements returns [%d] sql [%s]", rc, sql); 00489 ret = rc; 00490 } 00491 } 00492 00493 // clean up 00494 if (statements) 00495 { 00496 sql3_finalize_statements(statements); 00497 statements = NULL; 00498 } 00499 00500 // return result 00501 if (result_table) 00502 { 00503 *result_table = result; 00504 result = NULL; 00505 } 00506 metadata_table_free(result); 00507 return ret; 00508 }
static int sql3_execute_statements | ( | sqlite3 * | db, | |
const GPtrArray * | statements, | |||
metadata_table ** | result_table | |||
) | [static] |
Parse sql string and compile into byte code.
---------------------------------------------------------------------------
Name : sql3_execute_statements
[in] | db | - sqlite database object |
[in] | statements | - GPtrArray with compiled statements |
[in] | result_table | - location to store metadata_table holding query results, or NULL when caller is not interested in query results |
[out] | result_table | - metadata_table holding query results, or NULL when no results First row holds column names and cell values, other rows hold cell values only. |
--------------------------------------------------------------------------
Definition at line 393 of file sqlite3_wrapper.c.
References ER_INVALID_PARAMETER, ER_OK, ERRORPRINTF, execute_single_statement(), LOGPRINTF, and metadata_table_free.
Referenced by sql3_execute_query().
00394 { 00395 LOGPRINTF("entry"); 00396 00397 g_return_val_if_fail( db , ER_INVALID_PARAMETER); 00398 g_return_val_if_fail( statements , ER_INVALID_PARAMETER); 00399 g_return_val_if_fail((statements->len > 0 ), ER_INVALID_PARAMETER); 00400 g_return_val_if_fail( result_table , ER_INVALID_PARAMETER); 00401 g_return_val_if_fail(( result_table == NULL 00402 || *result_table == NULL), ER_INVALID_PARAMETER); 00403 00404 // execute each statement 00405 int ret = ER_OK; 00406 unsigned int stmt_idx; 00407 metadata_table *result = NULL; 00408 for ( stmt_idx = 0 ; stmt_idx < statements->len && ret == ER_OK ; stmt_idx++ ) 00409 { 00410 sqlite3_stmt *stmt = g_ptr_array_index(statements, stmt_idx); 00411 // NOTE: memleak on result if several loops? 00412 ret = execute_single_statement(stmt, &result); 00413 if (ret != ER_OK) 00414 { 00415 ERRORPRINTF( "execute_single_statement returns [%d] on stmt_idx [%d], sqlite error [%s]", 00416 ret, stmt_idx, sqlite3_errmsg(db) ); 00417 } 00418 } 00419 00420 // unbind and reset all statements 00421 for (stmt_idx = 0 ; stmt_idx < statements->len ; stmt_idx++) 00422 { 00423 sqlite3_stmt *stmt = g_ptr_array_index(statements, stmt_idx); 00424 00425 // unbind all parameters on this statement 00426 int n_parms = sqlite3_bind_parameter_count(stmt); 00427 int parm_idx; 00428 for (parm_idx = 0 ; parm_idx < n_parms ; parm_idx++) 00429 { 00430 sqlite3_bind_null(stmt, parm_idx + 1); 00431 } 00432 00433 // reset statement 00434 sqlite3_reset(stmt); 00435 } 00436 00437 // discard results on error 00438 if (ret != ER_OK) 00439 { 00440 metadata_table_free(result); 00441 } 00442 00443 if (result_table) 00444 { 00445 *result_table = result; 00446 result = NULL; 00447 } 00448 metadata_table_free(result); 00449 return ret; 00450 }
static void sql3_finalize_statements | ( | GPtrArray * | statements | ) | [static] |
Release compiled sql statements.
---------------------------------------------------------------------------
Name : sql3_finalize_statements
[in] | statements | - GPtrArray with compiled statements |
--------------------------------------------------------------------------
Definition at line 82 of file sqlite3_wrapper.c.
References LOGPRINTF.
Referenced by sql3_execute_query(), and sql3_prepare_statements().
00083 { 00084 LOGPRINTF("entry"); 00085 00086 if (statements) 00087 { 00088 unsigned int i; 00089 for (i = 0 ; i < statements->len ; i++) 00090 { 00091 sqlite3_stmt *stmt = g_ptr_array_index(statements, i); 00092 sqlite3_finalize(stmt); 00093 } 00094 g_ptr_array_free(statements, TRUE); 00095 } 00096 }
static int sql3_prepare_statements | ( | sqlite3 * | db, | |
const char * | sql, | |||
GPtrArray ** | statements | |||
) | [static] |
Parse sql string and compile into byte code.
---------------------------------------------------------------------------
Name : sql3_prepare_statements
[in] | db | - sqlite database object |
[in] | sql | - SQL statement(s) as text |
[out] | statements | - GPtrArray with compiled statements, or NULL |
--------------------------------------------------------------------------
Definition at line 112 of file sqlite3_wrapper.c.
References ER_INVALID_PARAMETER, ER_OK, ER_OUT_OF_MEMORY, ERMETADB_FAIL, ERRORPRINTF, LOGPRINTF, and sql3_finalize_statements().
Referenced by sql3_execute_query().
00113 { 00114 int ret = ER_OK; // return code 00115 const char *head = NULL; // start of current sql statement 00116 const char *tail = NULL; // start of next sql statement, if any 00117 sqlite3_stmt *stmt = NULL; 00118 GPtrArray *stmt_list = NULL; 00119 00120 LOGPRINTF("entry: sql [%s]", sql); 00121 00122 g_return_val_if_fail( db , ER_INVALID_PARAMETER); 00123 g_return_val_if_fail( sql , ER_INVALID_PARAMETER); 00124 g_return_val_if_fail((*sql != '\0' ), ER_INVALID_PARAMETER); 00125 g_return_val_if_fail( statements , ER_INVALID_PARAMETER); 00126 g_return_val_if_fail((*statements == NULL), ER_INVALID_PARAMETER); 00127 00128 // parse sql string and store compiled statements 00129 gboolean done = FALSE; 00130 for ( done = FALSE, head = sql ; !done ; head = tail ) 00131 { 00132 int rc = sqlite3_prepare_v2(db, head, -1, &stmt, &tail); 00133 if (rc != ER_OK) 00134 { 00135 ERRORPRINTF("sqlite error [%d] [%s] on prepare_v2 [%s]", rc, sqlite3_errmsg(db), head); 00136 ret = ERMETADB_FAIL; 00137 done = TRUE; 00138 } 00139 else 00140 { 00141 if (stmt) 00142 { 00143 // statement compiled: store it 00144 if (stmt_list == NULL) 00145 { 00146 stmt_list = g_ptr_array_new(); 00147 if (stmt_list == NULL) 00148 { 00149 ERRORPRINTF("cannot create GPtrArray"); 00150 ret = ER_OUT_OF_MEMORY; 00151 done = TRUE; 00152 } 00153 } 00154 if (stmt_list) 00155 { 00156 g_ptr_array_add(stmt_list, stmt); 00157 } 00158 stmt = NULL; 00159 } 00160 00161 if (*tail == '\0') 00162 { 00163 // no more sql to process 00164 done = TRUE; 00165 } 00166 } 00167 } 00168 00169 // discard compiled statements in case of error 00170 if (ret != ER_OK) 00171 { 00172 if (stmt_list) 00173 { 00174 sql3_finalize_statements(stmt_list); 00175 stmt_list = NULL; 00176 } 00177 } 00178 00179 // return list of prepared statements 00180 *statements = stmt_list; 00181 return ret; 00182 }
int sql3_strcase_compare | ( | void * | user_data, | |
int | left_len, | |||
const void * | left_void, | |||
int | right_len, | |||
const void * | right_void | |||
) |
Compare function to be used in custom collation sequence See documentation on sqlite3_create_collation() for details.
---------------------------------------------------------------------------
Name : sql3_strcase_cmp
--------------------------------------------------------------------------
Definition at line 706 of file sqlite3_wrapper.c.
References LOGPRINTF, and UNUSED.
Referenced by open_sqlite_database().
00711 { 00712 UNUSED(user_data); 00713 int ret = 0; 00714 const gchar *left = (gchar*)left_void; 00715 const gchar *right = (gchar*)right_void; 00716 00717 int len = MIN(left_len, right_len); 00718 if (len == 0) 00719 { 00720 // empty string sorts at end of list 00721 if (left_len == right_len) 00722 { 00723 ret = 0; 00724 } 00725 else if (left_len == 0) 00726 { 00727 ret = 1; 00728 } 00729 else 00730 { 00731 ret = -1; 00732 } 00733 } 00734 else 00735 { 00736 // non-empty string sorts case-insensitive 00737 ret = g_ascii_strncasecmp(left, right, len); 00738 if (ret == 0) 00739 { 00740 if (left_len < right_len) 00741 { 00742 ret = -1; 00743 } 00744 else 00745 { 00746 ret = 1; 00747 } 00748 } 00749 } 00750 00751 LOGPRINTF("return [%d] left [%.*s] right [%.*s]", ret, left_len, left, right_len, right); 00752 return ret; 00753 }
const int BEGIN_MAX_RETRIES = 20 [static] |
Definition at line 57 of file sqlite3_wrapper.c.
Referenced by begin_transaction().
const int BEGIN_RETRY_MS = 250 [static] |
Definition at line 58 of file sqlite3_wrapper.c.
Referenced by begin_transaction(), and sql3_commit_or_rollback().
const int COMMIT_MAX_RETRIES = 30 [static] |
Definition at line 61 of file sqlite3_wrapper.c.
Referenced by sql3_commit_or_rollback().
const int COMMIT_RETRY_MS = 100 [static] |
Definition at line 62 of file sqlite3_wrapper.c.
const int STEP_MAX_RETRIES = 10 [static] |
Definition at line 65 of file sqlite3_wrapper.c.
Referenced by execute_single_statement().
const int STEP_RETRY_MS = 100 [static] |
Definition at line 66 of file sqlite3_wrapper.c.
Referenced by execute_single_statement().