sqlite3_wrapper.c File Reference

#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"
Include dependency graph for sqlite3_wrapper.c:

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_tablecreate_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 Documentation

#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 (  )     (void)(x)

Definition at line 50 of file sqlite3_wrapper.c.


Function Documentation

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 }

Here is the caller graph for this function:

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 }

Here is the call graph for this function:

Here is the caller graph for this function:

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 }

Here is the call graph for this function:

Here is the caller graph for this function:

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 }

Here is the call graph for this function:

Here is the caller graph for this function:

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

Parameters:
[in] thiz - erMetadb object on which to start a transaction
Returns:
ER_OK or error

--------------------------------------------------------------------------

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 }

Here is the call graph for this function:

Here is the caller graph for this function:

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

Parameters:
[in] thiz - erMetadb object on which to start a transaction
Returns:
ER_OK or error

--------------------------------------------------------------------------

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 }

Here is the call graph for this function:

Here is the caller graph for this function:

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

Parameters:
[in/out] statements - GPtrArray with compiled statements
[in] parameters - metadata_table with parameters (value), or NULL table must have exactly one row
Returns:
ER_OK or error code

--------------------------------------------------------------------------

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 }

Here is the call graph for this function:

Here is the caller graph for this function:

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

Parameters:
[in] thiz - erMetadb object on which to end a transaction
[in] err - ER_OK or error code
Returns:
ER_OK or error or 'err' value when this is not ER_OK

--------------------------------------------------------------------------

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 }

Here is the caller graph for this function:

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

Parameters:
[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.
Returns:
ER_OK or error code

--------------------------------------------------------------------------

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 }

Here is the call graph for this function:

Here is the caller graph for this function:

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

Parameters:
[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.
Returns:
ER_OK or error code

--------------------------------------------------------------------------

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 }

Here is the call graph for this function:

Here is the caller graph for this function:

static void sql3_finalize_statements ( GPtrArray *  statements  )  [static]

Release compiled sql statements.

---------------------------------------------------------------------------

Name : sql3_finalize_statements

Parameters:
[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 }

Here is the caller graph for this function:

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

Parameters:
[in] db - sqlite database object
[in] sql - SQL statement(s) as text
[out] statements - GPtrArray with compiled statements, or NULL
Returns:
ER_OK or error code

--------------------------------------------------------------------------

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 }

Here is the call graph for this function:

Here is the caller graph for this function:

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 }

Here is the caller graph for this function:


Variable Documentation

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().

Generated by  doxygen 1.6.2-20100208