db_ut.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502
  1. /*
  2. * $Id$
  3. *
  4. * Copyright (C) 2001-2003 FhG Fokus
  5. * Copyright (C) 2007-2008 1&1 Internet AG
  6. *
  7. * This file is part of Kamailio, a free SIP server.
  8. *
  9. * Kamailio is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation; either version 2 of the License, or
  12. * (at your option) any later version
  13. *
  14. * Kamailio is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. */
  23. /**
  24. * \file lib/srdb1/db_ut.c
  25. * \brief Utility functions for database drivers.
  26. *
  27. * This utility methods are used from the database SQL driver to convert
  28. * values and print SQL queries from the internal API representation.
  29. * \ingroup db1
  30. */
  31. #if defined (__OS_darwin) || defined (__OS_freebsd)
  32. #include "../../pvar.h"
  33. #endif
  34. /**
  35. * make strptime available
  36. * use 600 for 'Single UNIX Specification, Version 3'
  37. * _XOPEN_SOURCE creates conflict in swab definition in Solaris
  38. */
  39. #ifndef __OS_solaris
  40. #define _XOPEN_SOURCE 600 /* glibc2 on linux, bsd */
  41. #define _BSD_SOURCE 1 /* needed on linux to "fix" the effect
  42. of the above define on
  43. features.h/unistd.h syscall() */
  44. #else
  45. #define _XOPEN_SOURCE_EXTENDED 1 /* solaris */
  46. #endif
  47. #include <time.h>
  48. #ifndef __OS_solaris
  49. #undef _XOPEN_SOURCE
  50. #undef _XOPEN_SOURCE_EXTENDED
  51. #else
  52. #undef _XOPEN_SOURCE_EXTENDED 1 /* solaris */
  53. #endif
  54. #include <limits.h>
  55. #include <errno.h>
  56. #include <stdio.h>
  57. #include <stdlib.h>
  58. #include <string.h>
  59. #include "../../mem/mem.h"
  60. #include "../../dprint.h"
  61. #include "db_ut.h"
  62. inline int db_str2int(const char* _s, int* _v)
  63. {
  64. long tmp;
  65. char* p = NULL;
  66. if (!_s || !_v) {
  67. LM_ERR("Invalid parameter value\n");
  68. return -1;
  69. }
  70. tmp = strtoul(_s, &p, 10);
  71. if ((tmp == ULONG_MAX && errno == ERANGE) ||
  72. (tmp < INT_MIN) || (tmp > UINT_MAX)) {
  73. LM_ERR("Value out of range\n");
  74. return -1;
  75. }
  76. if (p && *p != '\0') {
  77. LM_ERR("Unexpected characters: [%s]\n", p);
  78. return -2;
  79. }
  80. *_v = (int)tmp;
  81. return 0;
  82. }
  83. inline int db_str2longlong(const char* _s, long long * _v)
  84. {
  85. long long tmp;
  86. char* p = NULL;
  87. if (!_s || !_v) {
  88. LM_ERR("Invalid parameter value\n");
  89. return -1;
  90. }
  91. tmp = strtoll(_s, &p, 10);
  92. if (errno == ERANGE) {
  93. LM_ERR("Value out of range\n");
  94. return -1;
  95. }
  96. if (p && *p != '\0') {
  97. LM_ERR("Unexpected characters: [%s]\n", p);
  98. return -2;
  99. }
  100. *_v = tmp;
  101. return 0;
  102. }
  103. /*
  104. * Convert a string to double
  105. */
  106. inline int db_str2double(const char* _s, double* _v)
  107. {
  108. if ((!_s) || (!_v)) {
  109. LM_ERR("Invalid parameter value\n");
  110. return -1;
  111. }
  112. *_v = atof(_s);
  113. return 0;
  114. }
  115. /*
  116. * Convert an integer to string
  117. */
  118. inline int db_int2str(int _v, char* _s, int* _l)
  119. {
  120. int ret;
  121. if ((!_s) || (!_l) || (!*_l)) {
  122. LM_ERR("Invalid parameter value\n");
  123. return -1;
  124. }
  125. ret = snprintf(_s, *_l, "%-d", _v);
  126. if (ret < 0 || ret >= *_l) {
  127. LM_ERR("Error in snprintf\n");
  128. return -1;
  129. }
  130. *_l = ret;
  131. return 0;
  132. }
  133. /*
  134. * Convert an long long to string
  135. */
  136. inline int db_longlong2str(long long _v, char* _s, int* _l)
  137. {
  138. int ret;
  139. if ((!_s) || (!_l) || (!*_l)) {
  140. LM_ERR("Invalid parameter value\n");
  141. return -1;
  142. }
  143. ret = snprintf(_s, *_l, "%-lld", _v);
  144. if (ret < 0 || ret >= *_l) {
  145. LM_ERR("Error in snprintf\n");
  146. return -1;
  147. }
  148. *_l = ret;
  149. return 0;
  150. }
  151. /*
  152. * Convert a double to string
  153. */
  154. inline int db_double2str(double _v, char* _s, int* _l)
  155. {
  156. int ret;
  157. if ((!_s) || (!_l) || (!*_l)) {
  158. LM_ERR("Invalid parameter value\n");
  159. return -1;
  160. }
  161. ret = snprintf(_s, *_l, "%-10.2f", _v);
  162. if (ret < 0 || ret >= *_l) {
  163. LM_ERR("Error in snprintf\n");
  164. return -1;
  165. }
  166. *_l = ret;
  167. return 0;
  168. }
  169. /*
  170. * Convert a string to time_t
  171. */
  172. inline int db_str2time(const char* _s, time_t* _v)
  173. {
  174. struct tm time;
  175. if ((!_s) || (!_v)) {
  176. LM_ERR("Invalid parameter value\n");
  177. return -1;
  178. }
  179. /* Convert database time representation to time_t structure
  180. It is necessary to zero tm structure first */
  181. memset(&time, '\0', sizeof(struct tm));
  182. if (strptime(_s, "%Y-%m-%d %H:%M:%S", &time) == NULL) {
  183. LM_ERR("Error during time conversion\n");
  184. return -1;
  185. }
  186. /* Daylight saving information got lost in the database
  187. * so let mktime to guess it. This eliminates the bug when
  188. * contacts reloaded from the database have different time
  189. * of expiration by one hour when daylight saving is used
  190. */
  191. time.tm_isdst = -1;
  192. *_v = mktime(&time);
  193. return 0;
  194. }
  195. inline int db_time2str(time_t _v, char* _s, int* _l)
  196. {
  197. struct tm* t;
  198. int l;
  199. if ((!_s) || (!_l) || (*_l < 2)) {
  200. LM_ERR("Invalid parameter value\n");
  201. return -1;
  202. }
  203. *_s++ = '\'';
  204. /* Convert time_t structure to format accepted by the database */
  205. t = localtime(&_v);
  206. l = strftime(_s, *_l -1, "%Y-%m-%d %H:%M:%S", t);
  207. if (l == 0) {
  208. LM_ERR("Error during time conversion\n");
  209. /* the value of _s is now unspecified */
  210. _s = NULL;
  211. _l = 0;
  212. return -1;
  213. }
  214. *_l = l;
  215. *(_s + l) = '\'';
  216. *_l = l + 2;
  217. return 0;
  218. }
  219. /*
  220. * Print list of columns separated by comma
  221. */
  222. inline int db_print_columns(char* _b, const int _l, const db_key_t* _c, const int _n)
  223. {
  224. int i, ret, len = 0;
  225. if ((!_c) || (!_n) || (!_b) || (!_l)) {
  226. LM_ERR("Invalid parameter value\n");
  227. return -1;
  228. }
  229. for(i = 0; i < _n; i++) {
  230. if (i == (_n - 1)) {
  231. ret = snprintf(_b + len, _l - len, "%.*s ", _c[i]->len, _c[i]->s);
  232. if (ret < 0 || ret >= (_l - len)) goto error;
  233. len += ret;
  234. } else {
  235. ret = snprintf(_b + len, _l - len, "%.*s,", _c[i]->len, _c[i]->s);
  236. if (ret < 0 || ret >= (_l - len)) goto error;
  237. len += ret;
  238. }
  239. }
  240. return len;
  241. error:
  242. LM_ERR("Error in snprintf\n");
  243. return -1;
  244. }
  245. /*
  246. * Print values of SQL statement
  247. */
  248. int db_print_values(const db1_con_t* _c, char* _b, const int _l, const db_val_t* _v,
  249. const int _n, int (*val2str)(const db1_con_t*, const db_val_t*, char*, int*))
  250. {
  251. int i, l, len = 0;
  252. if (!_c || !_b || !_l || !_v || !_n) {
  253. LM_ERR("Invalid parameter value\n");
  254. return -1;
  255. }
  256. for(i = 0; i < _n; i++) {
  257. l = _l - len;
  258. if ( (*val2str)(_c, _v + i, _b + len, &l) < 0) {
  259. LM_ERR("Error while converting value to string\n");
  260. return -1;
  261. }
  262. len += l;
  263. if (i != (_n - 1)) {
  264. *(_b + len) = ',';
  265. len++;
  266. }
  267. }
  268. return len;
  269. }
  270. /*
  271. * Print where clause of SQL statement
  272. */
  273. int db_print_where(const db1_con_t* _c, char* _b, const int _l, const db_key_t* _k,
  274. const db_op_t* _o, const db_val_t* _v, const int _n, int (*val2str)
  275. (const db1_con_t*, const db_val_t*, char*, int*))
  276. {
  277. int i, l, ret, len = 0;
  278. if (!_c || !_b || !_l || !_k || !_v || !_n) {
  279. LM_ERR("Invalid parameter value\n");
  280. return -1;
  281. }
  282. for(i = 0; i < _n; i++) {
  283. if (_o && strncmp(_o[i], OP_BITWISE_AND, 1) == 0) {
  284. char tmp_buf[16];
  285. int tmp_len = 15;
  286. memset(tmp_buf, '0', 16);
  287. if ((*val2str)(_c, &(_v[i]), tmp_buf, &tmp_len) < 0) {
  288. LM_ERR("Error while converting value to string\n");
  289. return -1;
  290. }
  291. ret = snprintf(_b + len, _l - len, "%.*s&%.*s=%.*s", _k[i]->len, _k[i]->s, tmp_len, tmp_buf, tmp_len, tmp_buf);
  292. if (ret < 0 || ret >= (_l - len)) goto error;
  293. len += ret;
  294. } else {
  295. if (_o) {
  296. ret = snprintf(_b + len, _l - len, "%.*s%s", _k[i]->len, _k[i]->s, _o[i]);
  297. if (ret < 0 || ret >= (_l - len)) goto error;
  298. len += ret;
  299. } else {
  300. ret = snprintf(_b + len, _l - len, "%.*s=", _k[i]->len, _k[i]->s);
  301. if (ret < 0 || ret >= (_l - len)) goto error;
  302. len += ret;
  303. }
  304. l = _l - len;
  305. if ( (*val2str)(_c, &(_v[i]), _b + len, &l) < 0) {
  306. LM_ERR("Error while converting value to string\n");
  307. return -1;
  308. }
  309. len += l;
  310. }
  311. if (i != (_n - 1)) {
  312. ret = snprintf(_b + len, _l - len, " AND ");
  313. if (ret < 0 || ret >= (_l - len)) goto error;
  314. len += ret;
  315. }
  316. }
  317. return len;
  318. error:
  319. LM_ERR("Error in snprintf\n");
  320. return -1;
  321. }
  322. /*
  323. * Print set clause of update SQL statement
  324. */
  325. int db_print_set(const db1_con_t* _c, char* _b, const int _l, const db_key_t* _k,
  326. const db_val_t* _v, const int _n, int (*val2str)(const db1_con_t*,
  327. const db_val_t*,char*, int*))
  328. {
  329. int i, l, ret, len = 0;
  330. if (!_c || !_b || !_l || !_k || !_v || !_n) {
  331. LM_ERR("Invalid parameter value\n");
  332. return -1;
  333. }
  334. for(i = 0; i < _n; i++) {
  335. ret = snprintf(_b + len, _l - len, "%.*s=", _k[i]->len, _k[i]->s);
  336. if (ret < 0 || ret >= (_l - len)) goto error;
  337. len += ret;
  338. l = _l - len;
  339. if ( (*val2str)(_c, &(_v[i]), _b + len, &l) < 0) {
  340. LM_ERR("Error while converting value to string\n");
  341. return -1;
  342. }
  343. len += l;
  344. if (i != (_n - 1)) {
  345. if ((_l - len) >= 1) {
  346. *(_b + len++) = ',';
  347. }
  348. }
  349. }
  350. return len;
  351. error:
  352. LM_ERR("Error in snprintf\n");
  353. return -1;
  354. }
  355. /*
  356. * Convert db_val to pv_spec
  357. */
  358. int db_val2pv_spec(struct sip_msg* msg, db_val_t *dbval, pv_spec_t *pvs)
  359. {
  360. pv_value_t pv;
  361. #define LL_LEN 21 /* sign, 19 digits and \0 */
  362. static char ll_buf[LL_LEN];
  363. if(dbval->nul)
  364. {
  365. pv.flags = PV_VAL_NULL;
  366. } else
  367. {
  368. switch(dbval->type)
  369. {
  370. case DB1_STRING:
  371. pv.flags = PV_VAL_STR;
  372. pv.rs.s = (char*)dbval->val.string_val;
  373. pv.rs.len = strlen(pv.rs.s);
  374. break;
  375. case DB1_STR:
  376. pv.flags = PV_VAL_STR;
  377. pv.rs.s = (char*)dbval->val.str_val.s;
  378. pv.rs.len = dbval->val.str_val.len;
  379. break;
  380. case DB1_BLOB:
  381. pv.flags = PV_VAL_STR;
  382. pv.rs.s = (char*)dbval->val.blob_val.s;
  383. pv.rs.len = dbval->val.blob_val.len;
  384. break;
  385. case DB1_INT:
  386. pv.flags = PV_VAL_INT | PV_TYPE_INT;
  387. pv.ri = (int)dbval->val.int_val;
  388. break;
  389. case DB1_DATETIME:
  390. pv.flags = PV_VAL_INT | PV_TYPE_INT;
  391. pv.ri = (int)dbval->val.time_val;
  392. break;
  393. case DB1_BITMAP:
  394. pv.flags = PV_VAL_INT | PV_TYPE_INT;
  395. pv.ri = (int)dbval->val.bitmap_val;
  396. break;
  397. case DB1_BIGINT:
  398. /* BIGINT is stored as string */
  399. pv.flags = PV_VAL_STR;
  400. pv.rs.len = LL_LEN;
  401. db_longlong2str(dbval->val.ll_val, ll_buf, &pv.rs.len);
  402. pv.rs.s = ll_buf;
  403. /* if it fits, also store as 32 bit integer*/
  404. if (! ((unsigned long long)dbval->val.ll_val & 0xffffffff00000000ULL)) {
  405. pv.flags |= PV_VAL_INT | PV_TYPE_INT;
  406. pv.ri = (int)dbval->val.ll_val;
  407. }
  408. break;
  409. default:
  410. LM_NOTICE("unknown field type: %d, setting value to null\n",
  411. dbval->type);
  412. pv.flags = PV_VAL_NULL;
  413. }
  414. }
  415. /* null values are ignored for avp type PV */
  416. if (pv.flags == PV_VAL_NULL && pvs->type == PVT_AVP)
  417. return 0;
  418. /* add value to result pv */
  419. if (pv_set_spec_value(msg, pvs, 0, &pv) != 0)
  420. {
  421. LM_ERR("Failed to add value to spec\n");
  422. return -1;
  423. }
  424. return 0;
  425. }