diff options
author | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2015-07-10 13:20:25 +0100 |
---|---|---|
committer | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2015-07-10 13:20:25 +0100 |
commit | e1b9099abb7681ac0fcd9b586790bbefe61ab2f9 (patch) | |
tree | 44ded4ab196979dd33f788813c6ddaec2e9386e5 /src | |
parent | fbf262b29c96394458592afb32bef24a3f8bc9ec (diff) | |
download | rspamd-e1b9099abb7681ac0fcd9b586790bbefe61ab2f9.tar.gz rspamd-e1b9099abb7681ac0fcd9b586790bbefe61ab2f9.zip |
Move sqlite3 utils to a separate module.
Diffstat (limited to 'src')
-rw-r--r-- | src/libstat/backends/sqlite3_backend.c | 219 | ||||
-rw-r--r-- | src/libutil/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/libutil/sqlite_utils.c | 174 | ||||
-rw-r--r-- | src/libutil/sqlite_utils.h | 71 |
4 files changed, 296 insertions, 169 deletions
diff --git a/src/libstat/backends/sqlite3_backend.c b/src/libstat/backends/sqlite3_backend.c index 836886e1f..94252ceb2 100644 --- a/src/libstat/backends/sqlite3_backend.c +++ b/src/libstat/backends/sqlite3_backend.c @@ -23,19 +23,18 @@ */ #include "config.h" -#include "stat_internal.h" #include "main.h" #include "sqlite3.h" +#include "libutil/sqlite_utils.h" +#include "libstat/stat_internal.h" #define SQLITE3_BACKEND_TYPE "sqlite3" #define SQLITE3_SCHEMA_VERSION "1" #define SQLITE3_DEFAULT "default" -struct rspamd_sqlite3_prstmt; - struct rspamd_stat_sqlite3_db { sqlite3 *sqlite; - struct rspamd_sqlite3_prstmt *prstmt; + GArray *prstmt; gboolean in_transaction; }; @@ -93,14 +92,7 @@ enum rspamd_stat_sqlite3_stmt_idx { RSPAMD_STAT_BACKEND_MAX }; -static struct rspamd_sqlite3_prstmt { - enum rspamd_stat_sqlite3_stmt_idx idx; - const gchar *sql; - const gchar *args; - sqlite3_stmt *stmt; - gint result; - const gchar *ret; -} prepared_stmts[RSPAMD_STAT_BACKEND_MAX] = +static struct rspamd_sqlite3_prstmt prepared_stmts[RSPAMD_STAT_BACKEND_MAX] = { { .idx = RSPAMD_STAT_BACKEND_TRANSACTION_START_IM, @@ -184,145 +176,12 @@ static struct rspamd_sqlite3_prstmt { }; static GQuark -rspamd_sqlite3_quark (void) +rspamd_sqlite3_backend_quark (void) { return g_quark_from_static_string ("sqlite3-stat-backend"); } static gboolean -rspamd_sqlite3_init_prstmt (struct rspamd_stat_sqlite3_db *db, GError **err) -{ - int i; - - for (i = 0; i < RSPAMD_STAT_BACKEND_MAX; i ++) { - if (db->prstmt[i].stmt != NULL) { - /* Skip already prepared statements */ - continue; - } - if (sqlite3_prepare_v2 (db->sqlite, db->prstmt[i].sql, -1, - &db->prstmt[i].stmt, NULL) != SQLITE_OK) { - g_set_error (err, rspamd_sqlite3_quark (), - -1, "Cannot initialize prepared sql `%s`: %s", - db->prstmt[i].sql, sqlite3_errmsg (db->sqlite)); - - return FALSE; - } - } - - return TRUE; -} - -static int -rspamd_sqlite3_run_prstmt (struct rspamd_stat_sqlite3_db *db, int idx, ...) -{ - gint retcode; - va_list ap; - sqlite3_stmt *stmt; - gint i, rowid, nargs, j; - const char *argtypes; - - if (idx < 0 || idx >= RSPAMD_STAT_BACKEND_MAX) { - - return -1; - } - - stmt = db->prstmt[idx].stmt; - if (stmt == NULL) { - if ((retcode = sqlite3_prepare_v2 (db->sqlite, db->prstmt[idx].sql, -1, - &db->prstmt[idx].stmt, NULL)) != SQLITE_OK) { - msg_err ("Cannot initialize prepared sql `%s`: %s", - db->prstmt[idx].sql, sqlite3_errmsg (db->sqlite)); - - return retcode; - } - stmt = db->prstmt[idx].stmt; - } - - msg_debug ("executing `%s`", db->prstmt[idx].sql); - argtypes = db->prstmt[idx].args; - sqlite3_reset (stmt); - va_start (ap, idx); - nargs = 1; - - for (i = 0, rowid = 1; argtypes[i] != '\0'; i ++) { - switch (argtypes[i]) { - case 'T': - - for (j = 0; j < nargs; j ++, rowid ++) { - sqlite3_bind_text (stmt, rowid, va_arg (ap, const char*), -1, - SQLITE_STATIC); - } - - nargs = 1; - break; - case 'I': - - for (j = 0; j < nargs; j ++, rowid ++) { - sqlite3_bind_int64 (stmt, rowid, va_arg (ap, gint64)); - } - - nargs = 1; - break; - case 'S': - - for (j = 0; j < nargs; j ++, rowid ++) { - sqlite3_bind_int (stmt, rowid, va_arg (ap, gint)); - } - - nargs = 1; - break; - case '*': - nargs = va_arg (ap, gint); - break; - } - } - - va_end (ap); - retcode = sqlite3_step (stmt); - - if (retcode == db->prstmt[idx].result) { - argtypes = db->prstmt[idx].ret; - - for (i = 0; argtypes != NULL && argtypes[i] != '\0'; i ++) { - switch (argtypes[i]) { - case 'T': - *va_arg (ap, char**) = g_strdup (sqlite3_column_text (stmt, i)); - break; - case 'I': - *va_arg (ap, gint64*) = sqlite3_column_int64 (stmt, i); - break; - case 'S': - *va_arg (ap, int*) = sqlite3_column_int (stmt, i); - break; - } - } - - return SQLITE_OK; - } - else if (retcode != SQLITE_DONE) { - msg_debug ("failed to execute query %s: %d, %s", db->prstmt[idx].sql, - retcode, sqlite3_errmsg (db->sqlite)); - } - - return retcode; -} - -static void -rspamd_sqlite3_close_prstmt (struct rspamd_stat_sqlite3_db *db) -{ - int i; - - for (i = 0; i < RSPAMD_STAT_BACKEND_MAX; i++) { - if (db->prstmt[i].stmt != NULL) { - sqlite3_finalize (db->prstmt[i].stmt); - db->prstmt[i].stmt = NULL; - } - } - - return; -} - -static gboolean rspamd_sqlite3_wait (const gchar *lock) { gint fd; @@ -369,6 +228,12 @@ rspamd_sqlite3_opendb (const gchar *path, const ucl_object_t *opts, user_version[] = "PRAGMA user_version;"; flags = SQLITE_OPEN_READWRITE; +#ifdef SQLITE_OPEN_SHAREDCACHE + flags |= SQLITE_OPEN_SHAREDCACHE; +#endif +#ifdef SQLITE_OPEN_WAL + flags |= SQLITE_OPEN_WAL; +#endif if (create) { flags |= SQLITE_OPEN_CREATE; @@ -378,7 +243,7 @@ rspamd_sqlite3_opendb (const gchar *path, const ucl_object_t *opts, if (lock_fd == -1 && (errno == EEXIST || errno == EBUSY)) { if (!rspamd_sqlite3_wait (lock_path)) { - g_set_error (err, rspamd_sqlite3_quark (), + g_set_error (err, rspamd_sqlite3_backend_quark (), errno, "cannot create sqlite file %s: %s", path, strerror (errno)); @@ -393,7 +258,7 @@ rspamd_sqlite3_opendb (const gchar *path, const ucl_object_t *opts, } } else if (access (path, R_OK) == -1) { - g_set_error (err, rspamd_sqlite3_quark (), + g_set_error (err, rspamd_sqlite3_backend_quark (), errno, "cannot open sqlite file %s: %s", path, strerror (errno)); @@ -403,11 +268,11 @@ rspamd_sqlite3_opendb (const gchar *path, const ucl_object_t *opts, if ((rc = sqlite3_open_v2 (path, &sqlite, flags, NULL)) != SQLITE_OK) { #if SQLITE_VERSION_NUMBER >= 3008000 - g_set_error (err, rspamd_sqlite3_quark (), + g_set_error (err, rspamd_sqlite3_backend_quark (), rc, "cannot open sqlite db %s: %s", path, sqlite3_errstr (rc)); #else - g_set_error (err, rspamd_sqlite3_quark (), + g_set_error (err, rspamd_sqlite3_backend_quark (), rc, "cannot open sqlite db %s: %d", path, rc); #endif @@ -436,7 +301,7 @@ rspamd_sqlite3_opendb (const gchar *path, const ucl_object_t *opts, if (create) { if (sqlite3_exec (sqlite, create_tables_sql, NULL, NULL, NULL) != SQLITE_OK) { - g_set_error (err, rspamd_sqlite3_quark (), + g_set_error (err, rspamd_sqlite3_backend_quark (), -1, "cannot execute create sql `%s`: %s", create_tables_sql, sqlite3_errmsg (sqlite)); sqlite3_close (sqlite); @@ -454,10 +319,13 @@ rspamd_sqlite3_opendb (const gchar *path, const ucl_object_t *opts, bk = g_slice_alloc0 (sizeof (*bk)); bk->sqlite = sqlite; - bk->prstmt = g_slice_alloc0 (sizeof (prepared_stmts)); - memcpy (bk->prstmt, prepared_stmts, sizeof (prepared_stmts)); + bk->prstmt = rspamd_sqlite3_init_prstmt (sqlite, prepared_stmts, + RSPAMD_STAT_BACKEND_MAX, err); + + if (bk->prstmt == NULL) { + g_slice_free1 (sizeof (*bk), bk); + sqlite3_close (sqlite); - if (!rspamd_sqlite3_init_prstmt (bk, err)) { return NULL; } @@ -552,11 +420,12 @@ rspamd_sqlite3_close (gpointer p) if (bk->sqlite) { if (bk->in_transaction) { - rspamd_sqlite3_run_prstmt (bk, RSPAMD_STAT_BACKEND_TRANSACTION_COMMIT); + rspamd_sqlite3_run_prstmt (bk->sqlite, bk->prstmt, + RSPAMD_STAT_BACKEND_TRANSACTION_COMMIT); } + rspamd_sqlite3_close_prstmt (bk->sqlite, bk->prstmt); sqlite3_close (bk->sqlite); - rspamd_sqlite3_close_prstmt (bk); g_slice_free1 (sizeof (*bk), bk); } } @@ -608,14 +477,16 @@ rspamd_sqlite3_process_token (struct rspamd_task *task, struct token_node_s *tok } if (!bk->in_transaction) { - rspamd_sqlite3_run_prstmt (bk, RSPAMD_STAT_BACKEND_TRANSACTION_START_DEF); + rspamd_sqlite3_run_prstmt (bk->sqlite, bk->prstmt, + RSPAMD_STAT_BACKEND_TRANSACTION_START_DEF); bk->in_transaction = TRUE; } memcpy (&idx, tok->data, sizeof (idx)); /* TODO: language and user support */ - if (rspamd_sqlite3_run_prstmt (bk, RSPAMD_STAT_BACKEND_GET_TOKEN, + if (rspamd_sqlite3_run_prstmt (bk->sqlite, bk->prstmt, + RSPAMD_STAT_BACKEND_GET_TOKEN, idx, rt->user_id, rt->lang_id, &iv) == SQLITE_OK) { res->value = iv; @@ -644,7 +515,8 @@ rspamd_sqlite3_finalize_process (struct rspamd_task *task, gpointer runtime, bk = rt->db; if (bk->in_transaction) { - rspamd_sqlite3_run_prstmt (bk, RSPAMD_STAT_BACKEND_TRANSACTION_COMMIT); + rspamd_sqlite3_run_prstmt (bk->sqlite, bk->prstmt, + RSPAMD_STAT_BACKEND_TRANSACTION_COMMIT); bk->in_transaction = FALSE; } @@ -674,15 +546,17 @@ rspamd_sqlite3_learn_token (struct rspamd_task *task, struct token_node_s *tok, } if (!bk->in_transaction) { - rspamd_sqlite3_run_prstmt (bk, RSPAMD_STAT_BACKEND_TRANSACTION_START_IM); + rspamd_sqlite3_run_prstmt (bk->sqlite, bk->prstmt, + RSPAMD_STAT_BACKEND_TRANSACTION_START_IM); bk->in_transaction = TRUE; } iv = res->value; memcpy (&idx, tok->data, sizeof (idx)); - if (rspamd_sqlite3_run_prstmt (bk, RSPAMD_STAT_BACKEND_SET_TOKEN, - idx, rt->user_id, rt->lang_id, iv) == SQLITE_OK) { + if (rspamd_sqlite3_run_prstmt (bk->sqlite, bk->prstmt, + RSPAMD_STAT_BACKEND_SET_TOKEN, + idx, rt->user_id, rt->lang_id, iv) == SQLITE_OK) { return FALSE; } @@ -700,7 +574,8 @@ rspamd_sqlite3_finalize_learn (struct rspamd_task *task, gpointer runtime, bk = rt->db; if (bk->in_transaction) { - rspamd_sqlite3_run_prstmt (bk, RSPAMD_STAT_BACKEND_TRANSACTION_COMMIT); + rspamd_sqlite3_run_prstmt (bk->sqlite, bk->prstmt, + RSPAMD_STAT_BACKEND_TRANSACTION_COMMIT); bk->in_transaction = FALSE; } @@ -717,7 +592,8 @@ rspamd_sqlite3_total_learns (struct rspamd_task *task, gpointer runtime, g_assert (rt != NULL); bk = rt->db; - rspamd_sqlite3_run_prstmt (bk, RSPAMD_STAT_BACKEND_GET_LEARNS, &res); + rspamd_sqlite3_run_prstmt (bk->sqlite, bk->prstmt, + RSPAMD_STAT_BACKEND_GET_LEARNS, &res); return res; } @@ -732,9 +608,11 @@ rspamd_sqlite3_inc_learns (struct rspamd_task *task, gpointer runtime, g_assert (rt != NULL); bk = rt->db; - rspamd_sqlite3_run_prstmt (bk, RSPAMD_STAT_BACKEND_INC_LEARNS, + rspamd_sqlite3_run_prstmt (bk->sqlite, bk->prstmt, + RSPAMD_STAT_BACKEND_INC_LEARNS, SQLITE3_DEFAULT, SQLITE3_DEFAULT); - rspamd_sqlite3_run_prstmt (bk, RSPAMD_STAT_BACKEND_GET_LEARNS, &res); + rspamd_sqlite3_run_prstmt (bk->sqlite, bk->prstmt, + RSPAMD_STAT_BACKEND_GET_LEARNS, &res); return res; } @@ -749,9 +627,11 @@ rspamd_sqlite3_dec_learns (struct rspamd_task *task, gpointer runtime, g_assert (rt != NULL); bk = rt->db; - rspamd_sqlite3_run_prstmt (bk, RSPAMD_STAT_BACKEND_DEC_LEARNS, + rspamd_sqlite3_run_prstmt (bk->sqlite, bk->prstmt, + RSPAMD_STAT_BACKEND_DEC_LEARNS, SQLITE3_DEFAULT, SQLITE3_DEFAULT); - rspamd_sqlite3_run_prstmt (bk, RSPAMD_STAT_BACKEND_GET_LEARNS, &res); + rspamd_sqlite3_run_prstmt (bk->sqlite, bk->prstmt, + RSPAMD_STAT_BACKEND_GET_LEARNS, &res); return res; } @@ -766,7 +646,8 @@ rspamd_sqlite3_learns (struct rspamd_task *task, gpointer runtime, g_assert (rt != NULL); bk = rt->db; - rspamd_sqlite3_run_prstmt (bk, RSPAMD_STAT_BACKEND_GET_LEARNS, &res); + rspamd_sqlite3_run_prstmt (bk->sqlite, bk->prstmt, + RSPAMD_STAT_BACKEND_GET_LEARNS, &res); return res; } diff --git a/src/libutil/CMakeLists.txt b/src/libutil/CMakeLists.txt index 728eeaa47..29c3b2429 100644 --- a/src/libutil/CMakeLists.txt +++ b/src/libutil/CMakeLists.txt @@ -18,6 +18,7 @@ SET(LIBRSPAMDUTILSRC ${CMAKE_CURRENT_SOURCE_DIR}/regexp.c ${CMAKE_CURRENT_SOURCE_DIR}/rrd.c ${CMAKE_CURRENT_SOURCE_DIR}/shingles.c + ${CMAKE_CURRENT_SOURCE_DIR}/sqlite_utils.c ${CMAKE_CURRENT_SOURCE_DIR}/upstream.c ${CMAKE_CURRENT_SOURCE_DIR}/util.c) # Rspamdutil diff --git a/src/libutil/sqlite_utils.c b/src/libutil/sqlite_utils.c new file mode 100644 index 000000000..ba91a874f --- /dev/null +++ b/src/libutil/sqlite_utils.c @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2015, Vsevolod Stakhov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR ''AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "libutil/logger.h" +#include "libutil/sqlite_utils.h" + + +static GQuark +rspamd_sqlite3_quark (void) +{ + return g_quark_from_static_string ("rspamd-sqlite3"); +} + +GArray* +rspamd_sqlite3_init_prstmt (sqlite3 *db, + struct rspamd_sqlite3_prstmt *init_stmt, + gint max_idx, + GError **err) +{ + gint i; + GArray *res; + struct rspamd_sqlite3_prstmt *nst; + + res = g_array_sized_new (FALSE, TRUE, sizeof (struct rspamd_sqlite3_prstmt), + max_idx); + g_array_set_size (res, max_idx); + + for (i = 0; i < max_idx; i ++) { + nst = &g_array_index (res, struct rspamd_sqlite3_prstmt, i); + memcpy (nst, &init_stmt[i], sizeof (*nst)); + + if (sqlite3_prepare_v2 (db, init_stmt[i].sql, -1, + &nst->stmt, NULL) != SQLITE_OK) { + g_set_error (err, rspamd_sqlite3_quark (), + -1, "Cannot initialize prepared sql `%s`: %s", + nst->sql, sqlite3_errmsg (db)); + rspamd_sqlite3_close_prstmt (db, res); + + return NULL; + } + } + + return res; +} + +int +rspamd_sqlite3_run_prstmt (sqlite3 *db, GArray *stmts, + gint idx, ...) +{ + gint retcode; + va_list ap; + sqlite3_stmt *stmt; + gint i, rowid, nargs, j; + struct rspamd_sqlite3_prstmt *nst; + const char *argtypes; + + if (idx < 0 || idx >= (gint)stmts->len) { + + return -1; + } + + nst = &g_array_index (stmts, struct rspamd_sqlite3_prstmt, idx); + stmt = nst->stmt; + + g_assert (nst != NULL); + + msg_debug ("executing `%s`", nst->sql); + argtypes = nst->args; + sqlite3_reset (stmt); + va_start (ap, idx); + nargs = 1; + + for (i = 0, rowid = 1; argtypes[i] != '\0'; i ++) { + switch (argtypes[i]) { + case 'T': + + for (j = 0; j < nargs; j ++, rowid ++) { + sqlite3_bind_text (stmt, rowid, va_arg (ap, const char*), -1, + SQLITE_STATIC); + } + + nargs = 1; + break; + case 'I': + + for (j = 0; j < nargs; j ++, rowid ++) { + sqlite3_bind_int64 (stmt, rowid, va_arg (ap, gint64)); + } + + nargs = 1; + break; + case 'S': + + for (j = 0; j < nargs; j ++, rowid ++) { + sqlite3_bind_int (stmt, rowid, va_arg (ap, gint)); + } + + nargs = 1; + break; + case '*': + nargs = va_arg (ap, gint); + break; + } + } + + va_end (ap); + retcode = sqlite3_step (stmt); + + if (retcode == nst->result) { + argtypes = nst->ret; + + for (i = 0; argtypes != NULL && argtypes[i] != '\0'; i ++) { + switch (argtypes[i]) { + case 'T': + *va_arg (ap, char**) = g_strdup (sqlite3_column_text (stmt, i)); + break; + case 'I': + *va_arg (ap, gint64*) = sqlite3_column_int64 (stmt, i); + break; + case 'S': + *va_arg (ap, int*) = sqlite3_column_int (stmt, i); + break; + } + } + + return SQLITE_OK; + } + else if (retcode != SQLITE_DONE) { + msg_debug ("failed to execute query %s: %d, %s", nst->sql, + retcode, sqlite3_errmsg (db)); + } + + return retcode; +} + +void +rspamd_sqlite3_close_prstmt (sqlite3 *db, GArray *stmts) +{ + guint i; + struct rspamd_sqlite3_prstmt *nst; + + for (i = 0; i < stmts->len; i++) { + nst = &g_array_index (stmts, struct rspamd_sqlite3_prstmt, i); + if (nst->stmt != NULL) { + sqlite3_finalize (nst->stmt); + } + } + + g_array_free (stmts, TRUE); + + return; +} diff --git a/src/libutil/sqlite_utils.h b/src/libutil/sqlite_utils.h new file mode 100644 index 000000000..5cb71f3ad --- /dev/null +++ b/src/libutil/sqlite_utils.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2015, Vsevolod Stakhov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR ''AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#ifndef SRC_LIBUTIL_SQLITE_UTILS_H_ +#define SRC_LIBUTIL_SQLITE_UTILS_H_ + +#include "config.h" +#include "sqlite3.h" + +struct rspamd_sqlite3_prstmt { + gint idx; + const gchar *sql; + const gchar *args; + sqlite3_stmt *stmt; + gint result; + const gchar *ret; +}; + +/** + * Create prepared statements for specified database from init statements + * @param db + * @param max_idx + * @param err + * @return new prepared statements array or NULL + */ +GArray* rspamd_sqlite3_init_prstmt (sqlite3 *db, + struct rspamd_sqlite3_prstmt *init_stmt, + gint max_idx, + GError **err); + +/** + * Run prepared statements by its index getting parameters and setting results from + * varargs structure + * @param db + * @param stmts + * @param idx + * @return + */ +gint rspamd_sqlite3_run_prstmt (sqlite3 *db, GArray *stmts, + gint idx, ...); + +/** + * Close and free prepared statements + * @param db + * @param stmts + */ +void rspamd_sqlite3_close_prstmt (sqlite3 *db, GArray *stmts); + +#endif /* SRC_LIBUTIL_SQLITE_UTILS_H_ */ |