aboutsummaryrefslogtreecommitdiff
path: root/core/sql.c
diff options
context:
space:
mode:
Diffstat (limited to 'core/sql.c')
-rw-r--r--core/sql.c49
1 files changed, 49 insertions, 0 deletions
diff --git a/core/sql.c b/core/sql.c
new file mode 100644
index 0000000..a03ce5d
--- /dev/null
+++ b/core/sql.c
@@ -0,0 +1,49 @@
+void salis_exec_sql(int blob_cnt, const void **blobs, const int *blob_sizes, const char *sql_format, ...) {
+ assert(sql_format);
+
+ va_list args;
+ va_start(args, sql_format);
+ int sql_len = vsnprintf(NULL, 0, sql_format, args) + 1;
+ char *sql_str = malloc(sql_len);
+ assert(sql_str);
+ va_end(args);
+
+ va_start(args, sql_format);
+ vsprintf(sql_str, sql_format, args);
+ va_end(args);
+
+ int sql_res;
+ sqlite3_stmt *sql_stmt;
+
+ sql_res = sqlite3_prepare_v2(g_sim_db, sql_str, -1, &sql_stmt, NULL);
+ assert(sql_res == SQLITE_OK);
+ free(sql_str);
+
+ for (int i = 0; i < blob_cnt; ++i) {
+ assert(blobs[i]);
+ sql_res = sqlite3_bind_blob(sql_stmt, i + 1, blobs[i], blob_sizes[i], SQLITE_STATIC);
+ assert(sql_res == SQLITE_OK);
+ }
+
+ // Only handle SQLITE_BUSY error, in which case we retry the query.
+ // Setting 'journal_mode=wal;' should help prevent busy database errors.
+ while (true) {
+ sql_res = sqlite3_step(sql_stmt);
+
+ if (sql_res == SQLITE_DONE || sql_res == SQLITE_ROW) {
+ break;
+ }
+
+ g_warn("SQLite database returned error %d with message:", sql_res);
+ g_warn(sqlite3_errmsg(g_sim_db));
+
+ if (sql_res == SQLITE_BUSY) {
+ g_info("Will retry query...");
+ continue;
+ }
+
+ assert(false);
+ }
+
+ sqlite3_finalize(sql_stmt);
+}