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