pg_fld.c

Go to the documentation of this file.
00001 /* 
00002  * Portions Copyright (C) 2001-2003 FhG FOKUS
00003  * Copyright (C) 2003 August.Net Services, LLC
00004  * Portions Copyright (C) 2005-2008 iptelorg GmbH
00005  *
00006  * This file is part of SER, a free SIP server.
00007  *
00008  * SER is free software; you can redistribute it and/or modify it under the
00009  * terms of the GNU General Public License as published by the Free Software
00010  * Foundation; either version 2 of the License, or (at your option) any later
00011  * version
00012  *
00013  * For a license to use the ser software under conditions other than those
00014  * described here, or to purchase support for this software, please contact
00015  * iptel.org by e-mail at the following addresses: info@iptel.org
00016  *
00017  * SER is distributed in the hope that it will be useful, but WITHOUT ANY
00018  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00019  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
00020  * details.
00021  *
00022  * You should have received a copy of the GNU General Public License along
00023  * with this program; if not, write to the Free Software Foundation, Inc., 59
00024  * Temple Place, Suite 330, Boston, MA 02111-1307 USA
00025  */
00026 
00027 
00035 #include "pg_fld.h"
00036 #include "pg_con.h" /* flags */
00037 #include "pg_mod.h"
00038 
00039 #include "../../lib/srdb2/db_drv.h"
00040 #include "../../mem/mem.h"
00041 #include "../../dprint.h"
00042 
00043 #include <sys/types.h>
00044 #include <sys/socket.h>
00045 #include <netinet/in.h>
00046 #include <stdint.h>
00047 #include <string.h>
00048 
00054 #define PG_EPOCH_TIME ((int64_t)946684800)
00055 
00056 
00062 static void pg_fld_free(db_fld_t* fld, struct pg_fld* payload)
00063 {
00064         db_drv_free(&payload->gen);
00065         pkg_free(payload);
00066 }
00067 
00068 
00069 int pg_fld(db_fld_t* fld, char* table)
00070 {
00071         struct pg_fld* res;
00072 
00073         res = (struct pg_fld*)pkg_malloc(sizeof(struct pg_fld));
00074         if (res == NULL) {
00075                 ERR("postgres: No memory left\n");
00076                 return -1;
00077         }
00078         memset(res, '\0', sizeof(struct pg_fld));
00079         if (db_drv_init(&res->gen, pg_fld_free) < 0) goto error;
00080 
00081         DB_SET_PAYLOAD(fld, res);
00082         return 0;
00083 
00084  error:
00085         if (res) pkg_free(res);
00086         return -1;
00087 }
00088 
00089 
00090 union ull {
00091         uint64_t ui64;
00092         uint32_t ui32[2];
00093 };
00094 
00095 static inline uint64_t htonll(uint64_t in)
00096 {
00097         union ull* p = (union ull*)&in;
00098         
00099         return ((uint64_t)htonl(p->ui32[0]) << 32) + (uint64_t)htonl(p->ui32[1]);
00100 }
00101 
00102 
00103 static inline uint64_t ntohll(uint64_t in)
00104 {
00105         union ull* p = (union ull*)&in;
00106         return ((uint64_t)ntohl(p->ui32[0]) << 32) + (uint64_t)ntohl(p->ui32[1]);
00107 }
00108 
00109 
00110 static inline void db_int2pg_int4(struct pg_params* dst, int i, 
00111                                                                   db_fld_t* src)
00112 {
00113         struct pg_fld* pfld = DB_GET_PAYLOAD(src);
00114         pfld->v.int4[0] = htonl(src->v.int4);
00115 
00116         dst->fmt[i] = 1;
00117         dst->val[i] = pfld->v.byte;
00118         dst->len[i] = 4;
00119 }
00120 
00121 
00122 static inline void db_int2pg_int2(struct pg_params* dst, int i, 
00123                                                                   db_fld_t* src)
00124 {
00125         struct pg_fld* pfld = DB_GET_PAYLOAD(src);
00126         pfld->v.int2[0] = htons(src->v.int4);
00127 
00128         dst->fmt[i] = 1;
00129         dst->val[i] = pfld->v.byte;
00130         dst->len[i] = 2;
00131 }
00132 
00133 
00134 static inline void db_int2pg_timestamp(struct pg_params* dst, int i, 
00135                                                                            db_fld_t* src, unsigned int flags)
00136 {
00137         struct pg_fld* pfld = DB_GET_PAYLOAD(src);
00138         if (flags & PG_INT8_TIMESTAMP) {
00139                 pfld->v.int8 = ((int64_t)src->v.int4 - PG_EPOCH_TIME) * 1000000;
00140         } else {
00141                 pfld->v.dbl = (double)src->v.int4 - (double)PG_EPOCH_TIME;
00142         }
00143         pfld->v.int8 = htonll(pfld->v.int8);
00144 
00145         dst->fmt[i] = 1;
00146         dst->val[i] = pfld->v.byte;
00147         dst->len[i] = 8;
00148 }
00149 
00150 
00151 static inline void db_int2pg_int8(struct pg_params* dst, int i,
00152                                                                   db_fld_t* src)
00153 {
00154         struct pg_fld* pfld = DB_GET_PAYLOAD(src);
00155         pfld->v.int4[0] = 0;
00156         pfld->v.int4[1] = htonl(src->v.int4);
00157 
00158         dst->fmt[i] = 1;
00159         dst->val[i] = pfld->v.byte;
00160         dst->len[i] = 8;
00161 }
00162 
00163 
00164 static inline void db_int2pg_bool(struct pg_params* dst, int i, db_fld_t* src)
00165 {
00166         struct pg_fld* pfld = DB_GET_PAYLOAD(src);
00167         if (src->v.int4) pfld->v.byte[0] = 1;
00168         else pfld->v.byte[0] = 0;
00169 
00170         dst->fmt[i] = 1;
00171         dst->val[i] = pfld->v.byte;
00172         dst->len[i] = 1;
00173 }
00174 
00175 
00176 static inline void db_int2pg_inet(struct pg_params* dst, int i, db_fld_t* src)
00177 {
00178         struct pg_fld* pfld = DB_GET_PAYLOAD(src);
00179         pfld->v.byte[0] = AF_INET; /* Address family */
00180         pfld->v.byte[1] = 32; /* Netmask */
00181         pfld->v.byte[2] = 0; /* is CIDR */
00182         pfld->v.byte[3] = 4; /* Number of bytes */
00183         pfld->v.int4[1] = htonl(src->v.int4); /* Actuall IP address */
00184 
00185         dst->fmt[i] = 1;
00186         dst->val[i] = pfld->v.byte;
00187         dst->len[i] = 8;
00188 }
00189 
00190 
00191 static inline void db_float2pg_float4(struct pg_params* dst, int i, db_fld_t* src)
00192 {
00193         struct pg_fld* pfld = DB_GET_PAYLOAD(src);
00194         pfld->v.int4[0] = htonl(src->v.int4);
00195 
00196         dst->fmt[i] = 1;
00197         dst->val[i] = pfld->v.byte;
00198         dst->len[i] = 4;
00199 }
00200 
00201 
00202 static inline void db_float2pg_float8(struct pg_params* dst, int i, db_fld_t* src)
00203 {
00204         struct pg_fld* pfld = DB_GET_PAYLOAD(src);
00205         pfld->v.dbl = src->v.flt;
00206         pfld->v.int8 = htonll(pfld->v.int8);
00207 
00208         dst->fmt[i] = 1;
00209         dst->val[i] = pfld->v.byte;
00210         dst->len[i] = 8;
00211 }
00212 
00213 
00214 static inline void db_double2pg_float8(struct pg_params* dst, int i, db_fld_t* src)
00215 {
00216         struct pg_fld* pfld = DB_GET_PAYLOAD(src);
00217         pfld->v.int8 = htonll(src->v.int8);
00218 
00219         dst->fmt[i] = 1;
00220         dst->val[i] = pfld->v.byte;
00221         dst->len[i] = 8;
00222 }
00223 
00224 
00225 static inline void db_double2pg_float4(struct pg_params* dst, int i, db_fld_t* src)
00226 {
00227         struct pg_fld* pfld = DB_GET_PAYLOAD(src);
00228         pfld->v.flt = src->v.dbl;
00229         pfld->v.int4[0] = htonl(pfld->v.int4[0]);
00230 
00231         dst->fmt[i] = 1;
00232         dst->val[i] = pfld->v.byte;
00233         dst->len[i] = 4;
00234 }
00235 
00236 
00237 static inline void db_int2pg_bit(struct pg_params* dst, int i, db_fld_t* src)
00238 {
00239         struct pg_fld* pfld = DB_GET_PAYLOAD(src);
00240 
00241         pfld->v.int4[0] = htonl(32);
00242         pfld->v.int4[1] = htonl(src->v.int4);
00243 
00244         dst->fmt[i] = 1;
00245         dst->val[i] = pfld->v.byte;
00246         dst->len[i] = 8;
00247 }
00248 
00249 
00250 static inline void db_str2pg_string(struct pg_params* dst, int i,
00251                                                                         db_fld_t* src)
00252 {
00253         dst->fmt[i] = 1;
00254         dst->val[i] = src->v.lstr.s;
00255         dst->len[i] = src->v.lstr.len;
00256 }
00257 
00258 
00259 static inline void db_cstr2pg_string(struct pg_params* dst, int i,
00260                                                                          db_fld_t* src)
00261 {
00262         dst->fmt[i] = 0;
00263         dst->val[i] = src->v.cstr;
00264 }
00265 
00266 
00267 int pg_fld2pg(struct pg_params* dst, int off, pg_type_t* types,
00268                           db_fld_t* src, unsigned int flags)
00269 {
00270         int i;
00271         struct pg_fld* pfld;
00272 
00273         if (src == NULL) return 0;
00274 
00275         for(i = 0; !DB_FLD_EMPTY(src) && !DB_FLD_LAST(src[i]); i++) {
00276                 pfld = DB_GET_PAYLOAD(src + i);
00277 
00278                 /* NULL value */
00279                 if (src[i].flags & DB_NULL) {
00280                         dst->val[off + i] = NULL;
00281                         dst->len[off + i] = 0;
00282                         continue;
00283                 }
00284 
00285                 switch(src[i].type) {
00286                 case DB_INT:
00287                         if (pfld->oid == types[PG_INT2].oid)
00288                                 db_int2pg_int2(dst, off + i, src + i);
00289                         else if (pfld->oid == types[PG_INT4].oid)
00290                                 db_int2pg_int4(dst, off + i, src + i);
00291                         else if ((pfld->oid == types[PG_TIMESTAMP].oid) ||
00292                                          (pfld->oid == types[PG_TIMESTAMPTZ].oid))
00293                                 db_int2pg_timestamp(dst, off + i, src + i, flags);
00294                         else if (pfld->oid == types[PG_INT8].oid)
00295                                 db_int2pg_int8(dst, off + i, src + i);
00296                         else if (pfld->oid == types[PG_INET].oid)
00297                                 db_int2pg_inet(dst, off + i, src + i);
00298                         else if (pfld->oid == types[PG_BOOL].oid)
00299                                 db_int2pg_bool(dst, off + i, src + i);
00300                         else if (pfld->oid == types[PG_BIT].oid)
00301                                 db_int2pg_bit(dst, off + i, src + i);
00302                         else if (pfld->oid == types[PG_VARBIT].oid)
00303                                 db_int2pg_bit(dst, off + i, src + i);
00304                         else goto bug;
00305                         break;
00306 
00307                 case DB_BITMAP:
00308                         if (pfld->oid == types[PG_INT4].oid)
00309                                 db_int2pg_int4(dst, off + i, src + i);
00310                         else if (pfld->oid == types[PG_INT8].oid)
00311                                 db_int2pg_int8(dst, off + i, src + i);
00312                         else if (pfld->oid == types[PG_BIT].oid)
00313                                 db_int2pg_bit(dst, off + i, src + i);
00314                         else if (pfld->oid == types[PG_VARBIT].oid)
00315                                 db_int2pg_bit(dst, off + i, src + i);
00316                         else goto bug;
00317                         break;
00318 
00319                 case DB_DATETIME:
00320                         if (pfld->oid == types[PG_INT4].oid)
00321                                 db_int2pg_int4(dst, off + i, src + i);
00322                         else if ((pfld->oid == types[PG_TIMESTAMP].oid) ||
00323                                          (pfld->oid == types[PG_TIMESTAMPTZ].oid))
00324                                 db_int2pg_timestamp(dst, off + i, src + i, flags);
00325                         else if (pfld->oid == types[PG_INT8].oid)
00326                                 db_int2pg_int8(dst, off + i, src + i);
00327                         else goto bug;
00328                         break;
00329                          
00330                 case DB_FLOAT:
00331                         if (pfld->oid == types[PG_FLOAT4].oid)
00332                                 db_float2pg_float4(dst, off + i, src + i);
00333                         else if (pfld->oid == types[PG_FLOAT8].oid)
00334                                 db_float2pg_float8(dst, off + i, src + i);
00335                         else goto bug;
00336                         break;
00337 
00338                 case DB_DOUBLE:
00339                         if (pfld->oid == types[PG_FLOAT4].oid)
00340                                 db_double2pg_float4(dst, off + i, src + i);
00341                         else if (pfld->oid == types[PG_FLOAT8].oid)
00342                                 db_double2pg_float8(dst, off + i, src + i);
00343                         else goto bug;
00344                         break;
00345 
00346                 case DB_STR:
00347                         if (pfld->oid == types[PG_VARCHAR].oid ||
00348                                 pfld->oid == types[PG_BYTE].oid ||
00349                                 pfld->oid == types[PG_CHAR].oid ||
00350                                 pfld->oid == types[PG_TEXT].oid ||
00351                                 pfld->oid == types[PG_BPCHAR].oid)
00352                                 db_str2pg_string(dst, off + i, src + i);
00353                         else goto bug;
00354                         break;
00355 
00356                 case DB_CSTR:
00357                         if (pfld->oid == types[PG_VARCHAR].oid ||
00358                                 pfld->oid == types[PG_BYTE].oid ||
00359                                 pfld->oid == types[PG_CHAR].oid ||
00360                                 pfld->oid == types[PG_TEXT].oid ||
00361                                 pfld->oid == types[PG_BPCHAR].oid)
00362                                 db_cstr2pg_string(dst, off + i, src + i);
00363                         else goto bug;
00364                         break;
00365 
00366                 case DB_BLOB:
00367                         if (pfld->oid == types[PG_BYTE].oid)
00368                                 db_str2pg_string(dst, off + i, src + i);
00369                         else goto bug;
00370                         break;
00371 
00372                 default:
00373                         BUG("postgres: Unsupported field type %d in field %s\n",
00374                                 src[i].type, src[i].name);
00375                         return -1;
00376                 }
00377         }
00378 
00379         return 0;
00380 
00381  bug:
00382         BUG("postgres: Error while converting DB API type %d to Postgres Oid %d\n",
00383                 src[i].type, pfld->oid);
00384         return -1;
00385 
00386 }
00387 
00388 
00389 int pg_check_fld2pg(db_fld_t* fld, pg_type_t* types)
00390 {
00391         int i;
00392         const char* name = "UNKNOWN";
00393         struct pg_fld* pfld;
00394 
00395         if (fld == NULL) return 0;
00396 
00397         for(i = 0; !DB_FLD_EMPTY(fld) && !DB_FLD_LAST(fld[i]); i++) {
00398                 pfld = DB_GET_PAYLOAD(fld + i);
00399                 switch(fld[i].type) {
00400                 case DB_INT:
00401                         if (pfld->oid == types[PG_INT2].oid) continue;
00402                         if (pfld->oid == types[PG_INT4].oid) continue;
00403                         if (pfld->oid == types[PG_INT8].oid) continue;
00404                         if (pfld->oid == types[PG_BOOL].oid) continue;
00405                         if (pfld->oid == types[PG_INET].oid) continue;
00406                         if (pfld->oid == types[PG_TIMESTAMP].oid) continue;
00407                         if (pfld->oid == types[PG_TIMESTAMPTZ].oid) continue;
00408                         if (pfld->oid == types[PG_BIT].oid) continue;
00409                         if (pfld->oid == types[PG_VARBIT].oid) continue;
00410                         break;
00411 
00412                 case DB_BITMAP:
00413                         if (pfld->oid == types[PG_INT4].oid) continue;
00414                         if (pfld->oid == types[PG_INT8].oid) continue;
00415                         if (pfld->oid == types[PG_BIT].oid) continue;
00416                         if (pfld->oid == types[PG_VARBIT].oid) continue;
00417                         break;
00418 
00419                 case DB_FLOAT:
00420                 case DB_DOUBLE:
00421                         if (pfld->oid == types[PG_FLOAT4].oid) continue;
00422                         if (pfld->oid == types[PG_FLOAT8].oid) continue;
00423                         break;
00424 
00425                 case DB_CSTR:
00426                 case DB_STR:
00427                         if (pfld->oid == types[PG_BYTE].oid) continue;
00428                         if (pfld->oid == types[PG_CHAR].oid) continue;
00429                         if (pfld->oid == types[PG_TEXT].oid) continue;
00430                         if (pfld->oid == types[PG_BPCHAR].oid) continue;
00431                         if (pfld->oid == types[PG_VARCHAR].oid) continue;
00432                         break;
00433 
00434                 case DB_BLOB:
00435                         if (pfld->oid == types[PG_BYTE].oid) continue;
00436                         break;
00437 
00438                 case DB_DATETIME:
00439                         if (pfld->oid == types[PG_INT4].oid) continue;
00440                         if (pfld->oid == types[PG_INT8].oid) continue;
00441                         if (pfld->oid == types[PG_TIMESTAMP].oid) continue;
00442                         if (pfld->oid == types[PG_TIMESTAMPTZ].oid) continue;
00443                         break;
00444 
00445                 default:
00446                         BUG("postgres: Unsupported field type %d, bug in postgres module\n",
00447                                 fld[i].type);
00448                         return -1;
00449                 }
00450 
00451                 pg_oid2name(&name, types, pfld->oid);
00452                 ERR("postgres: Cannot convert column '%s' of type %s "
00453                         "to PostgreSQL column type '%s'\n", 
00454                         fld[i].name, db_fld_str[fld[i].type], name);
00455                 return -1;
00456         }
00457         return 0;
00458 }
00459 
00460 
00461 int pg_resolve_param_oids(db_fld_t* vals, db_fld_t* match, int n1, int n2, PGresult* types)
00462 {
00463         struct pg_fld* pfld;
00464         int i;
00465 
00466         if (n1 + n2 != PQnparams(types)) {
00467                 ERR("postgres: Number of command parameters do not match\n");
00468                 return -1;
00469         }
00470 
00471         for(i = 0; i < n1; i++) {
00472                 pfld = DB_GET_PAYLOAD(vals + i);
00473                 pfld->oid = PQparamtype(types, i);
00474         }
00475 
00476         for(i = 0; i < n2; i++) {
00477                 pfld = DB_GET_PAYLOAD(match + i);
00478                 pfld->oid = PQparamtype(types, n1 + i);
00479         }
00480 
00481         return 0;
00482 }
00483 
00484 
00485 int pg_resolve_result_oids(db_fld_t* fld, int n, PGresult* types)
00486 {
00487         struct pg_fld* pfld;
00488         int i;
00489         if (fld == NULL) return 0;
00490 
00491         if (n != PQnfields(types)) {
00492                 ERR("postgres: Result field numbers do not match\n");
00493                 return -1;
00494         }
00495 
00496         for(i = 0; i < n; i++) {
00497                 pfld = DB_GET_PAYLOAD(fld + i);
00498                 pfld->oid = PQftype(types, i);
00499         }
00500 
00501         return 0;
00502 }
00503 
00504 
00505 int pg_check_pg2fld(db_fld_t* fld, pg_type_t* types)
00506 {
00507         int i;
00508         const char* name = "UNKNOWN";
00509         struct pg_fld* pfld;
00510 
00511         if (fld == NULL) return 0;
00512 
00513         for(i = 0; !DB_FLD_EMPTY(fld) && !DB_FLD_LAST(fld[i]); i++) {
00514                 pfld = DB_GET_PAYLOAD(fld + i);
00515 
00516                 if (pfld->oid == 0) {
00517                         ERR("postgres: Unknown type fields not supported\n");
00518                         return -1;
00519                 }
00520 
00521                 switch(fld[i].type) {
00522                 case DB_INT:
00523                         if (pfld->oid == types[PG_INT2].oid) continue;
00524                         if (pfld->oid == types[PG_INT4].oid) continue;
00525                         if (pfld->oid == types[PG_INT8].oid) continue;
00526                         if (pfld->oid == types[PG_BOOL].oid) continue;
00527                         if (pfld->oid == types[PG_INET].oid) continue;
00528                         if (pfld->oid == types[PG_TIMESTAMP].oid) continue;
00529                         if (pfld->oid == types[PG_TIMESTAMPTZ].oid) continue;
00530                         if (pfld->oid == types[PG_BIT].oid) continue;
00531                         if (pfld->oid == types[PG_VARBIT].oid) continue;
00532                         break;
00533 
00534                 case DB_BITMAP:
00535                         if (pfld->oid == types[PG_INT2].oid) continue;
00536                         if (pfld->oid == types[PG_INT4].oid) continue;
00537                         if (pfld->oid == types[PG_INT8].oid) continue;
00538                         if (pfld->oid == types[PG_BIT].oid) continue;
00539                         if (pfld->oid == types[PG_VARBIT].oid) continue;
00540                         break;
00541 
00542                 case DB_FLOAT:
00543                         if (pfld->oid == types[PG_FLOAT4].oid) continue;
00544                         break;
00545 
00546                 case DB_DOUBLE:
00547                         if (pfld->oid == types[PG_FLOAT4].oid) continue;
00548                         if (pfld->oid == types[PG_FLOAT8].oid) continue;
00549                         break;
00550 
00551                 case DB_CSTR:
00552                         if (pfld->oid == types[PG_CHAR].oid) continue;
00553                         if (pfld->oid == types[PG_TEXT].oid) continue;
00554                         if (pfld->oid == types[PG_BPCHAR].oid) continue;
00555                         if (pfld->oid == types[PG_VARCHAR].oid) continue;
00556                         if (pfld->oid == types[PG_INT2].oid) continue;
00557                         if (pfld->oid == types[PG_INT4].oid) continue;
00558                         break;
00559 
00560                 case DB_STR:
00561                 case DB_BLOB:
00562                         if (pfld->oid == types[PG_BYTE].oid) continue;
00563                         if (pfld->oid == types[PG_CHAR].oid) continue;
00564                         if (pfld->oid == types[PG_TEXT].oid) continue;
00565                         if (pfld->oid == types[PG_BPCHAR].oid) continue;
00566                         if (pfld->oid == types[PG_VARCHAR].oid) continue;
00567                         if (pfld->oid == types[PG_INT2].oid) continue;
00568                         if (pfld->oid == types[PG_INT4].oid) continue;
00569                         break;
00570 
00571                 case DB_DATETIME:
00572                         if (pfld->oid == types[PG_INT2].oid) continue;
00573                         if (pfld->oid == types[PG_INT4].oid) continue;
00574                         if (pfld->oid == types[PG_TIMESTAMP].oid) continue;
00575                         if (pfld->oid == types[PG_TIMESTAMPTZ].oid) continue;
00576                         break;
00577 
00578                 default:
00579                         BUG("postgres: Unsupported field type %d, bug in postgres module\n",
00580                                 fld[i].type);
00581                         return -1;
00582                 }
00583 
00584                 pg_oid2name(&name, types, pfld->oid);
00585                 ERR("postgres: Cannot convert column '%s' of type %s "
00586                         "to DB API field of type %s\n", 
00587                         fld[i].name, name, db_fld_str[fld[i].type]);
00588                 return -1;
00589         }
00590         return 0;
00591 }
00592 
00593 
00594 static inline int pg_int2_2_db_cstr(db_fld_t* fld, char* val, int len)
00595 {
00596         struct pg_fld* pfld = DB_GET_PAYLOAD(fld);
00597         int size, v;
00598 
00599         v = (int16_t)ntohs(*((int16_t*)val));
00600 
00601     size = snprintf(pfld->buf, INT2STR_MAX_LEN, "%-d", v);
00602     if (size < 0 || size >= INT2STR_MAX_LEN) {
00603         BUG("postgres: Error while converting integer to string\n");
00604         return -1;
00605     }
00606 
00607         fld->v.cstr = pfld->buf;
00608         return 0;
00609 }
00610 
00611 
00612 static inline int pg_int4_2_db_cstr(db_fld_t* fld, char* val, int len)
00613 {
00614         struct pg_fld* pfld = DB_GET_PAYLOAD(fld);
00615         int size, v;
00616 
00617         v = (int32_t)ntohl(*((int32_t*)val));
00618 
00619     size = snprintf(pfld->buf, INT2STR_MAX_LEN, "%-d", v);
00620     if (len < 0 || size >= INT2STR_MAX_LEN) {
00621         BUG("postgres: Error while converting integer to string\n");
00622         return -1;
00623     }
00624 
00625         fld->v.cstr = pfld->buf;
00626         return 0;
00627 }
00628 
00629 
00630 static inline int pg_int2_2_db_str(db_fld_t* fld, char* val, int len)
00631 {
00632         struct pg_fld* pfld = DB_GET_PAYLOAD(fld);
00633         int size, v;
00634 
00635         v = (int16_t)ntohs(*((int16_t*)val));
00636 
00637     size = snprintf(pfld->buf, INT2STR_MAX_LEN, "%-d", v);
00638     if (size < 0 || size >= INT2STR_MAX_LEN) {
00639         BUG("postgres: Error while converting integer to string\n");
00640         return -1;
00641     }
00642 
00643         fld->v.lstr.s = pfld->buf;
00644         fld->v.lstr.len = size;
00645         return 0;
00646 }
00647 
00648 
00649 static inline int pg_int4_2_db_str(db_fld_t* fld, char* val, int len)
00650 {
00651         struct pg_fld* pfld = DB_GET_PAYLOAD(fld);
00652         int size, v;
00653 
00654         v = (int32_t)ntohl(*((int32_t*)val));
00655 
00656     size = snprintf(pfld->buf, INT2STR_MAX_LEN, "%-d", v);
00657     if (size < 0 || size >= INT2STR_MAX_LEN) {
00658         BUG("postgres: Error while converting integer to string\n");
00659         return -1;
00660     }
00661 
00662         fld->v.lstr.s = pfld->buf;
00663         fld->v.lstr.len = size;
00664         return 0;
00665 }
00666 
00667 
00668 static inline int pg_int2_2_db_int(db_fld_t* fld, char* val, int len)
00669 {
00670         fld->v.int4 = (int16_t)ntohs(*((int16_t*)val));
00671         return 0;
00672 }
00673 
00674 
00675 static inline int pg_int4_2_db_int(db_fld_t* fld, char* val, int len)
00676 {
00677         fld->v.int4 = (int32_t)ntohl(*((int32_t*)val));
00678         return 0;
00679 }
00680 
00681 
00682 static inline int pg_int8_2_db_int(db_fld_t* fld, char* val, int len)
00683 {
00684         fld->v.int8 = (int64_t)ntohll(*((int64_t*)val));
00685         return 0;
00686 }
00687 
00688 
00689 static inline int pg_bool2db_int(db_fld_t* fld, char* val, int len)
00690 {
00691         fld->v.int4 = val[0];
00692         return 0;
00693 }
00694 
00695 
00696 static inline int pg_inet2db_int(db_fld_t* fld, char* val, int len)
00697 {
00698         if (len != 8 || val[2] != 0) {
00699                 ERR("postgres: Unsupported 'inet' format, column %s\n", fld->name);
00700                 return -1;
00701         }
00702 
00703         if (val[0] != AF_INET) {
00704                 ERR("postgres: Unsupported address family %d in field %s\n",
00705                         val[0], fld->name);
00706                 return -1;
00707         }
00708 
00709         if (val[1] != 32) {
00710                 WARN("postgres: Netmasks shorter than 32-bits not supported, "
00711                          "column %s\n", fld->name);
00712         }
00713 
00714         if (val[3] != 4) {
00715                 ERR("postgres: Unsupported IP address size %d in column %s\n",
00716                         val[3], fld->name);
00717                 return -1;
00718         }
00719 
00720         fld->v.int4 = (int32_t)ntohl(((int32_t*)val)[1]);
00721         return 0;
00722 }
00723 
00724 
00725 static inline int pg_timestamp2db_int(db_fld_t* fld, char* val, int len, 
00726                                                                           unsigned int flags)
00727 {
00728         if (flags & PG_INT8_TIMESTAMP) {
00729                 /* int8 format */
00730                 fld->v.int4 = (int64_t)ntohll(((int64_t*)val)[0]) / (int64_t)1000000 + PG_EPOCH_TIME;
00731         } else {
00732                 /* double format */
00733                 fld->v.int4 = PG_EPOCH_TIME + ntohll(((int64_t*)val)[0]);
00734         }
00735         return 0;
00736 }
00737 
00738 
00739 static inline int pg_bit2db_int(db_fld_t* fld, char* val, int len)
00740 {
00741         int size;
00742 
00743         size = ntohl(*(uint32_t*)val);
00744         if (size != 32) {
00745                 ERR("postgres: Unsupported bit field size (%d), column %s\n",
00746                         size, fld->name);
00747                 return -1;
00748         }
00749         fld->v.int4 = ntohl(((uint32_t*)val)[1]);
00750         return 0;
00751 }
00752 
00753 
00754 static inline int pg_float42db_float(db_fld_t* fld, char* val, int len)
00755 {
00756         fld->v.int4 = (uint32_t)ntohl(*(uint32_t*)val);
00757         return 0;
00758 }
00759 
00760 
00761 static inline int pg_float42db_double(db_fld_t* fld, char* val, int len)
00762 {
00763         float tmp;
00764 
00765         tmp = ntohl(*(uint32_t*)val);
00766         fld->v.dbl = tmp;
00767         return 0;
00768 }
00769 
00770 
00771 static inline int pg_float82db_double(db_fld_t* fld, char* val, int len)
00772 {
00773         fld->v.int8 = ntohll(*(uint64_t*)val);
00774         return 0;
00775 }
00776 
00777 
00778 static inline int pg_string2db_cstr(db_fld_t* fld, char* val, int len)
00779 {
00780         fld->v.cstr = val;
00781         return 0;
00782 }
00783 
00784 
00785 static inline int pg_string2db_str(db_fld_t* fld, char* val, int len)
00786 {
00787         fld->v.lstr.s = val;
00788         fld->v.lstr.len = len;
00789         return 0;
00790 }
00791 
00792 
00793 
00794 int pg_pg2fld(db_fld_t* dst, PGresult* src, int row, 
00795                           pg_type_t* types, unsigned int flags)
00796 {
00797         char* val;
00798         int i, len, ret;
00799         Oid type;
00800         
00801         if (dst == NULL || src == NULL) return 0;
00802         ret = 0;
00803 
00804         for(i = 0; !DB_FLD_EMPTY(dst) && !DB_FLD_LAST(dst[i]); i++) {
00805                 if (PQgetisnull(src, row, i)) {
00806                         dst[i].flags |= DB_NULL;
00807                         continue;
00808                 } else {
00809                         dst[i].flags &= ~DB_NULL;
00810                 }
00811 
00812                 type = PQftype(src, i);
00813                 val = PQgetvalue(src, row, i);
00814                 len = PQgetlength(src, row, i);         
00815 
00816                 switch(dst[i].type) {
00817                 case DB_INT:
00818                         if (type == types[PG_INT2].oid)
00819                                 ret |= pg_int2_2_db_int(dst + i, val, len);
00820                         else if (type == types[PG_INT4].oid)
00821                                 ret |= pg_int4_2_db_int(dst + i, val, len);
00822                         else if (type == types[PG_INT8].oid)
00823                                 ret |= pg_int8_2_db_int(dst + i, val, len);
00824                         else if (type == types[PG_BOOL].oid)
00825                                 ret |= pg_bool2db_int(dst + i, val, len);
00826                         else if (type == types[PG_INET].oid)
00827                                 ret |= pg_inet2db_int(dst + i, val, len);
00828                         else if ((type == types[PG_TIMESTAMP].oid) ||
00829                                          (type == types[PG_TIMESTAMPTZ].oid))
00830                                 ret |= pg_timestamp2db_int(dst + i, val, len, flags);
00831                         else if (type == types[PG_BIT].oid)
00832                                 ret |= pg_bit2db_int(dst + i, val, len);
00833                         else if (type == types[PG_VARBIT].oid)
00834                                 ret |= pg_bit2db_int(dst + i, val, len);
00835                         else goto bug;
00836                         break;
00837 
00838                 case DB_FLOAT:
00839                         if (type == types[PG_FLOAT4].oid)
00840                                 ret |= pg_float42db_float(dst + i, val, len);
00841                         else goto bug;
00842                         break;
00843 
00844                 case DB_DOUBLE:
00845                         if (type == types[PG_FLOAT4].oid)
00846                                 ret |= pg_float42db_double(dst + i, val, len);
00847                         else if (type == types[PG_FLOAT8].oid)
00848                                 ret |= pg_float82db_double(dst + i, val, len);
00849                         else goto bug;
00850                         break;
00851 
00852                 case DB_DATETIME:
00853                         if (type == types[PG_INT2].oid)
00854                                 ret |= pg_int2_2_db_int(dst + i, val, len);
00855                         else if (type == types[PG_INT4].oid)
00856                                 ret |= pg_int4_2_db_int(dst + i, val, len);
00857                         else if ((type == types[PG_TIMESTAMP].oid) ||
00858                                          (type == types[PG_TIMESTAMPTZ].oid))
00859                                 ret |= pg_timestamp2db_int(dst + i, val, len, flags);
00860                         else goto bug;
00861                         break;
00862 
00863                 case DB_CSTR:
00864                         if ((type == types[PG_CHAR].oid) ||
00865                                 (type == types[PG_TEXT].oid) ||
00866                                 (type == types[PG_BPCHAR].oid) ||
00867                                 (type == types[PG_VARCHAR].oid))
00868                                 ret |= pg_string2db_cstr(dst + i, val, len);
00869                         else if (type == types[PG_INT2].oid)
00870                                 ret |= pg_int2_2_db_cstr(dst + i, val, len);
00871                         else if (type == types[PG_INT4].oid)
00872                                 ret |= pg_int4_2_db_cstr(dst + i, val, len);
00873                         else goto bug;
00874                         break;
00875 
00876                 case DB_STR:
00877                 case DB_BLOB:
00878                         if ((type == types[PG_BYTE].oid) ||
00879                                 (type == types[PG_CHAR].oid) ||
00880                                 (type == types[PG_TEXT].oid) ||
00881                                 (type == types[PG_BPCHAR].oid) ||
00882                                 (type == types[PG_VARCHAR].oid))
00883                                 ret |= pg_string2db_str(dst + i, val, len);
00884                         else if (type == types[PG_INT2].oid)
00885                                 ret |= pg_int2_2_db_str(dst + i, val, len);
00886                         else if (type == types[PG_INT4].oid)
00887                                 ret |= pg_int4_2_db_str(dst + i, val, len);
00888                         else goto bug;
00889                         break;
00890 
00891                 case DB_BITMAP:
00892                         if (type == types[PG_INT2].oid)
00893                                 ret |= pg_int2_2_db_int(dst + i, val, len);
00894                         else if (type == types[PG_INT4].oid)
00895                                 ret |= pg_int4_2_db_int(dst + i, val, len);
00896                         else if (type == types[PG_INT8].oid)
00897                                 ret |= pg_int8_2_db_int(dst + i, val, len);
00898                         else if (type == types[PG_BIT].oid)
00899                                 ret |= pg_bit2db_int(dst + i, val, len);
00900                         else if (type == types[PG_VARBIT].oid)
00901                                 ret |= pg_bit2db_int(dst + i, val, len);
00902                         else goto bug;
00903                         break;
00904 
00905                 default:
00906                         BUG("postgres: Unsupported field type %d in field %s\n",
00907                                 dst[i].type, dst[i].name);
00908                         return -1;                      
00909                 }
00910         }
00911         return ret;
00912 
00913  bug:
00914         BUG("postgres: Error while converting Postgres Oid %d to DB API type %d\n",
00915                 type, dst[i].type);
00916         return -1;
00917 }