- mysql module updated to new db api
authorJan Janak <jan@iptel.org>
Wed, 4 Apr 2007 11:48:20 +0000 (11:48 +0000)
committerJan Janak <jan@iptel.org>
Wed, 4 Apr 2007 11:48:20 +0000 (11:48 +0000)
18 files changed:
modules/db_mysql/dbase.c [deleted file]
modules/db_mysql/dbase.h [deleted file]
modules/db_mysql/my_cmd.c [new file with mode: 0644]
modules/db_mysql/my_cmd.h [moved from modules/db_mysql/row.h with 65% similarity]
modules/db_mysql/my_con.c
modules/db_mysql/my_con.h
modules/db_mysql/my_fld.c [moved from modules/db_mysql/db_con.c with 64% similarity]
modules/db_mysql/my_fld.h [moved from modules/db_mysql/val.h with 77% similarity]
modules/db_mysql/my_res.c [moved from modules/db_mysql/row.c with 52% similarity]
modules/db_mysql/my_res.h [moved from modules/db_mysql/defs.h with 81% similarity]
modules/db_mysql/my_uri.c [new file with mode: 0644]
modules/db_mysql/my_uri.h [moved from modules/db_mysql/utils.h with 73% similarity]
modules/db_mysql/mysql_mod.c [moved from modules/db_mysql/db_mod.c with 73% similarity]
modules/db_mysql/mysql_mod.h [moved from modules/db_mysql/db_mod.h with 94% similarity]
modules/db_mysql/res.c [deleted file]
modules/db_mysql/res.h [deleted file]
modules/db_mysql/utils.c [deleted file]
modules/db_mysql/val.c [deleted file]

