db_query.c

Go to the documentation of this file.
00001 /*
00002  * $Id$
00003  *
00004  * Copyright (C) 2007-2008 1&1 Internet AG
00005  *
00006  * This file is part of Kamailio, a free SIP server.
00007  *
00008  * Kamailio is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version
00012  *
00013  * Kamailio is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License 
00019  * along with this program; if not, write to the Free Software 
00020  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00021  *
00022  */
00023 
00035 #include <stdio.h>
00036 #include <stdlib.h>
00037 #include "../../dprint.h"
00038 #include "db_ut.h"
00039 #include "db_query.h"
00040 #include "../../globals.h"
00041 #include "../../timer.h"
00042 
00043 static str  sql_str;
00044 static char *sql_buf = NULL;
00045 
00046 static inline int db_do_submit_query(const db1_con_t* _h, const str *_query,
00047                 int (*submit_query)(const db1_con_t*, const str*))
00048 {
00049         int ret;
00050         unsigned int ms = 0;
00051 
00052         if(unlikely(cfg_get(core, core_cfg, latency_limit_action)>0))
00053                 ms = TICKS_TO_MS(get_ticks_raw());
00054 
00055         ret = submit_query(_h, _query);
00056 
00057         if(unlikely(cfg_get(core, core_cfg, latency_limit_action)>0)) {
00058                 ms = TICKS_TO_MS(get_ticks_raw()) - ms;
00059                 if(ms >= cfg_get(core, core_cfg, latency_limit_action)) {
00060                                 LOG(cfg_get(core, core_cfg, latency_log),
00061                                         "alert - query execution too long [%u ms] for [%.*s]\n",
00062                                    ms, _query->len<50?_query->len:50, _query->s);
00063                 }
00064         }
00065 
00066         return ret;
00067 }
00068 
00069 int db_do_query(const db1_con_t* _h, const db_key_t* _k, const db_op_t* _op,
00070         const db_val_t* _v, const db_key_t* _c, const int _n, const int _nc,
00071         const db_key_t _o, db1_res_t** _r, int (*val2str) (const db1_con_t*,
00072         const db_val_t*, char*, int* _len), int (*submit_query)(const db1_con_t*,
00073         const str*), int (*store_result)(const db1_con_t* _h, db1_res_t** _r))
00074 {
00075         int off, ret;
00076 
00077         if (!_h || !val2str || !submit_query || !store_result) {
00078                 LM_ERR("invalid parameter value\n");
00079                 return -1;
00080         }
00081 
00082         if (!_c) {
00083                 ret = snprintf(sql_buf, sql_buffer_size, "select * from %.*s ", CON_TABLE(_h)->len, CON_TABLE(_h)->s);
00084                 if (ret < 0 || ret >= sql_buffer_size) goto error;
00085                 off = ret;
00086         } else {
00087                 ret = snprintf(sql_buf, sql_buffer_size, "select ");
00088                 if (ret < 0 || ret >= sql_buffer_size) goto error;
00089                 off = ret;
00090 
00091                 ret = db_print_columns(sql_buf + off, sql_buffer_size - off, _c, _nc);
00092                 if (ret < 0) return -1;
00093                 off += ret;
00094 
00095                 ret = snprintf(sql_buf + off, sql_buffer_size - off, "from %.*s ", CON_TABLE(_h)->len, CON_TABLE(_h)->s);
00096                 if (ret < 0 || ret >= (sql_buffer_size - off)) goto error;
00097                 off += ret;
00098         }
00099         if (_n) {
00100                 ret = snprintf(sql_buf + off, sql_buffer_size - off, "where ");
00101                 if (ret < 0 || ret >= (sql_buffer_size - off)) goto error;
00102                 off += ret;
00103 
00104                 ret = db_print_where(_h, sql_buf + off,
00105                                 sql_buffer_size - off, _k, _op, _v, _n, val2str);
00106                 if (ret < 0) return -1;;
00107                 off += ret;
00108         }
00109         if (_o) {
00110                 ret = snprintf(sql_buf + off, sql_buffer_size - off, " order by %.*s", _o->len, _o->s);
00111                 if (ret < 0 || ret >= (sql_buffer_size - off)) goto error;
00112                 off += ret;
00113         }
00114         /*
00115          * Null-terminate the string for the postgres driver. Its query function
00116          * don't support a length parameter, so they need this for the correct
00117          * function of strlen. This zero is not included in the 'str' length.
00118          * We need to check the length here, otherwise we could overwrite the buffer
00119          * boundaries if off is equal to sql_buffer_size.
00120          */
00121         if (off + 1 >= sql_buffer_size) goto error;
00122         sql_buf[off + 1] = '\0';
00123         sql_str.s = sql_buf;
00124         sql_str.len = off;
00125 
00126         if (db_do_submit_query(_h, &sql_str, submit_query) < 0) {
00127                 LM_ERR("error while submitting query\n");
00128                 return -2;
00129         }
00130 
00131         if(_r) {
00132                 int tmp = store_result(_h, _r);
00133                 if (tmp < 0) {
00134                         LM_ERR("error while storing result");
00135                         return tmp;
00136                 }
00137         }
00138         return 0;
00139 
00140 error:
00141         LM_ERR("error while preparing query\n");
00142         return -1;
00143 }
00144 
00145 
00146 int db_do_raw_query(const db1_con_t* _h, const str* _s, db1_res_t** _r,
00147         int (*submit_query)(const db1_con_t* _h, const str* _c),
00148         int (*store_result)(const db1_con_t* _h, db1_res_t** _r))
00149 {
00150         if (!_h || !_s || !submit_query || !store_result) {
00151                 LM_ERR("invalid parameter value\n");
00152                 return -1;
00153         }
00154 
00155         if (db_do_submit_query(_h, _s, submit_query) < 0) {
00156                 LM_ERR("error while submitting query\n");
00157                 return -2;
00158         }
00159 
00160         if(_r) {
00161                 int tmp = store_result(_h, _r);
00162                 if (tmp < 0) {
00163                         LM_ERR("error while storing result");
00164                         return tmp;
00165                 }
00166         }
00167         return 0;
00168 }
00169 
00170 
00171 int db_do_insert_cmd(const db1_con_t* _h, const db_key_t* _k, const db_val_t* _v,
00172         const int _n, int (*val2str) (const db1_con_t*, const db_val_t*, char*, int*),
00173         int (*submit_query)(const db1_con_t* _h, const str* _c), int mode)
00174 {
00175         int off, ret;
00176 
00177         if (!_h || !_k || !_v || !_n || !val2str || !submit_query) {
00178                 LM_ERR("invalid parameter value\n");
00179                 return -1;
00180         }
00181 
00182         if(mode==1)
00183                 ret = snprintf(sql_buf, sql_buffer_size, "insert delayed into %.*s (",
00184                                 CON_TABLE(_h)->len, CON_TABLE(_h)->s);
00185         else
00186                 ret = snprintf(sql_buf, sql_buffer_size, "insert into %.*s (",
00187                                 CON_TABLE(_h)->len, CON_TABLE(_h)->s);
00188         if (ret < 0 || ret >= sql_buffer_size) goto error;
00189         off = ret;
00190 
00191         ret = db_print_columns(sql_buf + off, sql_buffer_size - off, _k, _n);
00192         if (ret < 0) return -1;
00193         off += ret;
00194 
00195         ret = snprintf(sql_buf + off, sql_buffer_size - off, ") values (");
00196         if (ret < 0 || ret >= (sql_buffer_size - off)) goto error;
00197         off += ret;
00198 
00199         ret = db_print_values(_h, sql_buf + off, sql_buffer_size - off, _v, _n, val2str);
00200         if (ret < 0) return -1;
00201         off += ret;
00202 
00203         if (off + 2 > sql_buffer_size) goto error;
00204         sql_buf[off++] = ')';
00205         sql_buf[off] = '\0';
00206         sql_str.s = sql_buf;
00207         sql_str.len = off;
00208 
00209         if (db_do_submit_query(_h, &sql_str, submit_query) < 0) {
00210                 LM_ERR("error while submitting query\n");
00211                 return -2;
00212         }
00213         return 0;
00214 
00215 error:
00216         LM_ERR("error while preparing insert operation\n");
00217         return -1;
00218 }
00219 
00220 int db_do_insert(const db1_con_t* _h, const db_key_t* _k, const db_val_t* _v,
00221         const int _n, int (*val2str) (const db1_con_t*, const db_val_t*, char*, int*),
00222         int (*submit_query)(const db1_con_t* _h, const str* _c))
00223 {
00224         return db_do_insert_cmd(_h, _k, _v, _n, val2str, submit_query, 0);
00225 }
00226 
00227 int db_do_insert_delayed(const db1_con_t* _h, const db_key_t* _k, const db_val_t* _v,
00228         const int _n, int (*val2str) (const db1_con_t*, const db_val_t*, char*, int*),
00229         int (*submit_query)(const db1_con_t* _h, const str* _c))
00230 {
00231         return db_do_insert_cmd(_h, _k, _v, _n, val2str, submit_query, 1);
00232 }
00233 
00234 int db_do_delete(const db1_con_t* _h, const db_key_t* _k, const db_op_t* _o,
00235         const db_val_t* _v, const int _n, int (*val2str) (const db1_con_t*,
00236         const db_val_t*, char*, int*), int (*submit_query)(const db1_con_t* _h,
00237         const str* _c))
00238 {
00239         int off, ret;
00240 
00241         if (!_h || !val2str || !submit_query) {
00242                 LM_ERR("invalid parameter value\n");
00243                 return -1;
00244         }
00245 
00246         ret = snprintf(sql_buf, sql_buffer_size, "delete from %.*s", CON_TABLE(_h)->len, CON_TABLE(_h)->s);
00247         if (ret < 0 || ret >= sql_buffer_size) goto error;
00248         off = ret;
00249 
00250         if (_n) {
00251                 ret = snprintf(sql_buf + off, sql_buffer_size - off, " where ");
00252                 if (ret < 0 || ret >= (sql_buffer_size - off)) goto error;
00253                 off += ret;
00254 
00255                 ret = db_print_where(_h, sql_buf + off,
00256                                 sql_buffer_size - off, _k, _o, _v, _n, val2str);
00257                 if (ret < 0) return -1;
00258                 off += ret;
00259         }
00260         if (off + 1 > sql_buffer_size) goto error;
00261         sql_buf[off] = '\0';
00262         sql_str.s = sql_buf;
00263         sql_str.len = off;
00264 
00265         if (db_do_submit_query(_h, &sql_str, submit_query) < 0) {
00266                 LM_ERR("error while submitting query\n");
00267                 return -2;
00268         }
00269         return 0;
00270 
00271 error:
00272         LM_ERR("error while preparing delete operation\n");
00273         return -1;
00274 }
00275 
00276 
00277 int db_do_update(const db1_con_t* _h, const db_key_t* _k, const db_op_t* _o,
00278         const db_val_t* _v, const db_key_t* _uk, const db_val_t* _uv, const int _n,
00279         const int _un, int (*val2str) (const db1_con_t*, const db_val_t*, char*, int*),
00280         int (*submit_query)(const db1_con_t* _h, const str* _c))
00281 {
00282         int off, ret;
00283 
00284         if (!_h || !_uk || !_uv || !_un || !val2str || !submit_query) {
00285                 LM_ERR("invalid parameter value\n");
00286                 return -1;
00287         }
00288 
00289         ret = snprintf(sql_buf, sql_buffer_size, "update %.*s set ", CON_TABLE(_h)->len, CON_TABLE(_h)->s);
00290         if (ret < 0 || ret >= sql_buffer_size) goto error;
00291         off = ret;
00292 
00293         ret = db_print_set(_h, sql_buf + off, sql_buffer_size - off, _uk, _uv, _un, val2str);
00294         if (ret < 0) return -1;
00295         off += ret;
00296 
00297         if (_n) {
00298                 ret = snprintf(sql_buf + off, sql_buffer_size - off, " where ");
00299                 if (ret < 0 || ret >= (sql_buffer_size - off)) goto error;
00300                 off += ret;
00301 
00302                 ret = db_print_where(_h, sql_buf + off, sql_buffer_size - off, _k, _o, _v, _n, val2str);
00303                 if (ret < 0) return -1;
00304                 off += ret;
00305         }
00306         if (off + 1 > sql_buffer_size) goto error;
00307         sql_buf[off] = '\0';
00308         sql_str.s = sql_buf;
00309         sql_str.len = off;
00310 
00311         if (db_do_submit_query(_h, &sql_str, submit_query) < 0) {
00312                 LM_ERR("error while submitting query\n");
00313                 return -2;
00314         }
00315         return 0;
00316 
00317 error:
00318         LM_ERR("error while preparing update operation\n");
00319         return -1;
00320 }
00321 
00322 
00323 int db_do_replace(const db1_con_t* _h, const db_key_t* _k, const db_val_t* _v,
00324         const int _n, int (*val2str) (const db1_con_t*, const db_val_t*, char*,
00325         int*), int (*submit_query)(const db1_con_t* _h, const str* _c))
00326 {
00327         int off, ret;
00328 
00329         if (!_h || !_k || !_v || !val2str|| !submit_query) {
00330                 LM_ERR("invalid parameter value\n");
00331                 return -1;
00332         }
00333 
00334         ret = snprintf(sql_buf, sql_buffer_size, "replace %.*s (", CON_TABLE(_h)->len, CON_TABLE(_h)->s);
00335         if (ret < 0 || ret >= sql_buffer_size) goto error;
00336         off = ret;
00337 
00338         ret = db_print_columns(sql_buf + off, sql_buffer_size - off, _k, _n);
00339         if (ret < 0) return -1;
00340         off += ret;
00341 
00342         ret = snprintf(sql_buf + off, sql_buffer_size - off, ") values (");
00343         if (ret < 0 || ret >= (sql_buffer_size - off)) goto error;
00344         off += ret;
00345 
00346         ret = db_print_values(_h, sql_buf + off, sql_buffer_size - off, _v, _n,
00347         val2str);
00348         if (ret < 0) return -1;
00349         off += ret;
00350 
00351         if (off + 2 > sql_buffer_size) goto error;
00352         sql_buf[off++] = ')';
00353         sql_buf[off] = '\0';
00354         sql_str.s = sql_buf;
00355         sql_str.len = off;
00356 
00357         if (db_do_submit_query(_h, &sql_str, submit_query) < 0) {
00358                 LM_ERR("error while submitting query\n");
00359                 return -2;
00360         }
00361         return 0;
00362 
00363  error:
00364         LM_ERR("error while preparing replace operation\n");
00365         return -1;
00366 }
00367 
00368 int db_query_init(void)
00369 {
00370     if (sql_buf != NULL)
00371     {
00372         LM_DBG("sql_buf not NULL on init\n");
00373         return 0;
00374     }
00375     LM_DBG("About to allocate sql_buf size = %d\n", sql_buffer_size);
00376     sql_buf = (char*)malloc(sql_buffer_size);
00377     if (sql_buf == NULL)
00378     {
00379         LM_ERR("failed to allocate sql_buf\n");
00380         return -1;
00381     }
00382     return 0;
00383 }
00384 
00389 int db_fetch_query(db_func_t *dbf, int frows,
00390                 db1_con_t* _h, const db_key_t* _k, const db_op_t* _op,
00391                 const db_val_t* _v, const db_key_t* _c, const int _n, const int _nc,
00392                 const db_key_t _o, db1_res_t** _r)
00393 {
00394 
00395         int ret;
00396 
00397         ret = 0;
00398         *_r = NULL;
00399 
00400         if (DB_CAPABILITY(*dbf, DB_CAP_FETCH)) {
00401                 if(dbf->query(_h, _k, _op, _v, _c, _n, _nc, _o, 0) < 0)
00402                 {
00403                         LM_ERR("unable to query db for fetch\n");
00404                         goto error;
00405                 }
00406                 if(dbf->fetch_result(_h, _r, frows)<0)
00407                 {
00408                         LM_ERR("unable to fetch the db result\n");
00409                         goto error;
00410                 }
00411                 ret = 1;
00412         } else {
00413                 if(dbf->query(_h, _k, _op, _v, _c, _n, _nc, _o, _r) < 0)
00414                 {
00415                         LM_ERR("unable to do full db querry\n");
00416                         goto error;
00417                 }
00418         }
00419 
00420         return ret;
00421 
00422 error:
00423         if(*_r)
00424         {
00425                 dbf->free_result(_h, *_r);
00426                 *_r = NULL;
00427         }
00428         return -1;
00429 }
00430 
00435 int db_fetch_next(db_func_t *dbf, int frows, db1_con_t* _h,
00436                 db1_res_t** _r)
00437 {
00438         int ret;
00439 
00440         ret = 0;
00441 
00442         if (DB_CAPABILITY(*dbf, DB_CAP_FETCH)) {
00443                 if(dbf->fetch_result(_h, _r, frows)<0) {
00444                         LM_ERR("unable to fetch next rows\n");
00445                         goto error;
00446                 }
00447                 ret = 1;
00448         }
00449         return ret;
00450 
00451 error:
00452         if(*_r)
00453         {
00454                 dbf->free_result(_h, *_r);
00455                 *_r = NULL;
00456         }
00457         return -1;
00458 }