Skip to content

Commit

Permalink
Merge pull request #3559 from vasilevalex/sqlite_newparams
Browse files Browse the repository at this point in the history
db_sqlite: new parameters for SQLite configuration
  • Loading branch information
bogdan-iancu authored Jan 16, 2025
2 parents 9f2aa5b + 083603b commit 7192510
Show file tree
Hide file tree
Showing 6 changed files with 128 additions and 55 deletions.
34 changes: 32 additions & 2 deletions modules/db_sqlite/db_sqlite.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,17 @@
#include <sqlite3.h>
#define ALLOC_LIMIT 10
#define LDEXT_LIST_DELIM ';'
#define BUSY_TIMEOUT 500

int db_sqlite_alloc_limit=ALLOC_LIMIT;


int db_sqlite_busy_timeout=BUSY_TIMEOUT;

static int sqlite_mod_init(void);
static void sqlite_mod_destroy(void);
static int db_sqlite_add_extension(modparam_t type, void *val);
struct db_sqlite_extension_list *extension_list=0;
static int db_sqlite_exec_pragma(modparam_t type, void *val);
struct db_sqlite_pragma_list *pragma_list=0;

/*
* SQLite database module interface
Expand All @@ -55,8 +57,11 @@ static const cmd_export_t cmds[] = {
*/
static const param_export_t params[] = {
{"alloc_limit", INT_PARAM, &db_sqlite_alloc_limit},
{"busy_timeout", INT_PARAM, &db_sqlite_busy_timeout},
{"load_extension", STR_PARAM|USE_FUNC_PARAM,
(void *)db_sqlite_add_extension},
{"exec_pragma", STR_PARAM|USE_FUNC_PARAM,
(void *)db_sqlite_exec_pragma},
{0, 0, 0}
};

Expand Down Expand Up @@ -92,11 +97,18 @@ static int sqlite_mod_init(void)
static void sqlite_mod_destroy(void)
{
struct db_sqlite_extension_list *foo=NULL;
struct db_sqlite_pragma_list *p_iter=NULL;

while (extension_list) {
foo=extension_list;
extension_list=extension_list->next;
pkg_free(foo);
}
while (pragma_list) {
p_iter=pragma_list;
pragma_list=pragma_list->next;
pkg_free(p_iter);
}
}


Expand Down Expand Up @@ -154,3 +166,21 @@ static int db_sqlite_add_extension(modparam_t type, void *val)
LM_ERR("no more pkg mem\n");
return -1;
}

static int db_sqlite_exec_pragma(modparam_t type, void *val)
{
struct db_sqlite_pragma_list *node;

node=pkg_malloc(sizeof(struct db_sqlite_pragma_list));
if (!node)
goto out;

node->pragma=(char *)val;
node->next=pragma_list;
pragma_list=node;

return 0;
out:
LM_ERR("no more pkg mem\n");
return -1;
}
6 changes: 6 additions & 0 deletions modules/db_sqlite/db_sqlite.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@ struct db_sqlite_extension_list {
struct db_sqlite_extension_list *next;
};

struct db_sqlite_pragma_list {
char *pragma;

struct db_sqlite_pragma_list *next;
};

int db_sqlite_bind_api(const str* mod, db_func_t *dbb);