diff --git a/modules/db_mysql/dbase.c b/modules/db_mysql/dbase.c
deleted file mode 100644 (file)
index 0909e42..0000000
+++ /dev/null
@@ -1,669 +0,0 @@
-/* 
- * $Id$ 
- *
- * MySQL module core functions
- *
- * Copyright (C) 2001-2003 FhG Fokus
- *
- * This file is part of ser, a free SIP server.
- *
- * ser is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version
- *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info@iptel.org
- *
- * ser is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License 
- * along with this program; if not, write to the Free Software 
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <time.h>
-#include <mysql/mysql.h>
-#include <mysql/errmsg.h>
-#include "../../mem/mem.h"
-#include "../../dprint.h"
-#include "../../db/db_pool.h"
-#include "../../globals.h"
-#include "../../pt.h"
-#include "utils.h"
-#include "val.h"
-#include "my_con.h"
-#include "res.h"
-#include "db_mod.h"
-#include "dbase.h"
-
-
-#define SQL_BUF_LEN 65536
-
-static char sql_buf[SQL_BUF_LEN];
-
-
-/*
- * Send an SQL query to the server
- */
-static int submit_query(db_con_t* _h, const char* _s)
-{      
-       time_t t;
-       int i, code;
-
-       if ((!_h) || (!_s)) {
-               LOG(L_ERR, "submit_query: Invalid parameter value\n");
-               return -1;
-       }
-
-       if (ping_interval) {
-               t = time(0);
-               if ((t - CON_TIMESTAMP(_h)) > ping_interval) {
-                       if (mysql_ping(CON_CONNECTION(_h))) {
-                               DBG("submit_query: mysql_ping failed\n");
-                       }
-               }
-               CON_TIMESTAMP(_h) = t;
-       }
-
-       /* screws up the terminal when the query contains a BLOB :-( (by bogdan)
-        * DBG("submit_query(): %s\n", _s);
-        */
-
-       /* When a server connection is lost and a query is attempted, most of
-        * the time the query will return a CR_SERVER_LOST, then at the second
-        * attempt to execute it, the mysql lib will reconnect and succeed.
-        * However is a few cases, the first attempt returns CR_SERVER_GONE_ERROR
-        * the second CR_SERVER_LOST and only the third succeeds.
-        * Thus the 3 in the loop count. Increasing the loop count over this
-        * value shouldn't be needed, but it doesn't hurt either, since the loop
-        * will most of the time stop at the second or sometimes at the third
-        * iteration.
-        */
-       for (i=0; i<(auto_reconnect ? 3 : 1); i++) {
-               if (mysql_query(CON_CONNECTION(_h), _s)==0) {
-                       return 0;
-               }
-               code = mysql_errno(CON_CONNECTION(_h));
-               if (code != CR_SERVER_GONE_ERROR && code != CR_SERVER_LOST) {
-                       break;
-               }
-       }
-       LOG(L_ERR, "submit_query: %s\n", mysql_error(CON_CONNECTION(_h)));
-       return -2;
-}
-
-
-/*
- * Print list of columns separated by comma
- */
-static int print_columns(char* _b, int _l, db_key_t* _c, int _n)
-{
-       int i, ret;
-       int len = 0;
-
-       if ((!_c) || (!_n) || (!_b) || (!_l)) {
-               LOG(L_ERR, "print_columns: Invalid parameter value\n");
-               return -1;
-       }
-
-       for(i = 0; i < _n; i++) {
-               if (i == (_n - 1)) {
-                       ret = snprintf(_b + len, _l - len, "%s ", _c[i]);
-                       if (ret < 0 || ret >= (_l - len)) goto error;
-                       len += ret;
-               } else {
-                       ret = snprintf(_b + len, _l - len, "%s,", _c[i]);
-                       if (ret < 0 || ret >= (_l - len)) goto error;
-                       len += ret;
-               }
-       }
-       return len;
-
- error:
-       LOG(L_ERR, "print_columns: Error in snprintf\n");
-       return -1;
-}
-
-
-/*
- * Print list of values separated by comma
- */
-static int print_values(MYSQL* _c, char* _b, int _l, db_val_t* _v, int _n)
-{
-       int i, res = 0, l;
-
-       if (!_c || !_b || !_l || !_v || !_n) {
-               LOG(L_ERR, "print_values: Invalid parameter value\n");
-               return -1;
-       }
-
-       for(i = 0; i < _n; i++) {
-               l = _l - res;
-               if (val2str(_c, _v + i, _b + res, &l) < 0) {
-                       LOG(L_ERR, "print_values: Error while converting value to string\n");
-                       return -1;
-               }
-               res += l;
-               if (i != (_n - 1)) {
-                       *(_b + res) = ',';
-                       res++;
-               }
-       }
-       return res;
-}
-
-
-/*
- * Print where clause of SQL statement
- */
-static int print_where(MYSQL* _c, char* _b, int _l, db_key_t* _k, db_op_t* _o, db_val_t* _v, int _n)
-{
-       int i;
-       int len = 0, ret;
-       int l;
-
-       if (!_c || !_b || !_l || !_k || !_v || !_n) {
-               LOG(L_ERR, "print_where: Invalid parameter value\n");
-               return -1;
-       }
-
-       for(i = 0; i < _n; i++) {
-               if (_v[i].nul) {
-                       ret = snprintf(_b + len, _l - len, "%s is ", _k[i]);
-                       if (ret < 0 || ret >= (_l - len)) goto error;
-                       len += ret;
-               } else if (_o) {
-                       ret = snprintf(_b + len, _l - len, "%s%s", _k[i], _o[i]);
-                       if (ret < 0 || ret >= (_l - len)) goto error;
-                       len += ret;
-               } else {
-                       ret = snprintf(_b + len, _l - len, "%s=", _k[i]);
-                       if (ret < 0 || ret >= (_l - len)) goto error;
-                       len += ret;
-               }
-               l = _l - len;
-               val2str(_c, &(_v[i]), _b + len, &l);
-               len += l;
-               if (i == (_n - 1))
-                       ret = snprintf(_b + len, _l - len, " ");
-               else
-                       ret = snprintf(_b + len, _l - len, " AND ");
-               if (ret < 0 || ret >= (_l - len)) goto error;
-               len += ret;
-       }
-       return len;
-
- error:
-       LOG(L_ERR, "print_where: Error in snprintf\n");
-       return -1;
-}
-
-
-/*
- * Print set clause of update SQL statement
- */
-static int print_set(MYSQL* _c, char* _b, int _l, db_key_t* _k, db_val_t* _v, int _n)
-{
-       int i;
-       int len = 0, ret;
-       int l;
-
-       if (!_c || !_b || !_l || !_k || !_v || !_n) {
-               LOG(L_ERR, "print_set: Invalid parameter value\n");
-               return -1;
-       }
-
-       for(i = 0; i < _n; i++) {
-               ret = snprintf(_b + len, _l - len, "%s=", _k[i]);
-               if (ret < 0 || ret >= (_l - len)) goto error;
-               len += ret;
-
-               l = _l - len;
-               val2str(_c, &(_v[i]), _b + len, &l);
-               len += l;
-               if (i != (_n - 1)) {
-                       if ((_l - len) >= 1) {
-                               *(_b + len++) = ',';
-                       }
-               }
-       }
-       return len;
-
- error:
-       LOG(L_ERR, "print_set: Error in snprintf\n");
-       return -1;
-}
-
-
-/*
- * Initialize database module
- * No function should be called before this
- */
-db_con_t* db_init(const char* _url)
-{
-       struct db_id* id;
-       struct my_con* con;
-       db_con_t* res;
-
-       id = 0;
-       res = 0;
-
-       /* if called from PROC_MAIN, allow it only from mod_init( when pt==0)*/
-       if (is_main && fixup_complete){
-               LOG(L_ERR, "BUG: mysql: db_init: called from the main process,"
-                                       " ignoring...\n");
-       }
-
-       if (!_url) {
-               LOG(L_ERR, "db_init: Invalid parameter value\n");
-               return 0;
-       }
-
-       res = pkg_malloc(sizeof(db_con_t) + sizeof(struct my_con*));
-       if (!res) {
-               LOG(L_ERR, "db_init: No memory left\n");
-               return 0;
-       }
-       memset(res, 0, sizeof(db_con_t) + sizeof(struct my_con*));
-
-       id = new_db_id(_url);
-       if (!id) {
-               LOG(L_ERR, "db_init: Cannot parse URL '%s'\n", _url);
-               goto err;
-       }
-
-            /* Find the connection in the pool */
-       con = (struct my_con*)pool_get(id);
-       if (!con) {
-               DBG("db_init: Connection '%s' not found in pool\n", _url);
-                    /* Not in the pool yet */
-               con = new_connection(id);
-               if (!con) {
-                       goto err;
-               }
-               pool_insert((struct pool_con*)con);
-       } else {
-               DBG("db_init: Connection '%s' found in pool\n", _url);
-       }
-
-       res->tail = (unsigned long)con;
-       return res;
-
- err:
-       if (id) free_db_id(id);
-       if (res) pkg_free(res);
-       return 0;
-}
-
-
-/*
- * Shut down database module
- * No function should be called after this
- */
-void db_close(db_con_t* _h)
-{
-       struct pool_con* con;
-
-       if (!_h) {
-               LOG(L_ERR, "db_close: Invalid parameter value\n");
-               return;
-       }
-
-       con = (struct pool_con*)_h->tail;
-       if (pool_remove(con) != 0) {
-               free_connection((struct my_con*)con);
-       }
-
-       pkg_free(_h);
-}
-
-
-/*
- * Retrieve result set
- */
-static int store_result(db_con_t* _h, db_res_t** _r)
-{
-       if ((!_h) || (!_r)) {
-               LOG(L_ERR, "store_result: Invalid parameter value\n");
-               return -1;
-       }
-
-       *_r = new_result();
-       if (*_r == 0) {
-               LOG(L_ERR, "store_result: No memory left\n");
-               return -2;
-       }
-
-       MYRES_RESULT(*_r) = mysql_store_result(CON_CONNECTION(_h));
-       if (!MYRES_RESULT(*_r)) {
-               if (mysql_field_count(CON_CONNECTION(_h)) == 0) {
-                       (*_r)->col.n = 0;
-                       (*_r)->n = 0;
-                       return 0;
-               } else {
-                       LOG(L_ERR, "store_result: %s\n", mysql_error(CON_CONNECTION(_h)));
-                       free_result(*_r);
-                       *_r = 0;
-                       return -3;
-               }
-       }
-
-       if (convert_result(_h, *_r) < 0) {
-               LOG(L_ERR, "store_result: Error while converting result\n");
-               mysql_free_result(MYRES_RESULT(*_r));
-               pkg_free((*_r)->data);
-               pkg_free(*_r);
-
-               /* This cannot be used because if convert_result fails,
-                * free_result will try to free rows and columns too 
-                * and free will be called two times
-                */
-               /* free_result(*_r); */
-               return -4;
-       }
-       
-       return 0;
-}
-
-
-/*
- * Release a result set from memory
- */
-int db_free_result(db_con_t* _h, db_res_t* _r)
-{
-     if ((!_h) || (!_r)) {
-            LOG(L_ERR, "db_free_result: Invalid parameter value\n");
-            return -1;
-     }
-
-     if (free_result(_r) < 0) {
-            LOG(L_ERR, "db_free_result: Unable to free result structure\n");
-            return -1;
-     }
-     return 0;
-}
-
-
-/*
- * Query table for specified rows
- * _h: structure representing database connection
- * _k: key names
- * _op: operators
- * _v: values of the keys that must match
- * _c: column names to return
- * _n: number of key=values pairs to compare
- * _nc: number of columns to return
- * _o: order by the specified column
- */
-int db_query(db_con_t* _h, db_key_t* _k, db_op_t* _op,
-            db_val_t* _v, db_key_t* _c, int _n, int _nc,
-            db_key_t _o, db_res_t** _r)
-{
-       int off, ret;
-
-       if (!_h) {
-               LOG(L_ERR, "db_query: Invalid parameter value\n");
-               return -1;
-       }
-
-       if (!_c) {
-               ret = snprintf(sql_buf, SQL_BUF_LEN, "select * from %s ", CON_TABLE(_h));
-               if (ret < 0 || ret >= SQL_BUF_LEN) goto error;
-               off = ret;
-       } else {
-               ret = snprintf(sql_buf, SQL_BUF_LEN, "select ");
-               if (ret < 0 || ret >= SQL_BUF_LEN) goto error;
-               off = ret;
-
-               ret = print_columns(sql_buf + off, SQL_BUF_LEN - off, _c, _nc);
-               if (ret < 0) return -1;
-               off += ret;
-
-               ret = snprintf(sql_buf + off, SQL_BUF_LEN - off, "from %s ", CON_TABLE(_h));
-               if (ret < 0 || ret >= (SQL_BUF_LEN - off)) goto error;
-               off += ret;
-       }
-       if (_n) {
-               ret = snprintf(sql_buf + off, SQL_BUF_LEN - off, "where ");
-               if (ret < 0 || ret >= (SQL_BUF_LEN - off)) goto error;
-               off += ret;
-
-               ret = print_where(CON_CONNECTION(_h), sql_buf + off, SQL_BUF_LEN - off, _k, _op, _v, _n);
-               if (ret < 0) return -1;;
-               off += ret;
-       }
-       if (_o) {
-               ret = snprintf(sql_buf + off, SQL_BUF_LEN - off, "order by %s", _o);
-               if (ret < 0 || ret >= (SQL_BUF_LEN - off)) goto error;
-               off += ret;
-       }
-       
-       *(sql_buf + off) = '\0';
-       if (submit_query(_h, sql_buf) < 0) {
-               LOG(L_ERR, "db_query: Error while submitting query\n");
-               return -2;
-       }
-
-       return store_result(_h, _r);
-
- error:
-       LOG(L_ERR, "db_query: Error in snprintf\n");
-       return -1;
-}
-
-
-/*
- * Execute a raw SQL query
- */
-int db_raw_query(db_con_t* _h, char* _s, db_res_t** _r)
-{
-       if ((!_h) || (!_s)) {
-               LOG(L_ERR, "db_raw_query: Invalid parameter value\n");
-               return -1;
-       }
-
-       if (submit_query(_h, _s) < 0) {
-               LOG(L_ERR, "db_raw_query: Error while submitting query\n");
-               return -2;
-       }
-
-       if(_r)
-           return store_result(_h, _r);
-       return 0;
-}
-
-
-/*
- * Insert a row into specified table
- * _h: structure representing database connection
- * _k: key names
- * _v: values of the keys
- * _n: number of key=value pairs
- */
-int db_insert(db_con_t* _h, db_key_t* _k, db_val_t* _v, int _n)
-{
-       int off, ret;
-
-       if ((!_h) || (!_k) || (!_v) || (!_n)) {
-               LOG(L_ERR, "db_insert: Invalid parameter value\n");
-               return -1;
-       }
-
-       ret = snprintf(sql_buf, SQL_BUF_LEN, "insert into %s (", CON_TABLE(_h));
-       if (ret < 0 || ret >= SQL_BUF_LEN) goto error;
-       off = ret;
-
-       ret = print_columns(sql_buf + off, SQL_BUF_LEN - off, _k, _n);
-       if (ret < 0) return -1;
-       off += ret;
-
-       ret = snprintf(sql_buf + off, SQL_BUF_LEN - off, ") values (");
-       if (ret < 0 || ret >= (SQL_BUF_LEN - off)) goto error;
-       off += ret;
-
-       ret = print_values(CON_CONNECTION(_h), sql_buf + off, SQL_BUF_LEN - off, _v, _n);
-       if (ret < 0) return -1;
-       off += ret;
-
-       *(sql_buf + off++) = ')';
-       *(sql_buf + off) = '\0';
-
-       if (submit_query(_h, sql_buf) < 0) {
-               LOG(L_ERR, "db_insert: Error while submitting query\n");
-               return -2;
-       }
-       return 0;
-
- error:
-       LOG(L_ERR, "db_insert: Error in snprintf\n");
-       return -1;
-}
-
-
-/*
- * Delete a row from the specified table
- * _h: structure representing database connection
- * _k: key names
- * _o: operators
- * _v: values of the keys that must match
- * _n: number of key=value pairs
- */
-int db_delete(db_con_t* _h, db_key_t* _k, db_op_t* _o, db_val_t* _v, int _n)
-{
-       int off, ret;
-
-       if (!_h) {
-               LOG(L_ERR, "db_delete: Invalid parameter value\n");
-               return -1;
-       }
-
-       ret = snprintf(sql_buf, SQL_BUF_LEN, "delete from %s", CON_TABLE(_h));
-       if (ret < 0 || ret >= SQL_BUF_LEN) goto error;
-       off = ret;
-
-       if (_n) {
-               ret = snprintf(sql_buf + off, SQL_BUF_LEN - off, " where ");
-               if (ret < 0 || ret >= (SQL_BUF_LEN - off)) goto error;
-               off += ret;
-
-               ret = print_where(CON_CONNECTION(_h), sql_buf + off, SQL_BUF_LEN - off, _k, _o, _v, _n);
-               if (ret < 0) return -1;
-               off += ret;
-       }
-
-       *(sql_buf + off) = '\0';
-       if (submit_query(_h, sql_buf) < 0) {
-               LOG(L_ERR, "db_delete: Error while submitting query\n");
-               return -2;
-       }
-       return 0;
-
- error:
-       LOG(L_ERR, "db_delete: Error in snprintf\n");
-       return -1;
-}
-
-
-/*
- * Update some rows in the specified table
- * _h: structure representing database connection
- * _k: key names
- * _o: operators
- * _v: values of the keys that must match
- * _uk: updated columns
- * _uv: updated values of the columns
- * _n: number of key=value pairs
- * _un: number of columns to update
- */
-int db_update(db_con_t* _h, db_key_t* _k, db_op_t* _o, db_val_t* _v,
-             db_key_t* _uk, db_val_t* _uv, int _n, int _un)
-{
-       int off, ret;
-
-       if ((!_h) || (!_uk) || (!_uv) || (!_un)) {
-               LOG(L_ERR, "db_update: Invalid parameter value\n");
-               return -1;
-       }
-
-       ret = snprintf(sql_buf, SQL_BUF_LEN, "update %s set ", CON_TABLE(_h));
-       if (ret < 0 || ret >= SQL_BUF_LEN) goto error;
-       off = ret;
-
-       ret = print_set(CON_CONNECTION(_h), sql_buf + off, SQL_BUF_LEN - off, _uk, _uv, _un);
-       if (ret < 0) return -1;
-       off += ret;
-
-       if (_n) {
-               ret = snprintf(sql_buf + off, SQL_BUF_LEN - off, " where ");
-               if (ret < 0 || ret >= (SQL_BUF_LEN - off)) goto error;
-               off += ret;
-
-               ret = print_where(CON_CONNECTION(_h), sql_buf + off, SQL_BUF_LEN - off, _k, _o, _v, _n);
-               if (ret < 0) return -1;
-               off += ret;
-
-               *(sql_buf + off) = '\0';
-       }
-
-       if (submit_query(_h, sql_buf) < 0) {
-               LOG(L_ERR, "db_update: Error while submitting query\n");
-               return -2;
-       }
-       return 0;
-
- error:
-       LOG(L_ERR, "db_update: Error in snprintf\n");
-       return -1;
-}
-
-
-/*
- * Just like insert, but replace the row if it exists
- */
-int db_replace(db_con_t* handle, db_key_t* keys, db_val_t* vals, int n)
-{
-       int off, ret;
-
-       if (!handle || !keys || !vals) {
-               LOG(L_ERR, "db_replace: Invalid parameter value\n");
-               return -1;
-       }
-
-       ret = snprintf(sql_buf, SQL_BUF_LEN, "replace %s (", CON_TABLE(handle));
-       if (ret < 0 || ret >= SQL_BUF_LEN) goto error;
-       off = ret;
-
-       ret = print_columns(sql_buf + off, SQL_BUF_LEN - off, keys, n);
-       if (ret < 0) return -1;
-       off += ret;
-
-       ret = snprintf(sql_buf + off, SQL_BUF_LEN - off, ") values (");
-       if (ret < 0 || ret >= (SQL_BUF_LEN - off)) goto error;
-       off += ret;
-
-       ret = print_values(CON_CONNECTION(handle), sql_buf + off, SQL_BUF_LEN - off, vals, n);
-       if (ret < 0) return -1;
-       off += ret;
-
-       *(sql_buf + off++) = ')';
-       *(sql_buf + off) = '\0';
-
-       if (submit_query(handle, sql_buf) < 0) {
-               LOG(L_ERR, "db_replace: Error while submitting query\n");
-               return -2;
-       }
-       return 0;
-
- error:
-       LOG(L_ERR, "db_replace: Error in snprintf\n");
-       return -1;
-}
diff --git a/modules/db_mysql/dbase.h b/modules/db_mysql/dbase.h
deleted file mode 100644 (file)
index 15dc163..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * $Id$
- *
- * MySQL module core functions
- *
- * Copyright (C) 2001-2003 FhG Fokus
- *
- * This file is part of ser, a free SIP server.
- *
- * ser is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version
- *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info@iptel.org
- *
- * ser is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License 
- * along with this program; if not, write to the Free Software 
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-
-#ifndef DBASE_H
-#define DBASE_H
-
-
-#include "../../db/db_con.h"
-#include "../../db/db_res.h"
-#include "../../db/db_key.h"
-#include "../../db/db_op.h"
-#include "../../db/db_val.h"
-
-
-/*
- * Initialize database connection
- */
-db_con_t* db_init(const char* _sqlurl);
-
-
-/*
- * Close a database connection
- */
-void db_close(db_con_t* _h);
-
-
-/*
- * Free all memory allocated by get_result
- */
-int db_free_result(db_con_t* _h, db_res_t* _r);
-
-
-/*
- * Do a query
- */
-int db_query(db_con_t* _h, db_key_t* _k, db_op_t* _op, db_val_t* _v, db_key_t* _c, int _n, int _nc,
-            db_key_t _o, db_res_t** _r);
-
-
-/*
- * Raw SQL query
- */
-int db_raw_query(db_con_t* _h, char* _s, db_res_t** _r);
-
-
-/*
- * Insert a row into table
- */
-int db_insert(db_con_t* _h, db_key_t* _k, db_val_t* _v, int _n);
-
-
-/*
- * Delete a row from table
- */
-int db_delete(db_con_t* _h, db_key_t* _k, db_op_t* _o, db_val_t* _v, int _n);
-
-
-/*
- * Update a row in table
- */
-int db_update(db_con_t* _h, db_key_t* _k, db_op_t* _o, db_val_t* _v,
-             db_key_t* _uk, db_val_t* _uv, int _n, int _un);
-
-
-/*
- * Just like insert, but replace the row if it exists
- */
-int db_replace(db_con_t* handle, db_key_t* keys, db_val_t* vals, int n);
-
-
-/*
- * Store name of table that will be used by
- * subsequent database functions
- */
-int use_table(db_con_t* _h, const char* _t);
-
-
-#endif /* DBASE_H */
diff --git a/modules/db_mysql/my_cmd.c b/modules/db_mysql/my_cmd.c
new file mode 100644 (file)
index 0000000..a124ff7
--- /dev/null
@@ -0,0 +1,732 @@
+/* 
+ * $Id$
+ *
+ * Copyright (C) 2001-2003 FhG Fokus
+ * Copyright (C) 2006-2007 iptelorg GmbH
+ *
+ * This file is part of ser, a free SIP server.
+ *
+ * ser is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * For a license to use the ser software under conditions
+ * other than those described here, or to purchase support for this
+ * software, please contact iptel.org by e-mail at the following addresses:
+ *    info@iptel.org
+ *
+ * ser is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#define _XOPEN_SOURCE 4     /* bsd */
+#define _XOPEN_SOURCE_EXTENDED 1    /* solaris */
+#define _SVID_SOURCE 1 /* timegm */
+
+#include <strings.h>
+#include <stdio.h>
+#include <time.h>  /*strptime, XOPEN issue must be >=4 */
+#include <string.h>
+#include "../../mem/mem.h"
+#include "../../str.h"
+#include "../../db/db_cmd.h"
+#include "../../ut.h"
+#include "my_con.h"
+#include "my_fld.h"
+#include "my_cmd.h"
+
+#define STR_BUF_SIZE 256
+
+enum {
+       STR_DELETE,
+       STR_INSERT,
+       STR_UPDATE,
+       STR_SELECT,
+       STR_REPLACE,
+       STR_WHERE,
+       STR_IS,
+       STR_AND,
+       STR_OR,
+       STR_ESC,
+       STR_OP_EQ,
+       STR_OP_LT,
+       STR_OP_GT,
+       STR_OP_LEQ,
+       STR_OP_GEQ,
+       STR_VALUES,
+       STR_FROM
+};
+
+static str strings[] = {
+       STR_STATIC_INIT("delete from "),
+       STR_STATIC_INIT("insert into "),
+       STR_STATIC_INIT("update "),
+       STR_STATIC_INIT("select "),
+       STR_STATIC_INIT("replace "),
+       STR_STATIC_INIT(" where "),
+       STR_STATIC_INIT(" is "),
+       STR_STATIC_INIT(" and "),
+       STR_STATIC_INIT(" or "),
+       STR_STATIC_INIT("?"),
+       STR_STATIC_INIT("="),
+       STR_STATIC_INIT("<"),
+       STR_STATIC_INIT(">"),
+       STR_STATIC_INIT("<="),
+       STR_STATIC_INIT(">="),
+       STR_STATIC_INIT(") values ("),
+       STR_STATIC_INIT(" from ")
+};
+
+
+#define APPEND_STR(p, str) do {                 \
+       memcpy((p), (str).s, (str).len); \
+       (p) += (str).len;                                \
+} while(0)
+
+
+#define APPEND_CSTR(p, cstr) do { \
+    int _len = strlen(cstr);      \
+       memcpy((p), (cstr), _len);        \
+       (p) += _len;                              \
+} while(0)
+
+
+
+static int my_cmd_free(db_cmd_t* cmd, struct my_cmd* payload)
+{
+       db_drv_free(&payload->gen);
+       if (payload->query.s) pkg_free(payload->query.s);
+       if (payload->st) mysql_stmt_close(payload->st);
+       pkg_free(payload);
+}
+
+
+static int build_delete_query(str* query, db_cmd_t* cmd)
+{
+       db_fld_t* fld;
+       int i;
+       char* p;
+
+       query->len = strings[STR_DELETE].len;
+       query->len += cmd->table.len;
+
+       if (!DB_FLD_EMPTY(cmd->params)) {
+               query->len += strings[STR_WHERE].len;
+
+               for(i = 0, fld = cmd->params; !DB_FLD_LAST(fld[i]); i++) {
+                       query->len += strlen(fld[i].name);
+
+                       switch(fld[i].op) {
+                       case DB_EQ:  query->len += strings[STR_OP_EQ].len; break;
+                       case DB_LT:  query->len += strings[STR_OP_LT].len; break;
+                       case DB_GT:  query->len += strings[STR_OP_GT].len; break;
+                       case DB_LEQ: query->len += strings[STR_OP_LEQ].len; break;
+                       case DB_GEQ: query->len += strings[STR_OP_GEQ].len; break;
+                       default:
+                               ERR("Unsupported db_fld operator %d\n", fld[i].op);
+                               return -1;
+                       }
+
+                       query->len += strings[STR_ESC].len;
+                       
+                       if (!DB_FLD_LAST(fld[i + 1])) query->len += strings[STR_AND].len;
+               }
+       }
+
+       query->s = pkg_malloc(query->len + 1);
+       if (query->s == NULL) {
+               ERR("No memory left\n");
+               return -1;
+       }
+       p = query->s;
+       
+       APPEND_STR(p, strings[STR_DELETE]);
+       APPEND_STR(p, cmd->table);
+
+       if (!DB_FLD_EMPTY(cmd->params)) {
+               APPEND_STR(p, strings[STR_WHERE]);
+
+               for(i = 0, fld = cmd->params; !DB_FLD_LAST(fld[i]); i++) {
+                       APPEND_CSTR(p, fld[i].name);
+
+                       switch(fld[i].op) {
+                       case DB_EQ:  APPEND_STR(p, strings[STR_OP_EQ]);  break;
+                       case DB_LT:  APPEND_STR(p, strings[STR_OP_LT]);  break;
+                       case DB_GT:  APPEND_STR(p, strings[STR_OP_GT]);  break;
+                       case DB_LEQ: APPEND_STR(p, strings[STR_OP_LEQ]); break;
+                       case DB_GEQ: APPEND_STR(p, strings[STR_OP_GEQ]); break;
+                       }
+                       
+                       APPEND_STR(p, strings[STR_ESC]);
+                       if (!DB_FLD_LAST(fld[i + 1])) APPEND_STR(p, strings[STR_AND]);
+               }
+       }
+                       
+       *p = '\0';
+       return 0;
+}
+
+
+static int build_select_query(str* query, db_cmd_t* cmd)
+{
+       db_fld_t* fld;
+       int i;
+       char* p;
+
+       query->len = strings[STR_SELECT].len;
+
+       if (DB_FLD_EMPTY(cmd->result)) {
+               query->len += 1; /* "*" */
+       } else {
+               for(i = 0, fld = cmd->result; !DB_FLD_LAST(fld[i]); i++) {
+                       query->len += strlen(fld[i].name);
+                       if (!DB_FLD_LAST(fld[i + 1])) query->len += 1; /* , */
+               }
+       }
+       query->len += strings[STR_FROM].len;
+       query->len += cmd->table.len;
+
+       if (!DB_FLD_EMPTY(cmd->params)) {
+               query->len += strings[STR_WHERE].len;
+
+               for(i = 0, fld = cmd->params; !DB_FLD_LAST(fld[i]); i++) {
+                       query->len += strlen(fld[i].name);
+
+                       switch(fld[i].op) {
+                       case DB_EQ:  query->len += strings[STR_OP_EQ].len; break;
+                       case DB_LT:  query->len += strings[STR_OP_LT].len; break;
+                       case DB_GT:  query->len += strings[STR_OP_GT].len; break;
+                       case DB_LEQ: query->len += strings[STR_OP_LEQ].len; break;
+                       case DB_GEQ: query->len += strings[STR_OP_GEQ].len; break;
+                       default:
+                               ERR("Unsupported db_fld operator %d\n", fld[i].op);
+                               return -1;
+                       }
+
+                       query->len += strings[STR_ESC].len;
+                       
+                       if (!DB_FLD_LAST(fld[i + 1])) query->len += strings[STR_AND].len;
+               }
+       }
+
+       query->s = pkg_malloc(query->len + 1);
+       if (query->s == NULL) {
+               ERR("No memory left\n");
+               return -1;
+       }
+       p = query->s;
+       
+       APPEND_STR(p, strings[STR_SELECT]);
+       if (DB_FLD_EMPTY(cmd->result)) {
+               *p++ = '*';
+       } else {
+               for(i = 0, fld = cmd->result; !DB_FLD_LAST(fld[i]); i++) {
+                       APPEND_CSTR(p, fld[i].name);
+                       if (!DB_FLD_LAST(fld[i + 1])) *p++ = ',';
+               }
+       }
+       APPEND_STR(p, strings[STR_FROM]);
+       APPEND_STR(p, cmd->table);
+
+       if (!DB_FLD_EMPTY(cmd->params)) {
+               APPEND_STR(p, strings[STR_WHERE]);
+
+               for(i = 0, fld = cmd->params; !DB_FLD_LAST(fld[i]); i++) {
+                       APPEND_CSTR(p, fld[i].name);
+
+                       switch(fld[i].op) {
+                       case DB_EQ:  APPEND_STR(p, strings[STR_OP_EQ]);  break;
+                       case DB_LT:  APPEND_STR(p, strings[STR_OP_LT]);  break;
+                       case DB_GT:  APPEND_STR(p, strings[STR_OP_GT]);  break;
+                       case DB_LEQ: APPEND_STR(p, strings[STR_OP_LEQ]); break;
+                       case DB_GEQ: APPEND_STR(p, strings[STR_OP_GEQ]); break;
+                       }
+                       
+                       APPEND_STR(p, strings[STR_ESC]);
+                       if (!DB_FLD_LAST(fld[i + 1])) APPEND_STR(p, strings[STR_AND]);
+               }
+       }
+                       
+       *p = '\0';
+       return 0;
+}
+
+
+static int build_replace_query(str* query, db_cmd_t* cmd)
+{
+       db_fld_t* fld;
+       int i;
+       char* p;
+
+       query->len = strings[STR_REPLACE].len;
+       query->len += cmd->table.len;
+       query->len += 2; /* " (" */
+
+       for(i = 0, fld = cmd->params; !DB_FLD_LAST(fld[i]); i++) {
+               query->len += strlen(fld[i].name);
+               query->len += strings[STR_ESC].len;
+               if (!DB_FLD_LAST(fld[i + 1])) query->len += 2; /* , twice */
+       }
+       query->len += strings[STR_VALUES].len;
+       query->len += 1; /* ) */
+
+       query->s = pkg_malloc(query->len + 1);
+       if (query->s == NULL) {
+               ERR("No memory left\n");
+               return -1;
+       }
+       p = query->s;
+       
+       APPEND_STR(p, strings[STR_REPLACE]);
+       APPEND_STR(p, cmd->table);
+       *p++ = ' ';
+       *p++ = '(';
+
+       for(i = 0, fld = cmd->params; !DB_FLD_LAST(fld[i]); i++) {
+               APPEND_CSTR(p, fld[i].name);
+               if (!DB_FLD_LAST(fld[i + 1])) *p++ = ',';
+       }
+       APPEND_STR(p, strings[STR_VALUES]);
+
+       for(i = 0, fld = cmd->params; !DB_FLD_LAST(fld[i]); i++) {
+               APPEND_STR(p, strings[STR_ESC]);
+               if (!DB_FLD_LAST(fld[i + 1])) *p++ = ',';
+       }
+       *p++ = ')';
+       *p = '\0';
+       return 0;
+}
+
+
+static inline int update_params(MYSQL_STMT* st, db_fld_t* params)
+{
+       int i;
+       struct db_fld* f;  /* Current field */
+       struct my_fld* fp; /* Current field payload */
+       struct tm* t;
+
+       /* Iterate through all the query parameters and update
+        * their values if needed
+        */
+
+       /* FIXME: We are updating internals of the prepared statement here,
+        * this is probably not nice but I could not find another way of
+        * updating the pointer to the buffer without the need to run
+        * mysql_stmt_bind_param again (which would be innefficient
+        */
+
+       for(i = 0; i < st->param_count; i++) {
+               fp = DB_GET_PAYLOAD(params + i);
+
+               fp->is_null = params[i].flags & DB_NULL;
+               if (fp->is_null) continue;
+
+               switch(params[i].type) {
+               case DB_STR:
+                       st->params[i].buffer = params[i].v.str.s;
+                       fp->length = params[i].v.str.len;
+                       break;
+
+               case DB_BLOB:
+                       st->params[i].buffer = params[i].v.blob.s;
+                       fp->length = params[i].v.blob.len;
+                       break;
+
+               case DB_CSTR:
+                       st->params[i].buffer = (char*)params[i].v.cstr;
+                       fp->length = strlen(params[i].v.cstr);
+                       break;
+
+               case DB_DATETIME:
+                       t = gmtime(&params[i].v.time);
+                       fp->time.second = t->tm_sec;
+                       fp->time.minute = t->tm_min;
+                       fp->time.hour = t->tm_hour;
+                       fp->time.day = t->tm_mday;
+                       fp->time.month = t->tm_mon + 1;
+                       fp->time.year = t->tm_year + 1900;
+                       break;
+               }
+       }
+
+       return 0;
+}
+
+
+
+static inline int update_result(db_fld_t* result, MYSQL_STMT* st)
+{
+       int i;
+       struct db_fld* r;  /* Current field in the result */
+       struct my_fld* rp; /* Payload of the current field in result */
+       struct tm t;
+
+       /* Iterate through all the query parameters and update
+        * their values if needed
+        */
+
+       for(i = 0; i < st->field_count; i++) {
+               rp = DB_GET_PAYLOAD(result + i);
+
+               if (rp->is_null) {
+                       result[i].flags |= DB_NULL;
+                       continue;
+               } else {
+                       result[i].flags &= ~DB_NULL;
+               }
+
+               switch(result[i].type) {
+               case DB_STR:
+                       result[i].v.str.len = rp->length;
+                       break;
+
+               case DB_BLOB:
+                       result[i].v.blob.len = rp->length;
+                       break;
+
+               case DB_CSTR:
+                       result[i].v.cstr[rp->length] = '\0';
+                       break;
+
+               case DB_DATETIME:
+                       memset(&t, '\0', sizeof(struct tm));
+                       t.tm_sec = rp->time.second;
+                       t.tm_min = rp->time.minute;
+                       t.tm_hour = rp->time.hour;
+                       t.tm_mday = rp->time.day;
+                       t.tm_mon = rp->time.month - 1;
+                       t.tm_year = rp->time.year - 1900;;
+
+                       /* Daylight saving information got lost in the database
+                        * so let timegm to guess it. This eliminates the bug when
+                        * contacts reloaded from the database have different time
+                        * of expiration by one hour when daylight saving is used
+                        */ 
+                       t.tm_isdst = -1;
+#ifdef HAVE_TIMEGM
+                       result[i].v.time = timegm(&t);
+#else
+                       result[i].v.time = _timegm(&t);
+#endif /* HAVE_TIMEGM */
+                       break;
+               }
+       }
+
+       return 0;
+}
+
+
+int my_cmd_write(db_res_t* res, db_cmd_t* cmd)
+{
+       struct my_cmd* mcmd;
+
+       mcmd = DB_GET_PAYLOAD(cmd);
+       if (mcmd->st->param_count && update_params(mcmd->st, cmd->params) < 0) return -1;
+       if (mysql_stmt_execute(mcmd->st)) {
+               ERR("Error while executing query: %s\n", mysql_stmt_error(mcmd->st));
+               return -1;
+       }
+       return 0;
+}
+
+
+int my_cmd_read(db_res_t* res, db_cmd_t* cmd)
+{
+       db_res_t* r;
+       struct my_cmd* mcmd;
+   
+       mcmd = DB_GET_PAYLOAD(cmd);
+       if (mcmd->st->param_count && update_params(mcmd->st, cmd->params) < 0) return -1;
+       if (mysql_stmt_execute(mcmd->st)) {
+               ERR("Error while executing query: %s\n", mysql_stmt_error(mcmd->st));
+               return -1;
+       }
+       return 0;
+}
+
+
+static int bind_params(MYSQL_STMT* st, db_fld_t* fld)
+{
+       int i, n;
+       struct my_fld* f;
+       MYSQL_BIND* params;
+
+       /* Calculate the number of parameters */
+       for(n = 0; !DB_FLD_EMPTY(fld) && !DB_FLD_LAST(fld[n]); n++);
+
+       params = (MYSQL_BIND*)pkg_malloc(sizeof(MYSQL_BIND) * n);
+       if (params == NULL) {
+               ERR("No memory left\n");
+               return -1;
+       }
+       memset(params, '\0', sizeof(MYSQL_BIND) * n);
+       
+       for(i = 0; i < n; i++) {
+               f = DB_GET_PAYLOAD(fld + i);
+               params[i].is_null = &f->is_null;
+               /* We can do it for all the types here, mysql will ignore it
+                * for fixed-size types such as MYSQL_TYPE_LONG
+                */
+               params[i].length = &f->length;
+               switch(fld[i].type) {
+               case DB_INT:
+               case DB_BITMAP:
+                       params[i].buffer_type = MYSQL_TYPE_LONG;
+                       params[i].buffer = &fld[i].v.int4;
+                       break;
+
+               case DB_FLOAT:
+                       params[i].buffer_type = MYSQL_TYPE_FLOAT;
+                       params[i].buffer = &fld[i].v.flt;
+                       break;
+                       
+               case DB_DOUBLE:
+                       params[i].buffer_type = MYSQL_TYPE_DOUBLE;
+                       params[i].buffer = &fld[i].v.dbl;
+                       break;
+
+               case DB_DATETIME:
+                       params[i].buffer_type = MYSQL_TYPE_DATETIME;
+                       params[i].buffer = &f->time;
+                       break;
+
+               case DB_STR:
+               case DB_CSTR:
+                       params[i].buffer_type = MYSQL_TYPE_VAR_STRING;
+                       params[i].buffer = ""; /* Updated on runtime */
+                       break;
+
+               case DB_BLOB:
+                       params[i].buffer_type = MYSQL_TYPE_BLOB;
+                       params[i].buffer = ""; /* Updated on runtime */
+                       break;
+
+               }
+       }
+
+       if (mysql_stmt_bind_param(st, params)) {
+               ERR("Error while binding parameters: %s\n", mysql_stmt_error(st));
+               goto error;
+       }
+
+       /* We do not need the array of MYSQL_BIND anymore, mysql_stmt_bind_param
+        * creates a copy in the statement and we will update it there
+        */
+       pkg_free(params);
+       return 0;
+   
+ error:
+       if (params) pkg_free(params);
+       return -1;
+}
+
+
+static int bind_result(MYSQL_STMT* st, db_fld_t* fld)
+{
+       int i, n;
+       struct my_fld* f;
+       MYSQL_BIND* result;
+
+       /* Calculate the number of fields in the result */
+       for(n = 0; !DB_FLD_EMPTY(fld) && !DB_FLD_LAST(fld[n]); n++);
+
+       result = (MYSQL_BIND*)pkg_malloc(sizeof(MYSQL_BIND) * n);
+       if (result == NULL) {
+               ERR("No memory left\n");
+               return -1;
+       }
+       memset(result, '\0', sizeof(MYSQL_BIND) * n);
+       
+       for(i = 0; i < n; i++) {
+               f = DB_GET_PAYLOAD(fld + i);
+               result[i].is_null = &f->is_null;
+               /* We can do it for all the types here, mysql will ignore it
+                * for fixed-size types such as MYSQL_TYPE_LONG
+                */
+               result[i].length = &f->length;
+               switch(fld[i].type) {
+               case DB_INT:
+               case DB_BITMAP:
+                       result[i].buffer_type = MYSQL_TYPE_LONG;
+                       result[i].buffer = &fld[i].v.int4;
+                       break;
+
+               case DB_FLOAT:
+                       result[i].buffer_type = MYSQL_TYPE_FLOAT;
+                       result[i].buffer = &fld[i].v.flt;
+                       break;
+                       
+               case DB_DOUBLE:
+                       result[i].buffer_type = MYSQL_TYPE_DOUBLE;
+                       result[i].buffer = &fld[i].v.dbl;
+                       break;
+
+               case DB_DATETIME:
+                       result[i].buffer_type = MYSQL_TYPE_DATETIME;
+                       result[i].buffer = &f->time;
+                       break;
+
+               case DB_STR:
+                       result[i].buffer_type = MYSQL_TYPE_VAR_STRING;
+                       f->buf.s = pkg_malloc(STR_BUF_SIZE);
+                       if (f->buf.s == NULL) {
+                               ERR("No memory left\n");
+                               return -1;
+                       }
+                       result[i].buffer = f->buf.s;
+                       fld[i].v.str.s = f->buf.s;
+                       result[i].buffer_length = STR_BUF_SIZE - 1;
+                       break;
+
+               case DB_CSTR:
+                       result[i].buffer_type = MYSQL_TYPE_VAR_STRING;
+                       f->buf.s = pkg_malloc(STR_BUF_SIZE);
+                       if (f->buf.s == NULL) {
+                               ERR("No memory left\n");
+                               return -1;
+                       }
+                       result[i].buffer = f->buf.s;
+                       fld[i].v.cstr = f->buf.s;
+                       result[i].buffer_length = STR_BUF_SIZE - 1;
+                       break;
+
+               case DB_BLOB:
+                       result[i].buffer_type = MYSQL_TYPE_BLOB;
+                       f->buf.s = pkg_malloc(STR_BUF_SIZE);
+                       if (f->buf.s == NULL) {
+                               ERR("No memory left\n");
+                               return -1;
+                       }
+                       result[i].buffer = f->buf.s;
+                       fld[i].v.blob.s = f->buf.s;
+                       result[i].buffer_length = STR_BUF_SIZE - 1;
+                       break;
+
+               }
+       }
+
+       if (mysql_stmt_bind_result(st, result)) {
+               ERR("Error while binding result: %s\n", mysql_stmt_error(st));
+               goto error;
+       }
+
+       /* We do not need the array of MYSQL_BIND anymore, mysql_stmt_bind_param
+        * creates a copy in the statement and we will update it there
+        */
+       pkg_free(result);
+       return 0;
+   
+ error:
+       if (result) pkg_free(result);
+       return -1;
+}
+
+
+int my_cmd(db_cmd_t* cmd)
+{
+       struct my_cmd* res;
+       struct my_con* mcon;
+
+       res = (struct my_cmd*)pkg_malloc(sizeof(struct my_cmd));
+       if (res == NULL) {
+               ERR("No memory left\n");
+               goto error;
+       }
+       memset(res, '\0', sizeof(struct my_cmd));
+       if (db_drv_init(&res->gen, my_cmd_free) < 0) goto error;
+
+       /* FIXME */
+       mcon = DB_GET_PAYLOAD(cmd->ctx->con[db_payload_idx]);
+       res->st = mysql_stmt_init(mcon->con);
+       if (res->st == NULL) {
+               ERR("No memory left\n");
+               goto error;
+       }
+
+       switch(cmd->type) {
+       case DB_PUT:
+               if (DB_FLD_EMPTY(cmd->params)) {
+                       ERR("BUG: No parameters provided for DB_PUT in context '%.*s'\n", 
+                               cmd->ctx->id.len, ZSW(cmd->ctx->id.s));
+                       goto error;
+               }
+               if (build_replace_query(&res->query, cmd) < 0) goto error;
+               if (mysql_stmt_prepare(res->st, res->query.s, res->query.len)) {
+                       ERR("Error while preparing replace query: %s\n", 
+                               mysql_stmt_error(res->st));
+                       goto error;
+               }
+               if (bind_params(res->st, cmd->params) < 0) goto error;
+               break;
+
+       case DB_DEL:
+               if (build_delete_query(&res->query, cmd) < 0) goto error;
+               if (mysql_stmt_prepare(res->st, res->query.s, res->query.len)) {
+                       ERR("Error while preparing delete query: %s\n",
+                               mysql_stmt_error(res->st));
+                               goto error;
+               }
+               if (!DB_FLD_EMPTY(cmd->params)) {
+                       if (bind_params(res->st, cmd->params) < 0) goto error;
+               }
+               break;
+
+       case DB_GET:
+               if (build_select_query(&res->query, cmd) < 0) goto error;
+               if (mysql_stmt_prepare(res->st, res->query.s, res->query.len)) {
+                       ERR("Error while preparing select query: %s\n",
+                               mysql_stmt_error(res->st));
+                       goto error;
+               }
+               if (!DB_FLD_EMPTY(cmd->params)) {
+                       if (bind_params(res->st, cmd->params) < 0) goto error;
+               }
+               if (bind_result(res->st, cmd->result) < 0) goto error;
+               break;
+       }
+
+       DB_SET_PAYLOAD(cmd, res);
+       return 0;
+
+ error:
+       if (res) {
+               db_drv_free(&res->gen);
+               if (res->query.s) pkg_free(res->query.s);
+               if (res->st) mysql_stmt_close(res->st);
+               pkg_free(res);
+       }
+       return -1;
+}
+
+
+int my_cmd_next(db_res_t* res)
+{
+       int ret;
+       struct my_cmd* mcmd;
+
+       mcmd = DB_GET_PAYLOAD(res->cmd);
+       ret = mysql_stmt_fetch(mcmd->st);
+       
+       if (ret == MYSQL_NO_DATA) return 1;
+
+       if (ret != 0) {
+               ERR("Error in mysql_stmt_fetch: %s\n", mysql_stmt_error(mcmd->st));
+               return -1;
+       }
+
+       if (update_result(res->cmd->result, mcmd->st) < 0) {
+               mysql_stmt_free_result(mcmd->st);
+               return -1;
+       }
+
+       res->cur_rec->fld = res->cmd->result;
+       return 0;
+}
+
similarity index 65%
rename from modules/db_mysql/row.h
rename to modules/db_mysql/my_cmd.h
index 004622b..f96f8d9 100644 (file)
@@ -1,9 +1,8 @@
 /* 
- * $Id$ 
- *
- * MySQL module row related functions
+ * $Id$
  *
  * Copyright (C) 2001-2003 FhG Fokus
+ * Copyright (C) 2006-2007 iptelorg GmbH
  *
  * This file is part of ser, a free SIP server.
  *
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-#ifndef ROW_H
-#define ROW_H
+#ifndef _MY_CMD_H
+#define _MY_CMD_H  1
 
-#include "../../db/db_con.h"
-#include "../../db/db_res.h"
-#include "../../db/db_row.h"
+#include "../../db/db_drv.h"
+#include "../../db/db_cmd.h"
+#include <mysql/mysql.h>
 
+struct my_cmd {
+       db_drv_t gen;
 
-/*
- * Convert a row from result into db API representation
- */
-int convert_row(db_con_t* _h, db_res_t* _res, db_row_t* _r);
+       str query;
+       MYSQL_STMT* st;
+};
 
