1/* src/interfaces/ecpg/ecpglib/data.c */
2
3#define POSTGRES_ECPG_INTERNAL
4#include "postgres_fe.h"
5
6#include <math.h>
7
8#include "ecpgtype.h"
9#include "ecpglib.h"
10#include "ecpgerrno.h"
11#include "ecpglib_extern.h"
12#include "sqlca.h"
13#include "pgtypes_numeric.h"
14#include "pgtypes_date.h"
15#include "pgtypes_timestamp.h"
16#include "pgtypes_interval.h"
17
18/* returns true if character c is a delimiter for the given array type */
19static bool
20array_delimiter(enum ARRAY_TYPE isarray, char c)
21{
22 if (isarray == ECPG_ARRAY_ARRAY && c == ',')
23 return true;
24
25 if (isarray == ECPG_ARRAY_VECTOR && c == ' ')
26 return true;
27
28 return false;
29}
30
31/* returns true if character c marks the boundary for the given array type */
32static bool
33array_boundary(enum ARRAY_TYPE isarray, char c)
34{
35 if (isarray == ECPG_ARRAY_ARRAY && c == '}')
36 return true;
37
38 if (isarray == ECPG_ARRAY_VECTOR && c == '\0')
39 return true;
40
41 return false;
42}
43
44/* returns true if some garbage is found at the end of the scanned string */
45static bool
46garbage_left(enum ARRAY_TYPE isarray, char **scan_length, enum COMPAT_MODE compat)
47{
48 /*
49 * INFORMIX allows for selecting a numeric into an int, the result is
50 * truncated
51 */
52 if (isarray == ECPG_ARRAY_NONE)
53 {
54 if (INFORMIX_MODE(compat) && **scan_length == '.')
55 {
56 /* skip invalid characters */
57 do
58 {
59 (*scan_length)++;
60 } while (isdigit((unsigned char) **scan_length));
61 }
62
63 if (**scan_length != ' ' && **scan_length != '\0')
64 return true;
65 }
66 else if (ECPG_IS_ARRAY(isarray) && !array_delimiter(isarray, **scan_length) && !array_boundary(isarray, **scan_length))
67 return true;
68
69 return false;
70}
71
72/* stolen code from src/backend/utils/adt/float.c */
73#if defined(WIN32) && !defined(NAN)
74static const uint32 nan[2] = {0xffffffff, 0x7fffffff};
75
76#define NAN (*(const double *) nan)
77#endif
78
79static double
80get_float8_infinity(void)
81{
82#ifdef INFINITY
83 return (double) INFINITY;
84#else
85 return (double) (HUGE_VAL * HUGE_VAL);
86#endif
87}
88
89static double
90get_float8_nan(void)
91{
92 /* (double) NAN doesn't work on some NetBSD/MIPS releases */
93#if defined(NAN) && !(defined(__NetBSD__) && defined(__mips__))
94 return (double) NAN;
95#else
96 return (double) (0.0 / 0.0);
97#endif
98}
99
100static bool
101check_special_value(char *ptr, double *retval, char **endptr)
102{
103 if (pg_strncasecmp(ptr, "NaN", 3) == 0)
104 {
105 *retval = get_float8_nan();
106 *endptr = ptr + 3;
107 return true;
108 }
109 else if (pg_strncasecmp(ptr, "Infinity", 8) == 0)
110 {
111 *retval = get_float8_infinity();
112 *endptr = ptr + 8;
113 return true;
114 }
115 else if (pg_strncasecmp(ptr, "-Infinity", 9) == 0)
116 {
117 *retval = -get_float8_infinity();
118 *endptr = ptr + 9;
119 return true;
120 }
121
122 return false;
123}
124
125/* imported from src/backend/utils/adt/encode.c */
126
127unsigned
128ecpg_hex_enc_len(unsigned srclen)
129{
130 return srclen << 1;
131}
132
133unsigned
134ecpg_hex_dec_len(unsigned srclen)
135{
136 return srclen >> 1;
137}
138
139static inline char
140get_hex(char c)
141{
142 static const int8 hexlookup[128] = {
143 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
144 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
145 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
146 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
147 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
148 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
149 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
150 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
151 };
152 int res = -1;
153
154 if (c > 0 && c < 127)
155 res = hexlookup[(unsigned char) c];
156
157 return (char) res;
158}
159
160static unsigned
161hex_decode(const char *src, unsigned len, char *dst)
162{
163 const char *s,
164 *srcend;
165 char v1,
166 v2,
167 *p;
168
169 srcend = src + len;
170 s = src;
171 p = dst;
172 while (s < srcend)
173 {
174 if (*s == ' ' || *s == '\n' || *s == '\t' || *s == '\r')
175 {
176 s++;
177 continue;
178 }
179 v1 = get_hex(*s++) << 4;
180 if (s >= srcend)
181 return -1;
182
183 v2 = get_hex(*s++);
184 *p++ = v1 | v2;
185 }
186
187 return p - dst;
188}
189
190unsigned
191ecpg_hex_encode(const char *src, unsigned len, char *dst)
192{
193 static const char hextbl[] = "0123456789abcdef";
194 const char *end = src + len;
195
196 while (src < end)
197 {
198 *dst++ = hextbl[(*src >> 4) & 0xF];
199 *dst++ = hextbl[*src & 0xF];
200 src++;
201 }
202 return len * 2;
203}
204
205bool
206ecpg_get_data(const PGresult *results, int act_tuple, int act_field, int lineno,
207 enum ECPGttype type, enum ECPGttype ind_type,
208 char *var, char *ind, long varcharsize, long offset,
209 long ind_offset, enum ARRAY_TYPE isarray, enum COMPAT_MODE compat, bool force_indicator)
210{
211 struct sqlca_t *sqlca = ECPGget_sqlca();
212 char *pval = (char *) PQgetvalue(results, act_tuple, act_field);
213 int binary = PQfformat(results, act_field);
214 int size = PQgetlength(results, act_tuple, act_field);
215 int value_for_indicator = 0;
216 long log_offset;
217
218 if (sqlca == NULL)
219 {
220 ecpg_raise(lineno, ECPG_OUT_OF_MEMORY,
221 ECPG_SQLSTATE_ECPG_OUT_OF_MEMORY, NULL);
222 return false;
223 }
224
225 /*
226 * If we are running in a regression test, do not log the offset variable,
227 * it depends on the machine's alignment.
228 */
229 if (ecpg_internal_regression_mode)
230 log_offset = -1;
231 else
232 log_offset = offset;
233
234 ecpg_log("ecpg_get_data on line %d: RESULT: %s offset: %ld; array: %s\n", lineno, pval ? (binary ? "BINARY" : pval) : "EMPTY", log_offset, ECPG_IS_ARRAY(isarray) ? "yes" : "no");
235
236 /* pval is a pointer to the value */
237 if (!pval)
238 {
239 /*
240 * This should never happen because we already checked that we found
241 * at least one tuple, but let's play it safe.
242 */
243 ecpg_raise(lineno, ECPG_NOT_FOUND, ECPG_SQLSTATE_NO_DATA, NULL);
244 return false;
245 }
246
247 /* We will have to decode the value */
248
249 /*
250 * check for null value and set indicator accordingly, i.e. -1 if NULL and
251 * 0 if not
252 */
253 if (PQgetisnull(results, act_tuple, act_field))
254 value_for_indicator = -1;
255
256 switch (ind_type)
257 {
258 case ECPGt_short:
259 case ECPGt_unsigned_short:
260 *((short *) (ind + ind_offset * act_tuple)) = value_for_indicator;
261 break;
262 case ECPGt_int:
263 case ECPGt_unsigned_int:
264 *((int *) (ind + ind_offset * act_tuple)) = value_for_indicator;
265 break;
266 case ECPGt_long:
267 case ECPGt_unsigned_long:
268 *((long *) (ind + ind_offset * act_tuple)) = value_for_indicator;
269 break;
270#ifdef HAVE_LONG_LONG_INT
271 case ECPGt_long_long:
272 case ECPGt_unsigned_long_long:
273 *((long long int *) (ind + ind_offset * act_tuple)) = value_for_indicator;
274 break;
275#endif /* HAVE_LONG_LONG_INT */
276 case ECPGt_NO_INDICATOR:
277 if (value_for_indicator == -1)
278 {
279 if (force_indicator == false)
280 {
281 /*
282 * Informix has an additional way to specify NULLs note
283 * that this uses special values to denote NULL
284 */
285 ECPGset_noind_null(type, var + offset * act_tuple);
286 }
287 else
288 {
289 ecpg_raise(lineno, ECPG_MISSING_INDICATOR,
290 ECPG_SQLSTATE_NULL_VALUE_NO_INDICATOR_PARAMETER,
291 NULL);
292 return false;
293 }
294 }
295 break;
296 default:
297 ecpg_raise(lineno, ECPG_UNSUPPORTED,
298 ECPG_SQLSTATE_ECPG_INTERNAL_ERROR,
299 ecpg_type_name(ind_type));
300 return false;
301 break;
302 }
303
304 if (value_for_indicator == -1)
305 return true;
306
307 /* let's check if it really is an array if it should be one */
308 if (isarray == ECPG_ARRAY_ARRAY)
309 {
310 if (*pval != '{')
311 {
312 ecpg_raise(lineno, ECPG_DATA_NOT_ARRAY,
313 ECPG_SQLSTATE_DATATYPE_MISMATCH, NULL);
314 return false;
315 }
316
317 switch (type)
318 {
319 case ECPGt_char:
320 case ECPGt_unsigned_char:
321 case ECPGt_varchar:
322 case ECPGt_string:
323 break;
324
325 default:
326 pval++;
327 break;
328 }
329 }
330
331 do
332 {
333 if (binary)
334 {
335 if (varcharsize == 0 || varcharsize * offset >= size)
336 memcpy(var + offset * act_tuple, pval, size);
337 else
338 {
339 memcpy(var + offset * act_tuple, pval, varcharsize * offset);
340
341 if (varcharsize * offset < size)
342 {
343 /* truncation */
344 switch (ind_type)
345 {
346 case ECPGt_short:
347 case ECPGt_unsigned_short:
348 *((short *) (ind + ind_offset * act_tuple)) = size;
349 break;
350 case ECPGt_int:
351 case ECPGt_unsigned_int:
352 *((int *) (ind + ind_offset * act_tuple)) = size;
353 break;
354 case ECPGt_long:
355 case ECPGt_unsigned_long:
356 *((long *) (ind + ind_offset * act_tuple)) = size;
357 break;
358#ifdef HAVE_LONG_LONG_INT
359 case ECPGt_long_long:
360 case ECPGt_unsigned_long_long:
361 *((long long int *) (ind + ind_offset * act_tuple)) = size;
362 break;
363#endif /* HAVE_LONG_LONG_INT */
364 default:
365 break;
366 }
367 sqlca->sqlwarn[0] = sqlca->sqlwarn[1] = 'W';
368 }
369 }
370 pval += size;
371 }
372 else
373 {
374 switch (type)
375 {
376 long res;
377 unsigned long ures;
378 double dres;
379 char *scan_length;
380 numeric *nres;
381 date ddres;
382 timestamp tres;
383 interval *ires;
384 char *endptr,
385 endchar;
386
387 case ECPGt_short:
388 case ECPGt_int:
389 case ECPGt_long:
390 res = strtol(pval, &scan_length, 10);
391 if (garbage_left(isarray, &scan_length, compat))
392 {
393 ecpg_raise(lineno, ECPG_INT_FORMAT,
394 ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
395 return false;
396 }
397 pval = scan_length;
398
399 switch (type)
400 {
401 case ECPGt_short:
402 *((short *) (var + offset * act_tuple)) = (short) res;
403 break;
404 case ECPGt_int:
405 *((int *) (var + offset * act_tuple)) = (int) res;
406 break;
407 case ECPGt_long:
408 *((long *) (var + offset * act_tuple)) = (long) res;
409 break;
410 default:
411 /* Cannot happen */
412 break;
413 }
414 break;
415
416 case ECPGt_unsigned_short:
417 case ECPGt_unsigned_int:
418 case ECPGt_unsigned_long:
419 ures = strtoul(pval, &scan_length, 10);
420 if (garbage_left(isarray, &scan_length, compat))
421 {
422 ecpg_raise(lineno, ECPG_UINT_FORMAT,
423 ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
424 return false;
425 }
426 pval = scan_length;
427
428 switch (type)
429 {
430 case ECPGt_unsigned_short:
431 *((unsigned short *) (var + offset * act_tuple)) = (unsigned short) ures;
432 break;
433 case ECPGt_unsigned_int:
434 *((unsigned int *) (var + offset * act_tuple)) = (unsigned int) ures;
435 break;
436 case ECPGt_unsigned_long:
437 *((unsigned long *) (var + offset * act_tuple)) = (unsigned long) ures;
438 break;
439 default:
440 /* Cannot happen */
441 break;
442 }
443 break;
444
445#ifdef HAVE_LONG_LONG_INT
446#ifdef HAVE_STRTOLL
447 case ECPGt_long_long:
448 *((long long int *) (var + offset * act_tuple)) = strtoll(pval, &scan_length, 10);
449 if (garbage_left(isarray, &scan_length, compat))
450 {
451 ecpg_raise(lineno, ECPG_INT_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
452 return false;
453 }
454 pval = scan_length;
455
456 break;
457#endif /* HAVE_STRTOLL */
458#ifdef HAVE_STRTOULL
459 case ECPGt_unsigned_long_long:
460 *((unsigned long long int *) (var + offset * act_tuple)) = strtoull(pval, &scan_length, 10);
461 if (garbage_left(isarray, &scan_length, compat))
462 {
463 ecpg_raise(lineno, ECPG_UINT_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
464 return false;
465 }
466 pval = scan_length;
467
468 break;
469#endif /* HAVE_STRTOULL */
470#endif /* HAVE_LONG_LONG_INT */
471
472 case ECPGt_float:
473 case ECPGt_double:
474 if (isarray && *pval == '"')
475 pval++;
476
477 if (!check_special_value(pval, &dres, &scan_length))
478 dres = strtod(pval, &scan_length);
479
480 if (isarray && *scan_length == '"')
481 scan_length++;
482
483 /* no special INFORMIX treatment for floats */
484 if (garbage_left(isarray, &scan_length, ECPG_COMPAT_PGSQL))
485 {
486 ecpg_raise(lineno, ECPG_FLOAT_FORMAT,
487 ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
488 return false;
489 }
490 pval = scan_length;
491
492 switch (type)
493 {
494 case ECPGt_float:
495 *((float *) (var + offset * act_tuple)) = dres;
496 break;
497 case ECPGt_double:
498 *((double *) (var + offset * act_tuple)) = dres;
499 break;
500 default:
501 /* Cannot happen */
502 break;
503 }
504 break;
505
506 case ECPGt_bool:
507 if (pval[0] == 'f' && pval[1] == '\0')
508 {
509 *((bool *) (var + offset * act_tuple)) = false;
510 pval++;
511 break;
512 }
513 else if (pval[0] == 't' && pval[1] == '\0')
514 {
515 *((bool *) (var + offset * act_tuple)) = true;
516 pval++;
517 break;
518 }
519 else if (pval[0] == '\0' && PQgetisnull(results, act_tuple, act_field))
520 {
521 /* NULL is valid */
522 break;
523 }
524
525 ecpg_raise(lineno, ECPG_CONVERT_BOOL,
526 ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
527 return false;
528 break;
529
530 case ECPGt_bytea:
531 {
532 struct ECPGgeneric_varchar *variable =
533 (struct ECPGgeneric_varchar *) (var + offset * act_tuple);
534 long dst_size,
535 src_size,
536 dec_size;
537
538 dst_size = ecpg_hex_enc_len(varcharsize);
539 src_size = size - 2; /* exclude backslash + 'x' */
540 dec_size = src_size < dst_size ? src_size : dst_size;
541 variable->len = hex_decode(pval + 2, dec_size, variable->arr);
542
543 if (dst_size < src_size)
544 {
545 long rcv_size = ecpg_hex_dec_len(size - 2);
546
547 /* truncation */
548 switch (ind_type)
549 {
550 case ECPGt_short:
551 case ECPGt_unsigned_short:
552 *((short *) (ind + ind_offset * act_tuple)) = rcv_size;
553 break;
554 case ECPGt_int:
555 case ECPGt_unsigned_int:
556 *((int *) (ind + ind_offset * act_tuple)) = rcv_size;
557 break;
558 case ECPGt_long:
559 case ECPGt_unsigned_long:
560 *((long *) (ind + ind_offset * act_tuple)) = rcv_size;
561 break;
562#ifdef HAVE_LONG_LONG_INT
563 case ECPGt_long_long:
564 case ECPGt_unsigned_long_long:
565 *((long long int *) (ind + ind_offset * act_tuple)) = rcv_size;
566 break;
567#endif /* HAVE_LONG_LONG_INT */
568 default:
569 break;
570 }
571 sqlca->sqlwarn[0] = sqlca->sqlwarn[1] = 'W';
572 }
573
574 pval += size;
575
576 }
577 break;
578
579 case ECPGt_char:
580 case ECPGt_unsigned_char:
581 case ECPGt_string:
582 {
583 char *str = (char *) (var + offset * act_tuple);
584
585 /*
586 * If varcharsize is unknown and the offset is that of
587 * char *, then this variable represents the array of
588 * character pointers. So, use extra indirection.
589 */
590 if (varcharsize == 0 && offset == sizeof(char *))
591 str = *(char **) str;
592
593 if (varcharsize == 0 || varcharsize > size)
594 {
595 /*
596 * compatibility mode, blank pad and null
597 * terminate char array
598 */
599 if (ORACLE_MODE(compat) && (type == ECPGt_char || type == ECPGt_unsigned_char))
600 {
601 memset(str, ' ', varcharsize);
602 memcpy(str, pval, size);
603 str[varcharsize - 1] = '\0';
604
605 /*
606 * compatibility mode empty string gets -1
607 * indicator but no warning
608 */
609 if (size == 0)
610 {
611 /* truncation */
612 switch (ind_type)
613 {
614 case ECPGt_short:
615 case ECPGt_unsigned_short:
616 *((short *) (ind + ind_offset * act_tuple)) = -1;
617 break;
618 case ECPGt_int:
619 case ECPGt_unsigned_int:
620 *((int *) (ind + ind_offset * act_tuple)) = -1;
621 break;
622 case ECPGt_long:
623 case ECPGt_unsigned_long:
624 *((long *) (ind + ind_offset * act_tuple)) = -1;
625 break;
626#ifdef HAVE_LONG_LONG_INT
627 case ECPGt_long_long:
628 case ECPGt_unsigned_long_long:
629 *((long long int *) (ind + ind_offset * act_tuple)) = -1;
630 break;
631#endif /* HAVE_LONG_LONG_INT */
632 default:
633 break;
634 }
635 }
636 }
637 else
638 {
639 strncpy(str, pval, size + 1);
640 }
641 /* do the rtrim() */
642 if (type == ECPGt_string)
643 {
644 char *last = str + size;
645
646 while (last > str && (*last == ' ' || *last == '\0'))
647 {
648 *last = '\0';
649 last--;
650 }
651 }
652 }
653 else
654 {
655 strncpy(str, pval, varcharsize);
656
657 /* compatibility mode, null terminate char array */
658 if (ORACLE_MODE(compat) && (varcharsize - 1) < size)
659 {
660 if (type == ECPGt_char || type == ECPGt_unsigned_char)
661 str[varcharsize - 1] = '\0';
662 }
663
664 if (varcharsize < size || (ORACLE_MODE(compat) && (varcharsize - 1) < size))
665 {
666 /* truncation */
667 switch (ind_type)
668 {
669 case ECPGt_short:
670 case ECPGt_unsigned_short:
671 *((short *) (ind + ind_offset * act_tuple)) = size;
672 break;
673 case ECPGt_int:
674 case ECPGt_unsigned_int:
675 *((int *) (ind + ind_offset * act_tuple)) = size;
676 break;
677 case ECPGt_long:
678 case ECPGt_unsigned_long:
679 *((long *) (ind + ind_offset * act_tuple)) = size;
680 break;
681#ifdef HAVE_LONG_LONG_INT
682 case ECPGt_long_long:
683 case ECPGt_unsigned_long_long:
684 *((long long int *) (ind + ind_offset * act_tuple)) = size;
685 break;
686#endif /* HAVE_LONG_LONG_INT */
687 default:
688 break;
689 }
690 sqlca->sqlwarn[0] = sqlca->sqlwarn[1] = 'W';
691 }
692 }
693 pval += size;
694 }
695 break;
696
697 case ECPGt_varchar:
698 {
699 struct ECPGgeneric_varchar *variable =
700 (struct ECPGgeneric_varchar *) (var + offset * act_tuple);
701
702 variable->len = size;
703 if (varcharsize == 0)
704 strncpy(variable->arr, pval, variable->len);
705 else
706 {
707 strncpy(variable->arr, pval, varcharsize);
708
709 if (variable->len > varcharsize)
710 {
711 /* truncation */
712 switch (ind_type)
713 {
714 case ECPGt_short:
715 case ECPGt_unsigned_short:
716 *((short *) (ind + ind_offset * act_tuple)) = variable->len;
717 break;
718 case ECPGt_int:
719 case ECPGt_unsigned_int:
720 *((int *) (ind + ind_offset * act_tuple)) = variable->len;
721 break;
722 case ECPGt_long:
723 case ECPGt_unsigned_long:
724 *((long *) (ind + ind_offset * act_tuple)) = variable->len;
725 break;
726#ifdef HAVE_LONG_LONG_INT
727 case ECPGt_long_long:
728 case ECPGt_unsigned_long_long:
729 *((long long int *) (ind + ind_offset * act_tuple)) = variable->len;
730 break;
731#endif /* HAVE_LONG_LONG_INT */
732 default:
733 break;
734 }
735 sqlca->sqlwarn[0] = sqlca->sqlwarn[1] = 'W';
736
737 variable->len = varcharsize;
738 }
739 }
740 pval += size;
741 }
742 break;
743
744 case ECPGt_decimal:
745 case ECPGt_numeric:
746 for (endptr = pval; *endptr && *endptr != ',' && *endptr != '}'; endptr++);
747 endchar = *endptr;
748 *endptr = '\0';
749 nres = PGTYPESnumeric_from_asc(pval, &scan_length);
750 *endptr = endchar;
751
752 /* did we get an error? */
753 if (nres == NULL)
754 {
755 ecpg_log("ecpg_get_data on line %d: RESULT %s; errno %d\n",
756 lineno, pval, errno);
757
758 if (INFORMIX_MODE(compat))
759 {
760 /*
761 * Informix wants its own NULL value here instead
762 * of an error
763 */
764 nres = PGTYPESnumeric_new();
765 if (nres)
766 ECPGset_noind_null(ECPGt_numeric, nres);
767 else
768 {
769 ecpg_raise(lineno, ECPG_OUT_OF_MEMORY,
770 ECPG_SQLSTATE_ECPG_OUT_OF_MEMORY, NULL);
771 return false;
772 }
773 }
774 else
775 {
776 ecpg_raise(lineno, ECPG_NUMERIC_FORMAT,
777 ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
778 return false;
779 }
780 }
781 else
782 {
783 if (!isarray && garbage_left(isarray, &scan_length, compat))
784 {
785 free(nres);
786 ecpg_raise(lineno, ECPG_NUMERIC_FORMAT,
787 ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
788 return false;
789 }
790 }
791 pval = scan_length;
792
793 if (type == ECPGt_numeric)
794 PGTYPESnumeric_copy(nres, (numeric *) (var + offset * act_tuple));
795 else
796 PGTYPESnumeric_to_decimal(nres, (decimal *) (var + offset * act_tuple));
797
798 PGTYPESnumeric_free(nres);
799 break;
800
801 case ECPGt_interval:
802 if (*pval == '"')
803 pval++;
804
805 for (endptr = pval; *endptr && *endptr != ',' && *endptr != '"' && *endptr != '}'; endptr++);
806 endchar = *endptr;
807 *endptr = '\0';
808 ires = PGTYPESinterval_from_asc(pval, &scan_length);
809 *endptr = endchar;
810
811 /* did we get an error? */
812 if (ires == NULL)
813 {
814 ecpg_log("ecpg_get_data on line %d: RESULT %s; errno %d\n",
815 lineno, pval, errno);
816
817 if (INFORMIX_MODE(compat))
818 {
819 /*
820 * Informix wants its own NULL value here instead
821 * of an error
822 */
823 ires = (interval *) ecpg_alloc(sizeof(interval), lineno);
824 if (!ires)
825 return false;
826
827 ECPGset_noind_null(ECPGt_interval, ires);
828 }
829 else
830 {
831 ecpg_raise(lineno, ECPG_INTERVAL_FORMAT,
832 ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
833 return false;
834 }
835 }
836 else
837 {
838 if (*scan_length == '"')
839 scan_length++;
840
841 if (!isarray && garbage_left(isarray, &scan_length, compat))
842 {
843 free(ires);
844 ecpg_raise(lineno, ECPG_INTERVAL_FORMAT,
845 ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
846 return false;
847 }
848 }
849 pval = scan_length;
850
851 PGTYPESinterval_copy(ires, (interval *) (var + offset * act_tuple));
852 free(ires);
853 break;
854
855 case ECPGt_date:
856 if (*pval == '"')
857 pval++;
858
859 for (endptr = pval; *endptr && *endptr != ',' && *endptr != '"' && *endptr != '}'; endptr++);
860 endchar = *endptr;
861 *endptr = '\0';
862 ddres = PGTYPESdate_from_asc(pval, &scan_length);
863 *endptr = endchar;
864
865 /* did we get an error? */
866 if (errno != 0)
867 {
868 ecpg_log("ecpg_get_data on line %d: RESULT %s; errno %d\n",
869 lineno, pval, errno);
870
871 if (INFORMIX_MODE(compat))
872 {
873 /*
874 * Informix wants its own NULL value here instead
875 * of an error
876 */
877 ECPGset_noind_null(ECPGt_date, &ddres);
878 }
879 else
880 {
881 ecpg_raise(lineno, ECPG_DATE_FORMAT,
882 ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
883 return false;
884 }
885 }
886 else
887 {
888 if (*scan_length == '"')
889 scan_length++;
890
891 if (!isarray && garbage_left(isarray, &scan_length, compat))
892 {
893 ecpg_raise(lineno, ECPG_DATE_FORMAT,
894 ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
895 return false;
896 }
897 }
898
899 *((date *) (var + offset * act_tuple)) = ddres;
900 pval = scan_length;
901 break;
902
903 case ECPGt_timestamp:
904 if (*pval == '"')
905 pval++;
906
907 for (endptr = pval; *endptr && *endptr != ',' && *endptr != '"' && *endptr != '}'; endptr++);
908 endchar = *endptr;
909 *endptr = '\0';
910 tres = PGTYPEStimestamp_from_asc(pval, &scan_length);
911 *endptr = endchar;
912
913 /* did we get an error? */
914 if (errno != 0)
915 {
916 ecpg_log("ecpg_get_data on line %d: RESULT %s; errno %d\n",
917 lineno, pval, errno);
918
919 if (INFORMIX_MODE(compat))
920 {
921 /*
922 * Informix wants its own NULL value here instead
923 * of an error
924 */
925 ECPGset_noind_null(ECPGt_timestamp, &tres);
926 }
927 else
928 {
929 ecpg_raise(lineno, ECPG_TIMESTAMP_FORMAT,
930 ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
931 return false;
932 }
933 }
934 else
935 {
936 if (*scan_length == '"')
937 scan_length++;
938
939 if (!isarray && garbage_left(isarray, &scan_length, compat))
940 {
941 ecpg_raise(lineno, ECPG_TIMESTAMP_FORMAT,
942 ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
943 return false;
944 }
945 }
946
947 *((timestamp *) (var + offset * act_tuple)) = tres;
948 pval = scan_length;
949 break;
950
951 default:
952 ecpg_raise(lineno, ECPG_UNSUPPORTED,
953 ECPG_SQLSTATE_ECPG_INTERNAL_ERROR,
954 ecpg_type_name(type));
955 return false;
956 break;
957 }
958 if (ECPG_IS_ARRAY(isarray))
959 {
960 bool string = false;
961
962 /* set array to next entry */
963 ++act_tuple;
964
965 /* set pval to the next entry */
966
967 /*
968 * *pval != '\0' should not be needed, but is used as a safety
969 * guard
970 */
971 for (; *pval != '\0' && (string || (!array_delimiter(isarray, *pval) && !array_boundary(isarray, *pval))); ++pval)
972 if (*pval == '"')
973 string = string ? false : true;
974
975 if (array_delimiter(isarray, *pval))
976 ++pval;
977 }
978 }
979 } while (*pval != '\0' && !array_boundary(isarray, *pval));
980
981 return true;
982}
983