Module: sip-router Branch: alexh/3.1/xavp DELETED Commit: b01c6a7ea86ef3c85652da198ba5405e049c988b URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=b01c6a7e...
Author: Alex Hermann alex@speakup.nl Committer: Alex Hermann alex@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 1b19526b..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;