685d73b33f85033251d855cdc8ead7e4cefa2675
[sip-router] / modules / db_postgres / pg_fld.c
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: info@iptel.org
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
31 /** \addtogroup postgres
32  * @{ 
33  */
34
35 /** \file 
36  * Data field conversion and type checking functions.
37  */
38
39 #include "pg_fld.h"
40 #include "pg_con.h" /* flags */
41 #include "pg_mod.h"
42
43 #include "../../lib/srdb2/db_drv.h"
44 #include "../../mem/mem.h"
45 #include "../../dprint.h"
46
47 #include <sys/types.h>
48 #include <sys/socket.h>
49 #include <netinet/in.h>
50 #include <stdint.h>
51 #include <string.h>
52
53 /**
54  * This is the epoch time in time_t format, this value is used to convert
55  * timestamp values to/from PostgreSQL format.
56  *  2000-01-01 00:00:00 +0000 as the value of time_t in UTC
57  */
58 #define PG_EPOCH_TIME ((int64_t)946684800)
59
60
61 /** Frees memory used by a pg_fld structure.
62  * This function frees all memory used by a pg_fld structure
63  * @param fld Generic db_fld_t* structure being freed.
64  * @param payload The postgresql extension structure to be freed
65  */
66 static void pg_fld_free(db_fld_t* fld, struct pg_fld* payload)
67 {
68         db_drv_free(&payload->gen);
69         pkg_free(payload);
70 }
71
72
73 int pg_fld(db_fld_t* fld, char* table)
74 {
75         struct pg_fld* res;
76
77         res = (struct pg_fld*)pkg_malloc(sizeof(struct pg_fld));
78         if (res == NULL) {
79                 ERR("postgres: No memory left\n");
80                 return -1;
81         }
82         memset(res, '\0', sizeof(struct pg_fld));
83         if (db_drv_init(&res->gen, pg_fld_free) < 0) goto error;
84
85         DB_SET_PAYLOAD(fld, res);
86         return 0;
87
88  error:
89         if (res) pkg_free(res);
90         return -1;
91 }
92
93
94 union ull {
95         uint64_t ui64;
96         uint32_t ui32[2];
97 };
98
99 static inline uint64_t htonll(uint64_t in)
100 {
101         union ull* p = (union ull*)&in;
102         
103         return ((uint64_t)htonl(p->ui32[0]) << 32) + (uint64_t)htonl(p->ui32[1]);
104 }
105
106
107 static inline uint64_t ntohll(uint64_t in)
108 {
109         union ull* p = (union ull*)&in;
110         return ((uint64_t)ntohl(p->ui32[0]) << 32) + (uint64_t)ntohl(p->ui32[1]);
111 }
112
113
114 static inline void db_int2pg_int4(struct pg_params* dst, int i, 
115                                                                   db_fld_t* src)
116 {
117         struct pg_fld* pfld = DB_GET_PAYLOAD(src);
118         pfld->v.int4[0] = htonl(src->v.int4);
119
120         dst->fmt[i] = 1;
121         dst->val[i] = pfld->v.byte;
122         dst->len[i] = 4;
123 }
124
125
126 static inline void db_int2pg_int2(struct pg_params* dst, int i, 
127                                                                   db_fld_t* src)
128 {
129         struct pg_fld* pfld = DB_GET_PAYLOAD(src);
130         pfld->v.int2[0] = htons(src->v.int4);
131
132         dst->fmt[i] = 1;
133         dst->val[i] = pfld->v.byte;
134         dst->len[i] = 2;
135 }
136
137
138 static inline void db_int2pg_timestamp(struct pg_params* dst, int i, 
139                                                                            db_fld_t* src, unsigned int flags)
140 {
141         struct pg_fld* pfld = DB_GET_PAYLOAD(src);
142         if (flags & PG_INT8_TIMESTAMP) {
143                 pfld->v.int8 = ((int64_t)src->v.int4 - PG_EPOCH_TIME) * 1000000;
144         } else {
145                 pfld->v.dbl = (double)src->v.int4 - (double)PG_EPOCH_TIME;
146         }
147         pfld->v.int8 = htonll(pfld->v.int8);
148
149         dst->fmt[i] = 1;
150         dst->val[i] = pfld->v.byte;
151         dst->len[i] = 8;
152 }
153
154
155 static inline void db_int2pg_int8(struct pg_params* dst, int i,
156                                                                   db_fld_t* src)
157 {
158         struct pg_fld* pfld = DB_GET_PAYLOAD(src);
159         pfld->v.int4[0] = 0;
160         pfld->v.int4[1] = htonl(src->v.int4);
161
162         dst->fmt[i] = 1;
163         dst->val[i] = pfld->v.byte;
164         dst->len[i] = 8;
165 }
166
167
168 static inline void db_int2pg_bool(struct pg_params* dst, int i, db_fld_t* src)
169 {
170         struct pg_fld* pfld = DB_GET_PAYLOAD(src);
171         if (src->v.int4) pfld->v.byte[0] = 1;
172         else pfld->v.byte[0] = 0;
173
174         dst->fmt[i] = 1;
175         dst->val[i] = pfld->v.byte;
176         dst->len[i] = 1;
177 }
178
179
180 static inline void db_int2pg_inet(struct pg_params* dst, int i, db_fld_t* src)
181 {
182         struct pg_fld* pfld = DB_GET_PAYLOAD(src);
183         pfld->v.byte[0] = AF_INET; /* Address family */
184         pfld->v.byte[1] = 32; /* Netmask */
185         pfld->v.byte[2] = 0; /* is CIDR */
186         pfld->v.byte[3] = 4; /* Number of bytes */
187         pfld->v.int4[1] = htonl(src->v.int4); /* Actuall IP address */
188
189         dst->fmt[i] = 1;
190         dst->val[i] = pfld->v.byte;
191         dst->len[i] = 8;
192 }
193
194
195 static inline void db_float2pg_float4(struct pg_params* dst, int i, db_fld_t* src)
196 {
197         struct pg_fld* pfld = DB_GET_PAYLOAD(src);
198         pfld->v.int4[0] = htonl(src->v.int4);
199
200         dst->fmt[i] = 1;
201         dst->val[i] = pfld->v.byte;
202         dst->len[i] = 4;
203 }
204
205
206 static inline void db_float2pg_float8(struct pg_params* dst, int i, db_fld_t* src)
207 {
208         struct pg_fld* pfld = DB_GET_PAYLOAD(src);
209         pfld->v.dbl = src->v.flt;
210         pfld->v.int8 = htonll(pfld->v.int8);
211
212         dst->fmt[i] = 1;
213         dst->val[i] = pfld->v.byte;
214         dst->len[i] = 8;
215 }
216
217
218 static inline void db_double2pg_float8(struct pg_params* dst, int i, db_fld_t* src)
219 {
220         struct pg_fld* pfld = DB_GET_PAYLOAD(src);
221         pfld->v.int8 = htonll(src->v.int8);
222
223         dst->fmt[i] = 1;
224         dst->val[i] = pfld->v.byte;
225         dst->len[i] = 8;
226 }
227
228
229 static inline void db_double2pg_float4(struct pg_params* dst, int i, db_fld_t* src)
230 {
231         struct pg_fld* pfld = DB_GET_PAYLOAD(src);
232         pfld->v.flt = src->v.dbl;
233         pfld->v.int4[0] = htonl(pfld->v.int4[0]);
234
235         dst->fmt[i] = 1;
236         dst->val[i] = pfld->v.byte;
237         dst->len[i] = 4;
238 }
239
240
241 static inline void db_int2pg_bit(struct pg_params* dst, int i, db_fld_t* src)
242 {
243         struct pg_fld* pfld = DB_GET_PAYLOAD(src);
244
245         pfld->v.int4[0] = htonl(32);
246         pfld->v.int4[1] = htonl(src->v.int4);
247
248         dst->fmt[i] = 1;
249         dst->val[i] = pfld->v.byte;
250         dst->len[i] = 8;
251 }
252
253 /*
254 static inline void db_int2pg_varbit(struct pg_params* dst, int i,
255                                                   db_fld_t* src)
256 {
257         unsigned int len = 32;
258         struct pg_fld* pfld = DB_GET_PAYLOAD(src);
259
260         pfld->v.int4[0] = htonl(len);
261         pfld->v.int4[1] = htonl(src->v.int4);
262
263         dst->fmt[i] = 1;
264         dst->val[i] = pfld->v.byte;
265         dst->len[i] = 4 + len / 8 + (len % 8 ? 1 : 0);
266 }
267 */
268
269
270 static inline void db_str2pg_string(struct pg_params* dst, int i,
271                                                                         db_fld_t* src)
272 {
273         dst->fmt[i] = 1;
274         dst->val[i] = src->v.lstr.s;
275         dst->len[i] = src->v.lstr.len;
276 }
277
278 static inline void db_cstr2pg_string(struct pg_params* dst, int i,
279                                                                          db_fld_t* src)
280 {
281         dst->fmt[i] = 0;
282         dst->val[i] = src->v.cstr;
283 }
284
285
286 int pg_fld2pg(struct pg_params* dst, int off, pg_type_t* types,
287                           db_fld_t* src, unsigned int flags)
288 {
289         int i;
290         struct pg_fld* pfld;
291
292         if (src == NULL) return 0;
293
294         for(i = 0; !DB_FLD_EMPTY(src) && !DB_FLD_LAST(src[i]); i++) {
295                 pfld = DB_GET_PAYLOAD(src + i);
296
297                 /* NULL value */
298                 if (src[i].flags & DB_NULL) {
299                         dst->val[off + i] = NULL;
300                         dst->len[off + i] = 0;
301                         continue;
302                 }
303
304                 switch(src[i].type) {
305                 case DB_INT:
306                         if (pfld->oid == types[PG_INT2].oid)
307                                 db_int2pg_int2(dst, off + i, src + i);
308                         else if (pfld->oid == types[PG_INT4].oid)
309                                 db_int2pg_int4(dst, off + i, src + i);
310                         else if ((pfld->oid == types[PG_TIMESTAMP].oid) ||
311                                          (pfld->oid == types[PG_TIMESTAMPTZ].oid))
312                                 db_int2pg_timestamp(dst, off + i, src + i, flags);
313                         else if (pfld->oid == types[PG_INT8].oid)
314                                 db_int2pg_int8(dst, off + i, src + i);
315                         else if (pfld->oid == types[PG_INET].oid)
316                                 db_int2pg_inet(dst, off + i, src + i);
317                         else if (pfld->oid == types[PG_BOOL].oid)
318                                 db_int2pg_bool(dst, off + i, src + i);
319                         else if (pfld->oid == types[PG_BIT].oid)
320                                 db_int2pg_bit(dst, off + i, src + i);
321                         else if (pfld->oid == types[PG_VARBIT].oid)
322                                 db_int2pg_bit(dst, off + i, src + i);
323                         else goto bug;
324                         break;
325
326                 case DB_BITMAP:
327                         if (pfld->oid == types[PG_INT4].oid)
328                                 db_int2pg_int4(dst, off + i, src + i);
329                         else if (pfld->oid == types[PG_INT8].oid)
330                                 db_int2pg_int8(dst, off + i, src + i);
331                         else if (pfld->oid == types[PG_BIT].oid)
332                                 db_int2pg_bit(dst, off + i, src + i);
333                         else if (pfld->oid == types[PG_VARBIT].oid)
334                                 db_int2pg_bit(dst, off + i, src + i);
335                         else goto bug;
336                         break;
337
338                 case DB_DATETIME:
339                         if (pfld->oid == types[PG_INT4].oid)
340                                 db_int2pg_int4(dst, off + i, src + i);
341                         else if ((pfld->oid == types[PG_TIMESTAMP].oid) ||
342                                          (pfld->oid == types[PG_TIMESTAMPTZ].oid))
343                                 db_int2pg_timestamp(dst, off + i, src + i, flags);
344                         else if (pfld->oid == types[PG_INT8].oid)
345                                 db_int2pg_int8(dst, off + i, src + i);
346                         else goto bug;
347                         break;
348                          
349                 case DB_FLOAT:
350                         if (pfld->oid == types[PG_FLOAT4].oid)
351                                 db_float2pg_float4(dst, off + i, src + i);
352                         else if (pfld->oid == types[PG_FLOAT8].oid)
353                                 db_float2pg_float8(dst, off + i, src + i);
354                         else goto bug;
355                         break;
356
357                 case DB_DOUBLE:
358                         if (pfld->oid == types[PG_FLOAT4].oid)
359                                 db_double2pg_float4(dst, off + i, src + i);
360                         else if (pfld->oid == types[PG_FLOAT8].oid)
361                                 db_double2pg_float8(dst, off + i, src + i);
362                         else goto bug;
363                         break;
364
365                 case DB_STR:
366                         if (pfld->oid == types[PG_VARCHAR].oid ||
367                                 pfld->oid == types[PG_BYTE].oid ||
368                                 pfld->oid == types[PG_CHAR].oid ||
369                                 pfld->oid == types[PG_TEXT].oid ||
370                                 pfld->oid == types[PG_BPCHAR].oid)
371                                 db_str2pg_string(dst, off + i, src + i);
372                         else goto bug;
373                         break;
374
375                 case DB_CSTR:
376                         if (pfld->oid == types[PG_VARCHAR].oid ||
377                                 pfld->oid == types[PG_BYTE].oid ||
378                                 pfld->oid == types[PG_CHAR].oid ||
379                                 pfld->oid == types[PG_TEXT].oid ||
380                                 pfld->oid == types[PG_BPCHAR].oid)
381                                 db_cstr2pg_string(dst, off + i, src + i);
382                         else goto bug;
383                         break;
384
385                 case DB_BLOB:
386                         if (pfld->oid == types[PG_BYTE].oid)
387                                 db_str2pg_string(dst, off + i, src + i);
388                         else goto bug;
389                         break;
390
391                 default:
392                         BUG("postgres: Unsupported field type %d in field %s\n",
393                                 src[i].type, src[i].name);
394                         return -1;
395                 }
396         }
397
398         return 0;
399
400  bug:
401         BUG("postgres: Error while converting DB API type %d to Postgres Oid %d\n",
402                 src[i].type, pfld->oid);
403         return -1;
404
405 }
406
407
408 int pg_check_fld2pg(db_fld_t* fld, pg_type_t* types)
409 {
410         int i;
411         const char* name = "UNKNOWN";
412         struct pg_fld* pfld;
413
414         if (fld == NULL) return 0;
415
416         for(i = 0; !DB_FLD_EMPTY(fld) && !DB_FLD_LAST(fld[i]); i++) {
417                 pfld = DB_GET_PAYLOAD(fld + i);
418                 switch(fld[i].type) {
419                 case DB_INT:
420                         if (pfld->oid == types[PG_INT2].oid) continue;
421                         if (pfld->oid == types[PG_INT4].oid) continue;
422                         if (pfld->oid == types[PG_INT8].oid) continue;
423                         if (pfld->oid == types[PG_BOOL].oid) continue;
424                         if (pfld->oid == types[PG_INET].oid) continue;
425                         if (pfld->oid == types[PG_TIMESTAMP].oid) continue;
426                         if (pfld->oid == types[PG_TIMESTAMPTZ].oid) continue;
427                         if (pfld->oid == types[PG_BIT].oid) continue;
428                         if (pfld->oid == types[PG_VARBIT].oid) continue;
429                         break;
430
431                 case DB_BITMAP:
432                         if (pfld->oid == types[PG_INT4].oid) continue;
433                         if (pfld->oid == types[PG_INT8].oid) continue;
434                         if (pfld->oid == types[PG_BIT].oid) continue;
435                         if (pfld->oid == types[PG_VARBIT].oid) continue;
436                         break;
437
438                 case DB_FLOAT:
439                 case DB_DOUBLE:
440                         if (pfld->oid == types[PG_FLOAT4].oid) continue;
441                         if (pfld->oid == types[PG_FLOAT8].oid) continue;
442                         break;
443
444                 case DB_CSTR:
445                 case DB_STR:
446                         if (pfld->oid == types[PG_BYTE].oid) continue;
447                         if (pfld->oid == types[PG_CHAR].oid) continue;
448                         if (pfld->oid == types[PG_TEXT].oid) continue;
449                         if (pfld->oid == types[PG_BPCHAR].oid) continue;
450                         if (pfld->oid == types[PG_VARCHAR].oid) continue;
451                         break;
452
453                 case DB_BLOB:
454                         if (pfld->oid == types[PG_BYTE].oid) continue;
455                         break;
456
457                 case DB_DATETIME:
458                         if (pfld->oid == types[PG_INT4].oid) continue;
459                         if (pfld->oid == types[PG_INT8].oid) continue;
460                         if (pfld->oid == types[PG_TIMESTAMP].oid) continue;
461                         if (pfld->oid == types[PG_TIMESTAMPTZ].oid) continue;
462                         break;
463
464                 default:
465                         BUG("postgres: Unsupported field type %d, bug in postgres module\n",
466                                 fld[i].type);
467                         return -1;
468                 }
469
470                 pg_oid2name(&name, types, pfld->oid);
471                 ERR("postgres: Cannot convert column '%s' of type %s "
472                         "to PostgreSQL column type '%s'\n", 
473                         fld[i].name, db_fld_str[fld[i].type], name);
474                 return -1;
475         }
476         return 0;
477 }
478
479
480 int pg_resolve_param_oids(db_fld_t* vals, db_fld_t* match, int n1, int n2, PGresult* types)
481 {
482         struct pg_fld* pfld;
483         int i;
484
485         if (n1 + n2 != PQnparams(types)) {
486                 ERR("postgres: Number of command parameters do not match\n");
487                 return -1;
488         }
489
490         for(i = 0; i < n1; i++) {
491                 pfld = DB_GET_PAYLOAD(vals + i);
492                 pfld->oid = PQparamtype(types, i);
493         }
494
495         for(i = 0; i < n2; i++) {
496                 pfld = DB_GET_PAYLOAD(match + i);
497                 pfld->oid = PQparamtype(types, n1 + i);
498         }
499
500         return 0;
501 }
502
503
504 int pg_resolve_result_oids(db_fld_t* fld, int n, PGresult* types)
505 {
506         struct pg_fld* pfld;
507         int i;
508         if (fld == NULL) return 0;
509
510         if (n != PQnfields(types)) {
511                 ERR("postgres: Result field numbers do not match\n");
512                 return -1;
513         }
514
515         for(i = 0; i < n; i++) {
516                 pfld = DB_GET_PAYLOAD(fld + i);
517                 pfld->oid = PQftype(types, i);
518         }
519
520         return 0;
521 }
522
523
524 int pg_check_pg2fld(db_fld_t* fld, pg_type_t* types)
525 {
526         int i;
527         const char* name = "UNKNOWN";
528         struct pg_fld* pfld;
529
530         if (fld == NULL) return 0;
531
532         for(i = 0; !DB_FLD_EMPTY(fld) && !DB_FLD_LAST(fld[i]); i++) {
533                 pfld = DB_GET_PAYLOAD(fld + i);
534
535                 if (pfld->oid == 0) {
536                         ERR("postgres: Unknown type fields not supported\n");
537                         return -1;
538                 }
539
540                 switch(fld[i].type) {
541                 case DB_INT:
542                         if (pfld->oid == types[PG_INT2].oid) continue;
543                         if (pfld->oid == types[PG_INT4].oid) continue;
544                         if (pfld->oid == types[PG_INT8].oid) continue;
545                         if (pfld->oid == types[PG_BOOL].oid) continue;
546                         if (pfld->oid == types[PG_INET].oid) continue;
547                         if (pfld->oid == types[PG_TIMESTAMP].oid) continue;
548                         if (pfld->oid == types[PG_TIMESTAMPTZ].oid) continue;
549                         if (pfld->oid == types[PG_BIT].oid) continue;
550                         if (pfld->oid == types[PG_VARBIT].oid) continue;
551                         break;
552
553                 case DB_BITMAP:
554                         if (pfld->oid == types[PG_INT2].oid) continue;
555                         if (pfld->oid == types[PG_INT4].oid) continue;
556                         if (pfld->oid == types[PG_INT8].oid) continue;
557                         if (pfld->oid == types[PG_BIT].oid) continue;
558                         if (pfld->oid == types[PG_VARBIT].oid) continue;
559                         break;
560
561                 case DB_FLOAT:
562                         if (pfld->oid == types[PG_FLOAT4].oid) continue;
563                         break;
564
565                 case DB_DOUBLE:
566                         if (pfld->oid == types[PG_FLOAT4].oid) continue;
567                         if (pfld->oid == types[PG_FLOAT8].oid) continue;
568                         break;
569
570                 case DB_CSTR:
571                         if (pfld->oid == types[PG_CHAR].oid) continue;
572                         if (pfld->oid == types[PG_TEXT].oid) continue;
573                         if (pfld->oid == types[PG_BPCHAR].oid) continue;
574                         if (pfld->oid == types[PG_VARCHAR].oid) continue;
575                         if (pfld->oid == types[PG_INT2].oid) continue;
576                         if (pfld->oid == types[PG_INT4].oid) continue;
577                         break;
578
579                 case DB_STR:
580                 case DB_BLOB:
581                         if (pfld->oid == types[PG_BYTE].oid) continue;
582                         if (pfld->oid == types[PG_CHAR].oid) continue;
583                         if (pfld->oid == types[PG_TEXT].oid) continue;
584                         if (pfld->oid == types[PG_BPCHAR].oid) continue;
585                         if (pfld->oid == types[PG_VARCHAR].oid) continue;
586                         if (pfld->oid == types[PG_INT2].oid) continue;
587                         if (pfld->oid == types[PG_INT4].oid) continue;
588                         break;
589
590                 case DB_DATETIME:
591                         if (pfld->oid == types[PG_INT2].oid) continue;
592                         if (pfld->oid == types[PG_INT4].oid) continue;
593                         if (pfld->oid == types[PG_TIMESTAMP].oid) continue;
594                         if (pfld->oid == types[PG_TIMESTAMPTZ].oid) continue;
595                         break;
596
597                 default:
598                         BUG("postgres: Unsupported field type %d, bug in postgres module\n",
599                                 fld[i].type);
600                         return -1;
601                 }
602
603                 pg_oid2name(&name, types, pfld->oid);
604                 ERR("postgres: Cannot convert column '%s' of type %s "
605                         "to DB API field of type %s\n", 
606                         fld[i].name, name, db_fld_str[fld[i].type]);
607                 return -1;
608         }
609         return 0;
610 }
611
612
613 static inline int pg_int2_2_db_cstr(db_fld_t* fld, char* val, int len)
614 {
615         struct pg_fld* pfld = DB_GET_PAYLOAD(fld);
616         int size, v;
617
618         v = (int16_t)ntohs(*((int16_t*)val));
619
620     size = snprintf(pfld->buf, INT2STR_MAX_LEN, "%-d", v);
621     if (size < 0 || size >= INT2STR_MAX_LEN) {
622         BUG("postgres: Error while converting integer to string\n");
623         return -1;
624     }
625
626         fld->v.cstr = pfld->buf;
627         return 0;
628 }
629
630
631 static inline int pg_int4_2_db_cstr(db_fld_t* fld, char* val, int len)
632 {
633         struct pg_fld* pfld = DB_GET_PAYLOAD(fld);
634         int size, v;
635
636         v = (int32_t)ntohl(*((int32_t*)val));
637
638     size = snprintf(pfld->buf, INT2STR_MAX_LEN, "%-d", v);
639     if (len < 0 || size >= INT2STR_MAX_LEN) {
640         BUG("postgres: Error while converting integer to string\n");
641         return -1;
642     }
643
644         fld->v.cstr = pfld->buf;
645         return 0;
646 }
647
648
649 static inline int pg_int2_2_db_str(db_fld_t* fld, char* val, int len)
650 {
651         struct pg_fld* pfld = DB_GET_PAYLOAD(fld);
652         int size, v;
653
654         v = (int16_t)ntohs(*((int16_t*)val));
655
656     size = snprintf(pfld->buf, INT2STR_MAX_LEN, "%-d", v);
657     if (size < 0 || size >= INT2STR_MAX_LEN) {
658         BUG("postgres: Error while converting integer to string\n");
659         return -1;
660     }
661
662         fld->v.lstr.s = pfld->buf;
663         fld->v.lstr.len = size;
664         return 0;
665 }
666
667
668 static inline int pg_int4_2_db_str(db_fld_t* fld, char* val, int len)
669 {
670         struct pg_fld* pfld = DB_GET_PAYLOAD(fld);
671         int size, v;
672
673         v = (int32_t)ntohl(*((int32_t*)val));
674
675     size = snprintf(pfld->buf, INT2STR_MAX_LEN, "%-d", v);
676     if (size < 0 || size >= INT2STR_MAX_LEN) {
677         BUG("postgres: Error while converting integer to string\n");
678         return -1;
679     }
680
681         fld->v.lstr.s = pfld->buf;
682         fld->v.lstr.len = size;
683         return 0;
684 }
685
686
687 static inline int pg_int2_2_db_int(db_fld_t* fld, char* val, int len)
688 {
689         fld->v.int4 = (int16_t)ntohs(*((int16_t*)val));
690         return 0;
691 }
692
693
694 static inline int pg_int4_2_db_int(db_fld_t* fld, char* val, int len)
695 {
696         fld->v.int4 = (int32_t)ntohl(*((int32_t*)val));
697         return 0;
698 }
699
700
701 static inline int pg_int8_2_db_int(db_fld_t* fld, char* val, int len)
702 {
703         fld->v.int8 = (int64_t)ntohll(*((int64_t*)val));
704         return 0;
705 }
706
707
708 static inline int pg_bool2db_int(db_fld_t* fld, char* val, int len)
709 {
710         fld->v.int4 = val[0];
711         return 0;
712 }
713
714
715 static inline int pg_inet2db_int(db_fld_t* fld, char* val, int len)
716 {
717         if (len != 8 || val[2] != 0) {
718                 ERR("postgres: Unsupported 'inet' format, column %s\n", fld->name);
719                 return -1;
720         }
721
722         if (val[0] != AF_INET) {
723                 ERR("postgres: Unsupported address family %d in field %s\n",
724                         val[0], fld->name);
725                 return -1;
726         }
727
728         if (val[1] != 32) {
729                 WARN("postgres: Netmasks shorter than 32-bits not supported, "
730                          "column %s\n", fld->name);
731         }
732
733         if (val[3] != 4) {
734                 ERR("postgres: Unsupported IP address size %d in column %s\n",
735                         val[3], fld->name);
736                 return -1;
737         }
738
739         fld->v.int4 = (int32_t)ntohl(((int32_t*)val)[1]);
740         return 0;
741 }
742
743
744 static inline int pg_timestamp2db_int(db_fld_t* fld, char* val, int len, 
745                                                                           unsigned int flags)
746 {
747         if (flags & PG_INT8_TIMESTAMP) {
748                 /* int8 format */
749                 fld->v.int4 = (int64_t)ntohll(((int64_t*)val)[0]) / (int64_t)1000000 + PG_EPOCH_TIME;
750         } else {
751                 /* double format */
752                 fld->v.int4 = PG_EPOCH_TIME + ntohll(((int64_t*)val)[0]);
753         }
754         return 0;
755 }
756
757
758 static inline int pg_bit2db_int(db_fld_t* fld, char* val, int len)
759 {
760         int size;
761
762         size = ntohl(*(uint32_t*)val);
763         if (size != 32) {
764                 ERR("postgres: Unsupported bit field size (%d), column %s\n",
765                         size, fld->name);
766                 return -1;
767         }
768         fld->v.int4 = ntohl(((uint32_t*)val)[1]);
769         return 0;
770 }
771
772
773 static inline int pg_float42db_float(db_fld_t* fld, char* val, int len)
774 {
775         fld->v.int4 = (uint32_t)ntohl(*(uint32_t*)val);
776         return 0;
777 }
778
779
780 static inline int pg_float42db_double(db_fld_t* fld, char* val, int len)
781 {
782         float tmp;
783
784         tmp = ntohl(*(uint32_t*)val);
785         fld->v.dbl = tmp;
786         return 0;
787 }
788
789
790 static inline int pg_float82db_double(db_fld_t* fld, char* val, int len)
791 {
792         fld->v.int8 = ntohll(*(uint64_t*)val);
793         return 0;
794 }
795
796
797 static inline int pg_string2db_cstr(db_fld_t* fld, char* val, int len)
798 {
799         fld->v.cstr = val;
800         return 0;
801 }
802
803
804 static inline int pg_string2db_str(db_fld_t* fld, char* val, int len)
805 {
806         fld->v.lstr.s = val;
807         fld->v.lstr.len = len;
808         return 0;
809 }
810
811
812
813 int pg_pg2fld(db_fld_t* dst, PGresult* src, int row, 
814                           pg_type_t* types, unsigned int flags)
815 {
816         char* val;
817         int i, len, ret;
818         Oid type;
819         
820         if (dst == NULL || src == NULL) return 0;
821         ret = 0;
822
823         for(i = 0; !DB_FLD_EMPTY(dst) && !DB_FLD_LAST(dst[i]); i++) {
824                 if (PQgetisnull(src, row, i)) {
825                         dst[i].flags |= DB_NULL;
826                         continue;
827                 } else {
828                         dst[i].flags &= ~DB_NULL;
829                 }
830
831                 type = PQftype(src, i);
832                 val = PQgetvalue(src, row, i);
833                 len = PQgetlength(src, row, i);         
834
835                 switch(dst[i].type) {
836                 case DB_INT:
837                         if (type == types[PG_INT2].oid)
838                                 ret |= pg_int2_2_db_int(dst + i, val, len);
839                         else if (type == types[PG_INT4].oid)
840                                 ret |= pg_int4_2_db_int(dst + i, val, len);
841                         else if (type == types[PG_INT8].oid)
842                                 ret |= pg_int8_2_db_int(dst + i, val, len);
843                         else if (type == types[PG_BOOL].oid)
844                                 ret |= pg_bool2db_int(dst + i, val, len);
845                         else if (type == types[PG_INET].oid)
846                                 ret |= pg_inet2db_int(dst + i, val, len);
847                         else if ((type == types[PG_TIMESTAMP].oid) ||
848                                          (type == types[PG_TIMESTAMPTZ].oid))
849                                 ret |= pg_timestamp2db_int(dst + i, val, len, flags);
850                         else if (type == types[PG_BIT].oid)
851                                 ret |= pg_bit2db_int(dst + i, val, len);
852                         else if (type == types[PG_VARBIT].oid)
853                                 ret |= pg_bit2db_int(dst + i, val, len);
854                         else goto bug;
855                         break;
856
857                 case DB_FLOAT:
858                         if (type == types[PG_FLOAT4].oid)
859                                 ret |= pg_float42db_float(dst + i, val, len);
860                         else goto bug;
861                         break;
862
863                 case DB_DOUBLE:
864                         if (type == types[PG_FLOAT4].oid)
865                                 ret |= pg_float42db_double(dst + i, val, len);
866                         else if (type == types[PG_FLOAT8].oid)
867                                 ret |= pg_float82db_double(dst + i, val, len);
868                         else goto bug;
869                         break;
870
871                 case DB_DATETIME:
872                         if (type == types[PG_INT2].oid)
873                                 ret |= pg_int2_2_db_int(dst + i, val, len);
874                         else if (type == types[PG_INT4].oid)
875                                 ret |= pg_int4_2_db_int(dst + i, val, len);
876                         else if ((type == types[PG_TIMESTAMP].oid) ||
877                                          (type == types[PG_TIMESTAMPTZ].oid))
878                                 ret |= pg_timestamp2db_int(dst + i, val, len, flags);
879                         else goto bug;
880                         break;
881
882                 case DB_CSTR:
883                         if ((type == types[PG_CHAR].oid) ||
884                                 (type == types[PG_TEXT].oid) ||
885                                 (type == types[PG_BPCHAR].oid) ||
886                                 (type == types[PG_VARCHAR].oid))
887                                 ret |= pg_string2db_cstr(dst + i, val, len);
888                         else if (type == types[PG_INT2].oid)
889                                 ret |= pg_int2_2_db_cstr(dst + i, val, len);
890                         else if (type == types[PG_INT4].oid)
891                                 ret |= pg_int4_2_db_cstr(dst + i, val, len);
892                         else goto bug;
893                         break;
894
895                 case DB_STR:
896                 case DB_BLOB:
897                         if ((type == types[PG_BYTE].oid) ||
898                                 (type == types[PG_CHAR].oid) ||
899                                 (type == types[PG_TEXT].oid) ||
900                                 (type == types[PG_BPCHAR].oid) ||
901                                 (type == types[PG_VARCHAR].oid))
902                                 ret |= pg_string2db_str(dst + i, val, len);
903                         else if (type == types[PG_INT2].oid)
904                                 ret |= pg_int2_2_db_str(dst + i, val, len);
905                         else if (type == types[PG_INT4].oid)
906                                 ret |= pg_int4_2_db_str(dst + i, val, len);
907                         else goto bug;
908                         break;
909
910                 case DB_BITMAP:
911                         if (type == types[PG_INT2].oid)
912                                 ret |= pg_int2_2_db_int(dst + i, val, len);
913                         else if (type == types[PG_INT4].oid)
914                                 ret |= pg_int4_2_db_int(dst + i, val, len);
915                         else if (type == types[PG_INT8].oid)
916                                 ret |= pg_int8_2_db_int(dst + i, val, len);
917                         else if (type == types[PG_BIT].oid)
918                                 ret |= pg_bit2db_int(dst + i, val, len);
919                         else if (type == types[PG_VARBIT].oid)
920                                 ret |= pg_bit2db_int(dst + i, val, len);
921                         else goto bug;
922                         break;
923
924                 default:
925                         BUG("postgres: Unsupported field type %d in field %s\n",
926                                 dst[i].type, dst[i].name);
927                         return -1;                      
928                 }
929         }
930         return ret;
931
932  bug:
933         BUG("postgres: Error while converting Postgres Oid %d to DB API type %d\n",
934                 type, dst[i].type);
935         return -1;
936 }
937
938
939 /** @} */