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