+int my_cmd(db_cmd_t* cmd);
 
-/*
- * Release memory used by row
- */
-int free_row(db_row_t* _r);
+/* Runtime execution function for DB_GET */
+int my_cmd_read(db_res_t* res, db_cmd_t* cmd);
+
+/* Runtime execution function for DB_PUT and DB_DEL */
+int my_cmd_write(db_res_t* res, db_cmd_t* cmd);
+
+int my_cmd_first(db_res_t* res);
 
+int my_cmd_next(db_res_t* res);
 
-#endif /* ROW_H */
+#endif /* _MY_CMD_H */
index 1564b4f..d884a81 100644 (file)
@@ -2,6 +2,7 @@
  * $Id$
  *
  * Copyright (C) 2001-2004 iptel.org
+ * Copyright (C) 2006-2007 iptelorg GmbH
  *
  * This file is part of ser, a free SIP server.
  *
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-#include "my_con.h"
 #include "../../mem/mem.h"
 #include "../../dprint.h"
 #include "../../ut.h"
-#include "utils.h"
 #include <string.h>
 #include <time.h>
+#include "my_uri.h"
+#include "my_con.h"
 
 
 /*
- * Create a new connection structure,
- * open the MySQL connection and set reference count to 1
+ * Close the connection and release memory
  */
