dbt_base.c

Go to the documentation of this file.
00001 /*
00002  * $Id: dbt_base.c 5713 2009-03-16 17:29:25Z henningw $
00003  *
00004  * DBText module core functions
00005  *
00006  * Copyright (C) 2001-2003 FhG Fokus
00007  *
00008  * This file is part of Kamailio, a free SIP server.
00009  *
00010  * Kamailio is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2 of the License, or
00013  * (at your option) any later version
00014  *
00015  * Kamailio is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  * GNU General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU General Public License 
00021  * along with this program; if not, write to the Free Software 
00022  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00023  * 
00024  * History:
00025  * --------
00026  * 2009-03-01 added support for ORDER-BY clause by Edgar Holleis
00027  * 2003-01-30 created by Daniel
00028  * 
00029  */
00030 
00031 #include <string.h>
00032 
00033 #include "../../str.h"
00034 #include "../../mem/mem.h"
00035 #include "../../mem/shm_mem.h"
00036  
00037 #include "dbtext.h"
00038 #include "dbt_res.h"
00039 #include "dbt_api.h"
00040 
00041 #ifndef CFG_DIR
00042 #define CFG_DIR "/tmp"
00043 #endif
00044 
00045 #define DBT_ID    "text://"
00046 #define DBT_ID_LEN   (sizeof(DBT_ID)-1)
00047 #define DBT_PATH_LEN 256
00048 /*
00049  * Initialize database connection
00050  */
00051 db_con_t* dbt_init(const str* _sqlurl)
00052 {
00053    db_con_t* _res;
00054    str _s;
00055    char dbt_path[DBT_PATH_LEN];
00056    
00057    if (!_sqlurl || !_sqlurl->s)
00058    {
00059       LM_ERR("invalid parameter value\n");
00060       return NULL;
00061    }
00062    _s.s = _sqlurl->s;
00063    _s.len = _sqlurl->len;
00064    if(_s.len <= DBT_ID_LEN || strncmp(_s.s, DBT_ID, DBT_ID_LEN)!=0)
00065    {
00066       LM_ERR("invalid database URL - should be:"
00067          " <%s[/]path/to/directory>\n", DBT_ID);
00068       return NULL;
00069    }
00070    /*
00071     * it would be possible to use the _sqlurl here, but the core API is
00072     * defined with a const str*, so this code would be not valid.
00073     */
00074    _s.s   += DBT_ID_LEN;
00075    _s.len -= DBT_ID_LEN;
00076    if(_s.s[0]!='/')
00077    {
00078       if(sizeof(CFG_DIR)+_s.len+2 > DBT_PATH_LEN)
00079       {
00080          LM_ERR("path to database is too long\n");
00081          return NULL;
00082       }
00083       strcpy(dbt_path, CFG_DIR);
00084       dbt_path[sizeof(CFG_DIR)] = '/';
00085       strncpy(&dbt_path[sizeof(CFG_DIR)+1], _s.s, _s.len);
00086       _s.len += sizeof(CFG_DIR);
00087       _s.s = dbt_path;
00088    }
00089    
00090    _res = pkg_malloc(sizeof(db_con_t)+sizeof(dbt_con_t));
00091    if (!_res)
00092    {
00093       LM_ERR("no pkg memory left\n");
00094       return NULL;
00095    }
00096    memset(_res, 0, sizeof(db_con_t) + sizeof(dbt_con_t));
00097    _res->tail = (unsigned long)((char*)_res+sizeof(db_con_t));
00098 
00099    LM_INFO("using database at: %.*s", _s.len, _s.s);
00100    DBT_CON_CONNECTION(_res) = dbt_cache_get_db(&_s);
00101    if (!DBT_CON_CONNECTION(_res))
00102    {
00103       LM_ERR("cannot get the link to database\n");
00104       return NULL;
00105    }
00106 
00107     return _res;
00108 }
00109 
00110 
00111 /*
00112  * Close a database connection
00113  */
00114 void dbt_close(db_con_t* _h)
00115 {
00116    if (!_h) 
00117    {
00118       LM_ERR("invalid parameter value\n");
00119       return;
00120    }
00121    
00122    if (DBT_CON_RESULT(_h)) 
00123       dbt_result_free(DBT_CON_RESULT(_h));
00124    
00125    pkg_free(_h);
00126     return;
00127 }
00128 
00129 
00130 /*
00131  * Free all memory allocated by get_result
00132  */
00133 int dbt_free_result(db_con_t* _h, db_res_t* _r)
00134 {
00135    if ((!_h) || (!_r))
00136    {
00137       LM_ERR("invalid parameter value\n");
00138       return -1;
00139    }
00140 
00141    if(db_free_result(_r) < 0) 
00142    {
00143       LM_ERR("unable to free result structure\n");
00144       return -1;
00145    }
00146 
00147    
00148    if(dbt_result_free(DBT_CON_RESULT(_h)) < 0) 
00149    {
00150       LM_ERR("unable to free internal structure\n");
00151       return -1;
00152    }
00153    DBT_CON_RESULT(_h) = NULL;
00154    return 0;
00155 }
00156 
00157 
00158 /*
00159  * Query table for specified rows
00160  * _h: structure representing database connection
00161  * _k: key names
00162  * _op: operators
00163  * _v: values of the keys that must match
00164  * _c: column names to return
00165  * _n: number of key=values pairs to compare
00166  * _nc: number of columns to return
00167  * _o: order by the specified column
00168  */
00169 
00170 int dbt_query(db_con_t* _h, db_key_t* _k, db_op_t* _op, db_val_t* _v, 
00171          db_key_t* _c, int _n, int _nc, db_key_t _o, db_res_t** _r)
00172 {
00173    dbt_table_p _tbc = NULL;
00174    dbt_row_p _drp = NULL;
00175    dbt_result_p _dres = NULL;
00176    
00177    int *lkey=NULL, *lres=NULL;
00178    
00179    db_key_t *_o_k=NULL;    /* columns in order-by */
00180    char *_o_op=NULL;       /* operators for oder-by */
00181    int _o_n;               /* no of elements in order-by */
00182    int *_o_l=NULL;         /* column selection for order-by */
00183    int _o_nc;              /* no of elements in _o_l but not lres */
00184 
00185    if ((!_h) || (!_r) || !CON_TABLE(_h))
00186    {
00187       LM_ERR("invalid parameters\n");
00188       return -1;
00189    }
00190    *_r = NULL;
00191    
00192 
00193    if (_o)
00194    {
00195       if (dbt_parse_orderbyclause(&_o_k, &_o_op, &_o_n, _o) < 0)
00196          return -1;
00197    }
00198 
00199    /* lock database */
00200    _tbc = dbt_db_get_table(DBT_CON_CONNECTION(_h), CON_TABLE(_h));
00201    if(!_tbc)
00202    {
00203       LM_ERR("table %.*s does not exist!\n", CON_TABLE(_h)->len, CON_TABLE(_h)->s);
00204       return -1;
00205    }
00206 
00207 
00208    if(!_tbc || _tbc->nrcols < _nc)
00209    {
00210       LM_ERR("table not loaded!\n");
00211       goto error;
00212    }
00213    if(_k)
00214    {
00215       lkey = dbt_get_refs(_tbc, _k, _n);
00216       if(!lkey)
00217          goto error;
00218    }
00219    if(_c)
00220    {
00221       lres = dbt_get_refs(_tbc, _c, _nc);
00222       if(!lres)
00223          goto error;
00224    }
00225    if(_o_k)
00226    {
00227       _o_l = dbt_get_refs(_tbc, _o_k, _o_n);
00228       if (!_o_l)
00229          goto error;
00230       /* enlarge select-columns lres by all order-by columns, _o_nc is how many */
00231       if (dbt_mangle_columnselection(&lres, &_nc, &_o_nc, _o_l, _o_n) < 0)
00232          goto error;
00233    }
00234 
00235    LM_DBG("new res with %d cols\n", _nc);
00236    _dres = dbt_result_new(_tbc, lres, _nc);
00237    
00238    if(!_dres)
00239       goto error;
00240    
00241    _drp = _tbc->rows;
00242    while(_drp)
00243    {
00244       if(dbt_row_match(_tbc, _drp, lkey, _op, _v, _n))
00245       {
00246          if(dbt_result_extract_fields(_tbc, _drp, lres, _dres))
00247          {
00248             LM_ERR("failed to extract result fields!\n");
00249             goto clean;
00250          }
00251       }
00252       _drp = _drp->next;
00253    }
00254 
00255    dbt_table_update_flags(_tbc, DBT_TBFL_ZERO, DBT_FL_IGN, 1);
00256    
00257    /* unlock database */
00258    dbt_release_table(DBT_CON_CONNECTION(_h), CON_TABLE(_h));
00259 
00260    if (_o_l)
00261    {
00262       if (_dres->nrrows > 1)
00263       {
00264          if (dbt_sort_result(_dres, _o_l, _o_op, _o_n, lres, _nc) < 0)
00265             goto error_nounlock;
00266       }
00267 
00268       /* last but not least, remove surplus columns */
00269       if (_o_nc)
00270          dbt_project_result(_dres, _o_nc);
00271    }
00272 
00273 
00274    /* dbt_result_print(_dres); */
00275    
00276    DBT_CON_RESULT(_h) = _dres;
00277    
00278    if(lkey)
00279       pkg_free(lkey);
00280    if(lres)
00281       pkg_free(lres);
00282    if(_o_k)
00283       pkg_free(_o_k);
00284    if(_o_op)
00285       pkg_free(_o_op);
00286    if(_o_l)
00287       pkg_free(_o_l);
00288 
00289    return dbt_get_result(_h, _r);
00290 
00291 error:
00292    /* unlock database */
00293    dbt_release_table(DBT_CON_CONNECTION(_h), CON_TABLE(_h));
00294 error_nounlock:
00295    if(lkey)
00296       pkg_free(lkey);
00297    if(lres)
00298       pkg_free(lres);
00299    if(_o_k)
00300       pkg_free(_o_k);
00301    if(_o_op)
00302       pkg_free(_o_op);
00303    if(_o_l)
00304       pkg_free(_o_l);
00305    LM_ERR("failed to query the table!\n");
00306 
00307    return -1;
00308 
00309 clean:
00310    /* unlock database */
00311    dbt_release_table(DBT_CON_CONNECTION(_h), CON_TABLE(_h));
00312    if(lkey)
00313       pkg_free(lkey);
00314    if(lres)
00315       pkg_free(lres);
00316    if(_o_k)
00317       pkg_free(_o_k);
00318    if(_o_op)
00319       pkg_free(_o_op);
00320    if(_o_l)
00321       pkg_free(_o_l);
00322    if(_dres)
00323       dbt_result_free(_dres);
00324 
00325    return -1;
00326 }
00327 
00328 /*
00329  * Raw SQL query -- is not the case to have this method
00330  */
00331 int dbt_raw_query(db_con_t* _h, char* _s, db_res_t** _r)
00332 {
00333    *_r = NULL;
00334     return -1;
00335 }
00336 
00337 /*
00338  * Insert a row into table
00339  */
00340 int dbt_insert(db_con_t* _h, db_key_t* _k, db_val_t* _v, int _n)
00341 {
00342    dbt_table_p _tbc = NULL;
00343    dbt_row_p _drp = NULL;
00344    
00345    int *lkey=NULL, i, j;
00346    
00347    if (!_h || !CON_TABLE(_h))
00348    {
00349       LM_ERR("invalid parameter\n");
00350       return -1;
00351    }
00352    if(!_k || !_v || _n<=0)
00353    {
00354       LM_ERR("no key-value to insert\n");
00355       return -1;
00356    }
00357    
00358    /* lock database */
00359    _tbc = dbt_db_get_table(DBT_CON_CONNECTION(_h), CON_TABLE(_h));
00360    if(!_tbc)
00361    {
00362       LM_ERR("table %.*s does not exist!\n", CON_TABLE(_h)->len, CON_TABLE(_h)->s);
00363       return -1;
00364    }
00365 
00366    if(_tbc->nrcols<_n)
00367    {
00368       LM_ERR("more values than columns!!\n");
00369       goto error;
00370    }
00371    
00372    if(_k)
00373    {
00374       lkey = dbt_get_refs(_tbc, _k, _n);
00375       if(!lkey)
00376          goto error;
00377    }
00378    _drp = dbt_row_new(_tbc->nrcols);
00379    if(!_drp)
00380    {
00381       LM_ERR("no shm memory for a new row!!\n");
00382       goto error;
00383    }
00384    
00385    for(i=0; i<_n; i++)
00386    {
00387       j = (lkey)?lkey[i]:i;
00388       if(dbt_is_neq_type(_tbc->colv[j]->type, _v[i].type))
00389       {
00390          LM_ERR("incompatible types v[%d] - c[%d]!\n", i, j);
00391          goto clean;
00392       }
00393       if(_v[i].type == DB_STRING && !_v[i].nul)
00394          _v[i].val.str_val.len = strlen(_v[i].val.string_val);
00395       if(dbt_row_set_val(_drp, &(_v[i]), _tbc->colv[j]->type, j))
00396       {
00397          LM_ERR("cannot set v[%d] in c[%d]!\n", i, j);
00398          goto clean;
00399       }
00400       
00401    }
00402 
00403    if(dbt_table_add_row(_tbc, _drp))
00404    {
00405       LM_ERR("cannot insert the new row!!\n");
00406       goto clean;
00407    }
00408 
00409    /* dbt_print_table(_tbc, NULL); */
00410    
00411    /* unlock databse */
00412    dbt_release_table(DBT_CON_CONNECTION(_h), CON_TABLE(_h));
00413 
00414    if(lkey)
00415       pkg_free(lkey);
00416 
00417     return 0;
00418    
00419 error:
00420    /* unlock database */
00421    dbt_release_table(DBT_CON_CONNECTION(_h), CON_TABLE(_h));
00422    if(lkey)
00423       pkg_free(lkey);
00424    LM_ERR("failed to insert row in table!\n");
00425     return -1;
00426    
00427 clean:
00428    if(lkey)
00429       pkg_free(lkey);
00430    
00431    if(_drp) // free row
00432       dbt_row_free(_tbc, _drp);
00433    /* unlock database */
00434    dbt_release_table(DBT_CON_CONNECTION(_h), CON_TABLE(_h));
00435    
00436     return -1;
00437 }
00438 
00439 /*
00440  * Delete a row from table
00441  */
00442 int dbt_delete(db_con_t* _h, db_key_t* _k, db_op_t* _o, db_val_t* _v, int _n)
00443 {
00444    dbt_table_p _tbc = NULL;
00445    dbt_row_p _drp = NULL, _drp0 = NULL;
00446    int *lkey = NULL;
00447 
00448    if (!_h || !CON_TABLE(_h))
00449    {
00450       LM_ERR("invalid parameters\n");
00451       return -1;
00452    }
00453 
00454    /* lock database */
00455    _tbc = dbt_db_get_table(DBT_CON_CONNECTION(_h), CON_TABLE(_h));
00456    if(!_tbc)
00457    {
00458       LM_ERR("failed to load table <%.*s>!\n", CON_TABLE(_h)->len,
00459             CON_TABLE(_h)->s);
00460       return -1;
00461    }
00462 
00463    if(!_k || !_v || _n<=0)
00464    {
00465       LM_DBG("deleting all records\n");
00466       dbt_table_free_rows(_tbc);
00467       /* unlock databse */
00468       dbt_release_table(DBT_CON_CONNECTION(_h), CON_TABLE(_h));
00469       return 0;
00470    }
00471 
00472    lkey = dbt_get_refs(_tbc, _k, _n);
00473    if(!lkey)
00474       goto error;
00475    
00476    _drp = _tbc->rows;
00477    while(_drp)
00478    {
00479       _drp0 = _drp->next;
00480       if(dbt_row_match(_tbc, _drp, lkey, _o, _v, _n))
00481       {
00482          // delete row
00483          if(_drp->prev)
00484             (_drp->prev)->next = _drp->next;
00485          else
00486             _tbc->rows = _drp->next;
00487          if(_drp->next)
00488             (_drp->next)->prev = _drp->prev;
00489          _tbc->nrrows--;
00490          // free row
00491          dbt_row_free(_tbc, _drp);
00492       }
00493       _drp = _drp0;
00494    }
00495 
00496    dbt_table_update_flags(_tbc, DBT_TBFL_MODI, DBT_FL_SET, 1);
00497    
00498    /* dbt_print_table(_tbc, NULL); */
00499    
00500    /* unlock database */
00501    dbt_release_table(DBT_CON_CONNECTION(_h), CON_TABLE(_h));
00502 
00503    if(lkey)
00504       pkg_free(lkey);
00505    
00506    return 0;
00507    
00508 error:
00509    /* unlock database */
00510    dbt_release_table(DBT_CON_CONNECTION(_h), CON_TABLE(_h));
00511 
00512    LM_ERR("failed to delete from table!\n");
00513    return -1;
00514 }
00515 
00516 /*
00517  * Update a row in table
00518  */
00519 int dbt_update(db_con_t* _h, db_key_t* _k, db_op_t* _o, db_val_t* _v,
00520          db_key_t* _uk, db_val_t* _uv, int _n, int _un)
00521 {
00522    dbt_table_p _tbc = NULL;
00523    dbt_row_p _drp = NULL;
00524    int i;
00525    int *lkey=NULL, *lres=NULL;
00526 
00527    if (!_h || !CON_TABLE(_h) || !_uk || !_uv || _un <= 0)
00528    {
00529       LM_ERR("invalid parameters\n");
00530       return -1;
00531    }
00532    
00533    /* lock database */
00534    _tbc = dbt_db_get_table(DBT_CON_CONNECTION(_h), CON_TABLE(_h));
00535    if(!_tbc)
00536    {
00537       LM_ERR("table %.*s does not exist!\n", CON_TABLE(_h)->len, CON_TABLE(_h)->s);
00538       return -1;
00539    }
00540 
00541    if(_k)
00542    {
00543       lkey = dbt_get_refs(_tbc, _k, _n);
00544       if(!lkey)
00545          goto error;
00546    }
00547    lres = dbt_get_refs(_tbc, _uk, _un);
00548    if(!lres)
00549       goto error;
00550    _drp = _tbc->rows;
00551    while(_drp)
00552    {
00553       if(dbt_row_match(_tbc, _drp, lkey, _o, _v, _n))
00554       { // update fields
00555          for(i=0; i<_un; i++)
00556          {
00557             if(dbt_is_neq_type(_tbc->colv[lres[i]]->type, _uv[i].type))
00558             {
00559                LM_ERR("incompatible types!\n");
00560                goto error;
00561             }
00562             
00563             if(dbt_row_update_val(_drp, &(_uv[i]),
00564                      _tbc->colv[lres[i]]->type, lres[i]))
00565             {
00566                LM_ERR("cannot set v[%d] in c[%d]!\n",
00567                      i, lres[i]);
00568                goto error;
00569             }
00570          }
00571       }
00572       _drp = _drp->next;
00573    }
00574 
00575    dbt_table_update_flags(_tbc, DBT_TBFL_MODI, DBT_FL_SET, 1);
00576    
00577    /* dbt_print_table(_tbc, NULL); */
00578    
00579    /* unlock database */
00580    dbt_release_table(DBT_CON_CONNECTION(_h), CON_TABLE(_h));
00581 
00582    if(lkey)
00583       pkg_free(lkey);
00584    if(lres)
00585       pkg_free(lres);
00586 
00587     return 0;
00588 
00589 error:
00590    /* unlock database */
00591    dbt_release_table(DBT_CON_CONNECTION(_h), CON_TABLE(_h));
00592 
00593    if(lkey)
00594       pkg_free(lkey);
00595    if(lres)
00596       pkg_free(lres);
00597    
00598    LM_ERR("failed to update the table!\n");
00599 
00600    return -1;
00601 }
00602 

Generated on Tue May 22 14:00:25 2012 for Kamailio - The Open Source SIP Server by  doxygen 1.5.6