#endif
Expand Down
43 changes: 0 additions & 43 deletions modules/db_sqlite/dbase.c
Original file line number Diff line number Diff line change
Expand Up @@ -117,10 +117,7 @@ db_sqlite_get_query_rows(const db_con_t* _h, const str* query, const db_val_t* _
int ret;
sqlite3_stmt* stmt;

again:
ret=sqlite3_prepare_v2(CON_CONNECTION(_h), query->s, query->len, &stmt, NULL);
if (ret == SQLITE_BUSY)
goto again;

if (ret != SQLITE_OK) {
LM_ERR("failed to prepare query\n");
Expand All @@ -134,11 +131,7 @@ db_sqlite_get_query_rows(const db_con_t* _h, const str* query, const db_val_t* _
}
#endif

again2:
ret=sqlite3_step(stmt);
if (ret == SQLITE_BUSY)
goto again2;

if (ret != SQLITE_ROW) {
sqlite3_finalize(stmt);
LM_ERR("failed to fetch query size\n");
Expand Down Expand Up @@ -180,12 +173,9 @@ int db_sqlite_query(const db_con_t* _h, const db_key_t* _k, const db_op_t* _op,
}


again:
ret=sqlite3_prepare_v2(CON_CONNECTION(_h),
query_holder.s, query_holder.len, &CON_SQLITE_PS(_h), NULL);

if (ret==SQLITE_BUSY)
goto again;
if (ret!=SQLITE_OK)
LM_ERR("failed to prepare: (%s)\n", sqlite3_errmsg(CON_CONNECTION(_h)));

Expand Down Expand Up @@ -383,11 +373,8 @@ int db_sqlite_raw_query(const db_con_t* _h, const str* _s, db_res_t** _r)
return -1;
}

again:
ret=sqlite3_prepare_v2(CON_CONNECTION(_h),
_s->s, _s->len, &CON_SQLITE_PS(_h), NULL);
if (ret==SQLITE_BUSY)
goto again;
if (ret!=SQLITE_OK)
LM_ERR("failed to prepare: (%s)\n",
sqlite3_errmsg(CON_CONNECTION(_h)));
Expand Down Expand Up @@ -432,11 +419,8 @@ int db_sqlite_insert(const db_con_t* _h, const db_key_t* _k, const db_val_t* _v,
return ret;
}

again:
ret=sqlite3_prepare_v2(CON_CONNECTION(_h),
query_holder.s, query_holder.len, &stmt, NULL);
if (ret==SQLITE_BUSY)
goto again;
if (ret!=SQLITE_OK)
LM_ERR("failed to prepare: (%s)\n",
sqlite3_errmsg(CON_CONNECTION(_h)));
Expand All @@ -448,10 +432,7 @@ int db_sqlite_insert(const db_con_t* _h, const db_key_t* _k, const db_val_t* _v,
}
#endif

again2:
ret = sqlite3_step(stmt);
if (ret==SQLITE_BUSY)
goto again2;

if (ret != SQLITE_DONE) {
LM_ERR("insert query failed %s\n", sqlite3_errmsg(CON_CONNECTION(_h)));
Expand Down Expand Up @@ -492,11 +473,8 @@ int db_sqlite_delete(const db_con_t* _h, const db_key_t* _k, const db_op_t* _o,
}


again:
ret=sqlite3_prepare_v2(CON_CONNECTION(_h),
query_holder.s, query_holder.len, &stmt, NULL);
if (ret==SQLITE_BUSY)
goto again;
if (ret!=SQLITE_OK)
LM_ERR("failed to prepare: (%s)\n",
sqlite3_errmsg(CON_CONNECTION(_h)));
Expand All @@ -508,10 +486,7 @@ int db_sqlite_delete(const db_con_t* _h, const db_key_t* _k, const db_op_t* _o,
}
#endif

again2:
ret = sqlite3_step(stmt);
if (ret==SQLITE_BUSY)
goto again2;

if (ret != SQLITE_DONE) {
LM_ERR("insert query failed %s\n", sqlite3_errmsg(CON_CONNECTION(_h)));
Expand Down Expand Up @@ -554,11 +529,8 @@ int db_sqlite_update(const db_con_t* _h, const db_key_t* _k, const db_op_t* _o,
return ret;
}

again:
ret=sqlite3_prepare_v2(CON_CONNECTION(_h),
query_holder.s, query_holder.len, &stmt, NULL);
if (ret==SQLITE_BUSY)
goto again;
if (ret!=SQLITE_OK)
LM_ERR("failed to prepare: (%s)\n",
sqlite3_errmsg(CON_CONNECTION(_h)));
Expand All @@ -571,10 +543,7 @@ int db_sqlite_update(const db_con_t* _h, const db_key_t* _k, const db_op_t* _o,
}
#endif

again2:
ret = sqlite3_step(stmt);
if (ret==SQLITE_BUSY)
goto again2;

if (ret != SQLITE_DONE) {
LM_ERR("insert query failed %s\n", sqlite3_errmsg(CON_CONNECTION(_h)));
Expand Down Expand Up @@ -611,11 +580,8 @@ int db_sqlite_replace(const db_con_t* _h, const db_key_t* _k, const db_val_t* _v
return ret;
}

again:
ret=sqlite3_prepare_v2(CON_CONNECTION(_h),
query_holder.s, query_holder.len, &stmt, NULL);
if (ret==SQLITE_BUSY)
goto again;
if (ret!=SQLITE_OK)
LM_ERR("failed to prepare: (%s)\n",
sqlite3_errmsg(CON_CONNECTION(_h)));
Expand All @@ -627,10 +593,7 @@ int db_sqlite_replace(const db_con_t* _h, const db_key_t* _k, const db_val_t* _v
}
#endif

again2:
ret = sqlite3_step(stmt);
if (ret==SQLITE_BUSY)
goto again2;

if (ret != SQLITE_DONE) {
LM_ERR("insert query failed %s\n", sqlite3_errmsg(CON_CONNECTION(_h)));
Expand Down Expand Up @@ -704,11 +667,8 @@ int db_last_inserted_id(const db_con_t* _h)
sql_str.s = sql_buf;
sql_str.len = off;

again:
ret=sqlite3_prepare_v2(CON_CONNECTION(_h),
sql_str.s, sql_str.len, &stmt, NULL);
if (ret==SQLITE_BUSY)
goto again;
if (ret!=SQLITE_OK)
LM_ERR("failed to prepare: (%s)\n",
sqlite3_errmsg(CON_CONNECTION(_h)));
Expand All @@ -720,10 +680,7 @@ int db_last_inserted_id(const db_con_t* _h)
}
#endif

again2:
ret = sqlite3_step(stmt);
if (ret==SQLITE_BUSY)
goto again2;

if (ret != SQLITE_DONE) {
LM_ERR("insert query failed %s\n", sqlite3_errmsg(CON_CONNECTION(_h)));
Expand Down
54 changes: 52 additions & 2 deletions modules/db_sqlite/doc/db_sqlite_admin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ modparam("db_sqlite", "alloc_limit", 25)
</emphasis>
</para>
<example>
<title>Set <varname>db_sqlite_alloc_limit</varname> parameter</title>
<title>Set <varname>load_extension</varname> parameter</title>
<programlisting format="linespecific">
...
modparam("db_sqlite", "load_extension", "/usr/lib/sqlite3/pcre.so")
Expand All @@ -103,7 +103,57 @@ modparam("db_sqlite", "load_extension", "/usr/lib/sqlite3/pcre.so;sqlite3_extens
</programlisting>
</example>
</section>

<section id="param_busy_timeout" xreflabel="busy_timeout">
<title><varname>busy_timeout</varname> (integer)</title>
<para>
This parameter sets the default busy_handler for the SQLite library, that sleeps for
a specified amount of time when a table is locked. The handler will sleep multiple
times until at least the specified "busy_timeout" duration (in milliseconds) has been
reached. Setting this parameter to a value less than or equal to zero turns off all
busy handlers. (read more in the
<ulink url="https://www.sqlite.org/capi3ref.html#sqlite3_busy_timeout">SQLite
official documentation</ulink>)
</para>
<para>
<emphasis>
Default value is 500.
</emphasis>
</para>
<example>
<title>Set <varname>busy_timeout</varname> parameter</title>
<programlisting format="linespecific">
...
modparam("db_sqlite", "busy_timeout", 5000)
...
</programlisting>
</example>
</section>
<section id="param_exec_pragma" xreflabel="exec_pragma">
<title><varname>exec_pragma</varname> (string)</title>
<para>
This parameter allows configuring an SQLite database with "PRAGMA" statements, (read
more in the <ulink url="https://sqlite.org/pragma.html">SQLite official documentation</ulink>)
To use this functionality you must specify the exec_pragma parameter value as
"pragma-name=pragma-value". Multiple parameters with the same name can be specified,
and they will be executed one by one on every database connection. If a parameter has an
incorrect name or syntax, it will be ignored by SQLite without any error messages.
</para>
<para>
<emphasis>
By default, no PRAGMA statements are executed.
</emphasis>
</para>
<example>
<title>Set <varname>exec_pragma</varname> parameter</title>
<programlisting format="linespecific">
...
modparam("db_sqlite", "exec_pragma", "journal_mode=wal")
modparam("db_sqlite", "exec_pragma", "synchronous=normal")
modparam("db_sqlite", "exec_pragma", "cache_size=-2000")
...
</programlisting>
</example>
</section>
</section>
<section id="exported_functions" xreflabel="exported_functions">
<title>Exported Functions</title>
Expand Down
2 changes: 0 additions & 2 deletions modules/db_sqlite/res.c
Original file line number Diff line number Diff line change
Expand Up @@ -374,8 +374,6 @@ static inline int db_sqlite_convert_rows(const db_con_t* _h, db_res_t* _r)

while (ret != SQLITE_DONE) {
ret = sqlite3_step(CON_SQLITE_PS(_h));
if (ret == SQLITE_BUSY)
continue;

if (ret == SQLITE_DONE) {
RES_ROW_N(_r) = RES_LAST_ROW(_r) = RES_NUM_ROWS(_r) = row;
Expand Down
Loading

0 comments on commit 7192510

Please sign in to comment.