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