-struct my_con* new_connection(struct db_id* id)
+static void my_con_free(db_con_t* con, struct my_con* payload)
 {
-       struct my_con* ptr;
+       if (!payload) return;
+       
+       /* Delete the structure only if there are no more references
+        * to it in the connection pool
+        */
+       if (db_pool_remove((db_pool_entry_t*)payload) == 0) return;
+
+       db_pool_entry_free(&payload->gen);
+       if (payload->con) pkg_free(payload->con);
+       pkg_free(payload);
+}
 
-       if (!id) {
-               LOG(L_ERR, "new_connection: Invalid parameter value\n");
-               return 0;
-       }
 
-       ptr = (struct my_con*)pkg_malloc(sizeof(struct my_con));
-       if (!ptr) {
-               LOG(L_ERR, "new_connection: No memory left\n");
-               return 0;
-       }
+static int my_con_connect(db_con_t* con)
+{
+       struct my_con* mcon;
+       struct my_uri* muri;
 
-       memset(ptr, 0, sizeof(struct my_con));
-       ptr->ref = 1;
-       
-       ptr->con = (MYSQL*)pkg_malloc(sizeof(MYSQL));
-       if (!ptr->con) {
-               LOG(L_ERR, "new_connection: No enough memory\n");
-               goto err;
-       }
+       mcon = DB_GET_PAYLOAD(con);
+       muri = DB_GET_PAYLOAD(con->uri);
 
-       mysql_init(ptr->con);
+       /* Do not reconnect already connected connections */
+       if (mcon->flags & MY_CONNECTED) return 0;
 
-       if (id->port) {
-               DBG("new_connection: Opening MySQL connection: %s://%s:%s@%s:%d/%s\n",
-                   ZSW(id->scheme),
-                   ZSW(id->username),
-                   ZSW(id->password),
-                   ZSW(id->host),
-                   id->port,
-                   ZSW(id->database)
-                   );
-       } else {
-               DBG("new_connection: Opening MySQL connection: %s://%s:%s@%s/%s\n",
-                   ZSW(id->scheme),
-                   ZSW(id->username),
-                   ZSW(id->password),
-                   ZSW(id->host),
-                   ZSW(id->database)
-                   );
-       }
+       DBG("my_con_connect: Connecting to %.*s:%.*s\n",
+               con->uri->scheme.len, ZSW(con->uri->scheme.s),
+               con->uri->body.len, ZSW(con->uri->body.s));
 
-       if (!mysql_real_connect(ptr->con, id->host, id->username, id->password, id->database, id->port, 0, 0)) {
-               LOG(L_ERR, "new_connection: %s\n", mysql_error(ptr->con));
-               mysql_close(ptr->con);
-               goto err;
+       if (!mysql_real_connect(mcon->con, muri->host, muri->username, 
+                                                       muri->password, muri->database, muri->port, 0, 0)) {
+               LOG(L_ERR, "my_con_connect: %s\n", mysql_error(mcon->con));
+               return -1;
        }
+       
+       /* Enable reconnection explicitly */
+       mcon->con->reconnect = 1;
+       
+       DBG("my_con_connect: Connection type is %s\n", mysql_get_host_info(mcon->con));
+       DBG("my_con_connect: Protocol version is %d\n", mysql_get_proto_info(mcon->con));
+       DBG("my_con_connect: Server version is %s\n", mysql_get_server_info(mcon->con));
 
-            /* Enable reconnection explicitly */
-       ptr->con->reconnect = 1;
+       mcon->timestamp = time(0);
+       mcon->flags |= MY_CONNECTED;
+       return 0;
+}
 
-       DBG("new_connection: Connection type is %s\n", mysql_get_host_info(ptr->con));
-       DBG("new_connection: Protocol version is %d\n", mysql_get_proto_info(ptr->con));
-       DBG("new_connection: Server version is %s\n", mysql_get_server_info(ptr->con));
 
+static void my_con_disconnect(db_con_t* con)
+{
+       struct my_con* mcon;
 
-       ptr->timestamp = time(0);
-       ptr->id = id;
-       return ptr;
+       mcon = DB_GET_PAYLOAD(con);
 
- err:
-       if (ptr && ptr->con) pkg_free(ptr->con);
-       if (ptr) pkg_free(ptr);
-       return 0;
+       if ((mcon->flags & MY_CONNECTED) == 0) return;
+
+       DBG("my_con_disconnect: Disconnecting from %.*s:%.*s\n",
+               con->uri->scheme.len, ZSW(con->uri->scheme.s),
+               con->uri->body.len, ZSW(con->uri->body.s));
+
+       mysql_close(mcon->con);
+       mcon->flags &= ~MY_CONNECTED;
 }
 
 
-/*
- * Close the connection and release memory
- */
-void free_connection(struct my_con* con)
+int my_con(db_con_t* con)
 {
-       if (!con) return;
-       if (con->id) free_db_id(con->id);
-       if (con->con) {
-               mysql_close(con->con);
-               pkg_free(con->con);
+       struct my_con* ptr;
+       struct my_uri* uri;
+
+       /* First try to lookup the connection in the connection pool and
+        * re-use it if a match is found
+        */
+       ptr = (struct my_con*)db_pool_get(con->uri);
+       if (ptr) {
+               DBG("my_con: Connection to %.*s:%.*s found in connection pool\n",
+                       con->uri->scheme.len, ZSW(con->uri->scheme.s),
+                       con->uri->body.len, ZSW(con->uri->body.s));
+               goto found;
+       }
+
+       ptr = (struct my_con*)pkg_malloc(sizeof(struct my_con));
+       if (!ptr) {
+               LOG(L_ERR, "my_con: No memory left\n");
+               goto error;
        }
-       pkg_free(con);
+       memset(ptr, '\0', sizeof(struct my_con));
+       if (db_pool_entry_init(&ptr->gen, my_con_free, con->uri) < 0) goto error;
+
+       ptr->con = (MYSQL*)pkg_malloc(sizeof(MYSQL));
+       if (!ptr->con) {
+               LOG(L_ERR, "my_con: No enough memory\n");
+               goto error;
+       }
+       mysql_init(ptr->con);
+
+       uri = DB_GET_PAYLOAD(con->uri);
+       DBG("my_con: Creating new connection to: %.*s:%.*s\n",
+               con->uri->scheme.len, ZSW(con->uri->scheme.s),
+               con->uri->body.len, ZSW(con->uri->body.s));
+
+       /* Put the newly created mysql connection into the pool */
+       db_pool_put((struct db_pool_entry*)ptr);
+       DBG("my_con: Connection stored in connection pool\n");
+
+ found:
+       /* Attach driver payload to the db_con structure and set connect and
+        * disconnect functions
+        */
+       DB_SET_PAYLOAD(con, ptr);
+       con->connect = my_con_connect;
+       con->disconnect = my_con_disconnect;
+       return 0;
+
+ error:
+       if (ptr) {
+               db_pool_entry_free(&ptr->gen);
+               if (ptr->con) pkg_free(ptr->con);
+               pkg_free(ptr);
+       }
+       return 0;
 }
index aa51a33..815e47c 100644 (file)
@@ -2,6 +2,7 @@
  * $Id$
  *
  * Copyright (C) 2001-2003 FhG Fokus
+ * Copyright (C) 2006-2007 iptelorg GmbH
  *
  * This file is part of ser, a free SIP server.
  *
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-#ifndef MY_CON_H
-#define MY_CON_H
+#ifndef _MY_CON_H
+#define _MY_CON_H  1
 
 #include "../../db/db_pool.h"
-#include "../../db/db_id.h"
+#include "../../db/db_con.h"
+#include "../../db/db_uri.h"
 
 #include <time.h>
 #include <mysql/mysql.h>
 
+enum my_flags {
+       MY_CONNECTED = 1
+};
 
 struct my_con {
-       struct db_id* id;        /* Connection identifier */
-       unsigned int ref;        /* Reference count */
-       struct pool_con* next;   /* Next connection in the pool */
+       /* Generic part of the structure */
+       db_pool_entry_t gen;
 
-       MYSQL* con;              /* Connection representation */
-       time_t timestamp;        /* Timestamp of last query */
+       MYSQL* con;
+       unsigned int flags;
+       time_t timestamp;
 };
 
 
-/*
- * Some convenience wrappers
- */
-#define CON_CONNECTION(db_con) (((struct my_con*)((db_con)->tail))->con)
-#define CON_TIMESTAMP(db_con)  (((struct my_con*)((db_con)->tail))->timestamp)
-
-
 /*
  * Create a new connection structure,
  * open the MySQL connection and set reference count to 1
  */
-struct my_con* new_connection(struct db_id* id);
-
-
-/*
- * Close the connection and release memory
- */
-void free_connection(struct my_con* con);
+int my_con(db_con_t* con);
 
-#endif /* MY_CON_H */
+#endif /* _MY_CON_H */
similarity index 64%
rename from modules/db_mysql/db_con.c
rename to modules/db_mysql/my_fld.c
index 094b2a0..5d93472 100644 (file)
@@ -1,9 +1,8 @@
 /* 
- * $Id$ 
- *
- * Database connection related functions
+ * $Id$
  *
  * Copyright (C) 2001-2003 FhG Fokus
+ * Copyright (C) 2006-2007 iptelorg GmbH
  *
  * This file is part of ser, a free SIP server.
  *
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-
 #include <string.h>
-#include "../../db/db.h"
-#include "../../dprint.h"
 #include "../../mem/mem.h"
+#include "../../dprint.h"
+#include "../../db/db_gen.h"
+#include "my_fld.h"
 
 
-/*
- * Store name of table that will be used by
- * subsequent database functions
- */
-int use_table(db_con_t* _h, const char* _t)
+static void my_fld_free(db_fld_t* fld, struct my_fld* payload)
+{
+       db_drv_free(&payload->gen);
+       if (payload->buf.s) pkg_free(payload->buf.s);
+       pkg_free(payload);
+}
+
+
+int my_fld(db_fld_t* fld)
 {
-       if ((!_h) || (!_t)) {
-               LOG(L_ERR, "use_table: Invalid parameter value\n");
+       struct my_fld* res;
+
+       ERR("my_fld executed\n");
+
+       res = (struct my_fld*)pkg_malloc(sizeof(struct my_fld));
+       if (res == NULL) {
+               ERR("No memory left\n");
                return -1;
        }
+       memset(res, '\0', sizeof(struct my_fld));
+       if (db_drv_init(&res->gen, my_fld_free) < 0) goto error;
 
-       CON_TABLE(_h) = _t;
+       DB_SET_PAYLOAD(fld, res);
        return 0;
+
+ error:
+       if (res) pkg_free(res);
+       return -1;
 }
similarity index 77%
rename from modules/db_mysql/val.h
rename to modules/db_mysql/my_fld.h
index e218ad9..7e264d9 100644 (file)
@@ -1,7 +1,8 @@
 /* 
- * $Id$ 
+ * $Id$
  *
  * Copyright (C) 2001-2003 FhG Fokus
+ * Copyright (C) 2006-2007 iptelorg GmbH
  *
  * This file is part of ser, a free SIP server.
  *
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-#ifndef VAL_H
-#define VAL_H
+#ifndef _MY_FLD_H
+#define _MY_FLD_H  1
 
+#include "../../db/db_drv.h"
+#include "../../db/db_fld.h"
 #include <mysql/mysql.h>
-#include "../../db/db_val.h"
 
+struct my_fld {
+       db_drv_t gen;
 
-/*
- * Does not copy strings
- */
-int str2val(db_type_t _t, db_val_t* _v, const char* _s, int _l);
-
-
-/*
- * Used when converting result from a query
- */
-int val2str(MYSQL* _c, db_val_t* _v, char* _s, int* _len);
+       my_bool is_null;
+       MYSQL_TIME time;
+       unsigned long length;
+       str buf;
+};
 
+int my_fld(db_fld_t* fld);
 
-#endif /* VAL_H */
+#endif /* _MY_FLD_H */
similarity index 52%
rename from modules/db_mysql/row.c
rename to modules/db_mysql/my_res.c
index 926fb06..6a2ed87 100644 (file)
@@ -1,9 +1,8 @@
 /* 
- * $Id$ 
- *
- * MySQL module row related functions
+ * $Id$
  *
  * Copyright (C) 2001-2003 FhG Fokus
+ * Copyright (C) 2006-2007 iptelorg GmbH
  *
  * This file is part of ser, a free SIP server.
  *
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-
-#include "../../dprint.h"
-#include "../../mem/mem.h"
 #include <mysql/mysql.h>
-#include "val.h"
-#include "my_con.h"
-#include "res.h"
-#include "row.h"
+#include "../../mem/mem.h"
+#include "../../dprint.h"
+#include "../../db/db_gen.h"
+#include "my_cmd.h"
+#include "my_res.h"
 
 
-/*
- * Convert a row from result into db API representation
- */
-int convert_row(db_con_t* _h, db_res_t* _res, db_row_t* _r)
+void my_res_free(db_res_t* res, struct my_res* payload)
 {
-       unsigned long* lengths;
-       int i;
+       struct my_cmd* mcmd;
 
-       if ((!_h) || (!_res) || (!_r)) {
-               LOG(L_ERR, "convert_row: Invalid parameter value\n");
-               return -1;
-       }
+       mcmd = DB_GET_PAYLOAD(res->cmd);
 
-       ROW_VALUES(_r) = (db_val_t*)pkg_malloc(sizeof(db_val_t) * RES_COL_N(_res));
-       ROW_N(_r) = RES_COL_N(_res);
-       if (!ROW_VALUES(_r)) {
-               LOG(L_ERR, "convert_row: No memory left\n");
-               return -1;
+       if (mysql_stmt_free_result(mcmd->st)) {
+               ERR("Error while freeing MySQL result: %s\n", mysql_stmt_error(mcmd->st));
        }
 
-       lengths = mysql_fetch_lengths(MYRES_RESULT(_res));
-
-       for(i = 0; i < RES_COL_N(_res); i++) {
-               if (str2val(RES_TYPES(_res)[i], &(ROW_VALUES(_r)[i]), 
-                               ((MYSQL_ROW)MYRES_ROW(_res))[i], lengths[i]) < 0) {
-                       LOG(L_ERR, "convert_row: Error while converting value\n");
-                       free_row(_r);
-                       return -3;
-               }
-       }
-       return 0;
+       db_drv_free(&payload->gen);
+       pkg_free(payload);
 }
 
 
 /*
- * Release memory used by row
+ * Attach a mysql specific structure to db_res, this structure contains a pointer
+ * to my_res_free which releases the mysql result stored in the mysql statement
+ * and if there is a cursor open in the statement then it will be closed as well
  */
-int free_row(db_row_t* _r)
+int my_res(db_res_t* res)
 {
-       if (!_r) {
-               LOG(L_ERR, "free_row: Invalid parameter value\n");
+       struct my_res* mr;
+
+       mr = (struct my_res*)pkg_malloc(sizeof(struct my_res));
+       if (mr == NULL) {
+               ERR("No memory left\n");
                return -1;
        }
-
-       if (ROW_VALUES(_r)) pkg_free(ROW_VALUES(_r));
+       if (db_drv_init(&mr->gen, my_res_free) < 0) goto error;
+       DB_SET_PAYLOAD(res, mr);
        return 0;
+       
+ error:
+       if (mr) {
+               db_drv_free(&mr->gen);
+               pkg_free(mr);
+       }
+       return -1;
 }
-
similarity index 81%
rename from modules/db_mysql/defs.h
rename to modules/db_mysql/my_res.h
index 2ef5a0a..e4daf47 100644 (file)
@@ -1,9 +1,8 @@
 /* 
- * $Id$ 
- *
- * MySQL module various definitions
+ * $Id$
  *
  * Copyright (C) 2001-2003 FhG Fokus
+ * Copyright (C) 2006-2007 iptelorg GmbH
  *
  * This file is part of ser, a free SIP server.
  *
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
+#ifndef _MY_RES_H
+#define _MY_RES_H  1
+
+#include "../../db/db_drv.h"
+#include "../../db/db_res.h"
 
-#ifndef DEFS_H
-#define DEFS_H
+struct my_res {
+       db_drv_t gen;
+};
 
-#define PARANOID
-#define SQL_BUF_LEN 65535
+int my_res(db_res_t* cmd);
 
-#endif /* DEFS_H */
+#endif /* _MY_RES_H */
diff --git a/modules/db_mysql/my_uri.c b/modules/db_mysql/my_uri.c
new file mode 100644 (file)
index 0000000..6390d79
--- /dev/null
@@ -0,0 +1,282 @@
+/* 
+ * $Id$ 
+ *
+ * MySQL module interface
+ *
+ * Copyright (C) 2001-2003 FhG FOKUS
+ * Copyright (C) 2006-2007 iptelorg GmbH
+ *
+ * This file is part of ser, a free SIP server.
+ *
+ * ser is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * For a license to use the ser software under conditions
+ * other than those described here, or to purchase support for this
+ * software, please contact iptel.org by e-mail at the following addresses:
+ *    info@iptel.org
+ *
+ * ser is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include "../../dprint.h"
+#include "../../mem/mem.h"
+#include "../../ut.h"
+#include "../../db/db_gen.h"
+#include "my_uri.h"
+
+
+/* compare s1 & s2  with a function f (which should return 0 if ==);
+ * s1 & s2 can be null
+ * return 0 if match, 1 if not */
+#define cmpstr(s1, s2, f) \
+       ((s1)!=(s2)) && ((s1)==0 || (s2)==0 || (f)((s1), (s2))!=0)
+
+/*
+ * Compare two connection identifiers
+ */
+static unsigned char my_uri_cmp(db_uri_t* uri1, db_uri_t* uri2)
+{
+       struct my_uri* muri1, *muri2;
+
+       if (!uri1 || !uri2) return 0;
+
+       muri1 = DB_GET_PAYLOAD(uri1);
+       muri2 = DB_GET_PAYLOAD(uri2);
+       if (muri1->port != muri2->port) return 0;
+
+       if (cmpstr(muri1->username, muri2->username, strcmp)) return 0;
+       if (cmpstr(muri1->password, muri2->password, strcmp)) return 0;
+       if (cmpstr(muri1->host, muri2->host, strcasecmp)) return 0;
+       if (cmpstr(muri1->database, muri2->database, strcmp)) return 0;
+       return 1;
+}
+
+
+
+/*
+ * Duplicate a string
+ */
+static int dupl_string(char** dst, const char* begin, const char* end)
+{
+       if (*dst) pkg_free(*dst);
+
+       *dst = pkg_malloc(end - begin + 1);
+       if ((*dst) == NULL) {
+               return -1;
+       }
+
+       memcpy(*dst, begin, end - begin);
+       (*dst)[end - begin] = '\0';
+       return 0;
+}
+
+
+/*
+ * Parse mysql URI of form 
+ * //[username[:password]@]hostname[:port]/database
+ *
+ * Returns 0 if parsing was successful and -1 otherwise
+ */
+static int parse_mysql_uri(struct my_uri* res, str* uri)
+{
+#define SHORTEST_DB_URL "//a/b"
+#define SHORTEST_DB_URL_LEN (sizeof(SHORTEST_DB_URL) - 1)
+
+       enum state {
+               ST_SLASH1,     /* First slash */
+               ST_SLASH2,     /* Second slash */
+               ST_USER_HOST,  /* Username or hostname */
+               ST_PASS_PORT,  /* Password or port part */
+               ST_HOST,       /* Hostname part */
+               ST_PORT,       /* Port part */
+               ST_DB          /* Database part */
+       };
+
+       enum state st;
+       int  i;
+       const char* begin;
+       char* prev_token;
+
+       prev_token = 0;
+
+       if (!res || !res) {
+               goto err;
+       }
+       
+       if (uri->len < SHORTEST_DB_URL_LEN) {
+               goto err;
+       }
+       
+       st = ST_SLASH1;
+       begin = uri->s;
+
+       for(i = 0; i < uri->len; i++) {
+               switch(st) {
+               case ST_SLASH1:
+                       switch(uri->s[i]) {
+                       case '/':
+                               st = ST_SLASH2;
+                               break;
+
+                       default:
+                               goto err;
+                       }
+                       break;
+
+               case ST_SLASH2:
+                       switch(uri->s[i]) {
+                       case '/':
+                               st = ST_USER_HOST;
+                               begin = uri->s + i + 1;
+                               break;
+                               
+                       default:
+                               goto err;
+                       }
+                       break;
+
+               case ST_USER_HOST:
+                       switch(uri->s[i]) {
+                       case '@':
+                               st = ST_HOST;
+                               if (dupl_string(&res->username, begin, uri->s + i) < 0) goto err;
+                               begin = uri->s + i + 1;
+                               break;
+
+                       case ':':
+                               st = ST_PASS_PORT;
+                               if (dupl_string(&prev_token, begin, uri->s + i) < 0) goto err;
+                               begin = uri->s + i + 1;
+                               break;
+
+                       case '/':
+                               if (dupl_string(&res->host, begin, uri->s + i) < 0) goto err;
+                               if (dupl_string(&res->database, uri->s + i + 1, uri->s + uri->len) < 0) goto err;
+                               return 0;
+                       }
+                       break;
+
+               case ST_PASS_PORT:
+                       switch(uri->s[i]) {
+                       case '@':
+                               st = ST_HOST;
+                               res->username = prev_token;
+                               if (dupl_string(&res->password, begin, uri->s + i) < 0) goto err;
+                               begin = uri->s + i + 1;
+                               break;
+
+                       case '/':
+                               res->host = prev_token;
+                               res->port = str2s(begin, uri->s + i - begin, 0);
+                               if (dupl_string(&res->database, uri->s + i + 1, uri->s + uri->len) < 0) goto err;
+                               return 0;
+                       }
+                       break;
+
+               case ST_HOST:
+                       switch(uri->s[i]) {
+                       case ':':
+                               st = ST_PORT;
+                               if (dupl_string(&res->host, begin, uri->s + i) < 0) goto err;
+                               begin = uri->s + i + 1;
+                               break;
+
+                       case '/':
+                               if (dupl_string(&res->host, begin, uri->s + i) < 0) goto err;
+                               if (dupl_string(&res->database, uri->s + i + 1, uri->s + uri->len) < 0) goto err;
+                               return 0;
+                       }
+                       break;
+
+               case ST_PORT:
+                       switch(uri->s[i]) {
+                       case '/':
+                               res->port = str2s(begin, uri->s + i - begin, 0);
+                               if (dupl_string(&res->database, uri->s + i + 1, uri->s + uri->len) < 0) goto err;
+                               return 0;
+                       }
+                       break;
+                       
+               case ST_DB:
+                       break;
+               }
+       }
+
+       if (st != ST_DB) goto err;
+       return 0;
+
+ err:
+       if (prev_token) pkg_free(prev_token);
+       if (res == NULL) return -1;
+       if (res->username) {
+               pkg_free(res->username);
+               res->username = NULL;
+       }
+       if (res->password) {
+               pkg_free(res->password);
+               res->password = NULL;
+       }
+       if (res->host) {
+               pkg_free(res->host);
+               res->host = NULL;
+       }
+       if (res->database) {
+               pkg_free(res->database);
+               res->database = NULL;
+       }
+       return -1;
+}
+
+
+
+static void my_uri_free(db_uri_t* uri, struct my_uri* payload)
+{
+       if (payload == NULL) return;
+       db_drv_free(&payload->drv);
+       if (payload->username) pkg_free(payload->username);
+       if (payload->password) pkg_free(payload->password);
+       if (payload->host) pkg_free(payload->host);
+       if (payload->database) pkg_free(payload->database);
+       pkg_free(payload);
+}
+
+
+int my_uri(db_uri_t* uri)
+{
+       struct my_uri* res;
+
+       ERR("my_uri called\n");
+
+       res = (struct my_uri*)pkg_malloc(sizeof(struct my_uri));
+       if (res == NULL) {
+               ERR("No memory left\n");
+               goto error;
+       }
+       memset(res, '\0', sizeof(struct my_uri));
+       if (db_drv_init(&res->drv, my_uri_free) < 0) goto error;
+       if (parse_mysql_uri(res, &uri->body) < 0) goto error;
+
+       DB_SET_PAYLOAD(uri, res);
+       uri->cmp = my_uri_cmp;
+       return 0;
+
+ error:
+       if (res) {
+               db_drv_free(&res->drv);
+               if (res) pkg_free(res);
+       }
+       return -1;
+}
+
similarity index 73%
rename from modules/db_mysql/utils.h
rename to modules/db_mysql/my_uri.h
index 65f3376..3978c9c 100644 (file)
@@ -1,9 +1,10 @@
 /* 
  * $Id$ 
  *
- * MySQL module utilities
+ * MySQL module interface
  *
- * Copyright (C) 2001-2003 FhG Fokus
+ * Copyright (C) 2001-2003 FhG FOKUS
+ * Copyright (C) 2006-2007 iptelorg GmbH
  *
  * This file is part of ser, a free SIP server.
  *
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
+#ifndef _MY_URI_H
+#define _MY_URI_H
 
-#ifndef UTILS_H
-#define UTILS_H
+#include "../../db/db_uri.h"
+#include "../../db/db_drv.h"
 
-#include <time.h>
+struct my_uri {
+       db_drv_t drv;
+       char* username;
+       char* password;
+       char* host;
+       unsigned short port;
+       char* database;
+};
 
 
-/*
- * Convert time_t structure to format accepted by MySQL database
- */
-int time2mysql(time_t _time, char* _result, int _res_len);
-
+int my_uri(db_uri_t* uri);
 
-/*
- * Convert MySQL time representation to time_t structure
- */
-time_t mysql2time(const char* _str);
 
+#endif /* _MY_URI_H */
 
-#endif /* UTILS_H */
similarity index 73%
rename from modules/db_mysql/db_mod.c
rename to modules/db_mysql/mysql_mod.c
index d0b4fc9..68744ea 100644 (file)
  */
 
 #include "../../sr_module.h"
-#include "dbase.h"
-#include "db_mod.h"
-
-#include <mysql.h>
+#include "../../db/db.h"
+#include "my_uri.h"
+#include "my_con.h"
+#include "my_cmd.h"
+#include "my_fld.h"
+#include "my_res.h"
+#include "mysql_mod.h"
 
 int ping_interval = 5 * 60; /* Default is 5 minutes */
 int auto_reconnect = 1;     /* Default is enabled */
@@ -51,16 +54,17 @@ MODULE_VERSION
  * MySQL database module interface
  */
 static cmd_export_t cmds[] = {
-       {"db_use_table",   (cmd_function)use_table,      2, 0, 0},
-       {"db_init",        (cmd_function)db_init,        1, 0, 0},
-       {"db_close",       (cmd_function)db_close,       2, 0, 0},
-       {"db_query",       (cmd_function)db_query,       2, 0, 0},
-       {"db_raw_query",   (cmd_function)db_raw_query,   2, 0, 0},
-       {"db_free_result", (cmd_function)db_free_result, 2, 0, 0},
-       {"db_insert",      (cmd_function)db_insert,      2, 0, 0},
-       {"db_delete",      (cmd_function)db_delete,      2, 0, 0},
-       {"db_update",      (cmd_function)db_update,      2, 0, 0},
-       {"db_replace",     (cmd_function)db_replace,     2, 0, 0},
+       {"db_ctx",         (cmd_function)NULL,  0, 0, 0},
+       {"db_con",         (cmd_function)my_con,  0, 0, 0},
+       {"db_uri",         (cmd_function)my_uri,  0, 0, 0},
+       {"db_cmd",         (cmd_function)my_cmd,  0, 0, 0},
+       {"db_put",         (cmd_function)my_cmd_write, 0, 0, 0},
+       {"db_del",         (cmd_function)my_cmd_write, 0, 0, 0},
+       {"db_get",         (cmd_function)my_cmd_read, 0, 0, 0},
+       {"db_res",         (cmd_function)my_res,  0, 0, 0},
+       {"db_fld",         (cmd_function)my_fld,  0, 0, 0},
+       {"db_first",       (cmd_function)my_cmd_next, 0, 0, 0},
+       {"db_next",        (cmd_function)my_cmd_next,  0, 0, 0},
        {0, 0, 0, 0, 0}
 };
 
@@ -90,6 +94,5 @@ struct module_exports exports = {
 
 static int mysql_mod_init(void)
 {
-       DBG("mysql: MySQL client version is %s\n", mysql_get_client_info());
        return 0;
 }
similarity index 94%
rename from modules/db_mysql/db_mod.h
rename to modules/db_mysql/mysql_mod.h
index 7fbf63e..628361a 100644 (file)
  *  2003-03-16  flags export parameter added (janakj)
  */
 
-#ifndef DB_MOD_H
-#define DB_MOD_H
+#ifndef _MYSQL_MOD_H
+#define _MYSQL_MOD_H
 
 extern int ping_interval;
 extern int auto_reconnect;
 
-#endif /* DB_MOD_H */
+#endif /* _MYSQL_MOD_H */
diff --git a/modules/db_mysql/res.c b/modules/db_mysql/res.c
deleted file mode 100644 (file)
index 23efd27..0000000
+++ /dev/null
@@ -1,264 +0,0 @@
-/* 
- * $Id$ 
- *
- * MySQL module result related functions
- *
- * Copyright (C) 2001-2003 FhG Fokus
- *
- * This file is part of ser, a free SIP server.
- *
- * ser is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version
- *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info@iptel.org
- *
- * ser is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License 
- * along with this program; if not, write to the Free Software 
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-
-#include <mysql/mysql.h>
-#include "../../mem/mem.h"
-#include "../../dprint.h"
-#include "row.h"
-#include "my_con.h"
-#include "res.h"
-
-
-/*
- * Get and convert columns from a result
- */
-static inline int get_columns(db_con_t* _h, db_res_t* _r)
-{
-       int n, i;
-       MYSQL_FIELD* fields;
-
-       if ((!_h) || (!_r)) {
-               LOG(L_ERR, "get_columns: Invalid parameter\n");
-               return -1;
-       }
-
-       n = mysql_field_count(CON_CONNECTION(_h));
-       if (!n) {
-               LOG(L_ERR, "get_columns: No columns\n");
-               return -2;
-       }
-       
-        RES_NAMES(_r) = (db_key_t*)pkg_malloc(sizeof(db_key_t) * n);
-       if (!RES_NAMES(_r)) {
-               LOG(L_ERR, "get_columns: No memory left\n");
-               return -3;
-       }
-
-       RES_TYPES(_r) = (db_type_t*)pkg_malloc(sizeof(db_type_t) * n);
-       if (!RES_TYPES(_r)) {
-               LOG(L_ERR, "get_columns: No memory left\n");
-               pkg_free(RES_NAMES(_r));
-               return -4;
-       }
-
-       RES_COL_N(_r) = n;
-
-       fields = mysql_fetch_fields(MYRES_RESULT(_r));
-       for(i = 0; i < n; i++) {
-               RES_NAMES(_r)[i] = fields[i].name;
-               switch(fields[i].type) {
-               case FIELD_TYPE_TINY:
-               case FIELD_TYPE_SHORT:
-               case FIELD_TYPE_LONG:
-               case FIELD_TYPE_INT24:
-               case FIELD_TYPE_TIMESTAMP:
-                       RES_TYPES(_r)[i] = DB_INT;
-                       break;
-
-               case FIELD_TYPE_FLOAT:
-                       RES_TYPES(_r)[i] = DB_FLOAT;
-                       break;
-
-               case FIELD_TYPE_DOUBLE:
-                       RES_TYPES(_r)[i] = DB_DOUBLE;
-                       break;
-
-               case FIELD_TYPE_DATETIME:
-                       RES_TYPES(_r)[i] = DB_DATETIME;
-                       break;
-
-               case FIELD_TYPE_BLOB:
-               case FIELD_TYPE_TINY_BLOB:
-               case FIELD_TYPE_MEDIUM_BLOB:
-               case FIELD_TYPE_LONG_BLOB:
-                       RES_TYPES(_r)[i] = DB_BLOB;
-                       break;
-
-               case FIELD_TYPE_SET:
-                       RES_TYPES(_r)[i] = DB_BITMAP;
-                       break;
-
-               default:
-                       RES_TYPES(_r)[i] = DB_STRING;
-                       break;
-               }               
-       }
-       return 0;
-}
-
-
-/*
- * Release memory used by rows
- */
-static inline int free_rows(db_res_t* _r)
-{
-       int i;
-
-       if (!_r) {
-               LOG(L_ERR, "free_rows: Invalid parameter value\n");
-               return -1;
-       }
-
-       for(i = 0; i < RES_ROW_N(_r); i++) {
-               free_row(&(RES_ROWS(_r)[i]));
-       }
-       if (RES_ROWS(_r)) pkg_free(RES_ROWS(_r));
-       return 0;
-}
-
-
-/*
- * Convert rows from mysql to db API representation
- */
-static inline int convert_rows(db_con_t* _h, db_res_t* _r)
-{
-       int n, i;
-
-       if ((!_h) || (!_r)) {
-               LOG(L_ERR, "convert_rows: Invalid parameter\n");
-               return -1;
-       }
-
-       n = mysql_num_rows(MYRES_RESULT(_r));
-       RES_ROW_N(_r) = n;
-       if (!n) {
-               RES_ROWS(_r) = 0;
-               return 0;
-       }
-       RES_ROWS(_r) = (struct db_row*)pkg_malloc(sizeof(db_row_t) * n);
-       if (!RES_ROWS(_r)) {
-               LOG(L_ERR, "convert_rows: No memory left\n");
-               return -2;
-       }
-
-       for(i = 0; i < n; i++) {
-               MYRES_ROW(_r) = mysql_fetch_row(MYRES_RESULT(_r));
-               if (!MYRES_ROW(_r)) {
-                       LOG(L_ERR, "convert_rows: %s\n", mysql_error(CON_CONNECTION(_h)));
-                       RES_ROW_N(_r) = i;
-                       free_rows(_r);
-                       return -3;
-               }
-               if (convert_row(_h, _r, &(RES_ROWS(_r)[i])) < 0) {
-                       LOG(L_ERR, "convert_rows: Error while converting row #%d\n", i);
-                       RES_ROW_N(_r) = i;
-                       free_rows(_r);
-                       return -4;
-               }
-       }
-       return 0;
-}
-
-
-/*
- * Release memory used by columns
- */
-static inline int free_columns(db_res_t* _r)
-{
-       if (!_r) {
-               LOG(L_ERR, "free_columns: Invalid parameter\n");
-               return -1;
-       }
-
-       if (RES_NAMES(_r)) pkg_free(RES_NAMES(_r));
-       if (RES_TYPES(_r)) pkg_free(RES_TYPES(_r));
-       return 0;
-}
-
-
-/*
- * Create a new result structure and initialize it
- */
-db_res_t* new_result(void)
-{
-       db_res_t* r;
-       r = (db_res_t*)pkg_malloc(sizeof(db_res_t));
-       if (!r) {
-               LOG(L_ERR, "new_result: No memory left\n");
-               return 0;
-       }
-       r->data = pkg_malloc(sizeof(struct my_res));
-       if(!r->data) {
-               pkg_free(r);
-               LOG(L_ERR, "store_result(): No memory left 2\n");
-               return 0;
-       }
-       MYRES_RESULT(r) = 0;
-       MYRES_ROW(r) = 0;
-       RES_NAMES(r) = 0;
-       RES_TYPES(r) = 0;
-       RES_COL_N(r) = 0;
-       RES_ROWS(r) = 0;
-       RES_ROW_N(r) = 0;
-       return r;
-}
-
-
-/*
- * Fill the structure with data from database
- */
-int convert_result(db_con_t* _h, db_res_t* _r)
-{
-       if ((!_h) || (!_r)) {
-               LOG(L_ERR, "convert_result: Invalid parameter\n");
-               return -1;
-       }
-
-       if (get_columns(_h, _r) < 0) {
-               LOG(L_ERR, "convert_result: Error while getting column names\n");
-               return -2;
-       }
-
-       if (convert_rows(_h, _r) < 0) {
-               LOG(L_ERR, "convert_result: Error while converting rows\n");
-               free_columns(_r);
-               return -3;
-       }
-       return 0;
-}
-
-
-/*
- * Release memory used by a result structure
- */
-int free_result(db_res_t* _r)
-{
-       if (!_r) {
-               LOG(L_ERR, "free_result: Invalid parameter\n");
-               return -1;
-       }
-
-       free_columns(_r);
-       free_rows(_r);
-       mysql_free_result(MYRES_RESULT(_r));
-       pkg_free(_r->data);
-       pkg_free(_r);
-       return 0;
-}
diff --git a/modules/db_mysql/res.h b/modules/db_mysql/res.h
deleted file mode 100644 (file)
index 57d70f2..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/* 
- * $Id$ 
- *
- * MySQL module result related functions
- *
- * Copyright (C) 2001-2003 FhG Fokus
- *
- * This file is part of ser, a free SIP server.
- *
- * ser is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version
- *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info@iptel.org
- *
- * ser is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License 
- * along with this program; if not, write to the Free Software 
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#ifndef RES_H
-#define RES_H
-
-#include "../../db/db_res.h"
-#include "../../db/db_con.h"
-
-struct my_res {
-       MYSQL_RES* res; /* The mysql result */
-       MYSQL_ROW  row; /* The current row */
-};
-
-#define MYRES_RESULT(db_res)   (((struct my_res*)(db_res)->data)->res)
-#define MYRES_ROW(db_res)      (((struct my_res*)(db_res)->data)->row)
-
-/*
- * Create a new result structure and initialize it
- */
-db_res_t* new_result(void);
-
-
-/*
- * Fill the structure with data from database
- */
-int convert_result(db_con_t* _h, db_res_t* _r);
-
-
-/*
- * Release memory used by a result structure
- */
-int free_result(db_res_t* _r);
-
-
-#endif /* RES_H */
diff --git a/modules/db_mysql/utils.c b/modules/db_mysql/utils.c
deleted file mode 100644 (file)
index 8d3413b..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-/* 
- * $Id$ 
- *
- * MySQL module utilities
- *
- * Copyright (C) 2001-2003 FhG Fokus
- *
- * This file is part of ser, a free SIP server.
- *
- * ser is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version
- *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info@iptel.org
- *
- * ser is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License 
- * along with this program; if not, write to the Free Software 
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * History:
- * -------
- * 2003-04-14 tm_isdst in struct tm set to -1 to let mktime 
- *            guess daylight saving (janakj)
- */
-
-
-#define _XOPEN_SOURCE 4     /* bsd */
-#define _XOPEN_SOURCE_EXTENDED 1    /* solaris */
-#define _SVID_SOURCE 1 /* timegm */
-
-#include <strings.h>
-#include <string.h>
-#include <time.h>  /*strptime, XOPEN issue must be >=4 */
-#include "../../ut.h"
-#include "utils.h"
-
-/*
- * Convert time_t structure to format accepted by MySQL database
- */
-int time2mysql(time_t _time, char* _result, int _res_len)
-{
-       struct tm* t;
-       
-            /*
-              if (_time == MAX_TIME_T) {
-              snprintf(_result, _res_len, "0000-00-00 00:00:00");
-              }
-            */
-
-       t = gmtime(&_time);
-       return strftime(_result, _res_len, "%Y-%m-%d %H:%M:%S", t);
-}
-
-
-/*
- * Convert MySQL time representation to time_t structure
- */
-time_t mysql2time(const char* _str)
-{
-       struct tm time;
-       
-            /* It is necessary to zero tm structure first */
-       memset(&time, '\0', sizeof(struct tm));
-       strptime(_str, "%Y-%m-%d %H:%M:%S", &time);
-
-            /* Daylight saving information got lost in the database
-             * so let timegm to guess it. This eliminates the bug when
-             * contacts reloaded from the database have different time
-             * of expiration by one hour when daylight saving is used
-             */ 
-       time.tm_isdst = -1;   
-#ifdef HAVE_TIMEGM
-       return timegm(&time);
-#else
-       return _timegm(&time);
-#endif /* HAVE_TIMEGM */
-}
diff --git a/modules/db_mysql/val.c b/modules/db_mysql/val.c
deleted file mode 100644 (file)
index 26f74e2..0000000
+++ /dev/null
@@ -1,393 +0,0 @@
-/* 
- * $Id$ 
- *
- * Copyright (C) 2001-2003 FhG Fokus
- *
- * This file is part of ser, a free SIP server.
- *
- * ser is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version
- *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- *    info@iptel.org
- *
- * ser is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License 
- * along with this program; if not, write to the Free Software 
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <limits.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "../../dprint.h"
-#include "utils.h"
-#include "val.h"
-
-
-/*
- * Convert a string to integer
- */
-static inline int str2int(const char* _s, int* _v)
-{
-
-       long tmp;
-
-       if (!_s || !_v) {
-              LOG(L_ERR, "str2int: Invalid parameter value\n");
-              return -1;
-       }
-
-       tmp = strtoul(_s, 0, 10);
-       if ((tmp == ULONG_MAX && errno == ERANGE) || 
-           (tmp < INT_MIN) || (tmp > UINT_MAX)) {
-               printf("str2int: Value out of range\n");
-               return -1;
-       }
-
-       *_v = (int)tmp;
-       return 0;
-}
-
-
-/*
- * Convert a string to double
- */
-static inline int str2double(const char* _s, double* _v)
-{
-       if ((!_s) || (!_v)) {
-               LOG(L_ERR, "str2double: Invalid parameter value\n");
-               return -1;
-       }
-
-       *_v = atof(_s);
-       return 0;
-}
-
-
-/*
- * Convert a string to double
- */
-static inline int str2float(const char* _s, float* _v)
-{
-       if ((!_s) || (!_v)) {
-               LOG(L_ERR, "str2float: Invalid parameter value\n");
-               return -1;
-       }
-
-       *_v = (float)atof(_s);
-       return 0;
-}
-
-
-/* 
- * Convert a string to time_t
- */
-static inline int str2time(const char* _s, time_t* _v)
-{
-       if ((!_s) || (!_v)) {
-               LOG(L_ERR, "str2time: Invalid parameter value\n");
-               return -1;
-       }
-
-       *_v = mysql2time(_s);
-       return 0;
-}
-
-
-/*
- * Convert an integer to string
- */
-static inline int int2str(int _v, char* _s, int* _l)
-{
-       int ret;
-
-       if ((!_s) || (!_l) || (!*_l)) {
-               LOG(L_ERR, "int2str: Invalid parameter value\n");
-               return -1;
-       }
-
-       ret = snprintf(_s, *_l, "%-d", _v);
-       if (ret < 0 || ret >= *_l) {
-               LOG(L_ERR, "int2str: Error in sprintf\n");
-               return -1;
-       }
-       *_l = ret;
-
-       return 0;
-}
-
-
-/*
- * Convert a double to string
- */
-static inline int double2str(double _v, char* _s, int* _l)
-{
-       int ret;
-
-       if ((!_s) || (!_l) || (!*_l)) {
-               LOG(L_ERR, "double2str: Invalid parameter value\n");
-               return -1;
-       }
-
-       ret = snprintf(_s, *_l, "%-10.2f", _v);
-       if (ret < 0 || ret >= *_l) {
-               LOG(L_ERR, "double2str: Error in snprintf\n");
-               return -1;
-       }
-       *_l = ret;
-
-       return 0;
-}
-
-
-/*
- * Convert time_t to string
- */
-static inline int time2str(time_t _v, char* _s, int* _l)
-{
-       int l;
-
-       if ((!_s) || (!_l) || (*_l < 2))  {
-               LOG(L_ERR, "time2str: Invalid parameter value\n");
-               return -1;
-       }
-
-       *_s++ = '\'';
-       l = time2mysql(_v, _s, *_l - 1);
-       *(_s + l) = '\'';
-       *_l = l + 2;
-       return 0;
-}
-
-/*
- * Does not copy strings
- */
-int str2val(db_type_t _t, db_val_t* _v, const char* _s, int _l)
-{
-       static str dummy_string = STR_STATIC_INIT("");
-       
-       if (!_v) {
-               LOG(L_ERR, "str2val: Invalid parameter value\n");
-               return -1;
-       }
-
-       if (!_s) {
-               memset(_v, 0, sizeof(db_val_t));
-                       /* Initialize the string pointers to a dummy empty
-                        * string so that we do not crash when the NULL flag
-                        * is set but the module does not check it properly
-                        */
-               VAL_STRING(_v) = dummy_string.s;
-               VAL_STR(_v) = dummy_string;
-               VAL_BLOB(_v) = dummy_string;
-               VAL_TYPE(_v) = _t;
-               VAL_NULL(_v) = 1;
-               return 0;
-       }
-       VAL_NULL(_v) = 0;
-
-       switch(_t) {
-       case DB_INT:
-               if (str2int(_s, &VAL_INT(_v)) < 0) {
-                       LOG(L_ERR, "str2val: Error while converting integer value from string\n");
-                       return -2;
-               } else {
-                       VAL_TYPE(_v) = DB_INT;
-                       return 0;
-               }
-               break;
-
-       case DB_BITMAP:
-               if (str2int(_s, &VAL_INT(_v)) < 0) {
-                       LOG(L_ERR, "str2val: Error while converting bitmap value from string\n");
-                       return -3;
-               } else {
-                       VAL_TYPE(_v) = DB_BITMAP;
-                       return 0;
-               }
-               break;
-       
-       case DB_DOUBLE:
-               if (str2double(_s, &VAL_DOUBLE(_v)) < 0) {
-                       LOG(L_ERR, "str2val: Error while converting double value from string\n");
-                       return -4;
-               } else {
-                       VAL_TYPE(_v) = DB_DOUBLE;
-                       return 0;
-               }
-               break;
-
-       case DB_FLOAT:
-               if (str2float(_s, &VAL_FLOAT(_v)) < 0) {
-                       LOG(L_ERR, "str2val: Error while converting float value from string\n");
-                       return -4;
-               } else {
-                       VAL_TYPE(_v) = DB_FLOAT;
-                       return 0;
-               }
-               break;
-
-       case DB_STRING:
-               VAL_STRING(_v) = _s;
-               VAL_TYPE(_v) = DB_STRING;
-               return 0;
-
-       case DB_STR:
-               VAL_STR(_v).s = (char*)_s;
-               VAL_STR(_v).len = _l;
-               VAL_TYPE(_v) = DB_STR;
-               return 0;
-
-       case DB_DATETIME:
-               if (str2time(_s, &VAL_TIME(_v)) < 0) {
-                       LOG(L_ERR, "str2val: Error while converting datetime value from string\n");
-                       return -5;
-               } else {
-                       VAL_TYPE(_v) = DB_DATETIME;
-                       return 0;
-               }
-               break;
-
-       case DB_BLOB:
-               VAL_BLOB(_v).s = (char*)_s;
-               VAL_BLOB(_v).len = _l;
-               VAL_TYPE(_v) = DB_BLOB;
-               return 0;
-       }
-       return -6;
-}
-
-
-/*
- * Used when converting result from a query
- */
-int val2str(MYSQL* _c, db_val_t* _v, char* _s, int* _len)
-{
-       int l;
-       char* old_s;
-
-       if (!_c || !_v || !_s || !_len || !*_len) {
-               LOG(L_ERR, "val2str: Invalid parameter value\n");
-               return -1;
-       }
-
-       if (VAL_NULL(_v)) {
-               if (*_len < sizeof("NULL")) {
-                       LOG(L_ERR, "val2str: Buffer too small\n");
-                       return -1;
-               }
-               *_len = snprintf(_s, *_len, "NULL");
-               return 0;
-       }
-       
-       switch(VAL_TYPE(_v)) {
-       case DB_INT:
-               if (int2str(VAL_INT(_v), _s, _len) < 0) {
-                       LOG(L_ERR, "val2str: Error while converting string to int\n");
-                       return -2;
-               } else {
-                       return 0;
-               }
-               break;
-
-       case DB_BITMAP:
-               if (int2str(VAL_BITMAP(_v), _s, _len) < 0) {
-                       LOG(L_ERR, "val2str: Error while converting string to int\n");
-                       return -3;
-               } else {
-                       return 0;
-               }
-               break;
-
-       case DB_DOUBLE:
-               if (double2str(VAL_DOUBLE(_v), _s, _len) < 0) {
-                       LOG(L_ERR, "val2str: Error while converting string to double\n");
-                       return -4;
-               } else {
-                       return 0;
-               }
-               break;
-
-       case DB_FLOAT:
-               if (double2str(VAL_FLOAT(_v), _s, _len) < 0) {
-                       LOG(L_ERR, "val2str: Error while converting string to double\n");
-                       return -4;
-               } else {
-                       return 0;
-               }
-               break;
-
-       case DB_STRING:
-               l = strlen(VAL_STRING(_v));
-               if (*_len < (l * 2 + 3)) {
-                       LOG(L_ERR, "val2str: Destination buffer too short\n");
-                       return -5;
-               } else {
-                       old_s = _s;
-                       *_s++ = '\'';
-                       _s += mysql_real_escape_string(_c, _s, VAL_STRING(_v), l);
-                       *_s++ = '\'';
-                       *_s = '\0'; /* FIXME */
-                       *_len = _s - old_s;
-                       return 0;
-               }
-               break;
-
-       case DB_STR:
-               l = VAL_STR(_v).len;
-               if (*_len < (l * 2 + 3)) {
-                       LOG(L_ERR, "val2str: Destination buffer too short\n");
-                       return -6;
-               } else {
-                       old_s = _s;
-                       *_s++ = '\'';
-                       _s += mysql_real_escape_string(_c, _s, VAL_STR(_v).s, l);
-                       *_s++ = '\'';
-                       *_s = '\0';
-                       *_len = _s - old_s;
-                       return 0;
-               }
-               break;
-
-       case DB_DATETIME:
-               if (time2str(VAL_TIME(_v), _s, _len) < 0) {
-                       LOG(L_ERR, "val2str: Error while converting string to time_t\n");
-                       return -7;
-               } else {
-                       return 0;
-               }
-               break;
-
-       case DB_BLOB:
-               l = VAL_BLOB(_v).len;
-               if (*_len < (l * 2 + 3)) {
-                       LOG(L_ERR, "val2str: Destination buffer too short\n");
-                       return -8;
-               } else {
-                       old_s = _s;
-                       *_s++ = '\'';
-                       _s += mysql_escape_string(_s, VAL_STR(_v).s, l);
-                       *_s++ = '\'';
-                       *_s = '\0';
-                       *_len = _s - old_s;
-                       return 0;
-               }                       
-               break;
-
-       default:
-               DBG("val2str: Unknown data type\n");
-               return -9;
-       }
-       /*return -8; --not reached*/
-}