pg_sql.c

Go to the documentation of this file.
00001 /* 
00002  * $Id$ 
00003  *
00004  * PostgreSQL Database Driver for SER
00005  *
00006  * Portions Copyright (C) 2001-2003 FhG FOKUS
00007  * Copyright (C) 2003 August.Net Services, LLC
00008  * Portions Copyright (C) 2005-2008 iptelorg GmbH
00009  *
00010  * This file is part of SER, a free SIP server.
00011  *
00012  * SER is free software; you can redistribute it and/or modify it under the
00013  * terms of the GNU General Public License as published by the Free Software
00014  * Foundation; either version 2 of the License, or (at your option) any later
00015  * version
00016  *
00017  * For a license to use the ser software under conditions other than those
00018  * described here, or to purchase support for this software, please contact
00019  * iptel.org by e-mail at the following addresses: info@iptel.org
00020  *
00021  * SER is distributed in the hope that it will be useful, but WITHOUT ANY
00022  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00023  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
00024  * details.
00025  *
00026  * You should have received a copy of the GNU General Public License along
00027  * with this program; if not, write to the Free Software Foundation, Inc., 59
00028  * Temple Place, Suite 330, Boston, MA 02111-1307 USA
00029  */
00030 
00040 #include "pg_sql.h"
00041 
00042 #include "../../lib/srdb2/db_cmd.h"
00043 #include "../../lib/srdb2/db_fld.h"
00044 #include "../../mem/mem.h"
00045 #include "../../dprint.h"
00046 #include "../../ut.h"
00047 
00048 #include <string.h>
00049 
00050 
00051 enum {
00052         STR_DELETE,
00053         STR_INSERT,
00054         STR_UPDATE,
00055         STR_SELECT,
00056         STR_REPLACE,
00057         STR_SET,
00058         STR_WHERE,
00059         STR_IS,
00060         STR_AND,
00061         STR_OR,
00062         STR_ESC,
00063         STR_OP_EQ,
00064         STR_OP_NE,
00065         STR_OP_LT,
00066         STR_OP_GT,
00067         STR_OP_LEQ,
00068         STR_OP_GEQ,
00069         STR_VALUES,
00070         STR_FROM,
00071         STR_OID,
00072         STR_TIMESTAMP,
00073         STR_ZT
00074 };
00075 
00076 
00077 static str strings[] = {
00078         STR_STATIC_INIT("delete from "),
00079         STR_STATIC_INIT("insert into "),
00080         STR_STATIC_INIT("update "),
00081         STR_STATIC_INIT("select "),
00082         STR_STATIC_INIT("replace "),
00083         STR_STATIC_INIT(" set "),
00084         STR_STATIC_INIT(" where "),
00085         STR_STATIC_INIT(" is "),
00086         STR_STATIC_INIT(" and "),
00087         STR_STATIC_INIT(" or "),
00088         STR_STATIC_INIT("?"),
00089         STR_STATIC_INIT("="),
00090         STR_STATIC_INIT("!="),
00091         STR_STATIC_INIT("<"),
00092         STR_STATIC_INIT(">"),
00093         STR_STATIC_INIT("<="),
00094         STR_STATIC_INIT(">="),
00095         STR_STATIC_INIT(") values ("),
00096         STR_STATIC_INIT(" from "),
00097         STR_STATIC_INIT("select typname,pg_type.oid from pg_type"),
00098         STR_STATIC_INIT("select timestamp '2000-01-01 00:00:00' + time '00:00:01'"), 
00099         STR_STATIC_INIT("\0")
00100 };
00101 
00102 
00106 struct string_buffer {
00107         char *s;                        
00108         int   len;                      
00109         int   size;                     
00110         int   increment;        
00111 };
00112 
00113 
00122 static inline int sb_add(struct string_buffer *sb, str *nstr)
00123 {
00124         int new_size = 0;
00125         int rsize = sb->len + nstr->len;
00126         int asize;
00127         char *newp;
00128         
00129         if (rsize > sb->size) {
00130                 asize = rsize - sb->size;
00131                 new_size = sb->size + (asize / sb->increment  + 
00132                                                            (asize % sb->increment > 0)) * sb->increment;
00133                 newp = pkg_malloc(new_size);
00134                 if (!newp) {
00135                         ERR("postgres: No memory left\n");
00136                         return -1;
00137                 }
00138                 if (sb->s) {
00139                         memcpy(newp, sb->s, sb->len);
00140                         pkg_free(sb->s);
00141                 }
00142                 sb->s = newp;
00143                 sb->size = new_size;
00144         }
00145         memcpy(sb->s + sb->len, nstr->s, nstr->len);
00146         sb->len += nstr->len;
00147         return 0;
00148 }
00149 
00150 
00159 static inline str* set_str(str *str, const char *s)
00160 {
00161         str->s = (char *)s;
00162         str->len = strlen(s);
00163         return str;
00164 }
00165 
00166 
00173 static str* get_marker(unsigned int i)
00174 {
00175         static char buf[INT2STR_MAX_LEN + 1];
00176         static str res;
00177         const char* c;
00178 
00179         buf[0] = '$';
00180         res.s = buf;
00181 
00182         c = int2str(i, &res.len);
00183         memcpy(res.s + 1, c, res.len);
00184         res.len++;
00185         return &res;
00186 }
00187 
00188 
00189 int build_update_sql(str* sql_cmd, db_cmd_t* cmd)
00190 {
00191         struct string_buffer sql_buf = {.s = NULL, .len = 0, 
00192                                                           .size = 0, .increment = 128};
00193         db_fld_t* fld;
00194         int i, rv = 0;
00195         str tmpstr;
00196 
00197         rv = sb_add(&sql_buf, &strings[STR_UPDATE]); /* "UPDATE " */
00198         rv |= sb_add(&sql_buf, set_str(&tmpstr, "\""));
00199         rv |= sb_add(&sql_buf, &cmd->table);             /* table name */
00200         rv |= sb_add(&sql_buf, set_str(&tmpstr, "\""));
00201         rv |= sb_add(&sql_buf, &strings[STR_SET]);       /* " SET " */
00202 
00203         /* column name-value pairs */
00204         for(i = 0, fld = cmd->vals; !DB_FLD_EMPTY(fld) && !DB_FLD_LAST(fld[i]); i++) {
00205                 rv |= sb_add(&sql_buf, set_str(&tmpstr, fld[i].name));
00206                 rv |= sb_add(&sql_buf, set_str(&tmpstr, "="));
00207                 rv |= sb_add(&sql_buf, &strings[STR_ESC]);
00208                 if (!DB_FLD_LAST(fld[i + 1])) rv |= sb_add(&sql_buf, set_str(&tmpstr, ","));
00209         }
00210         if (rv) goto error;
00211 
00212         if (!DB_FLD_EMPTY(cmd->match)) {
00213                 rv |= sb_add(&sql_buf, &strings[STR_WHERE]);
00214 
00215                 for(i = 0, fld = cmd->match; !DB_FLD_LAST(fld[i]); i++) {
00216                         rv |= sb_add(&sql_buf, set_str(&tmpstr, fld[i].name));
00217 
00218                         switch(fld[i].op) {
00219                         case DB_EQ:  rv |= sb_add(&sql_buf, &strings[STR_OP_EQ]);  break;
00220                         case DB_NE:  rv |= sb_add(&sql_buf, &strings[STR_OP_NE]);  break;
00221                         case DB_LT:  rv |= sb_add(&sql_buf, &strings[STR_OP_LT]);  break;
00222                         case DB_GT:  rv |= sb_add(&sql_buf, &strings[STR_OP_GT]);  break;
00223                         case DB_LEQ: rv |= sb_add(&sql_buf, &strings[STR_OP_LEQ]); break;
00224                         case DB_GEQ: rv |= sb_add(&sql_buf, &strings[STR_OP_GEQ]); break;
00225                         }
00226                         
00227                         rv |= sb_add(&sql_buf, get_marker(i + 1));
00228                         if (!DB_FLD_LAST(fld[i + 1])) rv |= sb_add(&sql_buf, &strings[STR_AND]);
00229                 }
00230         }
00231         rv |= sb_add(&sql_buf, &strings[STR_ZT]);
00232         if (rv) goto error;
00233 
00234         sql_cmd->s = sql_buf.s;
00235         sql_cmd->len = sql_buf.len;
00236         return 0;
00237 
00238 error:
00239         if (sql_buf.s) pkg_free(sql_buf.s);
00240         return -1;
00241 }
00242 
00243 
00244 int build_insert_sql(str* sql_cmd, db_cmd_t* cmd)
00245 {
00246         struct string_buffer sql_buf = {.s = NULL, .len = 0, 
00247                                                                         .size = 0, .increment = 128};
00248         db_fld_t* fld;
00249         int i, rv = 0;
00250         str tmpstr;
00251 
00252         rv = sb_add(&sql_buf, &strings[STR_INSERT]); /* "INSERT INTO " */
00253         rv |= sb_add(&sql_buf, set_str(&tmpstr, "\""));
00254         rv |= sb_add(&sql_buf, &cmd->table);             /* table name */
00255         rv |= sb_add(&sql_buf, set_str(&tmpstr, "\" ("));
00256 
00257         /* column names */
00258         for(i = 0, fld = cmd->vals; !DB_FLD_EMPTY(fld) && !DB_FLD_LAST(fld[i]); i++) {
00259                 rv |= sb_add(&sql_buf, set_str(&tmpstr, fld[i].name));
00260                 if (!DB_FLD_LAST(fld[i + 1])) rv |= sb_add(&sql_buf, set_str(&tmpstr, ","));
00261         }
00262         if (rv) goto error;
00263 
00264         rv |= sb_add(&sql_buf, &strings[STR_VALUES]);
00265 
00266         for(i = 0, fld = cmd->vals; !DB_FLD_EMPTY(fld) && !DB_FLD_LAST(fld[i]); i++) {
00267                 rv |= sb_add(&sql_buf, get_marker(i + 1));
00268                 if (!DB_FLD_LAST(fld[i + 1])) rv |= sb_add(&sql_buf, set_str(&tmpstr, ","));
00269         }
00270         rv |= sb_add(&sql_buf, set_str(&tmpstr, ")"));
00271         rv |= sb_add(&sql_buf, &strings[STR_ZT]);
00272         if (rv) goto error;
00273                                  
00274         sql_cmd->s = sql_buf.s;
00275         sql_cmd->len = sql_buf.len;
00276         return 0;
00277 
00278 error:
00279         if (sql_buf.s) pkg_free(sql_buf.s);
00280         return -1;
00281 }
00282 
00283 
00284 int build_delete_sql(str* sql_cmd, db_cmd_t* cmd)
00285 {
00286         struct string_buffer sql_buf = {.s = NULL, .len = 0, 
00287                                                                         .size = 0, .increment = 128};
00288         db_fld_t* fld;
00289         int i, rv = 0;
00290         str tmpstr;
00291 
00292         rv = sb_add(&sql_buf, &strings[STR_DELETE]); /* "DELETE FROM " */
00293         rv |= sb_add(&sql_buf, set_str(&tmpstr, "\""));
00294         rv |= sb_add(&sql_buf, &cmd->table);             /* table name */
00295         rv |= sb_add(&sql_buf, set_str(&tmpstr, "\""));
00296 
00297         if (!DB_FLD_EMPTY(cmd->match)) {
00298                 rv |= sb_add(&sql_buf, &strings[STR_WHERE]);
00299 
00300                 for(i = 0, fld = cmd->match; !DB_FLD_LAST(fld[i]); i++) {
00301                         rv |= sb_add(&sql_buf, set_str(&tmpstr, fld[i].name));
00302 
00303                         switch(fld[i].op) {
00304                         case DB_EQ:  rv |= sb_add(&sql_buf, &strings[STR_OP_EQ]);  break;
00305                         case DB_NE:  rv |= sb_add(&sql_buf, &strings[STR_OP_NE]);  break;
00306                         case DB_LT:  rv |= sb_add(&sql_buf, &strings[STR_OP_LT]);  break;
00307                         case DB_GT:  rv |= sb_add(&sql_buf, &strings[STR_OP_GT]);  break;
00308                         case DB_LEQ: rv |= sb_add(&sql_buf, &strings[STR_OP_LEQ]); break;
00309                         case DB_GEQ: rv |= sb_add(&sql_buf, &strings[STR_OP_GEQ]); break;
00310                         }
00311                         
00312                         rv |= sb_add(&sql_buf, get_marker(i + 1));
00313                         if (!DB_FLD_LAST(fld[i + 1])) rv |= sb_add(&sql_buf, &strings[STR_AND]);
00314                 }
00315         }
00316         rv |= sb_add(&sql_buf, &strings[STR_ZT]);
00317         if (rv) goto error;
00318 
00319         sql_cmd->s = sql_buf.s;
00320         sql_cmd->len = sql_buf.len;
00321         return 0;
00322 
00323 error:
00324         if (sql_buf.s) pkg_free(sql_buf.s);
00325         return -1;
00326 }
00327 
00328 
00329 int build_select_sql(str* sql_cmd, db_cmd_t* cmd)
00330 {
00331         struct string_buffer sql_buf = {.s = NULL, .len = 0, 
00332                                                                         .size = 0, .increment = 128};
00333         db_fld_t* fld;
00334         int i, rv = 0;
00335         str tmpstr;
00336 
00337         rv = sb_add(&sql_buf, &strings[STR_SELECT]); /* "SELECT " */
00338 
00339         if (DB_FLD_EMPTY(cmd->result)) {
00340                 rv |= sb_add(&sql_buf, set_str(&tmpstr, "*"));
00341         } else {
00342                 for(i = 0, fld = cmd->result; !DB_FLD_LAST(fld[i]); i++) {
00343                         rv |= sb_add(&sql_buf, set_str(&tmpstr, fld[i].name));
00344                         if (!DB_FLD_LAST(fld[i + 1])) rv |= sb_add(&sql_buf, set_str(&tmpstr, ","));
00345                 }
00346         }
00347 
00348         rv |= sb_add(&sql_buf, &strings[STR_FROM]);  /* " FROM " */
00349         rv |= sb_add(&sql_buf, set_str(&tmpstr, "\""));
00350         rv |= sb_add(&sql_buf, &cmd->table);             /* table name */
00351         rv |= sb_add(&sql_buf, set_str(&tmpstr, "\""));
00352 
00353         if (!DB_FLD_EMPTY(cmd->match)) {
00354                 rv |= sb_add(&sql_buf, &strings[STR_WHERE]);
00355 
00356                 for(i = 0, fld = cmd->match; !DB_FLD_LAST(fld[i]); i++) {
00357                         rv |= sb_add(&sql_buf, set_str(&tmpstr, fld[i].name));
00358 
00359                         switch(fld[i].op) {
00360                         case DB_EQ:  rv |= sb_add(&sql_buf, &strings[STR_OP_EQ]);  break;
00361                         case DB_NE:  rv |= sb_add(&sql_buf, &strings[STR_OP_NE]);  break;
00362                         case DB_LT:  rv |= sb_add(&sql_buf, &strings[STR_OP_LT]);  break;
00363                         case DB_GT:  rv |= sb_add(&sql_buf, &strings[STR_OP_GT]);  break;
00364                         case DB_LEQ: rv |= sb_add(&sql_buf, &strings[STR_OP_LEQ]); break;
00365                         case DB_GEQ: rv |= sb_add(&sql_buf, &strings[STR_OP_GEQ]); break;
00366                         }
00367                         
00368                         rv |= sb_add(&sql_buf, get_marker(i + 1));
00369                         if (!DB_FLD_LAST(fld[i + 1])) rv |= sb_add(&sql_buf, &strings[STR_AND]);
00370                 }
00371         }
00372         rv |= sb_add(&sql_buf, &strings[STR_ZT]);
00373         if (rv) goto error;
00374 
00375         sql_cmd->s = sql_buf.s;
00376         sql_cmd->len = sql_buf.len;
00377         return 0;
00378 
00379 error:
00380         if (sql_buf.s) pkg_free(sql_buf.s);
00381         return -1;
00382 }
00383 
00384 
00385 int build_select_oid_sql(str* sql_cmd)
00386 {
00387         struct string_buffer sql_buf = {.s = NULL, .len = 0, 
00388                                                                         .size = 0, .increment = 128};
00389         int rv = 0;
00390         
00391         rv = sb_add(&sql_buf, &strings[STR_OID]);
00392         rv |= sb_add(&sql_buf, &strings[STR_ZT]);
00393         if (rv) goto error;
00394 
00395         sql_cmd->s = sql_buf.s;
00396         sql_cmd->len = sql_buf.len;
00397         return 0;
00398 
00399  error:
00400         if (sql_buf.s) pkg_free(sql_buf.s);
00401         return -1;
00402 }
00403 
00404 
00405 int build_timestamp_format_sql(str* sql_cmd)
00406 {
00407         struct string_buffer sql_buf = {.s = NULL, .len = 0, 
00408                                                                         .size = 0, .increment = 128};
00409         int rv = 0;
00410         
00411         rv = sb_add(&sql_buf, &strings[STR_TIMESTAMP]);
00412         rv |= sb_add(&sql_buf, &strings[STR_ZT]);
00413         if (rv) goto error;
00414 
00415         sql_cmd->s = sql_buf.s;
00416         sql_cmd->len = sql_buf.len;
00417         return 0;
00418 
00419  error:
00420         if (sql_buf.s) pkg_free(sql_buf.s);
00421         return -1;
00422 }
00423