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 */
19 static bool
20 array_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 */
32 static bool
33 array_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 */
45 static bool
46 garbage_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)
74 static const uint32 nan[2] = {0xffffffff, 0x7fffffff};
75 
76 #define NAN (*(const double *) nan)
77 #endif
78 
79 static double
80 get_float8_infinity(void)
81 {
82 #ifdef INFINITY
83 	return (double) INFINITY;
84 #else
85 	return (double) (HUGE_VAL * HUGE_VAL);
86 #endif
87 }
88 
89 static double
90 get_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 
100 static bool
101 check_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 
127 unsigned
128 ecpg_hex_enc_len(unsigned srclen)
129 {
130 	return srclen << 1;
131 }
132 
133 unsigned
134 ecpg_hex_dec_len(unsigned srclen)
135 {
136 	return srclen >> 1;
137 }
138 
139 static inline char
140 get_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 
160 static unsigned
161 hex_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 
190 unsigned
191 ecpg_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 
205 bool
206 ecpg_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_bytea *variable =
533 						(struct ECPGgeneric_bytea *) (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