db_query.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516
  1. /*
  2. * $Id$
  3. *
  4. * Copyright (C) 2007-2008 1&1 Internet AG
  5. *
  6. * This file is part of Kamailio, a free SIP server.
  7. *
  8. * Kamailio is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version
  12. *
  13. * Kamailio is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  21. *
  22. */
  23. /**
  24. * \file lib/srdb1/db_query.c
  25. * \brief Query helper for database drivers
  26. * \ingroup db1
  27. *
  28. * This helper methods for database queries are used from the database
  29. * SQL driver to do the actual work. Each function uses some functions from
  30. * the actual driver with function pointers to the concrete, specific
  31. * implementation.
  32. */
  33. #include <stdio.h>
  34. #include <stdlib.h>
  35. #include "../../dprint.h"
  36. #include "db_ut.h"
  37. #include "db_query.h"
  38. #include "../../globals.h"
  39. #include "../../timer.h"
  40. static str sql_str;
  41. static char *sql_buf = NULL;
  42. static inline int db_do_submit_query(const db1_con_t* _h, const str *_query,
  43. int (*submit_query)(const db1_con_t*, const str*))
  44. {
  45. int ret;
  46. unsigned int ms = 0;
  47. if(unlikely(cfg_get(core, core_cfg, latency_limit_action)>0))
  48. ms = TICKS_TO_MS(get_ticks_raw());
  49. ret = submit_query(_h, _query);
  50. if(unlikely(cfg_get(core, core_cfg, latency_limit_action)>0)) {
  51. ms = TICKS_TO_MS(get_ticks_raw()) - ms;
  52. if(ms >= cfg_get(core, core_cfg, latency_limit_action)) {
  53. LOG(cfg_get(core, core_cfg, latency_log),
  54. "alert - query execution too long [%u ms] for [%.*s]\n",
  55. ms, _query->len<50?_query->len:50, _query->s);
  56. }
  57. }
  58. return ret;
  59. }
  60. static int db_do_query_internal(const db1_con_t* _h, const db_key_t* _k, const db_op_t* _op,
  61. const db_val_t* _v, const db_key_t* _c, const int _n, const int _nc,
  62. const db_key_t _o, db1_res_t** _r, int (*val2str) (const db1_con_t*,
  63. const db_val_t*, char*, int* _len), int (*submit_query)(const db1_con_t*,
  64. const str*), int (*store_result)(const db1_con_t* _h, db1_res_t** _r), int _l)
  65. {
  66. int off, ret;
  67. if (!_h || !val2str || !submit_query || !store_result) {
  68. LM_ERR("invalid parameter value\n");
  69. return -1;
  70. }
  71. if (!_c) {
  72. ret = snprintf(sql_buf, sql_buffer_size, "select * from %.*s ", CON_TABLE(_h)->len, CON_TABLE(_h)->s);
  73. if (ret < 0 || ret >= sql_buffer_size) goto error;
  74. off = ret;
  75. } else {
  76. ret = snprintf(sql_buf, sql_buffer_size, "select ");
  77. if (ret < 0 || ret >= sql_buffer_size) goto error;
  78. off = ret;
  79. ret = db_print_columns(sql_buf + off, sql_buffer_size - off, _c, _nc);
  80. if (ret < 0) return -1;
  81. off += ret;
  82. ret = snprintf(sql_buf + off, sql_buffer_size - off, "from %.*s ", CON_TABLE(_h)->len, CON_TABLE(_h)->s);
  83. if (ret < 0 || ret >= (sql_buffer_size - off)) goto error;
  84. off += ret;
  85. }
  86. if (_n) {
  87. ret = snprintf(sql_buf + off, sql_buffer_size - off, "where ");
  88. if (ret < 0 || ret >= (sql_buffer_size - off)) goto error;
  89. off += ret;
  90. ret = db_print_where(_h, sql_buf + off,
  91. sql_buffer_size - off, _k, _op, _v, _n, val2str);
  92. if (ret < 0) return -1;;
  93. off += ret;
  94. }
  95. if (_o) {
  96. ret = snprintf(sql_buf + off, sql_buffer_size - off, " order by %.*s", _o->len, _o->s);
  97. if (ret < 0 || ret >= (sql_buffer_size - off)) goto error;
  98. off += ret;
  99. }
  100. if (_l) {
  101. ret = snprintf(sql_buf + off, sql_buffer_size - off, " for update");
  102. if (ret < 0 || ret >= (sql_buffer_size - off)) goto error;
  103. off += ret;
  104. }
  105. /*
  106. * Null-terminate the string for the postgres driver. Its query function
  107. * don't support a length parameter, so they need this for the correct
  108. * function of strlen. This zero is not included in the 'str' length.
  109. * We need to check the length here, otherwise we could overwrite the buffer
  110. * boundaries if off is equal to sql_buffer_size.
  111. */
  112. if (off + 1 >= sql_buffer_size) goto error;
  113. sql_buf[off + 1] = '\0';
  114. sql_str.s = sql_buf;
  115. sql_str.len = off;
  116. if (db_do_submit_query(_h, &sql_str, submit_query) < 0) {
  117. LM_ERR("error while submitting query\n");
  118. return -2;
  119. }
  120. if(_r) {
  121. int tmp = store_result(_h, _r);
  122. if (tmp < 0) {
  123. LM_ERR("error while storing result");
  124. return tmp;
  125. }
  126. }
  127. return 0;
  128. error:
  129. LM_ERR("error while preparing query\n");
  130. return -1;
  131. }
  132. int db_do_query(const db1_con_t* _h, const db_key_t* _k, const db_op_t* _op,
  133. const db_val_t* _v, const db_key_t* _c, const int _n, const int _nc,
  134. const db_key_t _o, db1_res_t** _r, int (*val2str) (const db1_con_t*,
  135. const db_val_t*, char*, int* _len), int (*submit_query)(const db1_con_t*,
  136. const str*), int (*store_result)(const db1_con_t* _h, db1_res_t** _r))
  137. {
  138. return db_do_query_internal(_h, _k, _op, _v, _c, _n, _nc, _o, _r, val2str,
  139. submit_query, store_result, 0);
  140. }
  141. int db_do_query_lock(const db1_con_t* _h, const db_key_t* _k, const db_op_t* _op,
  142. const db_val_t* _v, const db_key_t* _c, const int _n, const int _nc,
  143. const db_key_t _o, db1_res_t** _r, int (*val2str) (const db1_con_t*,
  144. const db_val_t*, char*, int* _len), int (*submit_query)(const db1_con_t*,
  145. const str*), int (*store_result)(const db1_con_t* _h, db1_res_t** _r))
  146. {
  147. return db_do_query_internal(_h, _k, _op, _v, _c, _n, _nc, _o, _r, val2str,
  148. submit_query, store_result, 1);
  149. }
  150. int db_do_raw_query(const db1_con_t* _h, const str* _s, db1_res_t** _r,
  151. int (*submit_query)(const db1_con_t* _h, const str* _c),
  152. int (*store_result)(const db1_con_t* _h, db1_res_t** _r))
  153. {
  154. if (!_h || !_s || !submit_query || !store_result) {
  155. LM_ERR("invalid parameter value\n");
  156. return -1;
  157. }
  158. if (db_do_submit_query(_h, _s, submit_query) < 0) {
  159. LM_ERR("error while submitting query\n");
  160. return -2;
  161. }
  162. if(_r) {
  163. int tmp = store_result(_h, _r);
  164. if (tmp < 0) {
  165. LM_ERR("error while storing result");
  166. return tmp;
  167. }
  168. }
  169. return 0;
  170. }
  171. int db_do_insert_cmd(const db1_con_t* _h, const db_key_t* _k, const db_val_t* _v,
  172. const int _n, int (*val2str) (const db1_con_t*, const db_val_t*, char*, int*),
  173. int (*submit_query)(const db1_con_t* _h, const str* _c), int mode)
  174. {
  175. int off, ret;
  176. if (!_h || !_k || !_v || !_n || !val2str || !submit_query) {
  177. LM_ERR("invalid parameter value\n");
  178. return -1;
  179. }
  180. if(mode==1)
  181. ret = snprintf(sql_buf, sql_buffer_size, "insert delayed into %.*s (",
  182. CON_TABLE(_h)->len, CON_TABLE(_h)->s);
  183. else
  184. ret = snprintf(sql_buf, sql_buffer_size, "insert into %.*s (",
  185. CON_TABLE(_h)->len, CON_TABLE(_h)->s);
  186. if (ret < 0 || ret >= sql_buffer_size) goto error;
  187. off = ret;
  188. ret = db_print_columns(sql_buf + off, sql_buffer_size - off, _k, _n);
  189. if (ret < 0) return -1;
  190. off += ret;
  191. ret = snprintf(sql_buf + off, sql_buffer_size - off, ") values (");
  192. if (ret < 0 || ret >= (sql_buffer_size - off)) goto error;
  193. off += ret;
  194. ret = db_print_values(_h, sql_buf + off, sql_buffer_size - off, _v, _n, val2str);
  195. if (ret < 0) return -1;
  196. off += ret;
  197. if (off + 2 > sql_buffer_size) goto error;
  198. sql_buf[off++] = ')';
  199. sql_buf[off] = '\0';
  200. sql_str.s = sql_buf;
  201. sql_str.len = off;
  202. if (db_do_submit_query(_h, &sql_str, submit_query) < 0) {
  203. LM_ERR("error while submitting query\n");
  204. return -2;
  205. }
  206. return 0;
  207. error:
  208. LM_ERR("error while preparing insert operation\n");
  209. return -1;
  210. }
  211. int db_do_insert(const db1_con_t* _h, const db_key_t* _k, const db_val_t* _v,
  212. const int _n, int (*val2str) (const db1_con_t*, const db_val_t*, char*, int*),
  213. int (*submit_query)(const db1_con_t* _h, const str* _c))
  214. {
  215. return db_do_insert_cmd(_h, _k, _v, _n, val2str, submit_query, 0);
  216. }
  217. int db_do_insert_delayed(const db1_con_t* _h, const db_key_t* _k, const db_val_t* _v,
  218. const int _n, int (*val2str) (const db1_con_t*, const db_val_t*, char*, int*),
  219. int (*submit_query)(const db1_con_t* _h, const str* _c))
  220. {
  221. return db_do_insert_cmd(_h, _k, _v, _n, val2str, submit_query, 1);
  222. }
  223. int db_do_delete(const db1_con_t* _h, const db_key_t* _k, const db_op_t* _o,
  224. const db_val_t* _v, const int _n, int (*val2str) (const db1_con_t*,
  225. const db_val_t*, char*, int*), int (*submit_query)(const db1_con_t* _h,
  226. const str* _c))
  227. {
  228. int off, ret;
  229. if (!_h || !val2str || !submit_query) {
  230. LM_ERR("invalid parameter value\n");
  231. return -1;
  232. }
  233. ret = snprintf(sql_buf, sql_buffer_size, "delete from %.*s", CON_TABLE(_h)->len, CON_TABLE(_h)->s);
  234. if (ret < 0 || ret >= sql_buffer_size) goto error;
  235. off = ret;
  236. if (_n) {
  237. ret = snprintf(sql_buf + off, sql_buffer_size - off, " where ");
  238. if (ret < 0 || ret >= (sql_buffer_size - off)) goto error;
  239. off += ret;
  240. ret = db_print_where(_h, sql_buf + off,
  241. sql_buffer_size - off, _k, _o, _v, _n, val2str);
  242. if (ret < 0) return -1;
  243. off += ret;
  244. }
  245. if (off + 1 > sql_buffer_size) goto error;
  246. sql_buf[off] = '\0';
  247. sql_str.s = sql_buf;
  248. sql_str.len = off;
  249. if (db_do_submit_query(_h, &sql_str, submit_query) < 0) {
  250. LM_ERR("error while submitting query\n");
  251. return -2;
  252. }
  253. return 0;
  254. error:
  255. LM_ERR("error while preparing delete operation\n");
  256. return -1;
  257. }
  258. int db_do_update(const db1_con_t* _h, const db_key_t* _k, const db_op_t* _o,
  259. const db_val_t* _v, const db_key_t* _uk, const db_val_t* _uv, const int _n,
  260. const int _un, int (*val2str) (const db1_con_t*, const db_val_t*, char*, int*),
  261. int (*submit_query)(const db1_con_t* _h, const str* _c))
  262. {
  263. int off, ret;
  264. if (!_h || !_uk || !_uv || !_un || !val2str || !submit_query) {
  265. LM_ERR("invalid parameter value\n");
  266. return -1;
  267. }
  268. ret = snprintf(sql_buf, sql_buffer_size, "update %.*s set ", CON_TABLE(_h)->len, CON_TABLE(_h)->s);
  269. if (ret < 0 || ret >= sql_buffer_size) goto error;
  270. off = ret;
  271. ret = db_print_set(_h, sql_buf + off, sql_buffer_size - off, _uk, _uv, _un, val2str);
  272. if (ret < 0) return -1;
  273. off += ret;
  274. if (_n) {
  275. ret = snprintf(sql_buf + off, sql_buffer_size - off, " where ");
  276. if (ret < 0 || ret >= (sql_buffer_size - off)) goto error;
  277. off += ret;
  278. ret = db_print_where(_h, sql_buf + off, sql_buffer_size - off, _k, _o, _v, _n, val2str);
  279. if (ret < 0) return -1;
  280. off += ret;
  281. }
  282. if (off + 1 > sql_buffer_size) goto error;
  283. sql_buf[off] = '\0';
  284. sql_str.s = sql_buf;
  285. sql_str.len = off;
  286. if (db_do_submit_query(_h, &sql_str, submit_query) < 0) {
  287. LM_ERR("error while submitting query\n");
  288. return -2;
  289. }
  290. return 0;
  291. error:
  292. LM_ERR("error while preparing update operation\n");
  293. return -1;
  294. }
  295. int db_do_replace(const db1_con_t* _h, const db_key_t* _k, const db_val_t* _v,
  296. const int _n, int (*val2str) (const db1_con_t*, const db_val_t*, char*,
  297. int*), int (*submit_query)(const db1_con_t* _h, const str* _c))
  298. {
  299. int off, ret;
  300. if (!_h || !_k || !_v || !val2str|| !submit_query) {
  301. LM_ERR("invalid parameter value\n");
  302. return -1;
  303. }
  304. ret = snprintf(sql_buf, sql_buffer_size, "replace %.*s (", CON_TABLE(_h)->len, CON_TABLE(_h)->s);
  305. if (ret < 0 || ret >= sql_buffer_size) goto error;
  306. off = ret;
  307. ret = db_print_columns(sql_buf + off, sql_buffer_size - off, _k, _n);
  308. if (ret < 0) return -1;
  309. off += ret;
  310. ret = snprintf(sql_buf + off, sql_buffer_size - off, ") values (");
  311. if (ret < 0 || ret >= (sql_buffer_size - off)) goto error;
  312. off += ret;
  313. ret = db_print_values(_h, sql_buf + off, sql_buffer_size - off, _v, _n,
  314. val2str);
  315. if (ret < 0) return -1;
  316. off += ret;
  317. if (off + 2 > sql_buffer_size) goto error;
  318. sql_buf[off++] = ')';
  319. sql_buf[off] = '\0';
  320. sql_str.s = sql_buf;
  321. sql_str.len = off;
  322. if (db_do_submit_query(_h, &sql_str, submit_query) < 0) {
  323. LM_ERR("error while submitting query\n");
  324. return -2;
  325. }
  326. return 0;
  327. error:
  328. LM_ERR("error while preparing replace operation\n");
  329. return -1;
  330. }
  331. int db_query_init(void)
  332. {
  333. if (sql_buf != NULL)
  334. {
  335. LM_DBG("sql_buf not NULL on init\n");
  336. return 0;
  337. }
  338. LM_DBG("About to allocate sql_buf size = %d\n", sql_buffer_size);
  339. sql_buf = (char*)malloc(sql_buffer_size);
  340. if (sql_buf == NULL)
  341. {
  342. LM_ERR("failed to allocate sql_buf\n");
  343. return -1;
  344. }
  345. return 0;
  346. }
  347. static int db_fetch_query_internal(db_func_t *dbf, int frows,
  348. db1_con_t* _h, const db_key_t* _k, const db_op_t* _op,
  349. const db_val_t* _v, const db_key_t* _c, const int _n, const int _nc,
  350. const db_key_t _o, db1_res_t** _r, db_query_f _query)
  351. {
  352. int ret;
  353. if (!_query) {
  354. LM_ERR("bad query function pointer\n");
  355. goto error;
  356. }
  357. ret = 0;
  358. *_r = NULL;
  359. if (DB_CAPABILITY(*dbf, DB_CAP_FETCH)) {
  360. if(_query(_h, _k, _op, _v, _c, _n, _nc, _o, 0) < 0)
  361. {
  362. LM_ERR("unable to query db for fetch\n");
  363. goto error;
  364. }
  365. if(dbf->fetch_result(_h, _r, frows)<0)
  366. {
  367. LM_ERR("unable to fetch the db result\n");
  368. goto error;
  369. }
  370. ret = 1;
  371. } else {
  372. if(_query(_h, _k, _op, _v, _c, _n, _nc, _o, _r) < 0)
  373. {
  374. LM_ERR("unable to do full db querry\n");
  375. goto error;
  376. }
  377. }
  378. return ret;
  379. error:
  380. if(*_r)
  381. {
  382. dbf->free_result(_h, *_r);
  383. *_r = NULL;
  384. }
  385. return -1;
  386. }
  387. /**
  388. * wrapper around db query to handle fetch capability
  389. * return: -1 error; 0 ok with no fetch capability; 1 ok with fetch capability
  390. */
  391. int db_fetch_query(db_func_t *dbf, int frows,
  392. db1_con_t* _h, const db_key_t* _k, const db_op_t* _op,
  393. const db_val_t* _v, const db_key_t* _c, const int _n, const int _nc,
  394. const db_key_t _o, db1_res_t** _r)
  395. {
  396. return db_fetch_query_internal(dbf, frows, _h, _k, _op, _v, _c, _n,
  397. _nc, _o, _r, dbf->query);
  398. }
  399. /**
  400. * wrapper around db query_lock to handle fetch capability
  401. * return: -1 error; 0 ok with no fetch capability; 1 ok with fetch capability
  402. */
  403. int db_fetch_query_lock(db_func_t *dbf, int frows,
  404. db1_con_t* _h, const db_key_t* _k, const db_op_t* _op,
  405. const db_val_t* _v, const db_key_t* _c, const int _n, const int _nc,
  406. const db_key_t _o, db1_res_t** _r)
  407. {
  408. if (!dbf->query_lock)
  409. {
  410. LM_ERR("query_lock not supported by this database module\n");
  411. return -1;
  412. }
  413. return db_fetch_query_internal(dbf, frows, _h, _k, _op, _v, _c, _n,
  414. _nc, _o, _r, dbf->query_lock);
  415. }
  416. /**
  417. * wrapper around db fetch to handle fetch capability
  418. * return: -1 error; 0 ok with no fetch capability; 1 ok with fetch capability
  419. */
  420. int db_fetch_next(db_func_t *dbf, int frows, db1_con_t* _h,
  421. db1_res_t** _r)
  422. {
  423. int ret;
  424. ret = 0;
  425. if (DB_CAPABILITY(*dbf, DB_CAP_FETCH)) {
  426. if(dbf->fetch_result(_h, _r, frows)<0) {
  427. LM_ERR("unable to fetch next rows\n");
  428. goto error;
  429. }
  430. ret = 1;
  431. }
  432. return ret;
  433. error:
  434. if(*_r)
  435. {
  436. dbf->free_result(_h, *_r);
  437. *_r = NULL;
  438. }
  439. return -1;
  440. }