km_bdb_res.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555
  1. /*
  2. * $Id$
  3. *
  4. * db_berkeley module, portions of this code were templated using
  5. * the dbtext and postgres modules.
  6. * Copyright (C) 2007 Cisco Systems
  7. *
  8. * This file is part of SIP-router, a free SIP server.
  9. *
  10. * SIP-router is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License as published by
  12. * the Free Software Foundation; either version 2 of the License, or
  13. * (at your option) any later version
  14. *
  15. * SIP-router is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with this program; if not, write to the Free Software
  22. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  23. *
  24. * History:
  25. * --------
  26. * 2007-09-19 genesis (wiquan)
  27. */
  28. /*! \file
  29. * Berkeley DB :
  30. *
  31. * \ingroup database
  32. */
  33. #include <stdio.h>
  34. #include <string.h>
  35. #include <sys/types.h>
  36. #include "../../mem/mem.h"
  37. #include "km_bdb_res.h"
  38. int bdb_get_columns(table_p _tp, db1_res_t* _res, int* _lres, int _nc)
  39. {
  40. int col;
  41. if (!_res) {
  42. LM_ERR("invalid parameter\n");
  43. return -1;
  44. }
  45. if (_nc < 0 ) {
  46. LM_ERR("_nc parameter cannot be negative \n");
  47. return -1;
  48. }
  49. /* the number of rows (tuples) in the query result. */
  50. RES_NUM_ROWS(_res) = 1;
  51. if (!_lres)
  52. _nc = _tp->ncols;
  53. /* Save number of columns in the result structure */
  54. RES_COL_N(_res) = _nc;
  55. if (db_allocate_columns(_res, RES_COL_N(_res)) != 0) {
  56. LM_ERR("could not allocate columns");
  57. return -2;
  58. }
  59. /*
  60. * For each column both the name and the data type are saved.
  61. */
  62. for(col = 0; col < RES_COL_N(_res); col++) {
  63. column_p cp = NULL;
  64. cp = (_lres) ? _tp->colp[_lres[col]] : _tp->colp[col];
  65. RES_NAMES(_res)[col] = (str*)pkg_malloc(sizeof(str));
  66. if (! RES_NAMES(_res)[col]) {
  67. LM_ERR("no private memory left\n");
  68. db_free_columns(_res);
  69. return -3;
  70. }
  71. LM_DBG("allocate %lu bytes for RES_NAMES[%d] at %p\n",
  72. (unsigned long)sizeof(str), col, RES_NAMES(_res)[col]);
  73. /* The pointer that is here returned is part of the result structure. */
  74. RES_NAMES(_res)[col]->s = cp->name.s;
  75. RES_NAMES(_res)[col]->len = cp->name.len;
  76. LM_DBG("RES_NAMES(%p)[%d]=[%.*s]\n", RES_NAMES(_res)[col]
  77. , col, RES_NAMES(_res)[col]->len, RES_NAMES(_res)[col]->s);
  78. RES_TYPES(_res)[col] = cp->type;
  79. }
  80. return 0;
  81. }
  82. /**
  83. * Convert rows from Berkeley DB to db API representation
  84. */
  85. int bdb_convert_row(db1_res_t* _res, char *bdb_result, int* _lres)
  86. {
  87. int col, len, i, j;
  88. char **row_buf, *s;
  89. db_row_t* row = NULL;
  90. col = len = i = j = 0;
  91. if (!_res) {
  92. LM_ERR("invalid parameter\n");
  93. return -1;
  94. }
  95. /* Allocate a single row structure */
  96. len = sizeof(db_row_t);
  97. row = (db_row_t*)pkg_malloc(len);
  98. if (!row) {
  99. LM_ERR("no private memory left\n");
  100. return -1;
  101. }
  102. LM_DBG("allocate %d bytes for row %p\n", len, row);
  103. memset(row, 0, len);
  104. RES_ROWS(_res) = row;
  105. /* Save the number of rows in the current fetch */
  106. RES_ROW_N(_res) = 1;
  107. if (db_allocate_row(_res, row) != 0) {
  108. LM_ERR("could not allocate row");
  109. return -2;
  110. }
  111. /*
  112. * Allocate an array of pointers one per column.
  113. * It that will be used to hold the address of the string representation of each column.
  114. */
  115. len = sizeof(char *) * RES_COL_N(_res);
  116. row_buf = (char **)pkg_malloc(len);
  117. if (!row_buf) {
  118. LM_ERR("no private memory left\n");
  119. return -1;
  120. }
  121. LM_DBG("allocate for %d columns %d bytes in row buffer at %p\n", RES_COL_N(_res), len, row_buf);
  122. memset(row_buf, 0, len);
  123. /*populate the row_buf with bdb_result*/
  124. /*bdb_result is memory from our callers stack so we copy here*/
  125. s = strtok(bdb_result, DELIM);
  126. while( s!=NULL)
  127. {
  128. if(_lres) {
  129. /*only requested cols (_c was specified)*/
  130. for(i=0; i<ROW_N(row); i++)
  131. { if (col == _lres[i]) {
  132. len = strlen(s);
  133. row_buf[i] = pkg_malloc(len+1);
  134. if (!row_buf[i]) {
  135. LM_ERR("no private memory left\n");
  136. return -1;
  137. }
  138. LM_DBG("allocated %d bytes for row_buf[%d] at %p\n", len, i, row_buf[i]);
  139. memset(row_buf[i], 0, len+1);
  140. strncpy(row_buf[i], s, len);
  141. }
  142. }
  143. }
  144. else {
  145. len = strlen(s);
  146. row_buf[col] = pkg_malloc(len+1);
  147. if (!row_buf[col]) {
  148. LM_ERR("no private memory left\n");
  149. return -1;
  150. }
  151. LM_DBG("allocated %d bytes for row_buf[%d] at %p\n", len, col, row_buf[col]);
  152. memset(row_buf[col], 0, len+1);
  153. strncpy(row_buf[col], s, len);
  154. }
  155. s = strtok(NULL, DELIM);
  156. col++;
  157. }
  158. /*do the type conversion per col*/
  159. for(col = 0; col < ROW_N(row); col++) {
  160. /*skip the unrequested cols (as already specified)*/
  161. if(!row_buf[col]) continue;
  162. /* Convert the string representation into the value representation */
  163. if (bdb_str2val(RES_TYPES(_res)[col], &(ROW_VALUES(row)[col])
  164. , row_buf[col], strlen(row_buf[col])) < 0) {
  165. LM_ERR("while converting value\n");
  166. LM_DBG("freeing row at %p\n", row);
  167. db_free_row(row);
  168. return -3;
  169. }
  170. }
  171. /* pkg_free() must be done for the above allocations now that the row has been converted.
  172. * During bdb_convert_row (and subsequent bdb_str2val) processing, data types that don't need to be
  173. * converted (namely STRINGS) have their addresses saved. These data types should not have
  174. * their pkg_malloc() allocations freed here because they are still needed. However, some data types
  175. * (ex: INT, DOUBLE) should have their pkg_malloc() allocations freed because during the conversion
  176. * process, their converted values are saved in the union portion of the db_val_t structure.
  177. *
  178. * Warning: when the converted row is no longer needed, the data types whose addresses
  179. * were saved in the db_val_t structure must be freed or a memory leak will happen.
  180. * This processing should happen in the db_free_row() subroutine. The caller of
  181. * this routine should ensure that db_free_rows(), db_free_row() or db_free_result()
  182. * is eventually called.
  183. */
  184. for (col = 0; col < RES_COL_N(_res); col++) {
  185. switch (RES_TYPES(_res)[col])
  186. {
  187. case DB1_STRING:
  188. case DB1_STR:
  189. break;
  190. default:
  191. LM_DBG("col[%d] Col[%.*s] Type[%d] Freeing row_buf[%p]\n", col
  192. , RES_NAMES(_res)[col]->len, RES_NAMES(_res)[col]->s,
  193. RES_TYPES(_res)[col], row_buf[col]);
  194. LM_DBG("freeing row_buf[%d] at %p\n", col, row_buf[col]);
  195. pkg_free(row_buf[col]);
  196. }
  197. /* The following housekeeping may not be technically required, but it is a good practice
  198. * to NULL pointer fields that are no longer valid. Note that DB1_STRING fields have not
  199. * been pkg_free(). NULLing DB1_STRING fields would normally not be good to do because a memory
  200. * leak would occur. However, the pg_convert_row() routine has saved the DB1_STRING pointer
  201. * in the db_val_t structure. The db_val_t structure will eventually be used to pkg_free()
  202. * the DB1_STRING storage.
  203. */
  204. row_buf[col] = (char *)NULL;
  205. }
  206. LM_DBG("freeing row buffer at %p\n", row_buf);
  207. pkg_free(row_buf);
  208. row_buf = NULL;
  209. return 0;
  210. }
  211. /*rx is row index*/
  212. int bdb_append_row(db1_res_t* _res, char *bdb_result, int* _lres, int _rx)
  213. {
  214. int col, len, i, j;
  215. char **row_buf, *s;
  216. db_row_t* row = NULL;
  217. col = len = i = j = 0;
  218. if (!_res) {
  219. LM_ERR("invalid parameter");
  220. return -1;
  221. }
  222. row = &(RES_ROWS(_res)[_rx]);
  223. if (db_allocate_row(_res, row) != 0) {
  224. LM_ERR("could not allocate row");
  225. return -2;
  226. }
  227. /*
  228. * Allocate an array of pointers one per column.
  229. * It that will be used to hold the address of the string representation of each column.
  230. */
  231. len = sizeof(char *) * RES_COL_N(_res);
  232. row_buf = (char **)pkg_malloc(len);
  233. if (!row_buf) {
  234. LM_ERR("no private memory left\n");
  235. return -1;
  236. }
  237. LM_DBG("allocate for %d columns %d bytes in row buffer at %p\n", RES_COL_N(_res), len, row_buf);
  238. memset(row_buf, 0, len);
  239. /*populate the row_buf with bdb_result*/
  240. /*bdb_result is memory from our callers stack so we copy here*/
  241. s = strtok(bdb_result, DELIM);
  242. while( s!=NULL)
  243. {
  244. if(_lres) {
  245. /*only requested cols (_c was specified)*/
  246. for(i=0; i<ROW_N(row); i++) {
  247. if (col == _lres[i]) {
  248. len = strlen(s);
  249. row_buf[i] = pkg_malloc(len+1);
  250. if (!row_buf[i]) {
  251. LM_ERR("no private memory left\n");
  252. return -1;
  253. }
  254. memset(row_buf[i], 0, len+1);
  255. strncpy(row_buf[i], s, len);
  256. }
  257. }
  258. }
  259. else {
  260. len = strlen(s);
  261. #ifdef BDB_EXTRA_DEBUG
  262. LM_DBG("col[%i] = [%.*s]\n", col , len, s );
  263. #endif
  264. row_buf[col] = (char*)pkg_malloc(len+1);
  265. if (!row_buf[col]) {
  266. LM_ERR("no private memory left\n");
  267. return -1;
  268. }
  269. memset(row_buf[col], 0, len+1);
  270. strncpy(row_buf[col], s, len);
  271. }
  272. s = strtok(NULL, DELIM);
  273. col++;
  274. }
  275. /*do the type conversion per col*/
  276. for(col = 0; col < ROW_N(row); col++) {
  277. #ifdef BDB_EXTRA_DEBUG
  278. LM_DBG("tc 1: col[%i] == ", col );
  279. #endif
  280. /*skip the unrequested cols (as already specified)*/
  281. if(!row_buf[col]) continue;
  282. #ifdef BDB_EXTRA_DEBUG
  283. LM_DBG("tc 2: col[%i] \n", col );
  284. #endif
  285. /* Convert the string representation into the value representation */
  286. if (bdb_str2val(RES_TYPES(_res)[col], &(ROW_VALUES(row)[col])
  287. , row_buf[col], strlen(row_buf[col])) < 0) {
  288. LM_ERR("while converting value\n");
  289. LM_DBG("freeing row at %p\n", row);
  290. db_free_row(row);
  291. return -3;
  292. }
  293. }
  294. /* pkg_free() must be done for the above allocations now that the row has been converted.
  295. * During bdb_convert_row (and subsequent bdb_str2val) processing, data types that don't need to be
  296. * converted (namely STRINGS) have their addresses saved. These data types should not have
  297. * their pkg_malloc() allocations freed here because they are still needed. However, some data types
  298. * (ex: INT, DOUBLE) should have their pkg_malloc() allocations freed because during the conversion
  299. * process, their converted values are saved in the union portion of the db_val_t structure.
  300. *
  301. * Warning: when the converted row is no longer needed, the data types whose addresses
  302. * were saved in the db_val_t structure must be freed or a memory leak will happen.
  303. * This processing should happen in the db_free_row() subroutine. The caller of
  304. * this routine should ensure that db_free_rows(), db_free_row() or db_free_result()
  305. * is eventually called.
  306. */
  307. for (col = 0; col < RES_COL_N(_res); col++) {
  308. if (RES_TYPES(_res)[col] != DB1_STRING) {
  309. LM_DBG("col[%d] Col[%.*s] Type[%d] Freeing row_buf[%p]\n", col
  310. , RES_NAMES(_res)[col]->len, RES_NAMES(_res)[col]->s,
  311. RES_TYPES(_res)[col], row_buf[col]);
  312. LM_DBG("freeing row_buf[%d] at %p\n", col, row_buf[col]);
  313. pkg_free(row_buf[col]);
  314. }
  315. /* The following housekeeping may not be technically required, but it is a good practice
  316. * to NULL pointer fields that are no longer valid. Note that DB1_STRING fields have not
  317. * been pkg_free(). NULLing DB1_STRING fields would normally not be good to do because a memory
  318. * leak would occur. However, the pg_convert_row() routine has saved the DB1_STRING pointer
  319. * in the db_val_t structure. The db_val_t structure will eventually be used to pkg_free()
  320. * the DB1_STRING storage.
  321. */
  322. row_buf[col] = (char *)NULL;
  323. }
  324. LM_DBG("freeing row buffer at %p\n", row_buf);
  325. pkg_free(row_buf);
  326. row_buf = NULL;
  327. return 0;
  328. }
  329. int* bdb_get_colmap(table_p _dtp, db_key_t* _k, int _n)
  330. {
  331. int i, j, *_lref=NULL;
  332. if(!_dtp || !_k || _n < 0)
  333. return NULL;
  334. _lref = (int*)pkg_malloc(_n*sizeof(int));
  335. if(!_lref)
  336. return NULL;
  337. for(i=0; i < _n; i++)
  338. {
  339. for(j=0; j<_dtp->ncols; j++) {
  340. if(_k[i]->len==_dtp->colp[j]->name.len
  341. && !strncasecmp(_k[i]->s, _dtp->colp[j]->name.s,
  342. _dtp->colp[j]->name.len)) {
  343. _lref[i] = j;
  344. break;
  345. }
  346. }
  347. if(i>=_dtp->ncols) {
  348. LM_DBG("ERROR column <%.*s> not found\n", _k[i]->len, _k[i]->s);
  349. pkg_free(_lref);
  350. return NULL;
  351. }
  352. }
  353. return _lref;
  354. }
  355. int bdb_is_neq_type(db_type_t _t0, db_type_t _t1)
  356. {
  357. if(_t0 == _t1) return 0;
  358. switch(_t1)
  359. {
  360. case DB1_INT:
  361. if(_t0==DB1_DATETIME || _t0==DB1_BITMAP)
  362. return 0;
  363. case DB1_BIGINT:
  364. LM_ERR("BIGINT not supported");
  365. return 0;
  366. case DB1_DATETIME:
  367. if(_t0==DB1_INT)
  368. return 0;
  369. if(_t0==DB1_BITMAP)
  370. return 0;
  371. case DB1_DOUBLE:
  372. break;
  373. case DB1_STRING:
  374. if(_t0==DB1_STR)
  375. return 0;
  376. case DB1_STR:
  377. if(_t0==DB1_STRING || _t0==DB1_BLOB)
  378. return 0;
  379. case DB1_BLOB:
  380. if(_t0==DB1_STR)
  381. return 0;
  382. case DB1_BITMAP:
  383. if (_t0==DB1_INT)
  384. return 0;
  385. }
  386. return 1;
  387. }
  388. /*
  389. */
  390. int bdb_row_match(db_key_t* _k, db_op_t* _op, db_val_t* _v, int _n, db1_res_t* _r, int* _lkey )
  391. {
  392. int i, res;
  393. db_row_t* row = NULL;
  394. if(!_r || !_lkey)
  395. return 1;
  396. row = RES_ROWS(_r);
  397. for(i=0; i<_n; i++) {
  398. res = bdb_cmp_val(&(ROW_VALUES(row)[_lkey[i]]), &_v[i]);
  399. if(!_op || !strcmp(_op[i], OP_EQ)) {
  400. if(res!=0)
  401. return 0;
  402. } else {
  403. if(!strcmp(_op[i], OP_LT)) {
  404. if(res!=-1)
  405. return 0;
  406. } else {
  407. if(!strcmp(_op[i], OP_GT)) {
  408. if(res!=1)
  409. return 0;
  410. } else {
  411. if(!strcmp(_op[i], OP_LEQ)) {
  412. if(res==1)
  413. return 0;
  414. } else {
  415. if(!strcmp(_op[i], OP_GEQ)) {
  416. if(res==-1)
  417. return 0;
  418. } else {
  419. return res;
  420. }}}}}
  421. }
  422. return 1;
  423. }
  424. /*
  425. */
  426. int bdb_cmp_val(db_val_t* _vp, db_val_t* _v)
  427. {
  428. int _l, _n;
  429. if(!_vp && !_v)
  430. return 0;
  431. if(!_v)
  432. return 1;
  433. if(!_vp)
  434. return -1;
  435. if(_vp->nul && _v->nul)
  436. return 0;
  437. if(_v->nul)
  438. return 1;
  439. if(_vp->nul)
  440. return -1;
  441. switch(VAL_TYPE(_v))
  442. {
  443. case DB1_INT:
  444. return (_vp->val.int_val<_v->val.int_val)?-1:
  445. (_vp->val.int_val>_v->val.int_val)?1:0;
  446. case DB1_BIGINT:
  447. LM_ERR("BIGINT not supported");
  448. return -1;
  449. case DB1_DOUBLE:
  450. return (_vp->val.double_val<_v->val.double_val)?-1:
  451. (_vp->val.double_val>_v->val.double_val)?1:0;
  452. case DB1_DATETIME:
  453. return (_vp->val.int_val<_v->val.time_val)?-1:
  454. (_vp->val.int_val>_v->val.time_val)?1:0;
  455. case DB1_STRING:
  456. _l = strlen(_v->val.string_val);
  457. _l = (_l>_vp->val.str_val.len)?_vp->val.str_val.len:_l;
  458. _n = strncasecmp(_vp->val.str_val.s, _v->val.string_val, _l);
  459. if(_n)
  460. return _n;
  461. if(_vp->val.str_val.len == strlen(_v->val.string_val))
  462. return 0;
  463. if(_l==_vp->val.str_val.len)
  464. return -1;
  465. return 1;
  466. case DB1_STR:
  467. _l = _v->val.str_val.len;
  468. _l = (_l>_vp->val.str_val.len)?_vp->val.str_val.len:_l;
  469. _n = strncasecmp(_vp->val.str_val.s, _v->val.str_val.s, _l);
  470. if(_n)
  471. return _n;
  472. if(_vp->val.str_val.len == _v->val.str_val.len)
  473. return 0;
  474. if(_l==_vp->val.str_val.len)
  475. return -1;
  476. return 1;
  477. case DB1_BLOB:
  478. _l = _v->val.blob_val.len;
  479. _l = (_l>_vp->val.str_val.len)?_vp->val.str_val.len:_l;
  480. _n = strncasecmp(_vp->val.str_val.s, _v->val.blob_val.s, _l);
  481. if(_n)
  482. return _n;
  483. if(_vp->val.str_val.len == _v->val.blob_val.len)
  484. return 0;
  485. if(_l==_vp->val.str_val.len)
  486. return -1;
  487. return 1;
  488. case DB1_BITMAP:
  489. return (_vp->val.int_val<_v->val.bitmap_val)?-1:
  490. (_vp->val.int_val>_v->val.bitmap_val)?1:0;
  491. }
  492. return -2;
  493. }