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