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