diff options
author | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2016-05-23 16:37:16 +0100 |
---|---|---|
committer | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2016-05-23 16:37:16 +0100 |
commit | c15fd65bc3e7f447a816e9539afa92f444f53480 (patch) | |
tree | f4febdf6bf08508df7e2fe92f152c2e399c8791e /src/libutil/sqlite_utils.c | |
parent | 7657cc4be6d681b05f13042176283376c2a0d601 (diff) | |
download | rspamd-c15fd65bc3e7f447a816e9539afa92f444f53480.tar.gz rspamd-c15fd65bc3e7f447a816e9539afa92f444f53480.zip |
[Feature] Allow versioning for sqlite databases
Diffstat (limited to 'src/libutil/sqlite_utils.c')
-rw-r--r-- | src/libutil/sqlite_utils.c | 78 |
1 files changed, 76 insertions, 2 deletions
diff --git a/src/libutil/sqlite_utils.c b/src/libutil/sqlite_utils.c index 452559c76..e7768142c 100644 --- a/src/libutil/sqlite_utils.c +++ b/src/libutil/sqlite_utils.c @@ -248,7 +248,7 @@ rspamd_sqlite3_wait (rspamd_mempool_t *pool, const gchar *lock) sqlite3 * rspamd_sqlite3_open_or_create (rspamd_mempool_t *pool, const gchar *path, const - gchar *create_sql, GError **err) + gchar *create_sql, guint version, GError **err) { sqlite3 *sqlite; gint rc, flags, lock_fd; @@ -268,7 +268,8 @@ rspamd_sqlite3_open_or_create (rspamd_mempool_t *pool, const gchar *path, const other_pragmas[] = "PRAGMA read_uncommitted=\"ON\";" "PRAGMA cache_size=" - G_STRINGIFY(RSPAMD_SQLITE_CACHE_SIZE) ";"; + G_STRINGIFY(RSPAMD_SQLITE_CACHE_SIZE) ";", + db_version[] = "PRAGMA user_version;"; gboolean create = FALSE, has_lock = FALSE; flags = SQLITE_OPEN_READWRITE; @@ -401,6 +402,79 @@ rspamd_sqlite3_open_or_create (rspamd_mempool_t *pool, const gchar *path, const return NULL; } } + else if (has_lock && version > 0) { + /* Check user version */ + sqlite3_stmt *stmt = NULL; + guint32 db_ver; + GString *new_ver_sql; + + if (sqlite3_prepare (sqlite, db_version, -1, &stmt, NULL) != SQLITE_OK) { + msg_warn_pool_check ("Cannot get user version pragma", + sqlite3_errmsg (sqlite)); + } + else { + if (sqlite3_step (stmt) != SQLITE_ROW) { + msg_warn_pool_check ("Cannot get user version pragma, step failed", + sqlite3_errmsg (sqlite)); + sqlite3_finalize (stmt); + } + else { + db_ver = sqlite3_column_int (stmt, 0); + sqlite3_reset (stmt); + sqlite3_finalize (stmt); + + if (version > db_ver) { + msg_warn_pool_check ("Database version %ud is less than " + "desired version %ud, run create script", db_ver, + version); + + if (create_sql) { + if (sqlite3_exec (sqlite, create_sql, NULL, NULL, NULL) != SQLITE_OK) { + g_set_error (err, rspamd_sqlite3_quark (), + -1, "cannot execute create sql `%s`: %s", + create_sql, sqlite3_errmsg (sqlite)); + sqlite3_close (sqlite); + rspamd_file_unlock (lock_fd, FALSE); + unlink (lock_path); + if (lock_fd != -1) { + close (lock_fd); + } + + return NULL; + } + } + + new_ver_sql = g_string_new ("PRAGMA user_version="); + rspamd_printf_gstring (new_ver_sql, "%ud", version); + + if (sqlite3_exec (sqlite, new_ver_sql->str, NULL, NULL, NULL) + != SQLITE_OK) { + g_set_error (err, rspamd_sqlite3_quark (), + -1, "cannot execute update version sql `%s`: %s", + new_ver_sql->str, sqlite3_errmsg (sqlite)); + sqlite3_close (sqlite); + rspamd_file_unlock (lock_fd, FALSE); + unlink (lock_path); + if (lock_fd != -1) { + close (lock_fd); + } + + g_string_free (new_ver_sql, TRUE); + + return NULL; + } + + g_string_free (new_ver_sql, TRUE); + } + else if (db_ver > version) { + msg_warn_pool_check ("Database version %ud is more than " + "desired version %ud, this could cause" + " unexpected behaviour", db_ver, + version); + } + } + } + } if (sqlite3_exec (sqlite, sqlite_wal, NULL, NULL, NULL) != SQLITE_OK) { msg_warn_pool_check ("WAL mode is not supported (%s), locking issues might occur", |