bdb_res.c

Go to the documentation of this file.
00001 /*
00002  * $Id: bdb_res.c 5362 2008-12-15 16:33:22Z henningw $
00003  *
00004  * db_berkeley module, portions of this code were templated using
00005  * the dbtext and postgres modules.
00006 
00007  * Copyright (C) 2007 Cisco Systems
00008  *
00009  * This file is part of Kamailio, a free SIP server.
00010  *
00011  * Kamailio is free software; you can redistribute it and/or modify
00012  * it under the terms of the GNU General Public License as published by
00013  * the Free Software Foundation; either version 2 of the License, or
00014  * (at your option) any later version
00015  *
00016  * Kamailio is distributed in the hope that it will be useful,
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  * GNU General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU General Public License 
00022  * along with this program; if not, write to the Free Software 
00023  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00024  * 
00025  * History:
00026  * --------
00027  * 2007-09-19  genesis (wiquan)
00028  */
00029 
00030 #include <stdio.h>
00031 #include <string.h>
00032 #include <sys/types.h>
00033 #include "../../mem/mem.h"
00034 #include "bdb_res.h"
00035 
00036 
00037 int bdb_get_columns(table_p _tp, db_res_t* _res, int* _lres, int _nc)
00038 {
00039    int col;
00040 
00041    if (!_res) {
00042       LM_ERR("invalid parameter\n");
00043       return -1;
00044    }
00045 
00046    if (_nc < 0 ) {
00047       LM_ERR("_nc parameter cannot be negative \n");
00048       return -1;
00049    }
00050     /* the number of rows (tuples) in the query result. */
00051    RES_NUM_ROWS(_res) = 1;
00052 
00053    if (!_lres)
00054       _nc = _tp->ncols;
00055 
00056    /* Save number of columns in the result structure */
00057    RES_COL_N(_res) = _nc;
00058 
00059    if (db_allocate_columns(_res, RES_COL_N(_res)) != 0) {
00060       LM_ERR("could not allocate columns");
00061       return -2;
00062    }
00063 
00064    /*
00065     * For each column both the name and the data type are saved.
00066     */
00067    for(col = 0; col < RES_COL_N(_res); col++) {
00068       column_p cp = NULL;
00069       cp = (_lres) ? _tp->colp[_lres[col]] : _tp->colp[col];
00070 
00071       RES_NAMES(_res)[col] = (str*)pkg_malloc(sizeof(str));
00072       if (! RES_NAMES(_res)[col]) {
00073          LM_ERR("no private memory left\n");
00074          db_free_columns(_res);
00075          return -3;
00076       }
00077       LM_DBG("allocate %lu bytes for RES_NAMES[%d] at %p\n",
00078          (unsigned long)sizeof(str), col, RES_NAMES(_res)[col]);
00079 
00080       /* The pointer that is here returned is part of the result structure. */
00081       RES_NAMES(_res)[col]->s = cp->name.s;
00082       RES_NAMES(_res)[col]->len = cp->name.len;
00083 
00084       LM_DBG("RES_NAMES(%p)[%d]=[%.*s]\n", RES_NAMES(_res)[col]
00085          , col, RES_NAMES(_res)[col]->len, RES_NAMES(_res)[col]->s);
00086 
00087       RES_TYPES(_res)[col] = cp->type;
00088    }
00089    return 0;
00090 }
00091 
00092 
00093 
00094 /**
00095  * Convert rows from Berkeley DB to db API representation
00096  */
00097 int bdb_convert_row(db_res_t* _res, char *bdb_result, int* _lres)
00098 {
00099    int col, len, i, j;
00100    char **row_buf, *s;
00101    db_row_t* row = NULL;
00102    col = len = i = j = 0;
00103    
00104    if (!_res) {
00105       LM_ERR("invalid parameter\n");
00106       return -1;
00107    }
00108 
00109    /* Allocate a single row structure */
00110    len = sizeof(db_row_t);
00111    row = (db_row_t*)pkg_malloc(len);
00112    if (!row) {
00113       LM_ERR("no private memory left\n");
00114       return -1;
00115    }
00116    LM_DBG("allocate %d bytes for row %p\n", len, row);
00117    memset(row, 0, len);
00118    RES_ROWS(_res) = row;
00119    
00120    /* Save the number of rows in the current fetch */
00121    RES_ROW_N(_res) = 1;
00122 
00123    if (db_allocate_row(_res, row) != 0) {
00124       LM_ERR("could not allocate row");
00125       return -2;
00126    }
00127    /*
00128     * Allocate an array of pointers one per column.
00129     * It that will be used to hold the address of the string representation of each column.
00130     */
00131    len = sizeof(char *) * RES_COL_N(_res);
00132    row_buf = (char **)pkg_malloc(len);
00133    if (!row_buf) {
00134       LM_ERR("no private memory left\n");
00135       return -1;
00136    }
00137    LM_DBG("allocate for %d columns %d bytes in row buffer at %p\n", RES_COL_N(_res), len, row_buf);
00138    memset(row_buf, 0, len);
00139 
00140    /*populate the row_buf with bdb_result*/
00141    /*bdb_result is memory from our callers stack so we copy here*/
00142    s = strtok(bdb_result, DELIM);
00143    while( s!=NULL)
00144    {
00145       if(_lres) {
00146          /*only requested cols (_c was specified)*/
00147          for(i=0; i<ROW_N(row); i++)
00148          {  if (col == _lres[i]) {
00149                len = strlen(s);
00150                row_buf[i] = pkg_malloc(len+1);
00151                if (!row_buf[i]) {
00152                   LM_ERR("no private memory left\n");
00153                   return -1;
00154                }
00155                LM_DBG("allocated %d bytes for row_buf[%d] at %p\n", len, i, row_buf[i]);
00156                memset(row_buf[i], 0, len+1);
00157                strncpy(row_buf[i], s, len);
00158             }
00159             
00160          }
00161       }
00162       else {
00163          len = strlen(s);
00164          row_buf[col] = pkg_malloc(len+1);
00165          if (!row_buf[col]) {
00166             LM_ERR("no private memory left\n");
00167             return -1;
00168          }
00169             LM_DBG("allocated %d bytes for row_buf[%d] at %p\n", len, col, row_buf[col]);
00170          memset(row_buf[col], 0, len+1);
00171          strncpy(row_buf[col], s, len);
00172       }
00173       s = strtok(NULL, DELIM);
00174       col++;
00175    }
00176 
00177    /*do the type conversion per col*/
00178         for(col = 0; col < ROW_N(row); col++) {
00179       /*skip the unrequested cols (as already specified)*/
00180       if(!row_buf[col])  continue;
00181 
00182       /* Convert the string representation into the value representation */
00183       if (bdb_str2val(RES_TYPES(_res)[col], &(ROW_VALUES(row)[col])
00184             , row_buf[col], strlen(row_buf[col])) < 0) {
00185          LM_ERR("while converting value\n");
00186          LM_DBG("freeing row at %p\n", row);
00187          db_free_row(row);
00188          return -3;
00189       }
00190    }
00191 
00192    /* pkg_free() must be done for the above allocations now that the row has been converted.
00193     * During bdb_convert_row (and subsequent bdb_str2val) processing, data types that don't need to be
00194     * converted (namely STRINGS) have their addresses saved.  These data types should not have
00195     * their pkg_malloc() allocations freed here because they are still needed.  However, some data types
00196     * (ex: INT, DOUBLE) should have their pkg_malloc() allocations freed because during the conversion
00197     * process, their converted values are saved in the union portion of the db_val_t structure.
00198     *
00199     * Warning: when the converted row is no longer needed, the data types whose addresses
00200     * were saved in the db_val_t structure must be freed or a memory leak will happen.
00201     * This processing should happen in the db_free_row() subroutine.  The caller of
00202     * this routine should ensure that db_free_rows(), db_free_row() or db_free_result()
00203     * is eventually called.
00204     */
00205    for (col = 0; col < RES_COL_N(_res); col++) {
00206       switch (RES_TYPES(_res)[col]) 
00207       {
00208          case DB_STRING:
00209          case DB_STR:
00210             break;
00211          default:
00212          LM_DBG("col[%d] Col[%.*s] Type[%d] Freeing row_buf[%p]\n", col
00213             , RES_NAMES(_res)[col]->len, RES_NAMES(_res)[col]->s,
00214               RES_TYPES(_res)[col], row_buf[col]);
00215          LM_DBG("freeing row_buf[%d] at %p\n", col, row_buf[col]);
00216          pkg_free(row_buf[col]);
00217       }
00218       /* The following housekeeping may not be technically required, but it is a good practice
00219        * to NULL pointer fields that are no longer valid.  Note that DB_STRING fields have not
00220        * been pkg_free(). NULLing DB_STRING fields would normally not be good to do because a memory
00221        * leak would occur.  However, the pg_convert_row() routine has saved the DB_STRING pointer
00222        * in the db_val_t structure.  The db_val_t structure will eventually be used to pkg_free()
00223        * the DB_STRING storage.
00224        */
00225       row_buf[col] = (char *)NULL;
00226    }
00227    LM_DBG("freeing row buffer at %p\n", row_buf);
00228    pkg_free(row_buf);
00229    row_buf = NULL;
00230 
00231    return 0;
00232 
00233 }
00234 
00235 /*rx is row index*/
00236 int bdb_append_row(db_res_t* _res, char *bdb_result, int* _lres, int _rx)
00237 {
00238    int col, len, i, j;
00239    char **row_buf, *s;
00240    db_row_t* row = NULL;
00241    col = len = i = j = 0;
00242    
00243    if (!_res) {
00244       LM_ERR("invalid parameter");
00245       return -1;
00246    }
00247    
00248    row = &(RES_ROWS(_res)[_rx]);
00249    
00250    if (db_allocate_row(_res, row) != 0) {
00251       LM_ERR("could not allocate row");
00252       return -2;
00253    }
00254    
00255    /*
00256     * Allocate an array of pointers one per column.
00257     * It that will be used to hold the address of the string representation of each column.
00258     */
00259    len = sizeof(char *) * RES_COL_N(_res);
00260    row_buf = (char **)pkg_malloc(len);
00261    if (!row_buf) {
00262       LM_ERR("no private memory left\n");
00263       return -1;
00264    }
00265    LM_DBG("allocate for %d columns %d bytes in row buffer at %p\n", RES_COL_N(_res), len, row_buf);
00266    memset(row_buf, 0, len);
00267    
00268    /*populate the row_buf with bdb_result*/
00269    /*bdb_result is memory from our callers stack so we copy here*/
00270    s = strtok(bdb_result, DELIM);
00271    while( s!=NULL)
00272    {  
00273       if(_lres) {
00274          /*only requested cols (_c was specified)*/
00275          for(i=0; i<ROW_N(row); i++) {
00276             if (col == _lres[i]) {
00277                len = strlen(s);
00278                row_buf[i] = pkg_malloc(len+1);
00279                if (!row_buf[i]) {
00280                   LM_ERR("no private memory left\n");
00281                   return -1;
00282                }
00283                memset(row_buf[i], 0, len+1);
00284                strncpy(row_buf[i], s, len);
00285             }
00286          }
00287       }
00288       else {
00289          len = strlen(s);
00290 
00291 #ifdef BDB_EXTRA_DEBUG
00292       LM_DBG("col[%i] = [%.*s]\n", col , len, s );
00293 #endif
00294 
00295          row_buf[col] = (char*)pkg_malloc(len+1);
00296          if (!row_buf[col]) {
00297             LM_ERR("no private memory left\n");
00298             return -1;
00299          }
00300          memset(row_buf[col], 0, len+1);
00301          strncpy(row_buf[col], s, len);
00302       }
00303       s = strtok(NULL, DELIM);
00304       col++;
00305    }
00306    
00307    /*do the type conversion per col*/
00308    for(col = 0; col < ROW_N(row); col++) {
00309 #ifdef BDB_EXTRA_DEBUG
00310       LM_DBG("tc 1: col[%i] == ", col );
00311 #endif
00312 
00313       /*skip the unrequested cols (as already specified)*/
00314       if(!row_buf[col])  continue;
00315 
00316 #ifdef BDB_EXTRA_DEBUG
00317       LM_DBG("tc 2: col[%i] \n", col );
00318 #endif
00319 
00320       /* Convert the string representation into the value representation */
00321       if (bdb_str2val(RES_TYPES(_res)[col], &(ROW_VALUES(row)[col])
00322             , row_buf[col], strlen(row_buf[col])) < 0) {
00323          LM_ERR("while converting value\n");
00324          LM_DBG("freeing row at %p\n", row);
00325          db_free_row(row);
00326          return -3;
00327       }
00328    }
00329 
00330    /* pkg_free() must be done for the above allocations now that the row has been converted.
00331     * During bdb_convert_row (and subsequent bdb_str2val) processing, data types that don't need to be
00332     * converted (namely STRINGS) have their addresses saved.  These data types should not have
00333     * their pkg_malloc() allocations freed here because they are still needed.  However, some data types
00334     * (ex: INT, DOUBLE) should have their pkg_malloc() allocations freed because during the conversion
00335     * process, their converted values are saved in the union portion of the db_val_t structure.
00336     *
00337     * Warning: when the converted row is no longer needed, the data types whose addresses
00338     * were saved in the db_val_t structure must be freed or a memory leak will happen.
00339     * This processing should happen in the db_free_row() subroutine.  The caller of
00340     * this routine should ensure that db_free_rows(), db_free_row() or db_free_result()
00341     * is eventually called.
00342     */
00343    for (col = 0; col < RES_COL_N(_res); col++) {
00344       if (RES_TYPES(_res)[col] != DB_STRING) {
00345          LM_DBG("col[%d] Col[%.*s] Type[%d] Freeing row_buf[%p]\n", col
00346             , RES_NAMES(_res)[col]->len, RES_NAMES(_res)[col]->s,
00347               RES_TYPES(_res)[col], row_buf[col]);
00348          LM_DBG("freeing row_buf[%d] at %p\n", col, row_buf[col]);
00349          pkg_free(row_buf[col]);
00350       }
00351       /* The following housekeeping may not be technically required, but it is a good practice
00352        * to NULL pointer fields that are no longer valid.  Note that DB_STRING fields have not
00353        * been pkg_free(). NULLing DB_STRING fields would normally not be good to do because a memory
00354        * leak would occur.  However, the pg_convert_row() routine has saved the DB_STRING pointer
00355        * in the db_val_t structure.  The db_val_t structure will eventually be used to pkg_free()
00356        * the DB_STRING storage.
00357        */
00358       row_buf[col] = (char *)NULL;
00359    }
00360    LM_DBG("freeing row buffer at %p\n", row_buf);
00361    pkg_free(row_buf);
00362    row_buf = NULL;
00363    return 0;
00364 }
00365 
00366 
00367 
00368 int* bdb_get_colmap(table_p _dtp, db_key_t* _k, int _n)
00369 {
00370    int i, j, *_lref=NULL;
00371    
00372    if(!_dtp || !_k || _n < 0)
00373       return NULL;
00374    
00375    _lref = (int*)pkg_malloc(_n*sizeof(int));
00376    if(!_lref)
00377       return NULL;
00378    
00379    for(i=0; i < _n; i++)
00380    {
00381       for(j=0; j<_dtp->ncols; j++) {
00382          if(_k[i]->len==_dtp->colp[j]->name.len
00383          && !strncasecmp(_k[i]->s, _dtp->colp[j]->name.s,
00384                   _dtp->colp[j]->name.len)) {
00385             _lref[i] = j;
00386             break;
00387          }
00388       }
00389       if(i>=_dtp->ncols) {
00390          LM_DBG("ERROR column <%.*s> not found\n", _k[i]->len, _k[i]->s);
00391          pkg_free(_lref);
00392          return NULL;
00393       }
00394    }
00395    return _lref;
00396 }
00397 
00398 
00399 int bdb_is_neq_type(db_type_t _t0, db_type_t _t1)
00400 {
00401    if(_t0 == _t1) return 0;
00402    
00403    switch(_t1)
00404    {
00405       case DB_INT:
00406          if(_t0==DB_DATETIME || _t0==DB_BITMAP)
00407             return 0;
00408       case DB_BIGINT:
00409             LM_ERR("BIGINT not supported");
00410             return 0;
00411       case DB_DATETIME:
00412          if(_t0==DB_INT)
00413             return 0;
00414          if(_t0==DB_BITMAP)
00415             return 0;
00416       case DB_DOUBLE:
00417          break;
00418       case DB_STRING:
00419          if(_t0==DB_STR)
00420             return 0;
00421       case DB_STR:
00422          if(_t0==DB_STRING || _t0==DB_BLOB)
00423             return 0;
00424       case DB_BLOB:
00425          if(_t0==DB_STR)
00426             return 0;
00427       case DB_BITMAP:
00428          if (_t0==DB_INT)
00429             return 0;
00430    }
00431    return 1;
00432 }
00433 
00434 
00435 /*
00436 */
00437 int bdb_row_match(db_key_t* _k, db_op_t* _op, db_val_t* _v, int _n, db_res_t* _r, int* _lkey )
00438 {
00439    int i, res;
00440    db_row_t* row = NULL;
00441    
00442    if(!_r || !_lkey)
00443       return 1;
00444    
00445    row = RES_ROWS(_r);
00446    
00447    for(i=0; i<_n; i++) {
00448       res = bdb_cmp_val(&(ROW_VALUES(row)[_lkey[i]]), &_v[i]);
00449 
00450       if(!_op || !strcmp(_op[i], OP_EQ)) {
00451          if(res!=0)
00452             return 0;
00453       } else {
00454       if(!strcmp(_op[i], OP_LT)) {
00455          if(res!=-1)
00456             return 0;
00457       } else {
00458       if(!strcmp(_op[i], OP_GT)) {
00459          if(res!=1)
00460             return 0;
00461       } else {
00462       if(!strcmp(_op[i], OP_LEQ)) {
00463          if(res==1)
00464             return 0;
00465       } else {
00466       if(!strcmp(_op[i], OP_GEQ)) {
00467          if(res==-1)
00468             return 0;
00469       } else {
00470          return res;
00471       }}}}}
00472    }
00473    
00474    return 1;
00475 }
00476 
00477 /*
00478 */
00479 int bdb_cmp_val(db_val_t* _vp, db_val_t* _v)
00480 {
00481    int _l, _n;
00482    
00483    if(!_vp && !_v)
00484       return 0;
00485    if(!_v)
00486       return 1;
00487    if(!_vp)
00488       return -1;
00489    if(_vp->nul && _v->nul)
00490       return 0;
00491    if(_v->nul)
00492       return 1;
00493    if(_vp->nul)
00494       return -1;
00495    
00496    switch(VAL_TYPE(_v))
00497    {
00498       case DB_INT:
00499          return (_vp->val.int_val<_v->val.int_val)?-1:
00500                (_vp->val.int_val>_v->val.int_val)?1:0;
00501       case DB_BIGINT:
00502          LM_ERR("BIGINT not supported");
00503          return -1;
00504       case DB_DOUBLE:
00505          return (_vp->val.double_val<_v->val.double_val)?-1:
00506                (_vp->val.double_val>_v->val.double_val)?1:0;
00507       case DB_DATETIME:
00508          return (_vp->val.int_val<_v->val.time_val)?-1:
00509                (_vp->val.int_val>_v->val.time_val)?1:0;
00510       case DB_STRING:
00511          _l = strlen(_v->val.string_val);
00512          _l = (_l>_vp->val.str_val.len)?_vp->val.str_val.len:_l;
00513          _n = strncasecmp(_vp->val.str_val.s, _v->val.string_val, _l);
00514          if(_n)
00515             return _n;
00516          if(_vp->val.str_val.len == strlen(_v->val.string_val))
00517             return 0;
00518          if(_l==_vp->val.str_val.len)
00519             return -1;
00520          return 1;
00521       case DB_STR:
00522          _l = _v->val.str_val.len;
00523          _l = (_l>_vp->val.str_val.len)?_vp->val.str_val.len:_l;
00524          _n = strncasecmp(_vp->val.str_val.s, _v->val.str_val.s, _l);
00525          if(_n)
00526             return _n;
00527          if(_vp->val.str_val.len == _v->val.str_val.len)
00528             return 0;
00529          if(_l==_vp->val.str_val.len)
00530             return -1;
00531          return 1;
00532       case DB_BLOB:
00533          _l = _v->val.blob_val.len;
00534          _l = (_l>_vp->val.str_val.len)?_vp->val.str_val.len:_l;
00535          _n = strncasecmp(_vp->val.str_val.s, _v->val.blob_val.s, _l);
00536          if(_n)
00537             return _n;
00538          if(_vp->val.str_val.len == _v->val.blob_val.len)
00539             return 0;
00540          if(_l==_vp->val.str_val.len)
00541             return -1;
00542          return 1;
00543       case DB_BITMAP:
00544          return (_vp->val.int_val<_v->val.bitmap_val)?-1:
00545             (_vp->val.int_val>_v->val.bitmap_val)?1:0;
00546    }
00547    return -2;
00548 }

Generated on Thu May 17 12:00:25 2012 for Kamailio - The Open Source SIP Server by  doxygen 1.5.6