pg_sql.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424
  1. /*
  2. * $Id$
  3. *
  4. * PostgreSQL Database Driver for SER
  5. *
  6. * Portions Copyright (C) 2001-2003 FhG FOKUS
  7. * Copyright (C) 2003 August.Net Services, LLC
  8. * Portions Copyright (C) 2005-2008 iptelorg GmbH
  9. *
  10. * This file is part of SER, a free SIP server.
  11. *
  12. * SER is free software; you can redistribute it and/or modify it under the
  13. * terms of the GNU General Public License as published by the Free Software
  14. * Foundation; either version 2 of the License, or (at your option) any later
  15. * version
  16. *
  17. * For a license to use the ser software under conditions other than those
  18. * described here, or to purchase support for this software, please contact
  19. * iptel.org by e-mail at the following addresses: [email protected]
  20. *
  21. * SER is distributed in the hope that it will be useful, but WITHOUT ANY
  22. * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  23. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
  24. * details.
  25. *
  26. * You should have received a copy of the GNU General Public License along
  27. * with this program; if not, write to the Free Software Foundation, Inc., 59
  28. * Temple Place, Suite 330, Boston, MA 02111-1307 USA
  29. */
  30. /** \addtogroup postgres
  31. * @{
  32. */
  33. /** \file
  34. * Implementation of various functions that assemble SQL query strings for
  35. * PostgreSQL.
  36. */
  37. #include "pg_sql.h"
  38. #include "../../lib/srdb2/db_cmd.h"
  39. #include "../../lib/srdb2/db_fld.h"
  40. #include "../../mem/mem.h"
  41. #include "../../dprint.h"
  42. #include "../../ut.h"
  43. #include <string.h>
  44. enum {
  45. STR_DELETE,
  46. STR_INSERT,
  47. STR_UPDATE,
  48. STR_SELECT,
  49. STR_REPLACE,
  50. STR_SET,
  51. STR_WHERE,
  52. STR_IS,
  53. STR_AND,
  54. STR_OR,
  55. STR_ESC,
  56. STR_OP_EQ,
  57. STR_OP_NE,
  58. STR_OP_LT,
  59. STR_OP_GT,
  60. STR_OP_LEQ,
  61. STR_OP_GEQ,
  62. STR_VALUES,
  63. STR_FROM,
  64. STR_OID,
  65. STR_TIMESTAMP,
  66. STR_ZT
  67. };
  68. static str strings[] = {
  69. STR_STATIC_INIT("delete from "),
  70. STR_STATIC_INIT("insert into "),
  71. STR_STATIC_INIT("update "),
  72. STR_STATIC_INIT("select "),
  73. STR_STATIC_INIT("replace "),
  74. STR_STATIC_INIT(" set "),
  75. STR_STATIC_INIT(" where "),
  76. STR_STATIC_INIT(" is "),
  77. STR_STATIC_INIT(" and "),
  78. STR_STATIC_INIT(" or "),
  79. STR_STATIC_INIT("?"),
  80. STR_STATIC_INIT("="),
  81. STR_STATIC_INIT("!="),
  82. STR_STATIC_INIT("<"),
  83. STR_STATIC_INIT(">"),
  84. STR_STATIC_INIT("<="),
  85. STR_STATIC_INIT(">="),
  86. STR_STATIC_INIT(") values ("),
  87. STR_STATIC_INIT(" from "),
  88. STR_STATIC_INIT("select typname,pg_type.oid from pg_type"),
  89. STR_STATIC_INIT("select timestamp '2000-01-01 00:00:00' + time '00:00:01'"),
  90. STR_STATIC_INIT("\0")
  91. };
  92. /**
  93. * Reallocatable string buffer.
  94. */
  95. struct string_buffer {
  96. char *s; /**< allocated memory itself */
  97. int len; /**< used memory */
  98. int size; /**< total size of allocated memory */
  99. int increment; /**< increment when realloc is necessary */
  100. };
  101. /** Appends string to string buffer.
  102. * This function appends string to dynamically created string buffer,
  103. * the buffer is automatically extended if there is not enough room
  104. * in the buffer. The buffer is allocated using pkg_malloc.
  105. * @param sb string buffer
  106. * @param nstr string to add
  107. * @return 0 if OK, -1 if failed
  108. */
  109. static inline int sb_add(struct string_buffer *sb, str *nstr)
  110. {
  111. int new_size = 0;
  112. int rsize = sb->len + nstr->len;
  113. int asize;
  114. char *newp;
  115. if (rsize > sb->size) {
  116. asize = rsize - sb->size;
  117. new_size = sb->size + (asize / sb->increment +
  118. (asize % sb->increment > 0)) * sb->increment;
  119. newp = pkg_malloc(new_size);
  120. if (!newp) {
  121. ERR("postgres: No memory left\n");
  122. return -1;
  123. }
  124. if (sb->s) {
  125. memcpy(newp, sb->s, sb->len);
  126. pkg_free(sb->s);
  127. }
  128. sb->s = newp;
  129. sb->size = new_size;
  130. }
  131. memcpy(sb->s + sb->len, nstr->s, nstr->len);
  132. sb->len += nstr->len;
  133. return 0;
  134. }
  135. /** Creates str string from zero terminated string without copying.
  136. * This function initializes members of a temporary str structure
  137. * with the pointer and lenght of the string from s parameter.
  138. *
  139. * @param str A pointer to temporary str structure.
  140. * @param s A zero terminated string.
  141. * @return Pointer to the str structure.
  142. */
  143. static inline str* set_str(str *str, const char *s)
  144. {
  145. str->s = (char *)s;
  146. str->len = strlen(s);
  147. return str;
  148. }
  149. /** Returns a parameter marker for PostgreSQL with number i
  150. * The function builds a parameter marker for use in
  151. * PostgreSQL SQL queries, such as $1, $2, etc.
  152. * @param i Number of the parameter
  153. * @retval A pointer to static string with the marker
  154. */
  155. static str* get_marker(unsigned int i)
  156. {
  157. static char buf[INT2STR_MAX_LEN + 1];
  158. static str res;
  159. const char* c;
  160. buf[0] = '$';
  161. res.s = buf;
  162. c = int2str(i, &res.len);
  163. memcpy(res.s + 1, c, res.len);
  164. res.len++;
  165. return &res;
  166. }
  167. int build_update_sql(str* sql_cmd, db_cmd_t* cmd)
  168. {
  169. struct string_buffer sql_buf = {.s = NULL, .len = 0,
  170. .size = 0, .increment = 128};
  171. db_fld_t* fld;
  172. int i, rv = 0;
  173. str tmpstr;
  174. rv = sb_add(&sql_buf, &strings[STR_UPDATE]); /* "UPDATE " */
  175. rv |= sb_add(&sql_buf, set_str(&tmpstr, "\""));
  176. rv |= sb_add(&sql_buf, &cmd->table); /* table name */
  177. rv |= sb_add(&sql_buf, set_str(&tmpstr, "\""));
  178. rv |= sb_add(&sql_buf, &strings[STR_SET]); /* " SET " */
  179. /* column name-value pairs */
  180. for(i = 0, fld = cmd->vals; !DB_FLD_EMPTY(fld) && !DB_FLD_LAST(fld[i]); i++) {
  181. rv |= sb_add(&sql_buf, set_str(&tmpstr, fld[i].name));
  182. rv |= sb_add(&sql_buf, set_str(&tmpstr, "="));
  183. rv |= sb_add(&sql_buf, &strings[STR_ESC]);
  184. if (!DB_FLD_LAST(fld[i + 1])) rv |= sb_add(&sql_buf, set_str(&tmpstr, ","));
  185. }
  186. if (rv) goto error;
  187. if (!DB_FLD_EMPTY(cmd->match)) {
  188. rv |= sb_add(&sql_buf, &strings[STR_WHERE]);
  189. for(i = 0, fld = cmd->match; !DB_FLD_LAST(fld[i]); i++) {
  190. rv |= sb_add(&sql_buf, set_str(&tmpstr, fld[i].name));
  191. switch(fld[i].op) {
  192. case DB_EQ: rv |= sb_add(&sql_buf, &strings[STR_OP_EQ]); break;
  193. case DB_NE: rv |= sb_add(&sql_buf, &strings[STR_OP_NE]); break;
  194. case DB_LT: rv |= sb_add(&sql_buf, &strings[STR_OP_LT]); break;
  195. case DB_GT: rv |= sb_add(&sql_buf, &strings[STR_OP_GT]); break;
  196. case DB_LEQ: rv |= sb_add(&sql_buf, &strings[STR_OP_LEQ]); break;
  197. case DB_GEQ: rv |= sb_add(&sql_buf, &strings[STR_OP_GEQ]); break;
  198. }
  199. rv |= sb_add(&sql_buf, get_marker(i + 1));
  200. if (!DB_FLD_LAST(fld[i + 1])) rv |= sb_add(&sql_buf, &strings[STR_AND]);
  201. }
  202. }
  203. rv |= sb_add(&sql_buf, &strings[STR_ZT]);
  204. if (rv) goto error;
  205. sql_cmd->s = sql_buf.s;
  206. sql_cmd->len = sql_buf.len;
  207. return 0;
  208. error:
  209. if (sql_buf.s) pkg_free(sql_buf.s);
  210. return -1;
  211. }
  212. int build_insert_sql(str* sql_cmd, db_cmd_t* cmd)
  213. {
  214. struct string_buffer sql_buf = {.s = NULL, .len = 0,
  215. .size = 0, .increment = 128};
  216. db_fld_t* fld;
  217. int i, rv = 0;
  218. str tmpstr;
  219. rv = sb_add(&sql_buf, &strings[STR_INSERT]); /* "INSERT INTO " */
  220. rv |= sb_add(&sql_buf, set_str(&tmpstr, "\""));
  221. rv |= sb_add(&sql_buf, &cmd->table); /* table name */
  222. rv |= sb_add(&sql_buf, set_str(&tmpstr, "\" ("));
  223. /* column names */
  224. for(i = 0, fld = cmd->vals; !DB_FLD_EMPTY(fld) && !DB_FLD_LAST(fld[i]); i++) {
  225. rv |= sb_add(&sql_buf, set_str(&tmpstr, fld[i].name));
  226. if (!DB_FLD_LAST(fld[i + 1])) rv |= sb_add(&sql_buf, set_str(&tmpstr, ","));
  227. }
  228. if (rv) goto error;
  229. rv |= sb_add(&sql_buf, &strings[STR_VALUES]);
  230. for(i = 0, fld = cmd->vals; !DB_FLD_EMPTY(fld) && !DB_FLD_LAST(fld[i]); i++) {
  231. rv |= sb_add(&sql_buf, get_marker(i + 1));
  232. if (!DB_FLD_LAST(fld[i + 1])) rv |= sb_add(&sql_buf, set_str(&tmpstr, ","));
  233. }
  234. rv |= sb_add(&sql_buf, set_str(&tmpstr, ")"));
  235. rv |= sb_add(&sql_buf, &strings[STR_ZT]);
  236. if (rv) goto error;
  237. sql_cmd->s = sql_buf.s;
  238. sql_cmd->len = sql_buf.len;
  239. return 0;
  240. error:
  241. if (sql_buf.s) pkg_free(sql_buf.s);
  242. return -1;
  243. }
  244. int build_delete_sql(str* sql_cmd, db_cmd_t* cmd)
  245. {
  246. struct string_buffer sql_buf = {.s = NULL, .len = 0,
  247. .size = 0, .increment = 128};
  248. db_fld_t* fld;
  249. int i, rv = 0;
  250. str tmpstr;
  251. rv = sb_add(&sql_buf, &strings[STR_DELETE]); /* "DELETE FROM " */
  252. rv |= sb_add(&sql_buf, set_str(&tmpstr, "\""));
  253. rv |= sb_add(&sql_buf, &cmd->table); /* table name */
  254. rv |= sb_add(&sql_buf, set_str(&tmpstr, "\""));
  255. if (!DB_FLD_EMPTY(cmd->match)) {
  256. rv |= sb_add(&sql_buf, &strings[STR_WHERE]);
  257. for(i = 0, fld = cmd->match; !DB_FLD_LAST(fld[i]); i++) {
  258. rv |= sb_add(&sql_buf, set_str(&tmpstr, fld[i].name));
  259. switch(fld[i].op) {
  260. case DB_EQ: rv |= sb_add(&sql_buf, &strings[STR_OP_EQ]); break;
  261. case DB_NE: rv |= sb_add(&sql_buf, &strings[STR_OP_NE]); break;
  262. case DB_LT: rv |= sb_add(&sql_buf, &strings[STR_OP_LT]); break;
  263. case DB_GT: rv |= sb_add(&sql_buf, &strings[STR_OP_GT]); break;
  264. case DB_LEQ: rv |= sb_add(&sql_buf, &strings[STR_OP_LEQ]); break;
  265. case DB_GEQ: rv |= sb_add(&sql_buf, &strings[STR_OP_GEQ]); break;
  266. }
  267. rv |= sb_add(&sql_buf, get_marker(i + 1));
  268. if (!DB_FLD_LAST(fld[i + 1])) rv |= sb_add(&sql_buf, &strings[STR_AND]);
  269. }
  270. }
  271. rv |= sb_add(&sql_buf, &strings[STR_ZT]);
  272. if (rv) goto error;
  273. sql_cmd->s = sql_buf.s;
  274. sql_cmd->len = sql_buf.len;
  275. return 0;
  276. error:
  277. if (sql_buf.s) pkg_free(sql_buf.s);
  278. return -1;
  279. }
  280. int build_select_sql(str* sql_cmd, db_cmd_t* cmd)
  281. {
  282. struct string_buffer sql_buf = {.s = NULL, .len = 0,
  283. .size = 0, .increment = 128};
  284. db_fld_t* fld;
  285. int i, rv = 0;
  286. str tmpstr;
  287. rv = sb_add(&sql_buf, &strings[STR_SELECT]); /* "SELECT " */
  288. if (DB_FLD_EMPTY(cmd->result)) {
  289. rv |= sb_add(&sql_buf, set_str(&tmpstr, "*"));
  290. } else {
  291. for(i = 0, fld = cmd->result; !DB_FLD_LAST(fld[i]); i++) {
  292. rv |= sb_add(&sql_buf, set_str(&tmpstr, fld[i].name));
  293. if (!DB_FLD_LAST(fld[i + 1])) rv |= sb_add(&sql_buf, set_str(&tmpstr, ","));
  294. }
  295. }
  296. rv |= sb_add(&sql_buf, &strings[STR_FROM]); /* " FROM " */
  297. rv |= sb_add(&sql_buf, set_str(&tmpstr, "\""));
  298. rv |= sb_add(&sql_buf, &cmd->table); /* table name */
  299. rv |= sb_add(&sql_buf, set_str(&tmpstr, "\""));
  300. if (!DB_FLD_EMPTY(cmd->match)) {
  301. rv |= sb_add(&sql_buf, &strings[STR_WHERE]);
  302. for(i = 0, fld = cmd->match; !DB_FLD_LAST(fld[i]); i++) {
  303. rv |= sb_add(&sql_buf, set_str(&tmpstr, fld[i].name));
  304. switch(fld[i].op) {
  305. case DB_EQ: rv |= sb_add(&sql_buf, &strings[STR_OP_EQ]); break;
  306. case DB_NE: rv |= sb_add(&sql_buf, &strings[STR_OP_NE]); break;
  307. case DB_LT: rv |= sb_add(&sql_buf, &strings[STR_OP_LT]); break;
  308. case DB_GT: rv |= sb_add(&sql_buf, &strings[STR_OP_GT]); break;
  309. case DB_LEQ: rv |= sb_add(&sql_buf, &strings[STR_OP_LEQ]); break;
  310. case DB_GEQ: rv |= sb_add(&sql_buf, &strings[STR_OP_GEQ]); break;
  311. }
  312. rv |= sb_add(&sql_buf, get_marker(i + 1));
  313. if (!DB_FLD_LAST(fld[i + 1])) rv |= sb_add(&sql_buf, &strings[STR_AND]);
  314. }
  315. }
  316. rv |= sb_add(&sql_buf, &strings[STR_ZT]);
  317. if (rv) goto error;
  318. sql_cmd->s = sql_buf.s;
  319. sql_cmd->len = sql_buf.len;
  320. return 0;
  321. error:
  322. if (sql_buf.s) pkg_free(sql_buf.s);
  323. return -1;
  324. }
  325. int build_select_oid_sql(str* sql_cmd)
  326. {
  327. struct string_buffer sql_buf = {.s = NULL, .len = 0,
  328. .size = 0, .increment = 128};
  329. int rv = 0;
  330. rv = sb_add(&sql_buf, &strings[STR_OID]);
  331. rv |= sb_add(&sql_buf, &strings[STR_ZT]);
  332. if (rv) goto error;
  333. sql_cmd->s = sql_buf.s;
  334. sql_cmd->len = sql_buf.len;
  335. return 0;
  336. error:
  337. if (sql_buf.s) pkg_free(sql_buf.s);
  338. return -1;
  339. }
  340. int build_timestamp_format_sql(str* sql_cmd)
  341. {
  342. struct string_buffer sql_buf = {.s = NULL, .len = 0,
  343. .size = 0, .increment = 128};
  344. int rv = 0;
  345. rv = sb_add(&sql_buf, &strings[STR_TIMESTAMP]);
  346. rv |= sb_add(&sql_buf, &strings[STR_ZT]);
  347. if (rv) goto error;
  348. sql_cmd->s = sql_buf.s;
  349. sql_cmd->len = sql_buf.len;
  350. return 0;
  351. error:
  352. if (sql_buf.s) pkg_free(sql_buf.s);
  353. return -1;
  354. }
  355. /** @} */