123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424 |
- /*
- * $Id$
- *
- * PostgreSQL Database Driver for SER
- *
- * Portions Copyright (C) 2001-2003 FhG FOKUS
- * Copyright (C) 2003 August.Net Services, LLC
- * Portions Copyright (C) 2005-2008 iptelorg GmbH
- *
- * This file is part of SER, a free SIP server.
- *
- * SER is free software; you can redistribute it and/or modify it under the
- * terms of the GNU General Public License as published by the Free Software
- * Foundation; either version 2 of the License, or (at your option) any later
- * version
- *
- * For a license to use the ser software under conditions other than those
- * described here, or to purchase support for this software, please contact
- * iptel.org by e-mail at the following addresses: [email protected]
- *
- * SER is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc., 59
- * Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
- /** \addtogroup postgres
- * @{
- */
- /** \file
- * Implementation of various functions that assemble SQL query strings for
- * PostgreSQL.
- */
- #include "pg_sql.h"
- #include "../../lib/srdb2/db_cmd.h"
- #include "../../lib/srdb2/db_fld.h"
- #include "../../mem/mem.h"
- #include "../../dprint.h"
- #include "../../ut.h"
- #include <string.h>
- enum {
- STR_DELETE,
- STR_INSERT,
- STR_UPDATE,
- STR_SELECT,
- STR_REPLACE,
- STR_SET,
- STR_WHERE,
- STR_IS,
- STR_AND,
- STR_OR,
- STR_ESC,
- STR_OP_EQ,
- STR_OP_NE,
- STR_OP_LT,
- STR_OP_GT,
- STR_OP_LEQ,
- STR_OP_GEQ,
- STR_VALUES,
- STR_FROM,
- STR_OID,
- STR_TIMESTAMP,
- STR_ZT
- };
- static str strings[] = {
- STR_STATIC_INIT("delete from "),
- STR_STATIC_INIT("insert into "),
- STR_STATIC_INIT("update "),
- STR_STATIC_INIT("select "),
- STR_STATIC_INIT("replace "),
- STR_STATIC_INIT(" set "),
- STR_STATIC_INIT(" where "),
- STR_STATIC_INIT(" is "),
- STR_STATIC_INIT(" and "),
- STR_STATIC_INIT(" or "),
- STR_STATIC_INIT("?"),
- STR_STATIC_INIT("="),
- STR_STATIC_INIT("!="),
- STR_STATIC_INIT("<"),
- STR_STATIC_INIT(">"),
- STR_STATIC_INIT("<="),
- STR_STATIC_INIT(">="),
- STR_STATIC_INIT(") values ("),
- STR_STATIC_INIT(" from "),
- STR_STATIC_INIT("select typname,pg_type.oid from pg_type"),
- STR_STATIC_INIT("select timestamp '2000-01-01 00:00:00' + time '00:00:01'"),
- STR_STATIC_INIT("\0")
- };
- /**
- * Reallocatable string buffer.
- */
- struct string_buffer {
- char *s; /**< allocated memory itself */
- int len; /**< used memory */
- int size; /**< total size of allocated memory */
- int increment; /**< increment when realloc is necessary */
- };
- /** Appends string to string buffer.
- * This function appends string to dynamically created string buffer,
- * the buffer is automatically extended if there is not enough room
- * in the buffer. The buffer is allocated using pkg_malloc.
- * @param sb string buffer
- * @param nstr string to add
- * @return 0 if OK, -1 if failed
- */
- static inline int sb_add(struct string_buffer *sb, str *nstr)
- {
- int new_size = 0;
- int rsize = sb->len + nstr->len;
- int asize;
- char *newp;
-
- if (rsize > sb->size) {
- asize = rsize - sb->size;
- new_size = sb->size + (asize / sb->increment +
- (asize % sb->increment > 0)) * sb->increment;
- newp = pkg_malloc(new_size);
- if (!newp) {
- ERR("postgres: No memory left\n");
- return -1;
- }
- if (sb->s) {
- memcpy(newp, sb->s, sb->len);
- pkg_free(sb->s);
- }
- sb->s = newp;
- sb->size = new_size;
- }
- memcpy(sb->s + sb->len, nstr->s, nstr->len);
- sb->len += nstr->len;
- return 0;
- }
- /** Creates str string from zero terminated string without copying.
- * This function initializes members of a temporary str structure
- * with the pointer and lenght of the string from s parameter.
- *
- * @param str A pointer to temporary str structure.
- * @param s A zero terminated string.
- * @return Pointer to the str structure.
- */
- static inline str* set_str(str *str, const char *s)
- {
- str->s = (char *)s;
- str->len = strlen(s);
- return str;
- }
- /** Returns a parameter marker for PostgreSQL with number i
- * The function builds a parameter marker for use in
- * PostgreSQL SQL queries, such as $1, $2, etc.
- * @param i Number of the parameter
- * @retval A pointer to static string with the marker
- */
- static str* get_marker(unsigned int i)
- {
- static char buf[INT2STR_MAX_LEN + 1];
- static str res;
- const char* c;
- buf[0] = '$';
- res.s = buf;
- c = int2str(i, &res.len);
- memcpy(res.s + 1, c, res.len);
- res.len++;
- return &res;
- }
- int build_update_sql(str* sql_cmd, db_cmd_t* cmd)
- {
- struct string_buffer sql_buf = {.s = NULL, .len = 0,
- .size = 0, .increment = 128};
- db_fld_t* fld;
- int i, rv = 0;
- str tmpstr;
- rv = sb_add(&sql_buf, &strings[STR_UPDATE]); /* "UPDATE " */
- rv |= sb_add(&sql_buf, set_str(&tmpstr, "\""));
- rv |= sb_add(&sql_buf, &cmd->table); /* table name */
- rv |= sb_add(&sql_buf, set_str(&tmpstr, "\""));
- rv |= sb_add(&sql_buf, &strings[STR_SET]); /* " SET " */
- /* column name-value pairs */
- for(i = 0, fld = cmd->vals; !DB_FLD_EMPTY(fld) && !DB_FLD_LAST(fld[i]); i++) {
- rv |= sb_add(&sql_buf, set_str(&tmpstr, fld[i].name));
- rv |= sb_add(&sql_buf, set_str(&tmpstr, "="));
- rv |= sb_add(&sql_buf, &strings[STR_ESC]);
- if (!DB_FLD_LAST(fld[i + 1])) rv |= sb_add(&sql_buf, set_str(&tmpstr, ","));
- }
- if (rv) goto error;
- if (!DB_FLD_EMPTY(cmd->match)) {
- rv |= sb_add(&sql_buf, &strings[STR_WHERE]);
- for(i = 0, fld = cmd->match; !DB_FLD_LAST(fld[i]); i++) {
- rv |= sb_add(&sql_buf, set_str(&tmpstr, fld[i].name));
- switch(fld[i].op) {
- case DB_EQ: rv |= sb_add(&sql_buf, &strings[STR_OP_EQ]); break;
- case DB_NE: rv |= sb_add(&sql_buf, &strings[STR_OP_NE]); break;
- case DB_LT: rv |= sb_add(&sql_buf, &strings[STR_OP_LT]); break;
- case DB_GT: rv |= sb_add(&sql_buf, &strings[STR_OP_GT]); break;
- case DB_LEQ: rv |= sb_add(&sql_buf, &strings[STR_OP_LEQ]); break;
- case DB_GEQ: rv |= sb_add(&sql_buf, &strings[STR_OP_GEQ]); break;
- }
-
- rv |= sb_add(&sql_buf, get_marker(i + 1));
- if (!DB_FLD_LAST(fld[i + 1])) rv |= sb_add(&sql_buf, &strings[STR_AND]);
- }
- }
- rv |= sb_add(&sql_buf, &strings[STR_ZT]);
- if (rv) goto error;
- sql_cmd->s = sql_buf.s;
- sql_cmd->len = sql_buf.len;
- return 0;
- error:
- if (sql_buf.s) pkg_free(sql_buf.s);
- return -1;
- }
- int build_insert_sql(str* sql_cmd, db_cmd_t* cmd)
- {
- struct string_buffer sql_buf = {.s = NULL, .len = 0,
- .size = 0, .increment = 128};
- db_fld_t* fld;
- int i, rv = 0;
- str tmpstr;
- rv = sb_add(&sql_buf, &strings[STR_INSERT]); /* "INSERT INTO " */
- rv |= sb_add(&sql_buf, set_str(&tmpstr, "\""));
- rv |= sb_add(&sql_buf, &cmd->table); /* table name */
- rv |= sb_add(&sql_buf, set_str(&tmpstr, "\" ("));
- /* column names */
- for(i = 0, fld = cmd->vals; !DB_FLD_EMPTY(fld) && !DB_FLD_LAST(fld[i]); i++) {
- rv |= sb_add(&sql_buf, set_str(&tmpstr, fld[i].name));
- if (!DB_FLD_LAST(fld[i + 1])) rv |= sb_add(&sql_buf, set_str(&tmpstr, ","));
- }
- if (rv) goto error;
- rv |= sb_add(&sql_buf, &strings[STR_VALUES]);
- for(i = 0, fld = cmd->vals; !DB_FLD_EMPTY(fld) && !DB_FLD_LAST(fld[i]); i++) {
- rv |= sb_add(&sql_buf, get_marker(i + 1));
- if (!DB_FLD_LAST(fld[i + 1])) rv |= sb_add(&sql_buf, set_str(&tmpstr, ","));
- }
- rv |= sb_add(&sql_buf, set_str(&tmpstr, ")"));
- rv |= sb_add(&sql_buf, &strings[STR_ZT]);
- if (rv) goto error;
-
- sql_cmd->s = sql_buf.s;
- sql_cmd->len = sql_buf.len;
- return 0;
- error:
- if (sql_buf.s) pkg_free(sql_buf.s);
- return -1;
- }
- int build_delete_sql(str* sql_cmd, db_cmd_t* cmd)
- {
- struct string_buffer sql_buf = {.s = NULL, .len = 0,
- .size = 0, .increment = 128};
- db_fld_t* fld;
- int i, rv = 0;
- str tmpstr;
- rv = sb_add(&sql_buf, &strings[STR_DELETE]); /* "DELETE FROM " */
- rv |= sb_add(&sql_buf, set_str(&tmpstr, "\""));
- rv |= sb_add(&sql_buf, &cmd->table); /* table name */
- rv |= sb_add(&sql_buf, set_str(&tmpstr, "\""));
- if (!DB_FLD_EMPTY(cmd->match)) {
- rv |= sb_add(&sql_buf, &strings[STR_WHERE]);
- for(i = 0, fld = cmd->match; !DB_FLD_LAST(fld[i]); i++) {
- rv |= sb_add(&sql_buf, set_str(&tmpstr, fld[i].name));
- switch(fld[i].op) {
- case DB_EQ: rv |= sb_add(&sql_buf, &strings[STR_OP_EQ]); break;
- case DB_NE: rv |= sb_add(&sql_buf, &strings[STR_OP_NE]); break;
- case DB_LT: rv |= sb_add(&sql_buf, &strings[STR_OP_LT]); break;
- case DB_GT: rv |= sb_add(&sql_buf, &strings[STR_OP_GT]); break;
- case DB_LEQ: rv |= sb_add(&sql_buf, &strings[STR_OP_LEQ]); break;
- case DB_GEQ: rv |= sb_add(&sql_buf, &strings[STR_OP_GEQ]); break;
- }
-
- rv |= sb_add(&sql_buf, get_marker(i + 1));
- if (!DB_FLD_LAST(fld[i + 1])) rv |= sb_add(&sql_buf, &strings[STR_AND]);
- }
- }
- rv |= sb_add(&sql_buf, &strings[STR_ZT]);
- if (rv) goto error;
- sql_cmd->s = sql_buf.s;
- sql_cmd->len = sql_buf.len;
- return 0;
- error:
- if (sql_buf.s) pkg_free(sql_buf.s);
- return -1;
- }
- int build_select_sql(str* sql_cmd, db_cmd_t* cmd)
- {
- struct string_buffer sql_buf = {.s = NULL, .len = 0,
- .size = 0, .increment = 128};
- db_fld_t* fld;
- int i, rv = 0;
- str tmpstr;
- rv = sb_add(&sql_buf, &strings[STR_SELECT]); /* "SELECT " */
- if (DB_FLD_EMPTY(cmd->result)) {
- rv |= sb_add(&sql_buf, set_str(&tmpstr, "*"));
- } else {
- for(i = 0, fld = cmd->result; !DB_FLD_LAST(fld[i]); i++) {
- rv |= sb_add(&sql_buf, set_str(&tmpstr, fld[i].name));
- if (!DB_FLD_LAST(fld[i + 1])) rv |= sb_add(&sql_buf, set_str(&tmpstr, ","));
- }
- }
- rv |= sb_add(&sql_buf, &strings[STR_FROM]); /* " FROM " */
- rv |= sb_add(&sql_buf, set_str(&tmpstr, "\""));
- rv |= sb_add(&sql_buf, &cmd->table); /* table name */
- rv |= sb_add(&sql_buf, set_str(&tmpstr, "\""));
- if (!DB_FLD_EMPTY(cmd->match)) {
- rv |= sb_add(&sql_buf, &strings[STR_WHERE]);
- for(i = 0, fld = cmd->match; !DB_FLD_LAST(fld[i]); i++) {
- rv |= sb_add(&sql_buf, set_str(&tmpstr, fld[i].name));
- switch(fld[i].op) {
- case DB_EQ: rv |= sb_add(&sql_buf, &strings[STR_OP_EQ]); break;
- case DB_NE: rv |= sb_add(&sql_buf, &strings[STR_OP_NE]); break;
- case DB_LT: rv |= sb_add(&sql_buf, &strings[STR_OP_LT]); break;
- case DB_GT: rv |= sb_add(&sql_buf, &strings[STR_OP_GT]); break;
- case DB_LEQ: rv |= sb_add(&sql_buf, &strings[STR_OP_LEQ]); break;
- case DB_GEQ: rv |= sb_add(&sql_buf, &strings[STR_OP_GEQ]); break;
- }
-
- rv |= sb_add(&sql_buf, get_marker(i + 1));
- if (!DB_FLD_LAST(fld[i + 1])) rv |= sb_add(&sql_buf, &strings[STR_AND]);
- }
- }
- rv |= sb_add(&sql_buf, &strings[STR_ZT]);
- if (rv) goto error;
- sql_cmd->s = sql_buf.s;
- sql_cmd->len = sql_buf.len;
- return 0;
- error:
- if (sql_buf.s) pkg_free(sql_buf.s);
- return -1;
- }
- int build_select_oid_sql(str* sql_cmd)
- {
- struct string_buffer sql_buf = {.s = NULL, .len = 0,
- .size = 0, .increment = 128};
- int rv = 0;
-
- rv = sb_add(&sql_buf, &strings[STR_OID]);
- rv |= sb_add(&sql_buf, &strings[STR_ZT]);
- if (rv) goto error;
- sql_cmd->s = sql_buf.s;
- sql_cmd->len = sql_buf.len;
- return 0;
- error:
- if (sql_buf.s) pkg_free(sql_buf.s);
- return -1;
- }
- int build_timestamp_format_sql(str* sql_cmd)
- {
- struct string_buffer sql_buf = {.s = NULL, .len = 0,
- .size = 0, .increment = 128};
- int rv = 0;
-
- rv = sb_add(&sql_buf, &strings[STR_TIMESTAMP]);
- rv |= sb_add(&sql_buf, &strings[STR_ZT]);
- if (rv) goto error;
- sql_cmd->s = sql_buf.s;
- sql_cmd->len = sql_buf.len;
- return 0;
- error:
- if (sql_buf.s) pkg_free(sql_buf.s);
- return -1;
- }
- /** @} */
|