123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575 |
- /*
- * $Id$
- *
- * BDB Database Driver for SIP-router
- *
- * Copyright (C) 2008 iptelorg GmbH
- *
- * This file is part of SIP-router, a free SIP server.
- *
- * SIP-router 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.
- *
- * SIP-router 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.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
- /*! \addtogroup bdb
- * @{
- */
- /*! \file
- * Berkeley DB : Implementation of functions related to database commands.
- *
- * \ingroup database
- */
- #include <string.h>
- #include "../../mem/mem.h"
- #include "../../dprint.h"
- #include "../../ut.h"
- #include "bdb_cmd.h"
- #include "bdb_fld.h"
- #include "bdb_con.h"
- #include "bdb_uri.h"
- #include "bdb_res.h"
- #include "bdb_lib.h"
- #include "bdb_crs_compat.h"
- #define BDB_BUF_SIZE 1024
- /** Destroys a bdb_cmd structure.
- * This function frees all memory used by ld_cmd structure.
- * @param cmd A pointer to generic db_cmd command being freed.
- * @param payload A pointer to ld_cmd structure to be freed.
- */
- static void bdb_cmd_free(db_cmd_t* cmd, bdb_cmd_t* payload)
- {
- db_drv_free(&payload->gen);
- if (payload->dbcp)
- payload->dbcp->CLOSE_CURSOR(payload->dbcp);
- if(payload->skey.s)
- pkg_free(payload->skey.s);
- pkg_free(payload);
- }
- int bdb_prepare_query(db_cmd_t* cmd, bdb_cmd_t *bcmd)
- {
- bdb_tcache_t *tbc = NULL;
- bdb_table_t *tp = NULL;
- bdb_fld_t *f;
- db_fld_t *fld;
- int mode;
- int i;
- if(bcmd->bcon==NULL || bcmd->bcon->dbp==NULL)
- return -1;
-
- tbc = bdblib_get_table(bcmd->bcon->dbp, &cmd->table);
- if(tbc==NULL)
- {
- ERR("bdb: table does not exist!\n");
- return -1;
- }
- tp = tbc->dtp;
- if(tp==NULL || tp->db==NULL)
- {
- ERR("bdb: table not loaded!\n");
- return -1;
- }
- mode = 0;
- if (!DB_FLD_EMPTY(cmd->result))
- { /* columns to be returned provided */
- if (cmd->result_count > tp->ncols)
- {
- ERR("bdb: too many columns in query\n");
- goto error;
- }
- } else {
- mode = 1;
- cmd->result = db_fld(tp->ncols + 1);
- cmd->result_count = tp->ncols;
- for(i = 0; i < cmd->result_count; i++) {
- if (bdb_fld(cmd->result + i, cmd->table.s) < 0)
- goto error;
- }
- }
-
- for (i = 0; i < cmd->result_count; i++) {
- fld = cmd->result + i;
- f = DB_GET_PAYLOAD(fld);
- if(mode==1)
- {
- DBG("bdb: column name [%.*s]\n", tp->colp[i]->name.len,
- tp->colp[i]->name.s);
-
- f->name = pkg_malloc(tp->colp[i]->name.len+1);
- if (f->name == NULL) {
- ERR("bdb: Out of private memory\n");
- goto error;
- }
- strncpy(f->name, tp->colp[i]->name.s, tp->colp[i]->name.len);
- f->name[tp->colp[i]->name.len] = '\0';
- fld->name = f->name;
- fld->type = tp->colp[i]->type;
- f->col_pos = i;
- } else {
- f->col_pos = bdb_get_colpos(tp, fld->name);
- if(f->col_pos == -1)
- {
- ERR("bdb: Column not found\n");
- goto error;
- }
- }
- switch(fld->type) {
- case DB_INT:
- case DB_BITMAP:
- case DB_FLOAT:
- case DB_DOUBLE:
- case DB_DATETIME:
- case DB_STR:
- if (!f->buf.s) f->buf.s = pkg_malloc(BDB_BUF_SIZE);
- if (f->buf.s == NULL) {
- ERR("bdb: No memory left\n");
- goto error;
- }
- fld[i].v.lstr.s = f->buf.s;
- break;
- case DB_CSTR:
- if (!f->buf.s) f->buf.s = pkg_malloc(BDB_BUF_SIZE);
- if (f->buf.s == NULL) {
- ERR("bdb: No memory left\n");
- goto error;
- }
- fld[i].v.cstr = f->buf.s;
- break;
- case DB_BLOB:
- if (!f->buf.s) f->buf.s = pkg_malloc(BDB_BUF_SIZE);
- if (f->buf.s == NULL) {
- ERR("mysql: No memory left\n");
- goto error;
- }
- fld[i].v.blob.s = f->buf.s;
- break;
- case DB_NONE:
- /* Eliminates gcc warning */
- break;
- }
- }
-
- if (!DB_FLD_EMPTY(cmd->match))
- {
- if (cmd->match_count > tp->ncols)
- {
- ERR("bdb: too many columns in match struct of query\n");
- goto error;
- }
- for (i = 0; i < cmd->match_count; i++) {
- fld = cmd->result + i;
- f = DB_GET_PAYLOAD(fld);
- f->col_pos = bdb_get_colpos(tp, fld->name);
- if(f->col_pos == -1)
- {
- ERR("bdb: Match column not found\n");
- goto error;
- }
- }
- }
- return 0;
- error:
- return -1;
- }
- int bdb_query(db_cmd_t* cmd, bdb_cmd_t *bcmd)
- {
- DBT key;
- DB *db;
- static char kbuf[MAX_ROW_SIZE];
- int klen;
- bdb_tcache_t *tbc = NULL;
- bdb_table_t *tp = NULL;
- if(bcmd->bcon==NULL || bcmd->bcon->dbp==NULL)
- return -1;
-
- tbc = bdblib_get_table(bcmd->bcon->dbp, &cmd->table);
- if(tbc==NULL)
- {
- ERR("bdb: table does not exist!\n");
- return -1;
- }
- tp = tbc->dtp;
- if(tp==NULL)
- {
- ERR("bdb: table not loaded!\n");
- return -1;
- }
- db = tp->db;
- if(db==NULL)
- {
- ERR("bdb: db structure not intialized!\n");
- return -1;
- }
- if (DB_FLD_EMPTY(cmd->match))
- { /* no match constraint */
- if (db->cursor(db, NULL, &bcmd->dbcp, 0) != 0)
- {
- ERR("bdb: error creating cursor\n");
- goto error;
- }
- bcmd->skey.len = 0;
- return 0;
- }
- memset(&key, 0, sizeof(DBT));
- memset(kbuf, 0, MAX_ROW_SIZE);
-
- klen=MAX_ROW_SIZE;
- if(bdblib_valtochar(tp, cmd->match, cmd->match_count,
- kbuf, &klen, BDB_KEY)!=0)
- {
- ERR("bdb: error creating key\n");
- goto error;
- }
-
- if(klen > bcmd->skey_size || bcmd->skey.s==NULL)
- {
- if(bcmd->skey.s!=NULL)
- pkg_free(bcmd->skey.s);
- bcmd->skey.s = (char*)pkg_malloc(klen*sizeof(char));
- if(bcmd->skey.s == NULL)
- {
- ERR("bdb: no pkg memory\n");
- goto error;
- }
- bcmd->skey_size = klen;
- }
- memcpy(bcmd->skey.s, kbuf, klen);
- bcmd->skey.len = klen;
- return 0;
- error:
- return -1;
- }
- int bdb_cmd(db_cmd_t* cmd)
- {
- bdb_cmd_t *bcmd;
- db_con_t *con;
- bdb_con_t *bcon;
- bcmd = (bdb_cmd_t*)pkg_malloc(sizeof(bdb_cmd_t));
- if (bcmd == NULL) {
- ERR("bdb: No memory left\n");
- goto error;
- }
- memset(bcmd, '\0', sizeof(bdb_cmd_t));
- if (db_drv_init(&bcmd->gen, bdb_cmd_free) < 0) goto error;
- con = cmd->ctx->con[db_payload_idx];
- bcon = DB_GET_PAYLOAD(con);
- bcmd->bcon = bcon;
- switch(cmd->type) {
- case DB_PUT:
- case DB_DEL:
- case DB_UPD:
- ERR("bdb: The driver does not support DB modifications yet.\n");
- goto error;
- break;
- case DB_GET:
- if(bdb_prepare_query(cmd, bcmd)!=0)
- {
- ERR("bdb: error preparing query.\n");
- goto error;
- }
- break;
- case DB_SQL:
- ERR("bdb: The driver does not support raw queries yet.\n");
- goto error;
- }
- DB_SET_PAYLOAD(cmd, bcmd);
- return 0;
- error:
- if (bcmd) {
- DB_SET_PAYLOAD(cmd, NULL);
- db_drv_free(&bcmd->gen);
- pkg_free(bcmd);
- }
- return -1;
- }
- int bdb_cmd_exec(db_res_t* res, db_cmd_t* cmd)
- {
- db_con_t* con;
- bdb_cmd_t *bcmd;
- bdb_con_t *bcon;
- /* First things first: retrieve connection info from the currently active
- * connection and also mysql payload from the database command
- */
- con = cmd->ctx->con[db_payload_idx];
- bcmd = DB_GET_PAYLOAD(cmd);
- bcon = DB_GET_PAYLOAD(con);
- if ((bcon->flags & BDB_CONNECTED)==0) {
- ERR("bdb: not connected\n");
- return -1;
- }
- bcmd->next_flag = -1;
- switch(cmd->type) {
- case DB_DEL:
- case DB_PUT:
- case DB_UPD:
- /* no result expected - cleanup */
- DBG("bdb: query with no result.\n");
- break;
- case DB_GET:
- return bdb_query(cmd, bcmd);
- break;
- default:
- /* result expected - no cleanup */
- DBG("bdb: query with result.\n");
- }
- return 0;
- }
- int bdb_update_result(db_cmd_t *cmd, DBT *data)
- {
- bdb_fld_t *f;
- db_fld_t *fld;
- int i;
- int col;
- char *s;
- static str col_map[MAX_NUM_COLS];
- memset(col_map, 0, MAX_NUM_COLS*sizeof(str));
- col = 0;
- s = (char*)data->data;
- col_map[col].s = s;
- while(*s!='\0')
- {
- if(*s == *DELIM)
- {
- col_map[col].len = s - col_map[col].s;
- col++;
- col_map[col].s = s+1;
- }
- s++;
- }
- col_map[col].len = s - col_map[col].s;
- for (i = 0; i < cmd->result_count; i++) {
- fld = cmd->result + i;
- f = DB_GET_PAYLOAD(fld);
- if(col_map[f->col_pos].len == 0)
- {
- fld->flags |= DB_NULL;
- continue;
- }
- fld->flags &= ~DB_NULL;
- switch(fld->type) {
- case DB_STR:
- fld->v.lstr.s = f->buf.s;
- if(col_map[f->col_pos].len < BDB_BUF_SIZE)
- {
- fld->v.lstr.len = col_map[f->col_pos].len;
- } else {
- /* truncate ?!? */
- fld->v.lstr.len = BDB_BUF_SIZE - 1;
- }
- memcpy(fld->v.lstr.s, col_map[f->col_pos].s, fld->v.lstr.len);
- break;
- case DB_BLOB:
- fld->v.blob.s = f->buf.s;
- if(col_map[f->col_pos].len < BDB_BUF_SIZE)
- {
- fld->v.blob.len = col_map[f->col_pos].len;
- } else {
- /* truncate ?!? */
- fld->v.blob.len = BDB_BUF_SIZE - 1;
- }
- memcpy(fld->v.blob.s, col_map[f->col_pos].s, fld->v.blob.len);
- break;
- case DB_CSTR:
- fld->v.cstr = f->buf.s;
- if(col_map[f->col_pos].len < BDB_BUF_SIZE)
- {
- memcpy(fld->v.cstr, col_map[f->col_pos].s,
- col_map[f->col_pos].len);
- fld->v.cstr[col_map[f->col_pos].len] = '\0';
- } else {
- /* truncate ?!? */
- memcpy(fld->v.cstr, col_map[f->col_pos].s,
- BDB_BUF_SIZE - 1);
- fld->v.cstr[BDB_BUF_SIZE - 1] = '\0';;
- }
- break;
-
- case DB_DATETIME:
- /* str to time */
- col_map[f->col_pos].s[col_map[f->col_pos].len]='\0';
- if (bdb_str2time(col_map[f->col_pos].s, &fld->v.time) < 0)
- {
- ERR("Error while converting INT value from string\n");
- return -1;
- }
- break;
- case DB_INT:
- /* str to int */
- col_map[f->col_pos].s[col_map[f->col_pos].len]='\0';
- if (bdb_str2int(col_map[f->col_pos].s, &fld->v.int4) < 0)
- {
- ERR("Error while converting INT value from string\n");
- return -1;
- }
- break;
- case DB_FLOAT:
- case DB_DOUBLE:
- /* str to dowuble */
- col_map[f->col_pos].s[col_map[f->col_pos].len]='\0';
- if (bdb_str2double(col_map[f->col_pos].s, &fld->v.dbl) < 0)
- {
- ERR("Error while converting DOUBLE value from string\n");
- return -1;
- }
- break;
- case DB_BITMAP:
- /* str to int */
- col_map[f->col_pos].s[col_map[f->col_pos].len]='\0';
- if (bdb_str2int(col_map[f->col_pos].s, &fld->v.int4) < 0)
- {
- ERR("Error while converting BITMAP value from string\n");
- return -1;
- }
- break;
- case DB_NONE:
- break;
- }
- }
- return 0;
- }
- int bdb_cmd_first(db_res_t* res)
- {
- bdb_cmd_t *bcmd;
- bcmd = DB_GET_PAYLOAD(res->cmd);
- switch (bcmd->next_flag) {
- case -2: /* table is empty */
- return 1;
- case 0: /* cursor position is 0 */
- return 0;
- case 1: /* next row */
- case 2: /* EOF */
- ERR("bdb: no next row.\n");
- return -1;
- default:
- return bdb_cmd_next(res);
- }
- }
- int bdb_cmd_next(db_res_t* res)
- {
- db_con_t *con;
- bdb_res_t *bres;
- bdb_con_t *bcon;
- bdb_cmd_t *bcmd;
- DBT key, data;
- int ret;
- static char dbuf[MAX_ROW_SIZE];
- con = res->cmd->ctx->con[db_payload_idx];
- bres = DB_GET_PAYLOAD(res);
- bcon = DB_GET_PAYLOAD(con);
- bcmd = DB_GET_PAYLOAD(res->cmd);
- if (bcmd->next_flag == 2 || bcmd->next_flag == -2) return 1;
- memset(&key, 0, sizeof(DBT));
- memset(&data, 0, sizeof(DBT));
- memset(dbuf, 0, MAX_ROW_SIZE);
-
- data.data = dbuf;
- data.ulen = MAX_ROW_SIZE;
- data.flags = DB_DBT_USERMEM;
- ret = 0;
- if(bcmd->skey.len==0)
- {
- while((ret = bcmd->dbcp->c_get(bcmd->dbcp, &key, &data, DB_NEXT))==0)
- {
- if(!strncasecmp((char*)key.data,"METADATA",8))
- continue;
- break;
- }
- if(ret!=0)
- {
- bcmd->next_flag = bcmd->next_flag<0?-2:2;
- return 1;
- }
- } else {
- key.data = bcmd->skey.s;
- key.ulen = bcmd->skey_size;
- key.flags = DB_DBT_USERMEM;
- key.size = bcmd->skey.len;
- ret = bcmd->dbcp->c_get(bcmd->dbcp, &key, &data, DB_NEXT);
- if(ret!=0)
- {
- bcmd->next_flag = bcmd->next_flag<0?-2:2;
- return 1;
- }
- }
- if (bcmd->next_flag <= 0) {
- bcmd->next_flag++;
- }
- if (bdb_update_result(res->cmd, &data) < 0) {
- return -1;
- }
- res->cur_rec->fld = res->cmd->result;
- return 0;
- }
- /** @} */
|