Module: sip-router
Branch: alexh/3.1/xavp
Commit: b01c6a7ea86ef3c85652da198ba5405e049c988b
URL:
http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=b01c6a7…
Author: Alex Hermann <alex(a)speakup.nl>
Committer: Alex Hermann <alex(a)speakup.nl>
Date: Tue Dec 21 10:06:29 2010 +0100
modules_k/sqlops: Add xavp support to sqlops
Introduce a new function sql_xquery that stores the result in an xavp.
---
modules_k/sqlops/doc/sqlops_admin.xml | 54 ++++++++++++++
modules_k/sqlops/sql_api.c | 130 +++++++++++++++++++++++++++++++++
modules_k/sqlops/sql_api.h | 4 +
modules_k/sqlops/sqlops.c | 56 ++++++++++++++
4 files changed, 244 insertions(+), 0 deletions(-)
diff --git a/modules_k/sqlops/doc/sqlops_admin.xml
b/modules_k/sqlops/doc/sqlops_admin.xml
index 0c0a444..24a6d8c 100644
--- a/modules_k/sqlops/doc/sqlops_admin.xml
+++ b/modules_k/sqlops/doc/sqlops_admin.xml
@@ -60,6 +60,14 @@
times.
</para>
</listitem>
+ <listitem>
+ <para>
+ <emphasis>alternatively, results can be stored in xavps. Columns are
+ accessed by their names, rows by xavp index. Xavp's are automatically
+ available during the transactions lifetime and don't need to be
+ destroyed manually.
+ </para>
+ </listitem>
</itemizedlist>
</section>
@@ -192,6 +200,52 @@ sql_result_free("ra");
</section>
<section>
<title>
+ <function moreinfo="none">sql_xquery(connection, query,
result)</function>
+ </title>
+ <para>
+ Make a SQL query using 'connection' and store data in 'result' xavp.
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <emphasis>connection</emphasis> - the name of the connection
+ to be used for query (defined via the <quote>sqlcon</quote> parameter).
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis>query</emphasis> - SQL query string or pseudo-variables
containing SQL query.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis>result</emphasis> - string name to identify the
+ result xavp. Each row will be added to this xavp, each column can
+ be accessed by its name.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ This function can be used from REQUEST_ROUTE, FAILURE_ROUTE,
+ ONREPLY_ROUTE, BRANCH_ROUTE.
+ </para>
+ <example>
+ <title><function>sql_xquery()</function> usage</title>
+ <programlisting format="linespecific">
+...
+modparam("sqlops","sqlcon","ca=>&exampledb;")
+...
+sql_xquery("ca", "select * from domain", "ra");
+ xlog("first domain: $xavp(ra=>domain) with id:
$xavp(ra=>domain_id)\n");
+ pv_unset("$xavp(ra)");
+ xlog("second domain: $xavp(ra=>domain) with id:
$xavp(ra=>domain_id)\n");
+
+...
+</programlisting>
+ </example>
+ </section>
+ <section>
+ <title>
<function moreinfo="none">sql_result_free(result)</function>
</title>
<para>
diff --git a/modules_k/sqlops/sql_api.c b/modules_k/sqlops/sql_api.c
index 5b69108..7f77d37 100644
--- a/modules_k/sqlops/sql_api.c
+++ b/modules_k/sqlops/sql_api.c
@@ -32,6 +32,9 @@
#include "../../dprint.h"
#include "../../lib/kcore/hash_func.h"
#include "../../ut.h"
+#ifdef WITH_XAVP
+#include "../../xavp.h"
+#endif
#include "sql_api.h"
@@ -345,6 +348,133 @@ error:
return -1;
}
+#ifdef WITH_XAVP
+int sql_do_xquery(struct sip_msg *msg, sql_con_t *con, pv_elem_t *query,
+ pv_elem_t *res)
+{
+ db1_res_t* db_res = NULL;
+ sr_xavp_t *row = NULL;
+ sr_xval_t val;
+ int i, j;
+ str sq, xavp;
+
+ if(msg==NULL || query==NULL)
+ {
+ LM_ERR("bad parameters\n");
+ return -1;
+ }
+ if(pv_printf_s(msg, query, &sq)!=0)
+ {
+ LM_ERR("cannot print the sql query\n");
+ return -1;
+ }
+ if(con->dbf.raw_query(con->dbh, &sq, &db_res)!=0)
+ {
+ LM_ERR("cannot do the query\n");
+ return -1;
+ }
+
+ if(db_res==NULL || RES_ROW_N(db_res)<=0 || RES_COL_N(db_res)<=0)
+ {
+ LM_DBG("no result after query\n");
+ con->dbf.free_result(con->dbh, db_res);
+ return 2;
+ }
+
+ if(pv_printf_s(msg, res, &xavp)!=0)
+ {
+ LM_ERR("cannot print the result parameter\n");
+ return -1;
+ }
+
+ for(i=RES_ROW_N(db_res)-1; i>=0; i--)
+ {
+ row = NULL;
+ for(j=RES_COL_N(db_res)-1; j>=0; j--)
+ {
+ if(RES_ROWS(db_res)[i].values[j].nul)
+ {
+ val.type = SR_XTYPE_NULL;
+ } else
+ {
+ switch(RES_ROWS(db_res)[i].values[j].type)
+ {
+ case DB1_STRING:
+ val.type = SR_XTYPE_STR;
+ sq.s=
+ (char*)RES_ROWS(db_res)[i].values[j].val.string_val;
+ sq.len=strlen(sq.s);
+ break;
+ case DB1_STR:
+ val.type = SR_XTYPE_STR;
+ sq.len=
+ RES_ROWS(db_res)[i].values[j].val.str_val.len;
+ sq.s=
+ (char*)RES_ROWS(db_res)[i].values[j].val.str_val.s;
+ break;
+ case DB1_BLOB:
+ val.type = SR_XTYPE_STR;
+ sq.len=
+ RES_ROWS(db_res)[i].values[j].val.blob_val.len;
+ sq.s=
+ (char*)RES_ROWS(db_res)[i].values[j].val.blob_val.s;
+ break;
+ case DB1_INT:
+ val.type = SR_XTYPE_INT;
+ val.v.i
+ = (int)RES_ROWS(db_res)[i].values[j].val.int_val;
+ break;
+ case DB1_DATETIME:
+ val.type = SR_XTYPE_INT;
+ val.v.i
+ = (int)RES_ROWS(db_res)[i].values[j].val.time_val;
+ break;
+ case DB1_BITMAP:
+ val.type = SR_XTYPE_INT;
+ val.v.i
+ = (int)RES_ROWS(db_res)[i].values[j].val.bitmap_val;
+ break;
+ default:
+ val.type = SR_XTYPE_NULL;
+ }
+ if(val.type == SR_XTYPE_STR)
+ {
+ if(sq.len==0)
+ {
+ val.v.s = _sql_empty_str;
+ } else {
+ val.v.s.s = (char*)pkg_malloc(sq.len*sizeof(char));
+ if(val.v.s.s == NULL)
+ {
+ LM_ERR("no more memory\n");
+ goto error;
+ }
+ memcpy(val.v.s.s, sq.s, sq.len);
+ val.v.s.len = sq.len;
+ }
+ }
+ }
+ /* Add column to current row, under the column's name */
+ LM_DBG("Adding column: %.*s\n", RES_NAMES(db_res)[j]->len,
RES_NAMES(db_res)[j]->s);
+ xavp_add_value(RES_NAMES(db_res)[j], &val, &row);
+ }
+ /* Add row to result xavp */
+ val.type = SR_XTYPE_XAVP;
+ val.v.xavp = row;
+ LM_DBG("Adding row\n");
+ xavp_add_value(&xavp, &val, NULL);
+ }
+
+ con->dbf.free_result(con->dbh, db_res);
+ return 1;
+
+error:
+ con->dbf.free_result(con->dbh, db_res);
+ return -1;
+
+}
+#endif
+
int sql_parse_param(char *val)
{
str name;
diff --git a/modules_k/sqlops/sql_api.h b/modules_k/sqlops/sql_api.h
index 1b19526..1b4eb20 100644
--- a/modules_k/sqlops/sql_api.h
+++ b/modules_k/sqlops/sql_api.h
@@ -72,6 +72,10 @@ void sql_destroy(void);
int sql_connect(void);
int sql_do_query(struct sip_msg *msg, sql_con_t *con, pv_elem_t *query,
sql_result_t *res);
+#ifdef WITH_XAVP
+int sql_do_xquery(struct sip_msg *msg, sql_con_t *con, pv_elem_t *query,
+ pv_elem_t *res);
+#endif
sql_con_t* sql_get_connection(str *name);
sql_result_t* sql_get_result(str *name);
diff --git a/modules_k/sqlops/sqlops.c b/modules_k/sqlops/sqlops.c
index a9fa054..18293ff 100644
--- a/modules_k/sqlops/sqlops.c
+++ b/modules_k/sqlops/sqlops.c
@@ -58,11 +58,17 @@ MODULE_VERSION
/** module functions */
static int sql_query(struct sip_msg*, char*, char*, char*);
+#ifdef WITH_XAVP
+static int sql_xquery(struct sip_msg *msg, char *dbl, char *query, char *res);
+#endif
static int sql_rfree(struct sip_msg*, char*, char*);
static int child_init(int rank);
static void destroy(void);
static int fixup_sql_query(void** param, int param_no);
+#ifdef WITH_XAVP
+static int fixup_sql_xquery(void** param, int param_no);
+#endif
static int fixup_sql_rfree(void** param, int param_no);
static int sql_param(modparam_t type, void* val);
@@ -77,6 +83,11 @@ static cmd_export_t cmds[]={
{"sql_query", (cmd_function)sql_query, 3, fixup_sql_query, 0,
REQUEST_ROUTE | FAILURE_ROUTE |
ONREPLY_ROUTE | BRANCH_ROUTE | LOCAL_ROUTE},
+#ifdef WITH_XAVP
+ {"sql_xquery", (cmd_function)sql_xquery, 3, fixup_sql_xquery, 0,
+ REQUEST_ROUTE | FAILURE_ROUTE |
+ ONREPLY_ROUTE | BRANCH_ROUTE | LOCAL_ROUTE},
+#endif
{"sql_result_free", (cmd_function)sql_rfree, 1, fixup_sql_rfree, 0,
REQUEST_ROUTE | FAILURE_ROUTE |
ONREPLY_ROUTE | BRANCH_ROUTE | LOCAL_ROUTE},
@@ -137,6 +148,14 @@ static int sql_query(struct sip_msg *msg, char *dbl, char *query,
char *res)
(sql_result_t*)res);
}
+#ifdef WITH_XAVP
+static int sql_xquery(struct sip_msg *msg, char *dbl, char *query, char *res)
+{
+ return sql_do_xquery(msg, (sql_con_t*)dbl, (pv_elem_t*)query,
+ (pv_elem_t*)res);
+}
+#endif
+
static int sql_rfree(struct sip_msg *msg, char *res, char *s2)
{
sql_reset_result((sql_result_t*)res);
@@ -180,6 +199,43 @@ static int fixup_sql_query(void** param, int param_no)
return 0;
}
+#ifdef WITH_XAVP
+static int fixup_sql_xquery(void** param, int param_no)
+{
+ sql_con_t *con = NULL;
+ pv_elem_t *pv = NULL;
+ str s;
+
+ s.s = (char*)(*param);
+ s.len = strlen(s.s);
+
+ if (param_no==1) {
+ con = sql_get_connection(&s);
+ if(con==NULL)
+ {
+ LM_ERR("invalid connection [%s]\n", s.s);
+ return E_UNSPEC;
+ }
+ *param = (void*)con;
+ } else if (param_no==2) {
+ if(pv_parse_format(&s, &pv)<0)
+ {
+ LM_ERR("invalid query string [%s]\n", s.s);
+ return E_UNSPEC;
+ }
+ *param = (void*)pv;
+ } else if (param_no==3) {
+ if(pv_parse_format(&s, &pv)<0)
+ {
+ LM_ERR("invalid result [%s]\n", s.s);
+ return E_UNSPEC;
+ }
+ *param = (void*)pv;
+ }
+ return 0;
+}
+#endif
+
static int fixup_sql_rfree(void** param, int param_no)
{
sql_result_t *res = NULL;