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