aboutsummaryrefslogtreecommitdiffstats
path: root/src/libutil/sqlite_utils.c
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@highsecure.ru>2016-05-23 16:37:16 +0100
committerVsevolod Stakhov <vsevolod@highsecure.ru>2016-05-23 16:37:16 +0100
commitc15fd65bc3e7f447a816e9539afa92f444f53480 (patch)
treef4febdf6bf08508df7e2fe92f152c2e399c8791e /src/libutil/sqlite_utils.c
parent7657cc4be6d681b05f13042176283376c2a0d601 (diff)
downloadrspamd-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.c78
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",