/* APR cleanup function used to close the database when its pool is destoryed. DATA should be the svn_sqlite__db_t handle for the database. */ static apr_status_t close_apr(void *data) { svn_sqlite__db_t *db = data; svn_error_t *err = SVN_NO_ERROR; int result; int i; /* Finalize any existing prepared statements. */ for (i = 0; i < db->nbr_statements; i++) { if (db->prepared_stmts[i]) err = svn_error_compose_create( svn_sqlite__finalize(db->prepared_stmts[i]), err); } result = sqlite3_close(db->db3); /* If there's a pre-existing error, return it. */ if (err) { result = err->apr_err; svn_error_clear(err); return result; } if (result != SQLITE_OK) return SQLITE_ERROR_CODE(result); return APR_SUCCESS; }
/* Don't call this function directly! Use svn_atomic__init_once(). */ static svn_error_t * init_sqlite(void *baton, apr_pool_t *pool) { if (sqlite3_libversion_number() < SQLITE_VERSION_NUMBER) { return svn_error_createf(SVN_ERR_SQLITE_ERROR, NULL, _("SQLite compiled for %s, but running with %s"), SQLITE_VERSION, sqlite3_libversion()); } #if APR_HAS_THREADS #if SQLITE_VERSION_AT_LEAST(3,5,0) /* SQLite 3.5 allows verification of its thread-safety at runtime. Older versions are simply expected to have been configured with --enable-threadsafe, which compiles with -DSQLITE_THREADSAFE=1 (or -DTHREADSAFE, for older versions). */ if (! sqlite3_threadsafe()) return svn_error_create(SVN_ERR_SQLITE_ERROR, NULL, _("SQLite is required to be compiled and run in " "thread-safe mode")); #endif #if SQLITE_VERSION_AT_LEAST(3,6,0) /* If SQLite has been already initialized, sqlite3_config() returns SQLITE_MISUSE. */ { int err = sqlite3_config(SQLITE_CONFIG_MULTITHREAD); if (err != SQLITE_OK && err != SQLITE_MISUSE) return svn_error_create(SQLITE_ERROR_CODE(err), NULL, "Could not configure SQLite"); } SQLITE_ERR_MSG(sqlite3_initialize(), "Could not initialize SQLite"); #endif #endif /* APR_HAS_THRADS */ return SVN_NO_ERROR; }
static svn_error_t * internal_open(sqlite3 **db3, const char *path, svn_sqlite__mode_t mode, apr_pool_t *scratch_pool) { { int flags; if (mode == svn_sqlite__mode_readonly) flags = SQLITE_OPEN_READONLY; else if (mode == svn_sqlite__mode_readwrite) flags = SQLITE_OPEN_READWRITE; else if (mode == svn_sqlite__mode_rwcreate) flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE; else SVN_ERR_MALFUNCTION(); /* If this flag is defined (3.6.x), then let's turn off SQLite's mutexes. All svn objects are single-threaded, so we can already guarantee that our use of the SQLite handle will be serialized properly. Note: in 3.6.x, we've already config'd SQLite into MULTITHREAD mode, so this is probably redundant, but if we are running in a process where somebody initialized SQLite before us it is needed anyway. */ #ifdef SQLITE_OPEN_NOMUTEX flags |= SQLITE_OPEN_NOMUTEX; #endif /* Open the database. Note that a handle is returned, even when an error occurs (except for out-of-memory); thus, we can safely use it to extract an error message and construct an svn_error_t. */ { /* We'd like to use SQLITE_ERR_MSG here, but we can't since it would just return an error and leave the database open. So, we need to do this manually. */ /* ### SQLITE_CANTOPEN */ int err_code = sqlite3_open_v2(path, db3, flags, NULL); if (err_code != SQLITE_OK) { /* Save the error message before closing the SQLite handle. */ char *msg = apr_pstrdup(scratch_pool, sqlite3_errmsg(*db3)); /* We don't catch the error here, since we care more about the open error than the close error at this point. */ sqlite3_close(*db3); return svn_error_createf(SQLITE_ERROR_CODE(err_code), NULL, "sqlite: %s: '%s'", msg, path); } } } /* Retry until timeout when database is busy. */ SQLITE_ERR_MSG(sqlite3_busy_timeout(*db3, BUSY_TIMEOUT), sqlite3_errmsg(*db3)); return SVN_NO_ERROR; }
/* APR cleanup function used to close the database when its pool is destroyed. DATA should be the svn_sqlite__db_t handle for the database. */ static apr_status_t close_apr(void *data) { svn_sqlite__db_t *db = data; svn_error_t *err = SVN_NO_ERROR; apr_status_t result; int i; /* Check to see if we've already closed this database. */ if (db->db3 == NULL) return APR_SUCCESS; /* Finalize any prepared statements. */ if (db->prepared_stmts) { for (i = 0; i < db->nbr_statements + STMT_INTERNAL_LAST; i++) { if (db->prepared_stmts[i]) { if (i < db->nbr_statements && db->prepared_stmts[i]->needs_reset) { #ifdef SVN_DEBUG const char *stmt_text = db->statement_strings[i]; SVN_UNUSED(stmt_text); SVN_ERR_MALFUNCTION_NO_RETURN(); #else err = svn_error_compose_create(err, svn_sqlite__reset(db->prepared_stmts[i])); #endif } err = svn_error_compose_create( svn_sqlite__finalize(db->prepared_stmts[i]), err); } } } result = sqlite3_close(db->db3); /* If there's a pre-existing error, return it. */ if (err) { result = err->apr_err; svn_error_clear(err); return result; } if (result != SQLITE_OK) return SQLITE_ERROR_CODE(result); /* ### lossy */ db->db3 = NULL; return APR_SUCCESS; }
svn_error_t * svn_sqlite__exec(svn_sqlite__db_t *db, const char *sql) { char *err_msg; int sqlite_err = sqlite3_exec(db->db3, sql, NULL, NULL, &err_msg); if (sqlite_err != SQLITE_OK) { svn_error_t *err = svn_error_create(SQLITE_ERROR_CODE(sqlite_err), NULL, err_msg); sqlite3_free(err_msg); return err; } return SVN_NO_ERROR; }
/* Run the statement SQL on DB, ignoring SQLITE_OK and IGNORED_ERR. (Note: the IGNORED_ERR parameter itself is not ignored.) */ static svn_error_t * exec_sql2(svn_sqlite__db_t *db, const char *sql, int ignored_err) { char *err_msg; int sqlite_err = sqlite3_exec(db->db3, sql, NULL, NULL, &err_msg); if (sqlite_err != SQLITE_OK && sqlite_err != ignored_err) { svn_error_t *err = svn_error_createf(SQLITE_ERROR_CODE(sqlite_err), NULL, _("%s, executing statement '%s'"), err_msg, sql); sqlite3_free(err_msg); return err; } return SVN_NO_ERROR; }
svn_error_t * svn_sqlite__step(svn_boolean_t *got_row, svn_sqlite__stmt_t *stmt) { int sqlite_result = sqlite3_step(stmt->s3stmt); if (sqlite_result != SQLITE_DONE && sqlite_result != SQLITE_ROW) { svn_error_t *err1, *err2; err1 = svn_error_create(SQLITE_ERROR_CODE(sqlite_result), NULL, sqlite3_errmsg(stmt->db->db3)); err2 = svn_sqlite__reset(stmt); return svn_error_compose_create(err1, err2); } *got_row = (sqlite_result == SQLITE_ROW); return SVN_NO_ERROR; }