Branch data 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 : 222 : array_delimiter(enum ARRAY_TYPE isarray, char c)
21 : : {
22 [ + - + + ]: 222 : if (isarray == ECPG_ARRAY_ARRAY && c == ',')
23 : 198 : return true;
24 : :
25 [ - + - - ]: 24 : if (isarray == ECPG_ARRAY_VECTOR && c == ' ')
26 : 0 : return true;
27 : :
28 : 24 : return false;
29 : : }
30 : :
31 : : /* returns true if character c marks the boundary for the given array type */
32 : : static bool
33 : 112 : array_boundary(enum ARRAY_TYPE isarray, char c)
34 : : {
35 [ + - + + ]: 112 : if (isarray == ECPG_ARRAY_ARRAY && c == '}')
36 : 22 : return true;
37 : :
38 [ - + - - ]: 90 : if (isarray == ECPG_ARRAY_VECTOR && c == '\0')
39 : 0 : return true;
40 : :
41 : 90 : return false;
42 : : }
43 : :
44 : : /* returns true if some garbage is found at the end of the scanned string */
45 : : static bool
46 : 586 : 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 [ + + ]: 586 : if (isarray == ECPG_ARRAY_NONE)
53 : : {
54 [ + + - + : 566 : 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 [ + - - + ]: 566 : if (**scan_length != ' ' && **scan_length != '\0')
64 : 0 : return true;
65 : : }
66 [ - + - - : 20 : else if (ECPG_IS_ARRAY(isarray) && !array_delimiter(isarray, **scan_length) && !array_boundary(isarray, **scan_length))
+ + - + ]
67 : 0 : return true;
68 : :
69 : 586 : return false;
70 : : }
71 : :
72 : :
73 : : /*
74 : : * Portability wrappers borrowed from src/include/utils/float.h
75 : : */
76 : : static double
77 : 16 : get_float8_infinity(void)
78 : : {
79 : 16 : return (double) INFINITY;
80 : : }
81 : :
82 : : static double
83 : 8 : get_float8_nan(void)
84 : : {
85 : 8 : return (double) NAN;
86 : : }
87 : :
88 : :
89 : : static bool
90 : 90 : check_special_value(char *ptr, double *retval, char **endptr)
91 : : {
92 [ + + ]: 90 : if (pg_strncasecmp(ptr, "NaN", 3) == 0)
93 : : {
94 : 8 : *retval = get_float8_nan();
95 : 8 : *endptr = ptr + 3;
96 : 8 : return true;
97 : : }
98 [ + + ]: 82 : else if (pg_strncasecmp(ptr, "Infinity", 8) == 0)
99 : : {
100 : 8 : *retval = get_float8_infinity();
101 : 8 : *endptr = ptr + 8;
102 : 8 : return true;
103 : : }
104 [ + + ]: 74 : else if (pg_strncasecmp(ptr, "-Infinity", 9) == 0)
105 : : {
106 : 8 : *retval = -get_float8_infinity();
107 : 8 : *endptr = ptr + 9;
108 : 8 : return true;
109 : : }
110 : :
111 : 66 : return false;
112 : : }
113 : :
114 : : /* imported from src/backend/utils/adt/encode.c */
115 : :
116 : : unsigned
117 : 70 : ecpg_hex_enc_len(unsigned srclen)
118 : : {
119 : 70 : return srclen << 1;
120 : : }
121 : :
122 : : unsigned
123 : 6 : ecpg_hex_dec_len(unsigned srclen)
124 : : {
125 : 6 : return srclen >> 1;
126 : : }
127 : :
128 : : static inline char
129 : 18276 : 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 : 18276 : int res = -1;
142 : :
143 [ + - + - ]: 18276 : if (c > 0 && c < 127)
144 : 18276 : res = hexlookup[(unsigned char) c];
145 : :
146 : 18276 : return (char) res;
147 : : }
148 : :
149 : : static unsigned
150 : 18 : 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 : 18 : srcend = src + len;
159 : 18 : s = src;
160 : 18 : p = dst;
161 [ + + ]: 9156 : while (s < srcend)
162 : : {
163 [ + - + - : 9138 : if (*s == ' ' || *s == '\n' || *s == '\t' || *s == '\r')
+ - - + ]
164 : : {
165 : 0 : s++;
166 : 0 : continue;
167 : : }
168 : 9138 : v1 = get_hex(*s++) << 4;
169 [ - + ]: 9138 : if (s >= srcend)
170 : 0 : return -1;
171 : :
172 : 9138 : v2 = get_hex(*s++);
173 : 9138 : *p++ = v1 | v2;
174 : : }
175 : :
176 : 18 : return p - dst;
177 : : }
178 : :
179 : : unsigned
180 : 26 : ecpg_hex_encode(const char *src, unsigned len, char *dst)
181 : : {
182 : : static const char hextbl[] = "0123456789abcdef";
183 : 26 : const char *end = src + len;
184 : :
185 [ + + ]: 13338 : while (src < end)
186 : : {
187 : 13312 : *dst++ = hextbl[(*src >> 4) & 0xF];
188 : 13312 : *dst++ = hextbl[*src & 0xF];
189 : 13312 : src++;
190 : : }
191 : 26 : return len * 2;
192 : : }
193 : :
194 : : bool
195 : 2882 : 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 : 2882 : struct sqlca_t *sqlca = ECPGget_sqlca();
201 : 2882 : char *pval = (char *) PQgetvalue(results, act_tuple, act_field);
202 : 2882 : int binary = PQfformat(results, act_field);
203 : 2882 : int size = PQgetlength(results, act_tuple, act_field);
204 : 2882 : int value_for_indicator = 0;
205 : : long log_offset;
206 : :
207 [ - + ]: 2882 : 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 [ + + ]: 2882 : if (ecpg_internal_regression_mode)
219 : 1210 : log_offset = -1;
220 : : else
221 : 1672 : log_offset = offset;
222 : :
223 [ + + - + : 2882 : 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 [ - + ]: 2882 : 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 [ + + ]: 2882 : if (PQgetisnull(results, act_tuple, act_field))
243 : 96 : value_for_indicator = -1;
244 : :
245 [ + + + - : 2882 : switch (ind_type)
+ - ]
246 : : {
247 : 100 : case ECPGt_short:
248 : : case ECPGt_unsigned_short:
249 : 100 : *((short *) (ind + ind_offset * act_tuple)) = value_for_indicator;
250 : 100 : break;
251 : 160 : case ECPGt_int:
252 : : case ECPGt_unsigned_int:
253 : 160 : *((int *) (ind + ind_offset * act_tuple)) = value_for_indicator;
254 : 160 : break;
255 : 20 : case ECPGt_long:
256 : : case ECPGt_unsigned_long:
257 : 20 : *((long *) (ind + ind_offset * act_tuple)) = value_for_indicator;
258 : 20 : 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 : 2602 : case ECPGt_NO_INDICATOR:
264 [ + + ]: 2602 : if (value_for_indicator == -1)
265 : : {
266 [ + + ]: 36 : 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 : 24 : ECPGset_noind_null(type, var + offset * act_tuple);
273 : : }
274 : : else
275 : : {
276 : 12 : ecpg_raise(lineno, ECPG_MISSING_INDICATOR,
277 : : ECPG_SQLSTATE_NULL_VALUE_NO_INDICATOR_PARAMETER,
278 : : NULL);
279 : 12 : return false;
280 : : }
281 : : }
282 : 2590 : 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 [ + + ]: 2870 : if (value_for_indicator == -1)
292 : 84 : return true;
293 : :
294 : : /* let's check if it really is an array if it should be one */
295 [ + + ]: 2786 : if (isarray == ECPG_ARRAY_ARRAY)
296 : : {
297 [ - + ]: 12 : 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 [ + + ]: 12 : switch (type)
305 : : {
306 : 2 : case ECPGt_char:
307 : : case ECPGt_unsigned_char:
308 : : case ECPGt_varchar:
309 : : case ECPGt_string:
310 : 2 : break;
311 : :
312 : 10 : default:
313 : 10 : pval++;
314 : 10 : break;
315 : : }
316 : : }
317 : :
318 : : do
319 : : {
320 [ + + ]: 2876 : if (binary)
321 : : {
322 [ + + + - ]: 8 : if (varcharsize == 0 || varcharsize * offset >= size)
323 : 8 : 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 : 8 : pval += size;
356 : : }
357 : : else
358 : : {
359 [ + - - - : 2868 : 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 : 496 : case ECPGt_short:
373 : : case ECPGt_int:
374 : : case ECPGt_long:
375 : 496 : res = strtol(pval, &scan_length, 10);
376 [ - + ]: 496 : 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 : 496 : pval = scan_length;
383 : :
384 [ + + + - ]: 496 : switch (type)
385 : : {
386 : 32 : case ECPGt_short:
387 : 32 : *((short *) (var + offset * act_tuple)) = (short) res;
388 : 32 : break;
389 : 438 : case ECPGt_int:
390 : 438 : *((int *) (var + offset * act_tuple)) = (int) res;
391 : 438 : break;
392 : 26 : case ECPGt_long:
393 : 26 : *((long *) (var + offset * act_tuple)) = (long) res;
394 : 26 : break;
395 : 0 : default:
396 : : /* Cannot happen */
397 : 0 : break;
398 : : }
399 : 496 : 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 [ # # # # ]: 0 : 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 : 90 : case ECPGt_float:
453 : : case ECPGt_double:
454 [ + - - + ]: 90 : if (isarray && *pval == '"')
455 : 0 : pval++;
456 : :
457 [ + + ]: 90 : if (!check_special_value(pval, &dres, &scan_length))
458 : 66 : dres = strtod(pval, &scan_length);
459 : :
460 [ + - - + ]: 90 : if (isarray && *scan_length == '"')
461 : 0 : scan_length++;
462 : :
463 : : /* no special INFORMIX treatment for floats */
464 [ - + ]: 90 : 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 : 90 : pval = scan_length;
471 : :
472 [ + + - ]: 90 : switch (type)
473 : : {
474 : 14 : case ECPGt_float:
475 : 14 : *((float *) (var + offset * act_tuple)) = dres;
476 : 14 : break;
477 : 76 : case ECPGt_double:
478 : 76 : *((double *) (var + offset * act_tuple)) = dres;
479 : 76 : break;
480 : 0 : default:
481 : : /* Cannot happen */
482 : 0 : break;
483 : : }
484 : 90 : break;
485 : :
486 : 24 : case ECPGt_bool:
487 [ + + + - ]: 24 : if (pval[0] == 'f' && pval[1] == '\0')
488 : : {
489 : 10 : *((bool *) (var + offset * act_tuple)) = false;
490 : 10 : pval++;
491 : 10 : break;
492 : : }
493 [ + - + - ]: 14 : else if (pval[0] == 't' && pval[1] == '\0')
494 : : {
495 : 14 : *((bool *) (var + offset * act_tuple)) = true;
496 : 14 : pval++;
497 : 14 : 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 : 18 : case ECPGt_bytea:
511 : : {
512 : 18 : struct ECPGgeneric_bytea *variable =
513 : 18 : (struct ECPGgeneric_bytea *) (var + offset * act_tuple);
514 : : long dst_size,
515 : : src_size,
516 : : dec_size;
517 : :
518 : 18 : dst_size = ecpg_hex_enc_len(varcharsize);
519 : 18 : src_size = size - 2; /* exclude backslash + 'x' */
520 : 18 : dec_size = src_size < dst_size ? src_size : dst_size;
521 : 18 : variable->len = hex_decode(pval + 2, dec_size, variable->arr);
522 : :
523 [ + + ]: 18 : if (dst_size < src_size)
524 : : {
525 : 6 : long rcv_size = ecpg_hex_dec_len(size - 2);
526 : :
527 : : /* truncation */
528 [ - + - - : 6 : 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 : 6 : case ECPGt_int:
535 : : case ECPGt_unsigned_int:
536 : 6 : *((int *) (ind + ind_offset * act_tuple)) = rcv_size;
537 : 6 : 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 : 6 : sqlca->sqlwarn[0] = sqlca->sqlwarn[1] = 'W';
550 : : }
551 : :
552 : 18 : pval += size;
553 : : }
554 : 18 : break;
555 : :
556 : 2082 : case ECPGt_char:
557 : : case ECPGt_unsigned_char:
558 : : case ECPGt_string:
559 : : {
560 : 2082 : 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 [ + + - + ]: 2082 : if (varcharsize == 0 && offset == sizeof(char *))
568 : 0 : str = *(char **) str;
569 : :
570 [ + + ]: 2082 : if (varcharsize > size)
571 : : {
572 : : /*
573 : : * compatibility mode, blank pad and null
574 : : * terminate char array
575 : : */
576 [ + + - + : 1918 : if (ORACLE_MODE(compat) && (type == ECPGt_char || type == ECPGt_unsigned_char))
- - ]
577 : : {
578 : 18 : memset(str, ' ', varcharsize);
579 : 18 : memcpy(str, pval, size);
580 : 18 : str[varcharsize - 1] = '\0';
581 : :
582 : : /*
583 : : * compatibility mode empty string gets -1
584 : : * indicator but no warning
585 : : */
586 [ + + ]: 18 : if (size == 0)
587 : : {
588 : : /* truncation */
589 [ + - - - : 4 : switch (ind_type)
- ]
590 : : {
591 : 4 : case ECPGt_short:
592 : : case ECPGt_unsigned_short:
593 : 4 : *((short *) (ind + ind_offset * act_tuple)) = -1;
594 : 4 : 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 : 1900 : strncpy(str, pval, size + 1);
615 : : }
616 : : /* do the rtrim() */
617 [ + + ]: 1918 : if (type == ECPGt_string)
618 : : {
619 : 4 : char *last = str + size;
620 : :
621 [ + + + + : 26 : while (last > str && (*last == ' ' || *last == '\0'))
+ + ]
622 : : {
623 : 22 : *last = '\0';
624 : 22 : last--;
625 : : }
626 : : }
627 : : }
628 : : else
629 : : {
630 : 164 : int charsize = varcharsize;
631 : :
632 : : /*
633 : : * assume that the caller provided storage exactly
634 : : * fit when varcharsize is zero.
635 : : */
636 [ + + ]: 164 : if (varcharsize == 0)
637 : 68 : charsize = size + 1;
638 : :
639 : 164 : strncpy(str, pval, charsize);
640 : :
641 : : /* compatibility mode, null terminate char array */
642 [ + + + + ]: 164 : if (ORACLE_MODE(compat) && (charsize - 1) < size)
643 : : {
644 [ - + - - ]: 6 : if (type == ECPGt_char || type == ECPGt_unsigned_char)
645 : 6 : str[charsize - 1] = '\0';
646 : : }
647 : :
648 [ + + + + : 164 : if (charsize < size || (ORACLE_MODE(compat) && (charsize - 1) < size))
+ + ]
649 : : {
650 : : /* truncation */
651 [ + + - - : 12 : switch (ind_type)
+ ]
652 : : {
653 : 6 : case ECPGt_short:
654 : : case ECPGt_unsigned_short:
655 : 6 : *((short *) (ind + ind_offset * act_tuple)) = size;
656 : 6 : break;
657 : 2 : case ECPGt_int:
658 : : case ECPGt_unsigned_int:
659 : 2 : *((int *) (ind + ind_offset * act_tuple)) = size;
660 : 2 : 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 : 4 : default:
670 : 4 : break;
671 : : }
672 : 12 : sqlca->sqlwarn[0] = sqlca->sqlwarn[1] = 'W';
673 : : }
674 : : }
675 : 2082 : pval += size;
676 : : }
677 : 2082 : break;
678 : :
679 : 44 : case ECPGt_varchar:
680 : : {
681 : 44 : struct ECPGgeneric_varchar *variable =
682 : 44 : (struct ECPGgeneric_varchar *) (var + offset * act_tuple);
683 : :
684 : 44 : variable->len = size;
685 [ - + ]: 44 : if (varcharsize == 0)
686 : 0 : strncpy(variable->arr, pval, variable->len);
687 : : else
688 : : {
689 : 44 : strncpy(variable->arr, pval, varcharsize);
690 : :
691 [ - + ]: 44 : if (variable->len > varcharsize)
692 : : {
693 : : /* truncation */
694 [ # # # # : 0 : 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 : 44 : pval += size;
721 : : }
722 : 44 : break;
723 : :
724 : 46 : case ECPGt_decimal:
725 : : case ECPGt_numeric:
726 [ + + + + : 194 : for (endptr = pval; *endptr && *endptr != ',' && *endptr != '}'; endptr++);
+ + ]
727 : 46 : endchar = *endptr;
728 : 46 : *endptr = '\0';
729 : 46 : nres = PGTYPESnumeric_from_asc(pval, &scan_length);
730 : 46 : *endptr = endchar;
731 : :
732 : : /* did we get an error? */
733 [ - + ]: 46 : 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 [ - + - - ]: 46 : 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 : 46 : pval = scan_length;
772 : :
773 [ + + ]: 46 : if (type == ECPGt_numeric)
774 : 30 : PGTYPESnumeric_copy(nres, (numeric *) (var + offset * act_tuple));
775 : : else
776 : 16 : PGTYPESnumeric_to_decimal(nres, (decimal *) (var + offset * act_tuple));
777 : :
778 : 46 : PGTYPESnumeric_free(nres);
779 : 46 : break;
780 : :
781 : 20 : case ECPGt_interval:
782 [ + - ]: 20 : if (*pval == '"')
783 : 20 : pval++;
784 : :
785 [ + - + - : 220 : for (endptr = pval; *endptr && *endptr != ',' && *endptr != '"' && *endptr != '}'; endptr++);
+ + + - ]
786 : 20 : endchar = *endptr;
787 : 20 : *endptr = '\0';
788 : 20 : ires = PGTYPESinterval_from_asc(pval, &scan_length);
789 : 20 : *endptr = endchar;
790 : :
791 : : /* did we get an error? */
792 [ - + ]: 20 : 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 [ + - ]: 20 : if (*scan_length == '"')
819 : 20 : scan_length++;
820 : :
821 [ - + - - ]: 20 : 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 : 20 : pval = scan_length;
830 : :
831 : 20 : PGTYPESinterval_copy(ires, (interval *) (var + offset * act_tuple));
832 : 20 : free(ires);
833 : 20 : break;
834 : :
835 : 22 : case ECPGt_date:
836 [ - + ]: 22 : if (*pval == '"')
837 : 0 : pval++;
838 : :
839 [ + + + + : 242 : for (endptr = pval; *endptr && *endptr != ',' && *endptr != '"' && *endptr != '}'; endptr++);
+ - + + ]
840 : 22 : endchar = *endptr;
841 : 22 : *endptr = '\0';
842 : 22 : ddres = PGTYPESdate_from_asc(pval, &scan_length);
843 : 22 : *endptr = endchar;
844 : :
845 : : /* did we get an error? */
846 [ - + ]: 22 : 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 [ - + ]: 22 : if (*scan_length == '"')
869 : 0 : scan_length++;
870 : :
871 [ - + - - ]: 22 : 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 : 22 : *((date *) (var + offset * act_tuple)) = ddres;
880 : 22 : pval = scan_length;
881 : 22 : break;
882 : :
883 : 26 : case ECPGt_timestamp:
884 [ + + ]: 26 : if (*pval == '"')
885 : 20 : pval++;
886 : :
887 [ + + + - : 640 : for (endptr = pval; *endptr && *endptr != ',' && *endptr != '"' && *endptr != '}'; endptr++);
+ + + - ]
888 : 26 : endchar = *endptr;
889 : 26 : *endptr = '\0';
890 : 26 : tres = PGTYPEStimestamp_from_asc(pval, &scan_length);
891 : 26 : *endptr = endchar;
892 : :
893 : : /* did we get an error? */
894 [ - + ]: 26 : 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 [ + + ]: 26 : if (*scan_length == '"')
917 : 20 : scan_length++;
918 : :
919 [ - + - - ]: 26 : 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 : 26 : *((timestamp *) (var + offset * act_tuple)) = tres;
928 : 26 : pval = scan_length;
929 : 26 : 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 [ + + - + ]: 2868 : if (ECPG_IS_ARRAY(isarray))
939 : : {
940 : 102 : bool string = false;
941 : :
942 : : /* set array to next entry */
943 : 102 : ++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 [ + + - + : 102 : 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 [ + + ]: 102 : if (array_delimiter(isarray, *pval))
956 : 90 : ++pval;
957 : : }
958 : : }
959 [ + + + + ]: 2876 : } while (*pval != '\0' && !array_boundary(isarray, *pval));
960 : :
961 : 2786 : return true;
962 : : }
|