sql_api.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852
  1. /**
  2. * $Id$
  3. *
  4. * Copyright (C) 2008 Elena-Ramona Modroiu (asipto.com)
  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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  21. */
  22. /*! \file
  23. * \ingroup sqlops
  24. * \brief SIP-router SQL-operations :: API
  25. *
  26. * - Module: \ref sqlops
  27. */
  28. #include "../../mem/mem.h"
  29. #include "../../dprint.h"
  30. #include "../../hashes.h"
  31. #include "../../ut.h"
  32. #include "../../lib/srdb1/db_ut.h"
  33. #ifdef WITH_XAVP
  34. #include "../../xavp.h"
  35. #endif
  36. #include "sql_api.h"
  37. sql_con_t *_sql_con_root = NULL;
  38. sql_result_t *_sql_result_root = NULL;
  39. static char _sql_empty_buf[1];
  40. sql_con_t* sql_get_connection(str *name)
  41. {
  42. sql_con_t *sc;
  43. unsigned int conid;
  44. conid = core_case_hash(name, 0, 0);
  45. sc = _sql_con_root;
  46. while(sc)
  47. {
  48. if(conid==sc->conid && sc->name.len==name->len
  49. && strncmp(sc->name.s, name->s, name->len)==0)
  50. return sc;
  51. sc = sc->next;
  52. }
  53. return NULL;
  54. }
  55. int sql_init_con(str *name, str *url)
  56. {
  57. sql_con_t *sc;
  58. unsigned int conid;
  59. *_sql_empty_buf = '\0';
  60. conid = core_case_hash(name, 0, 0);
  61. sc = _sql_con_root;
  62. while(sc)
  63. {
  64. if(conid==sc->conid && sc->name.len==name->len
  65. && strncmp(sc->name.s, name->s, name->len)==0)
  66. {
  67. LM_ERR("duplicate connection name\n");
  68. return -1;
  69. }
  70. sc = sc->next;
  71. }
  72. sc = (sql_con_t*)pkg_malloc(sizeof(sql_con_t));
  73. if(sc==NULL)
  74. {
  75. LM_ERR("no pkg memory\n");
  76. return -1;
  77. }
  78. memset(sc, 0, sizeof(sql_con_t));
  79. sc->conid = conid;
  80. sc->name = *name;
  81. sc->db_url = *url;
  82. sc->next = _sql_con_root;
  83. _sql_con_root = sc;
  84. return 0;
  85. }
  86. int pv_parse_con_name(pv_spec_p sp, str *in)
  87. {
  88. sql_con_t *con;
  89. if(sp==NULL || in==NULL || in->len<=0)
  90. return -1;
  91. con = sql_get_connection(in);
  92. if (con==NULL) {
  93. LM_ERR("invalid connection [%.*s]\n", in->len, in->s);
  94. return -1;
  95. }
  96. sp->pvp.pvn.type = PV_NAME_INTSTR;
  97. sp->pvp.pvn.u.isname.type = AVP_VAL_STR;
  98. sp->pvp.pvn.u.isname.name.s = *in;
  99. return 0;
  100. }
  101. int pv_get_sqlrows(struct sip_msg *msg, pv_param_t *param,
  102. pv_value_t *res)
  103. {
  104. sql_con_t *con;
  105. str* sc;
  106. sc = &param->pvn.u.isname.name.s;
  107. con = sql_get_connection(sc);
  108. if(con==NULL)
  109. {
  110. LM_ERR("invalid connection [%.*s]\n", sc->len, sc->s);
  111. return -1;
  112. }
  113. if (!DB_CAPABILITY(con->dbf, DB_CAP_AFFECTED_ROWS))
  114. {
  115. LM_ERR("con: %p database module does not have DB_CAP_AFFECTED_ROWS [%.*s]\n",
  116. con, sc->len, sc->s);
  117. return -1;
  118. }
  119. return pv_get_sintval(msg, param, res, con->dbf.affected_rows(con->dbh));
  120. }
  121. int sql_connect(void)
  122. {
  123. sql_con_t *sc;
  124. sc = _sql_con_root;
  125. while(sc)
  126. {
  127. if (db_bind_mod(&sc->db_url, &sc->dbf))
  128. {
  129. LM_DBG("database module not found for [%.*s]\n",
  130. sc->name.len, sc->name.s);
  131. return -1;
  132. }
  133. if (!DB_CAPABILITY(sc->dbf, DB_CAP_RAW_QUERY))
  134. {
  135. LM_ERR("database module does not have DB_CAP_ALL [%.*s]\n",
  136. sc->name.len, sc->name.s);
  137. return -1;
  138. }
  139. sc->dbh = sc->dbf.init(&sc->db_url);
  140. if (sc->dbh==NULL)
  141. {
  142. LM_ERR("failed to connect to the database [%.*s]\n",
  143. sc->name.len, sc->name.s);
  144. return -1;
  145. }
  146. sc = sc->next;
  147. }
  148. return 0;
  149. }
  150. void sql_disconnect(void)
  151. {
  152. sql_con_t *sc;
  153. sc = _sql_con_root;
  154. while(sc)
  155. {
  156. if (sc->dbh!=NULL)
  157. sc->dbf.close(sc->dbh);
  158. sc->dbh= NULL;
  159. sc = sc->next;
  160. }
  161. }
  162. sql_result_t* sql_get_result(str *name)
  163. {
  164. sql_result_t *sr;
  165. unsigned int resid;
  166. resid = core_case_hash(name, 0, 0);
  167. sr = _sql_result_root;
  168. while(sr)
  169. {
  170. if(sr->resid==resid && sr->name.len==name->len
  171. && strncmp(sr->name.s, name->s, name->len)==0)
  172. return sr;
  173. sr = sr->next;
  174. }
  175. sr = (sql_result_t*)pkg_malloc(sizeof(sql_result_t));
  176. if(sr==NULL)
  177. {
  178. LM_ERR("no pkg memory\n");
  179. return NULL;
  180. }
  181. memset(sr, 0, sizeof(sql_result_t));
  182. sr->name = *name;
  183. sr->resid = resid;
  184. sr->next = _sql_result_root;
  185. _sql_result_root = sr;
  186. return sr;
  187. }
  188. void sql_reset_result(sql_result_t *res)
  189. {
  190. int i, j;
  191. if(res->cols)
  192. {
  193. for(i=0; i<res->ncols; i++)
  194. if(res->cols[i].name.s!=NULL)
  195. pkg_free(res->cols[i].name.s);
  196. pkg_free(res->cols);
  197. res->cols = NULL;
  198. }
  199. if(res->vals)
  200. {
  201. for(i=0; i<res->nrows; i++)
  202. {
  203. for(j=0; j<res->ncols; j++)
  204. {
  205. if(res->vals[i][j].flags&PV_VAL_STR
  206. && res->vals[i][j].value.s.len>0)
  207. pkg_free(res->vals[i][j].value.s.s);
  208. }
  209. pkg_free(res->vals[i]);
  210. }
  211. pkg_free(res->vals);
  212. res->vals = NULL;
  213. }
  214. res->nrows = 0;
  215. res->ncols = 0;
  216. }
  217. int sql_do_query(sql_con_t *con, str *query, sql_result_t *res)
  218. {
  219. db1_res_t* db_res = NULL;
  220. int i, j;
  221. str sv;
  222. if(query==NULL)
  223. {
  224. LM_ERR("bad parameters\n");
  225. return -1;
  226. }
  227. if(con->dbf.raw_query(con->dbh, query, &db_res)!=0)
  228. {
  229. LM_ERR("cannot do the query\n");
  230. return -1;
  231. }
  232. if(db_res==NULL || RES_ROW_N(db_res)<=0 || RES_COL_N(db_res)<=0)
  233. {
  234. LM_DBG("no result after query\n");
  235. con->dbf.free_result(con->dbh, db_res);
  236. return 2;
  237. }
  238. if(!res)
  239. {
  240. LM_DBG("no sqlresult parameter, ignoring result from query\n");
  241. con->dbf.free_result(con->dbh, db_res);
  242. return 3;
  243. }
  244. sql_reset_result(res);
  245. res->ncols = RES_COL_N(db_res);
  246. res->nrows = RES_ROW_N(db_res);
  247. LM_DBG("rows [%d] cols [%d]\n", res->nrows, res->ncols);
  248. res->cols = (sql_col_t*)pkg_malloc(res->ncols*sizeof(sql_col_t));
  249. if(res->cols==NULL)
  250. {
  251. res->ncols = 0;
  252. res->nrows = 0;
  253. LM_ERR("no more memory\n");
  254. return -1;
  255. }
  256. memset(res->cols, 0, res->ncols*sizeof(sql_col_t));
  257. for(i=0; i<res->ncols; i++)
  258. {
  259. res->cols[i].name.len = (RES_NAMES(db_res)[i])->len;
  260. res->cols[i].name.s = (char*)pkg_malloc((res->cols[i].name.len+1)
  261. *sizeof(char));
  262. if(res->cols[i].name.s==NULL)
  263. {
  264. LM_ERR("no more memory\n");
  265. goto error;
  266. }
  267. memcpy(res->cols[i].name.s, RES_NAMES(db_res)[i]->s,
  268. res->cols[i].name.len);
  269. res->cols[i].name.s[res->cols[i].name.len]='\0';
  270. res->cols[i].colid = core_case_hash(&res->cols[i].name, 0, 0);
  271. }
  272. res->vals = (sql_val_t**)pkg_malloc(res->nrows*sizeof(sql_val_t*));
  273. if(res->vals==NULL)
  274. {
  275. LM_ERR("no more memory\n");
  276. goto error;
  277. }
  278. memset(res->vals, 0, res->nrows*sizeof(sql_val_t*));
  279. for(i=0; i<res->nrows; i++)
  280. {
  281. res->vals[i] = (sql_val_t*)pkg_malloc(res->ncols*sizeof(sql_val_t));
  282. if(res->vals[i]==NULL)
  283. {
  284. LM_ERR("no more memory\n");
  285. goto error;
  286. }
  287. memset(res->vals[i], 0, res->ncols*sizeof(sql_val_t));
  288. for(j=0; j<res->ncols; j++)
  289. {
  290. if(RES_ROWS(db_res)[i].values[j].nul)
  291. {
  292. res->vals[i][j].flags = PV_VAL_NULL;
  293. continue;
  294. }
  295. sv.s = NULL;
  296. sv.len = 0;
  297. switch(RES_ROWS(db_res)[i].values[j].type)
  298. {
  299. case DB1_STRING:
  300. res->vals[i][j].flags = PV_VAL_STR;
  301. sv.s=
  302. (char*)RES_ROWS(db_res)[i].values[j].val.string_val;
  303. sv.len=strlen(sv.s);
  304. break;
  305. case DB1_STR:
  306. res->vals[i][j].flags = PV_VAL_STR;
  307. sv.len=
  308. RES_ROWS(db_res)[i].values[j].val.str_val.len;
  309. sv.s=
  310. (char*)RES_ROWS(db_res)[i].values[j].val.str_val.s;
  311. break;
  312. case DB1_BLOB:
  313. res->vals[i][j].flags = PV_VAL_STR;
  314. sv.len=
  315. RES_ROWS(db_res)[i].values[j].val.blob_val.len;
  316. sv.s=
  317. (char*)RES_ROWS(db_res)[i].values[j].val.blob_val.s;
  318. break;
  319. case DB1_INT:
  320. res->vals[i][j].flags = PV_VAL_INT;
  321. res->vals[i][j].value.n
  322. = (int)RES_ROWS(db_res)[i].values[j].val.int_val;
  323. break;
  324. case DB1_DATETIME:
  325. res->vals[i][j].flags = PV_VAL_INT;
  326. res->vals[i][j].value.n
  327. = (int)RES_ROWS(db_res)[i].values[j].val.time_val;
  328. break;
  329. case DB1_BITMAP:
  330. res->vals[i][j].flags = PV_VAL_INT;
  331. res->vals[i][j].value.n
  332. = (int)RES_ROWS(db_res)[i].values[j].val.bitmap_val;
  333. break;
  334. case DB1_BIGINT:
  335. res->vals[i][j].flags = PV_VAL_STR;
  336. res->vals[i][j].value.s.len = 21*sizeof(char);
  337. res->vals[i][j].value.s.s
  338. = (char*)pkg_malloc(res->vals[i][j].value.s.len);
  339. if(res->vals[i][j].value.s.s==NULL)
  340. {
  341. LM_ERR("no more memory\n");
  342. goto error;
  343. }
  344. db_longlong2str(RES_ROWS(db_res)[i].values[j].val.ll_val,
  345. res->vals[i][j].value.s.s, &res->vals[i][j].value.s.len);
  346. break;
  347. default:
  348. res->vals[i][j].flags = PV_VAL_NULL;
  349. }
  350. if(res->vals[i][j].flags == PV_VAL_STR && sv.s)
  351. {
  352. if(sv.len<=0)
  353. {
  354. res->vals[i][j].value.s.s = _sql_empty_buf;
  355. res->vals[i][j].value.s.len = 0;
  356. continue;
  357. }
  358. res->vals[i][j].value.s.s
  359. = (char*)pkg_malloc(sv.len*sizeof(char));
  360. if(res->vals[i][j].value.s.s==NULL)
  361. {
  362. LM_ERR("no more memory\n");
  363. goto error;
  364. }
  365. memcpy(res->vals[i][j].value.s.s, sv.s, sv.len);
  366. res->vals[i][j].value.s.len = sv.len;
  367. }
  368. }
  369. }
  370. con->dbf.free_result(con->dbh, db_res);
  371. return 1;
  372. error:
  373. con->dbf.free_result(con->dbh, db_res);
  374. sql_reset_result(res);
  375. return -1;
  376. }
  377. #ifdef WITH_XAVP
  378. int sql_exec_xquery(struct sip_msg *msg, sql_con_t *con, str *query,
  379. str *xavp)
  380. {
  381. db1_res_t* db_res = NULL;
  382. sr_xavp_t *row = NULL;
  383. sr_xval_t val;
  384. int i, j;
  385. if(msg==NULL || query==NULL || xavp==NULL)
  386. {
  387. LM_ERR("bad parameters\n");
  388. return -1;
  389. }
  390. if(con->dbf.raw_query(con->dbh, query, &db_res)!=0)
  391. {
  392. LM_ERR("cannot do the query\n");
  393. return -1;
  394. }
  395. if(db_res==NULL || RES_ROW_N(db_res)<=0 || RES_COL_N(db_res)<=0)
  396. {
  397. LM_DBG("no result after query\n");
  398. con->dbf.free_result(con->dbh, db_res);
  399. return 2;
  400. }
  401. for(i=RES_ROW_N(db_res)-1; i>=0; i--)
  402. {
  403. row = NULL;
  404. for(j=RES_COL_N(db_res)-1; j>=0; j--)
  405. {
  406. if(RES_ROWS(db_res)[i].values[j].nul)
  407. {
  408. val.type = SR_XTYPE_NULL;
  409. } else
  410. {
  411. switch(RES_ROWS(db_res)[i].values[j].type)
  412. {
  413. case DB1_STRING:
  414. val.type = SR_XTYPE_STR;
  415. val.v.s.s=
  416. (char*)RES_ROWS(db_res)[i].values[j].val.string_val;
  417. val.v.s.len=strlen(val.v.s.s);
  418. break;
  419. case DB1_STR:
  420. val.type = SR_XTYPE_STR;
  421. val.v.s.len=
  422. RES_ROWS(db_res)[i].values[j].val.str_val.len;
  423. val.v.s.s=
  424. (char*)RES_ROWS(db_res)[i].values[j].val.str_val.s;
  425. break;
  426. case DB1_BLOB:
  427. val.type = SR_XTYPE_STR;
  428. val.v.s.len=
  429. RES_ROWS(db_res)[i].values[j].val.blob_val.len;
  430. val.v.s.s=
  431. (char*)RES_ROWS(db_res)[i].values[j].val.blob_val.s;
  432. break;
  433. case DB1_INT:
  434. val.type = SR_XTYPE_INT;
  435. val.v.i
  436. = (int)RES_ROWS(db_res)[i].values[j].val.int_val;
  437. break;
  438. case DB1_DATETIME:
  439. val.type = SR_XTYPE_INT;
  440. val.v.i
  441. = (int)RES_ROWS(db_res)[i].values[j].val.time_val;
  442. break;
  443. case DB1_BITMAP:
  444. val.type = SR_XTYPE_INT;
  445. val.v.i
  446. = (int)RES_ROWS(db_res)[i].values[j].val.bitmap_val;
  447. break;
  448. case DB1_BIGINT:
  449. val.type = SR_XTYPE_LLONG;
  450. val.v.ll
  451. = RES_ROWS(db_res)[i].values[j].val.ll_val;
  452. break;
  453. default:
  454. val.type = SR_XTYPE_NULL;
  455. }
  456. }
  457. /* Add column to current row, under the column's name */
  458. LM_DBG("Adding column: %.*s\n", RES_NAMES(db_res)[j]->len, RES_NAMES(db_res)[j]->s);
  459. xavp_add_value(RES_NAMES(db_res)[j], &val, &row);
  460. }
  461. /* Add row to result xavp */
  462. val.type = SR_XTYPE_XAVP;
  463. val.v.xavp = row;
  464. LM_DBG("Adding row\n");
  465. xavp_add_value(xavp, &val, NULL);
  466. }
  467. con->dbf.free_result(con->dbh, db_res);
  468. return 1;
  469. }
  470. int sql_do_xquery(struct sip_msg *msg, sql_con_t *con, pv_elem_t *query,
  471. pv_elem_t *res)
  472. {
  473. str sv, xavp;
  474. if(msg==NULL || query==NULL || res==NULL)
  475. {
  476. LM_ERR("bad parameters\n");
  477. return -1;
  478. }
  479. if(pv_printf_s(msg, query, &sv)!=0)
  480. {
  481. LM_ERR("cannot print the sql query\n");
  482. return -1;
  483. }
  484. if(pv_printf_s(msg, res, &xavp)!=0)
  485. {
  486. LM_ERR("cannot print the result parameter\n");
  487. return -1;
  488. }
  489. return sql_exec_xquery(msg, con, &sv, &xavp);
  490. }
  491. #endif
  492. int sql_do_pvquery(struct sip_msg *msg, sql_con_t *con, pv_elem_t *query,
  493. pvname_list_t *res)
  494. {
  495. db1_res_t* db_res = NULL;
  496. pvname_list_t* pv;
  497. str sv;
  498. int i, j;
  499. if(msg==NULL || query==NULL || res==NULL)
  500. {
  501. LM_ERR("bad parameters\n");
  502. return -1;
  503. }
  504. if(pv_printf_s(msg, query, &sv)!=0)
  505. {
  506. LM_ERR("cannot print the sql query\n");
  507. return -1;
  508. }
  509. if(con->dbf.raw_query(con->dbh, &sv, &db_res)!=0)
  510. {
  511. LM_ERR("cannot do the query\n");
  512. return -1;
  513. }
  514. if(db_res==NULL || RES_ROW_N(db_res)<=0 || RES_COL_N(db_res)<=0)
  515. {
  516. LM_DBG("no result after query\n");
  517. con->dbf.free_result(con->dbh, db_res);
  518. return 2;
  519. }
  520. for(i=RES_ROW_N(db_res)-1; i>=0; i--)
  521. {
  522. pv = res;
  523. for(j=0; j<RES_COL_N(db_res); j++)
  524. {
  525. if (pv == NULL) {
  526. LM_ERR("Missing pv spec for column %d\n", j+1);
  527. goto error;
  528. }
  529. if (db_val2pv_spec(msg, &RES_ROWS(db_res)[0].values[j], &pv->sname) != 0) {
  530. LM_ERR("Failed to convert value for column %.*s\n",
  531. RES_NAMES(db_res)[j]->len, RES_NAMES(db_res)[j]->s);
  532. goto error;
  533. }
  534. pv = pv->next;
  535. }
  536. }
  537. con->dbf.free_result(con->dbh, db_res);
  538. return 1;
  539. error:
  540. con->dbf.free_result(con->dbh, db_res);
  541. return -1;
  542. }
  543. int sql_parse_param(char *val)
  544. {
  545. str name;
  546. str tok;
  547. str in;
  548. char *p;
  549. /* parse: name=>db_url*/
  550. in.s = val;
  551. in.len = strlen(in.s);
  552. p = in.s;
  553. while(p<in.s+in.len && (*p==' ' || *p=='\t' || *p=='\n' || *p=='\r'))
  554. p++;
  555. if(p>in.s+in.len || *p=='\0')
  556. goto error;
  557. name.s = p;
  558. while(p < in.s + in.len)
  559. {
  560. if(*p=='=' || *p==' ' || *p=='\t' || *p=='\n' || *p=='\r')
  561. break;
  562. p++;
  563. }
  564. if(p>in.s+in.len || *p=='\0')
  565. goto error;
  566. name.len = p - name.s;
  567. if(*p!='=')
  568. {
  569. while(p<in.s+in.len && (*p==' ' || *p=='\t' || *p=='\n' || *p=='\r'))
  570. p++;
  571. if(p>in.s+in.len || *p=='\0' || *p!='=')
  572. goto error;
  573. }
  574. p++;
  575. if(*p!='>')
  576. goto error;
  577. p++;
  578. while(p<in.s+in.len && (*p==' ' || *p=='\t' || *p=='\n' || *p=='\r'))
  579. p++;
  580. tok.s = p;
  581. tok.len = in.len + (int)(in.s - p);
  582. LM_DBG("cname: [%.*s] url: [%.*s]\n", name.len, name.s, tok.len, tok.s);
  583. return sql_init_con(&name, &tok);
  584. error:
  585. LM_ERR("invalid sqlops parameter [%.*s] at [%d]\n", in.len, in.s,
  586. (int)(p-in.s));
  587. return -1;
  588. }
  589. void sql_destroy(void)
  590. {
  591. sql_result_t *r;
  592. sql_result_t *r0;
  593. sql_disconnect();
  594. r=_sql_result_root;
  595. while(r)
  596. {
  597. r0 = r->next;
  598. sql_reset_result(r);
  599. pkg_free(r);
  600. r = r0;
  601. }
  602. }
  603. /**
  604. *
  605. */
  606. int sqlops_do_query(str *scon, str *squery, str *sres)
  607. {
  608. sql_con_t *con = NULL;
  609. sql_result_t *res = NULL;
  610. con = sql_get_connection(scon);
  611. if(con==NULL)
  612. {
  613. LM_ERR("invalid connection [%.*s]\n", scon->len, scon->s);
  614. goto error;
  615. }
  616. res = sql_get_result(sres);
  617. if(res==NULL)
  618. {
  619. LM_ERR("invalid result [%.*s]\n", sres->len, sres->s);
  620. goto error;
  621. }
  622. if(sql_do_query(con, squery, res)<0)
  623. goto error;
  624. return 0;
  625. error:
  626. return -1;
  627. }
  628. /**
  629. *
  630. */
  631. int sqlops_get_value(str *sres, int i, int j, sql_val_t **val)
  632. {
  633. sql_result_t *res = NULL;
  634. res = sql_get_result(sres);
  635. if(res==NULL)
  636. {
  637. LM_ERR("invalid result [%.*s]\n", sres->len, sres->s);
  638. goto error;
  639. }
  640. if(i>=res->nrows)
  641. {
  642. LM_ERR("row index out of bounds [%d/%d]\n", i, res->nrows);
  643. goto error;
  644. }
  645. if(j>=res->ncols)
  646. {
  647. LM_ERR("column index out of bounds [%d/%d]\n", j, res->ncols);
  648. goto error;
  649. }
  650. *val = &res->vals[i][j];
  651. return 0;
  652. error:
  653. return -1;
  654. }
  655. /**
  656. *
  657. */
  658. int sqlops_is_null(str *sres, int i, int j)
  659. {
  660. sql_result_t *res = NULL;
  661. res = sql_get_result(sres);
  662. if(res==NULL)
  663. {
  664. LM_ERR("invalid result [%.*s]\n", sres->len, sres->s);
  665. goto error;
  666. }
  667. if(i>=res->nrows)
  668. {
  669. LM_ERR("row index out of bounds [%d/%d]\n", i, res->nrows);
  670. goto error;
  671. }
  672. if(i>=res->ncols)
  673. {
  674. LM_ERR("column index out of bounds [%d/%d]\n", j, res->ncols);
  675. goto error;
  676. }
  677. if(res->vals[i][j].flags&PV_VAL_NULL)
  678. return 1;
  679. return 0;
  680. error:
  681. return -1;
  682. }
  683. /**
  684. *
  685. */
  686. int sqlops_get_column(str *sres, int i, str *col)
  687. {
  688. sql_result_t *res = NULL;
  689. res = sql_get_result(sres);
  690. if(res==NULL)
  691. {
  692. LM_ERR("invalid result [%.*s]\n", sres->len, sres->s);
  693. goto error;
  694. }
  695. if(i>=res->ncols)
  696. {
  697. LM_ERR("column index out of bounds [%d/%d]\n", i, res->ncols);
  698. goto error;
  699. }
  700. *col = res->cols[i].name;
  701. return 0;
  702. error:
  703. return -1;
  704. }
  705. /**
  706. *
  707. */
  708. int sqlops_num_columns(str *sres)
  709. {
  710. sql_result_t *res = NULL;
  711. res = sql_get_result(sres);
  712. if(res==NULL)
  713. {
  714. LM_ERR("invalid result [%.*s]\n", sres->len, sres->s);
  715. goto error;
  716. }
  717. return res->ncols;
  718. error:
  719. return -1;
  720. }
  721. /**
  722. *
  723. */
  724. int sqlops_num_rows(str *sres)
  725. {
  726. sql_result_t *res = NULL;
  727. res = sql_get_result(sres);
  728. if(res==NULL)
  729. {
  730. LM_ERR("invalid result [%.*s]\n", sres->len, sres->s);
  731. goto error;
  732. }
  733. return res->nrows;
  734. error:
  735. return -1;
  736. }
  737. /**
  738. *
  739. */
  740. void sqlops_reset_result(str *sres)
  741. {
  742. sql_result_t *res = NULL;
  743. res = sql_get_result(sres);
  744. if(res==NULL)
  745. {
  746. LM_ERR("invalid result [%.*s]\n", sres->len, sres->s);
  747. return;
  748. }
  749. sql_reset_result(res);
  750. return;
  751. }
  752. /**
  753. *
  754. */
  755. int sqlops_do_xquery(sip_msg_t *msg, str *scon, str *squery, str *xavp)
  756. {
  757. sql_con_t *con = NULL;
  758. con = sql_get_connection(scon);
  759. if(con==NULL)
  760. {
  761. LM_ERR("invalid connection [%.*s]\n", scon->len, scon->s);
  762. goto error;
  763. }
  764. if(sql_exec_xquery(msg, con, squery, xavp)<0)
  765. goto error;
  766. return 0;
  767. error:
  768. return -1;
  769. }