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