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 444 : array_delimiter(enum ARRAY_TYPE isarray, char c)
21 : {
22 444 : if (isarray == ECPG_ARRAY_ARRAY && c == ',')
23 396 : return true;
24 :
25 48 : if (isarray == ECPG_ARRAY_VECTOR && c == ' ')
26 0 : return true;
27 :
28 48 : return false;
29 : }
30 :
31 : /* returns true if character c marks the boundary for the given array type */
32 : static bool
33 224 : array_boundary(enum ARRAY_TYPE isarray, char c)
34 : {
35 224 : if (isarray == ECPG_ARRAY_ARRAY && c == '}')
36 44 : return true;
37 :
38 180 : if (isarray == ECPG_ARRAY_VECTOR && c == '\0')
39 0 : return true;
40 :
41 180 : return false;
42 : }
43 :
44 : /* returns true if some garbage is found at the end of the scanned string */
45 : static bool
46 1156 : 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 1156 : if (isarray == ECPG_ARRAY_NONE)
53 : {
54 1116 : if (INFORMIX_MODE(compat) && **scan_length == '.')
55 : {
56 : /* skip invalid characters */
57 : do
58 : {
59 0 : (*scan_length)++;
60 0 : } while (isdigit((unsigned char) **scan_length));
61 : }
62 :
63 1116 : if (**scan_length != ' ' && **scan_length != '\0')
64 0 : return true;
65 : }
66 40 : else if (ECPG_IS_ARRAY(isarray) && !array_delimiter(isarray, **scan_length) && !array_boundary(isarray, **scan_length))
67 0 : return true;
68 :
69 1156 : return false;
70 : }
71 :
72 :
73 : /*
74 : * Portability wrappers borrowed from src/include/utils/float.h
75 : */
76 : static double
77 32 : get_float8_infinity(void)
78 : {
79 32 : return (double) INFINITY;
80 : }
81 :
82 : static double
83 16 : get_float8_nan(void)
84 : {
85 16 : return (double) NAN;
86 : }
87 :
88 :
89 : static bool
90 180 : check_special_value(char *ptr, double *retval, char **endptr)
91 : {
92 180 : if (pg_strncasecmp(ptr, "NaN", 3) == 0)
93 : {
94 16 : *retval = get_float8_nan();
95 16 : *endptr = ptr + 3;
96 16 : return true;
97 : }
98 164 : else if (pg_strncasecmp(ptr, "Infinity", 8) == 0)
99 : {
100 16 : *retval = get_float8_infinity();
101 16 : *endptr = ptr + 8;
102 16 : return true;
103 : }
104 148 : else if (pg_strncasecmp(ptr, "-Infinity", 9) == 0)
105 : {
106 16 : *retval = -get_float8_infinity();
107 16 : *endptr = ptr + 9;
108 16 : return true;
109 : }
110 :
111 132 : return false;
112 : }
113 :
114 : /* imported from src/backend/utils/adt/encode.c */
115 :
116 : unsigned
117 140 : ecpg_hex_enc_len(unsigned srclen)
118 : {
119 140 : return srclen << 1;
120 : }
121 :
122 : unsigned
123 12 : ecpg_hex_dec_len(unsigned srclen)
124 : {
125 12 : return srclen >> 1;
126 : }
127 :
128 : static inline char
129 36552 : 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 36552 : int res = -1;
142 :
143 36552 : if (c > 0 && c < 127)
144 36552 : res = hexlookup[(unsigned char) c];
145 :
146 36552 : return (char) res;
147 : }
148 :
149 : static unsigned
150 36 : hex_decode(const char *src, unsigned len, char *dst)
151 : {
152 : const char *s,
153 : *srcend;
154 : char v1,
155 : v2,
156 : *p;
157 :
158 36 : srcend = src + len;
159 36 : s = src;
160 36 : p = dst;
161 18312 : while (s < srcend)
162 : {
163 18276 : if (*s == ' ' || *s == '\n' || *s == '\t' || *s == '\r')
164 : {
165 0 : s++;
166 0 : continue;
167 : }
168 18276 : v1 = get_hex(*s++) << 4;
169 18276 : if (s >= srcend)
170 0 : return -1;
171 :
172 18276 : v2 = get_hex(*s++);
173 18276 : *p++ = v1 | v2;
174 : }
175 :
176 36 : return p - dst;
177 : }
178 :
179 : unsigned
180 52 : ecpg_hex_encode(const char *src, unsigned len, char *dst)
181 : {
182 : static const char hextbl[] = "0123456789abcdef";
183 52 : const char *end = src + len;
184 :
185 26676 : while (src < end)
186 : {
187 26624 : *dst++ = hextbl[(*src >> 4) & 0xF];
188 26624 : *dst++ = hextbl[*src & 0xF];
189 26624 : src++;
190 : }
191 52 : return len * 2;
192 : }
193 :
194 : bool
195 5732 : 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 5732 : struct sqlca_t *sqlca = ECPGget_sqlca();
201 5732 : char *pval = (char *) PQgetvalue(results, act_tuple, act_field);
202 5732 : int binary = PQfformat(results, act_field);
203 5732 : int size = PQgetlength(results, act_tuple, act_field);
204 5732 : int value_for_indicator = 0;
205 : long log_offset;
206 :
207 5732 : 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 5732 : if (ecpg_internal_regression_mode)
219 2388 : log_offset = -1;
220 : else
221 3344 : log_offset = offset;
222 :
223 5732 : 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 5732 : 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 5732 : if (PQgetisnull(results, act_tuple, act_field))
243 192 : value_for_indicator = -1;
244 :
245 5732 : switch (ind_type)
246 : {
247 200 : case ECPGt_short:
248 : case ECPGt_unsigned_short:
249 200 : *((short *) (ind + ind_offset * act_tuple)) = value_for_indicator;
250 200 : break;
251 320 : case ECPGt_int:
252 : case ECPGt_unsigned_int:
253 320 : *((int *) (ind + ind_offset * act_tuple)) = value_for_indicator;
254 320 : break;
255 40 : case ECPGt_long:
256 : case ECPGt_unsigned_long:
257 40 : *((long *) (ind + ind_offset * act_tuple)) = value_for_indicator;
258 40 : break;
259 0 : 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 5172 : case ECPGt_NO_INDICATOR:
264 5172 : if (value_for_indicator == -1)
265 : {
266 72 : 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 48 : ECPGset_noind_null(type, var + offset * act_tuple);
273 : }
274 : else
275 : {
276 24 : ecpg_raise(lineno, ECPG_MISSING_INDICATOR,
277 : ECPG_SQLSTATE_NULL_VALUE_NO_INDICATOR_PARAMETER,
278 : NULL);
279 24 : return false;
280 : }
281 : }
282 5148 : break;
283 0 : default:
284 0 : ecpg_raise(lineno, ECPG_UNSUPPORTED,
285 : ECPG_SQLSTATE_ECPG_INTERNAL_ERROR,
286 : ecpg_type_name(ind_type));
287 0 : return false;
288 : break;
289 : }
290 :
291 5708 : if (value_for_indicator == -1)
292 168 : return true;
293 :
294 : /* let's check if it really is an array if it should be one */
295 5540 : if (isarray == ECPG_ARRAY_ARRAY)
296 : {
297 24 : 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 24 : switch (type)
305 : {
306 4 : case ECPGt_char:
307 : case ECPGt_unsigned_char:
308 : case ECPGt_varchar:
309 : case ECPGt_string:
310 4 : break;
311 :
312 20 : default:
313 20 : pval++;
314 20 : break;
315 : }
316 : }
317 :
318 : do
319 : {
320 5720 : if (binary)
321 : {
322 16 : if (varcharsize == 0 || varcharsize * offset >= size)
323 16 : 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 0 : case ECPGt_short:
334 : case ECPGt_unsigned_short:
335 0 : *((short *) (ind + ind_offset * act_tuple)) = size;
336 0 : break;
337 0 : case ECPGt_int:
338 : case ECPGt_unsigned_int:
339 0 : *((int *) (ind + ind_offset * act_tuple)) = size;
340 0 : break;
341 0 : case ECPGt_long:
342 : case ECPGt_unsigned_long:
343 0 : *((long *) (ind + ind_offset * act_tuple)) = size;
344 0 : break;
345 0 : 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 0 : default:
350 0 : break;
351 : }
352 0 : sqlca->sqlwarn[0] = sqlca->sqlwarn[1] = 'W';
353 : }
354 : }
355 16 : pval += size;
356 : }
357 : else
358 : {
359 5704 : 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 976 : case ECPGt_short:
373 : case ECPGt_int:
374 : case ECPGt_long:
375 976 : res = strtol(pval, &scan_length, 10);
376 976 : if (garbage_left(isarray, &scan_length, compat))
377 : {
378 0 : ecpg_raise(lineno, ECPG_INT_FORMAT,
379 : ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
380 0 : return false;
381 : }
382 976 : pval = scan_length;
383 :
384 : switch (type)
385 : {
386 64 : case ECPGt_short:
387 64 : *((short *) (var + offset * act_tuple)) = (short) res;
388 64 : break;
389 860 : case ECPGt_int:
390 860 : *((int *) (var + offset * act_tuple)) = (int) res;
391 860 : break;
392 52 : case ECPGt_long:
393 52 : *((long *) (var + offset * act_tuple)) = (long) res;
394 52 : break;
395 0 : default:
396 : /* Cannot happen */
397 0 : break;
398 : }
399 976 : break;
400 :
401 0 : 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 : ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
409 0 : return false;
410 : }
411 0 : pval = scan_length;
412 :
413 : switch (type)
414 : {
415 0 : case ECPGt_unsigned_short:
416 0 : *((unsigned short *) (var + offset * act_tuple)) = (unsigned short) ures;
417 0 : break;
418 0 : case ECPGt_unsigned_int:
419 0 : *((unsigned int *) (var + offset * act_tuple)) = (unsigned int) ures;
420 0 : break;
421 0 : case ECPGt_unsigned_long:
422 0 : *((unsigned long *) (var + offset * act_tuple)) = (unsigned long) ures;
423 0 : break;
424 0 : default:
425 : /* Cannot happen */
426 0 : break;
427 : }
428 0 : break;
429 :
430 0 : 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 0 : 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 180 : case ECPGt_float:
453 : case ECPGt_double:
454 180 : if (isarray && *pval == '"')
455 0 : pval++;
456 :
457 180 : if (!check_special_value(pval, &dres, &scan_length))
458 132 : dres = strtod(pval, &scan_length);
459 :
460 180 : if (isarray && *scan_length == '"')
461 0 : scan_length++;
462 :
463 : /* no special INFORMIX treatment for floats */
464 180 : if (garbage_left(isarray, &scan_length, ECPG_COMPAT_PGSQL))
465 : {
466 0 : ecpg_raise(lineno, ECPG_FLOAT_FORMAT,
467 : ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
468 0 : return false;
469 : }
470 180 : pval = scan_length;
471 :
472 : switch (type)
473 : {
474 28 : case ECPGt_float:
475 28 : *((float *) (var + offset * act_tuple)) = dres;
476 28 : break;
477 152 : case ECPGt_double:
478 152 : *((double *) (var + offset * act_tuple)) = dres;
479 152 : break;
480 0 : default:
481 : /* Cannot happen */
482 0 : break;
483 : }
484 180 : break;
485 :
486 48 : case ECPGt_bool:
487 48 : if (pval[0] == 'f' && pval[1] == '\0')
488 : {
489 20 : *((bool *) (var + offset * act_tuple)) = false;
490 20 : pval++;
491 20 : break;
492 : }
493 28 : else if (pval[0] == 't' && pval[1] == '\0')
494 : {
495 28 : *((bool *) (var + offset * act_tuple)) = true;
496 28 : pval++;
497 28 : 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 : ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
507 0 : return false;
508 : break;
509 :
510 36 : case ECPGt_bytea:
511 : {
512 36 : struct ECPGgeneric_bytea *variable =
513 36 : (struct ECPGgeneric_bytea *) (var + offset * act_tuple);
514 : long dst_size,
515 : src_size,
516 : dec_size;
517 :
518 36 : dst_size = ecpg_hex_enc_len(varcharsize);
519 36 : src_size = size - 2; /* exclude backslash + 'x' */
520 36 : dec_size = src_size < dst_size ? src_size : dst_size;
521 36 : variable->len = hex_decode(pval + 2, dec_size, variable->arr);
522 :
523 36 : if (dst_size < src_size)
524 : {
525 12 : long rcv_size = ecpg_hex_dec_len(size - 2);
526 :
527 : /* truncation */
528 : switch (ind_type)
529 : {
530 0 : case ECPGt_short:
531 : case ECPGt_unsigned_short:
532 0 : *((short *) (ind + ind_offset * act_tuple)) = rcv_size;
533 0 : break;
534 12 : case ECPGt_int:
535 : case ECPGt_unsigned_int:
536 12 : *((int *) (ind + ind_offset * act_tuple)) = rcv_size;
537 12 : break;
538 0 : case ECPGt_long:
539 : case ECPGt_unsigned_long:
540 0 : *((long *) (ind + ind_offset * act_tuple)) = rcv_size;
541 0 : break;
542 0 : 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 0 : default:
547 0 : break;
548 : }
549 12 : sqlca->sqlwarn[0] = sqlca->sqlwarn[1] = 'W';
550 : }
551 :
552 36 : pval += size;
553 : }
554 36 : break;
555 :
556 4148 : case ECPGt_char:
557 : case ECPGt_unsigned_char:
558 : case ECPGt_string:
559 : {
560 4148 : 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 4148 : if (varcharsize == 0 && offset == sizeof(char *))
568 0 : str = *(char **) str;
569 :
570 4148 : if (varcharsize > size)
571 : {
572 : /*
573 : * compatibility mode, blank pad and null
574 : * terminate char array
575 : */
576 3820 : if (ORACLE_MODE(compat) && (type == ECPGt_char || type == ECPGt_unsigned_char))
577 : {
578 36 : memset(str, ' ', varcharsize);
579 36 : memcpy(str, pval, size);
580 36 : str[varcharsize - 1] = '\0';
581 :
582 : /*
583 : * compatibility mode empty string gets -1
584 : * indicator but no warning
585 : */
586 36 : if (size == 0)
587 : {
588 : /* truncation */
589 : switch (ind_type)
590 : {
591 8 : case ECPGt_short:
592 : case ECPGt_unsigned_short:
593 8 : *((short *) (ind + ind_offset * act_tuple)) = -1;
594 8 : break;
595 0 : case ECPGt_int:
596 : case ECPGt_unsigned_int:
597 0 : *((int *) (ind + ind_offset * act_tuple)) = -1;
598 0 : break;
599 0 : case ECPGt_long:
600 : case ECPGt_unsigned_long:
601 0 : *((long *) (ind + ind_offset * act_tuple)) = -1;
602 0 : break;
603 0 : 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 0 : default:
608 0 : break;
609 : }
610 : }
611 : }
612 : else
613 : {
614 3784 : strncpy(str, pval, size + 1);
615 : }
616 : /* do the rtrim() */
617 3820 : if (type == ECPGt_string)
618 : {
619 8 : char *last = str + size;
620 :
621 52 : while (last > str && (*last == ' ' || *last == '\0'))
622 : {
623 44 : *last = '\0';
624 44 : last--;
625 : }
626 : }
627 : }
628 : else
629 : {
630 328 : int charsize = varcharsize;
631 :
632 : /*
633 : * assume that the caller provided storage exactly
634 : * fit when varcharsize is zero.
635 : */
636 328 : if (varcharsize == 0)
637 136 : charsize = size + 1;
638 :
639 328 : strncpy(str, pval, charsize);
640 :
641 : /* compatibility mode, null terminate char array */
642 328 : if (ORACLE_MODE(compat) && (charsize - 1) < size)
643 : {
644 12 : if (type == ECPGt_char || type == ECPGt_unsigned_char)
645 12 : str[charsize - 1] = '\0';
646 : }
647 :
648 328 : if (charsize < size || (ORACLE_MODE(compat) && (charsize - 1) < size))
649 : {
650 : /* truncation */
651 : switch (ind_type)
652 : {
653 12 : case ECPGt_short:
654 : case ECPGt_unsigned_short:
655 12 : *((short *) (ind + ind_offset * act_tuple)) = size;
656 12 : break;
657 4 : case ECPGt_int:
658 : case ECPGt_unsigned_int:
659 4 : *((int *) (ind + ind_offset * act_tuple)) = size;
660 4 : break;
661 0 : case ECPGt_long:
662 : case ECPGt_unsigned_long:
663 0 : *((long *) (ind + ind_offset * act_tuple)) = size;
664 0 : break;
665 0 : 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 8 : default:
670 8 : break;
671 : }
672 24 : sqlca->sqlwarn[0] = sqlca->sqlwarn[1] = 'W';
673 : }
674 : }
675 4148 : pval += size;
676 : }
677 4148 : break;
678 :
679 88 : case ECPGt_varchar:
680 : {
681 88 : struct ECPGgeneric_varchar *variable =
682 88 : (struct ECPGgeneric_varchar *) (var + offset * act_tuple);
683 :
684 88 : variable->len = size;
685 88 : if (varcharsize == 0)
686 0 : strncpy(variable->arr, pval, variable->len);
687 : else
688 : {
689 88 : strncpy(variable->arr, pval, varcharsize);
690 :
691 88 : if (variable->len > varcharsize)
692 : {
693 : /* truncation */
694 : switch (ind_type)
695 : {
696 0 : case ECPGt_short:
697 : case ECPGt_unsigned_short:
698 0 : *((short *) (ind + ind_offset * act_tuple)) = variable->len;
699 0 : break;
700 0 : case ECPGt_int:
701 : case ECPGt_unsigned_int:
702 0 : *((int *) (ind + ind_offset * act_tuple)) = variable->len;
703 0 : break;
704 0 : case ECPGt_long:
705 : case ECPGt_unsigned_long:
706 0 : *((long *) (ind + ind_offset * act_tuple)) = variable->len;
707 0 : break;
708 0 : 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 0 : default:
713 0 : break;
714 : }
715 0 : sqlca->sqlwarn[0] = sqlca->sqlwarn[1] = 'W';
716 :
717 0 : variable->len = varcharsize;
718 : }
719 : }
720 88 : pval += size;
721 : }
722 88 : break;
723 :
724 92 : case ECPGt_decimal:
725 : case ECPGt_numeric:
726 388 : for (endptr = pval; *endptr && *endptr != ',' && *endptr != '}'; endptr++);
727 92 : endchar = *endptr;
728 92 : *endptr = '\0';
729 92 : nres = PGTYPESnumeric_from_asc(pval, &scan_length);
730 92 : *endptr = endchar;
731 :
732 : /* did we get an error? */
733 92 : 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 : }
754 : else
755 : {
756 0 : ecpg_raise(lineno, ECPG_NUMERIC_FORMAT,
757 : ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
758 0 : return false;
759 : }
760 : }
761 : else
762 : {
763 92 : if (!isarray && garbage_left(isarray, &scan_length, compat))
764 : {
765 0 : free(nres);
766 0 : ecpg_raise(lineno, ECPG_NUMERIC_FORMAT,
767 : ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
768 0 : return false;
769 : }
770 : }
771 92 : pval = scan_length;
772 :
773 92 : if (type == ECPGt_numeric)
774 60 : PGTYPESnumeric_copy(nres, (numeric *) (var + offset * act_tuple));
775 : else
776 32 : PGTYPESnumeric_to_decimal(nres, (decimal *) (var + offset * act_tuple));
777 :
778 92 : PGTYPESnumeric_free(nres);
779 92 : break;
780 :
781 40 : case ECPGt_interval:
782 40 : if (*pval == '"')
783 40 : pval++;
784 :
785 440 : for (endptr = pval; *endptr && *endptr != ',' && *endptr != '"' && *endptr != '}'; endptr++);
786 40 : endchar = *endptr;
787 40 : *endptr = '\0';
788 40 : ires = PGTYPESinterval_from_asc(pval, &scan_length);
789 40 : *endptr = endchar;
790 :
791 : /* did we get an error? */
792 40 : 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 : }
809 : else
810 : {
811 0 : ecpg_raise(lineno, ECPG_INTERVAL_FORMAT,
812 : ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
813 0 : return false;
814 : }
815 : }
816 : else
817 : {
818 40 : if (*scan_length == '"')
819 40 : scan_length++;
820 :
821 40 : if (!isarray && garbage_left(isarray, &scan_length, compat))
822 : {
823 0 : free(ires);
824 0 : ecpg_raise(lineno, ECPG_INTERVAL_FORMAT,
825 : ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
826 0 : return false;
827 : }
828 : }
829 40 : pval = scan_length;
830 :
831 40 : PGTYPESinterval_copy(ires, (interval *) (var + offset * act_tuple));
832 40 : free(ires);
833 40 : break;
834 :
835 44 : case ECPGt_date:
836 44 : if (*pval == '"')
837 0 : pval++;
838 :
839 484 : for (endptr = pval; *endptr && *endptr != ',' && *endptr != '"' && *endptr != '}'; endptr++);
840 44 : endchar = *endptr;
841 44 : *endptr = '\0';
842 44 : ddres = PGTYPESdate_from_asc(pval, &scan_length);
843 44 : *endptr = endchar;
844 :
845 : /* did we get an error? */
846 44 : 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 : }
859 : else
860 : {
861 0 : ecpg_raise(lineno, ECPG_DATE_FORMAT,
862 : ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
863 0 : return false;
864 : }
865 : }
866 : else
867 : {
868 44 : if (*scan_length == '"')
869 0 : scan_length++;
870 :
871 44 : if (!isarray && garbage_left(isarray, &scan_length, compat))
872 : {
873 0 : ecpg_raise(lineno, ECPG_DATE_FORMAT,
874 : ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
875 0 : return false;
876 : }
877 : }
878 :
879 44 : *((date *) (var + offset * act_tuple)) = ddres;
880 44 : pval = scan_length;
881 44 : break;
882 :
883 52 : case ECPGt_timestamp:
884 52 : if (*pval == '"')
885 40 : pval++;
886 :
887 1280 : for (endptr = pval; *endptr && *endptr != ',' && *endptr != '"' && *endptr != '}'; endptr++);
888 52 : endchar = *endptr;
889 52 : *endptr = '\0';
890 52 : tres = PGTYPEStimestamp_from_asc(pval, &scan_length);
891 52 : *endptr = endchar;
892 :
893 : /* did we get an error? */
894 52 : 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 : }
907 : else
908 : {
909 0 : ecpg_raise(lineno, ECPG_TIMESTAMP_FORMAT,
910 : ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
911 0 : return false;
912 : }
913 : }
914 : else
915 : {
916 52 : if (*scan_length == '"')
917 40 : scan_length++;
918 :
919 52 : if (!isarray && garbage_left(isarray, &scan_length, compat))
920 : {
921 0 : ecpg_raise(lineno, ECPG_TIMESTAMP_FORMAT,
922 : ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
923 0 : return false;
924 : }
925 : }
926 :
927 52 : *((timestamp *) (var + offset * act_tuple)) = tres;
928 52 : pval = scan_length;
929 52 : break;
930 :
931 0 : default:
932 0 : ecpg_raise(lineno, ECPG_UNSUPPORTED,
933 : ECPG_SQLSTATE_ECPG_INTERNAL_ERROR,
934 : ecpg_type_name(type));
935 0 : return false;
936 : break;
937 : }
938 5704 : if (ECPG_IS_ARRAY(isarray))
939 : {
940 204 : bool string = false;
941 :
942 : /* set array to next entry */
943 204 : ++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 204 : 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 204 : if (array_delimiter(isarray, *pval))
956 180 : ++pval;
957 : }
958 : }
959 5720 : } while (*pval != '\0' && !array_boundary(isarray, *pval));
960 :
961 5540 : return true;
962 : }
|