Age Owner Branch data TLA 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
5183 meskes@postgresql.or 20 :CBC 111 : array_delimiter(enum ARRAY_TYPE isarray, char c)
21 : : {
22 [ + - + + ]: 111 : if (isarray == ECPG_ARRAY_ARRAY && c == ',')
23 : 99 : return true;
24 : :
25 [ - + - - ]: 12 : if (isarray == ECPG_ARRAY_VECTOR && c == ' ')
5183 meskes@postgresql.or 26 :UBC 0 : return true;
27 : :
5183 meskes@postgresql.or 28 :CBC 12 : return false;
29 : : }
30 : :
31 : : /* returns true if character c marks the boundary for the given array type */
32 : : static bool
33 : 56 : array_boundary(enum ARRAY_TYPE isarray, char c)
34 : : {
35 [ + - + + ]: 56 : if (isarray == ECPG_ARRAY_ARRAY && c == '}')
36 : 11 : return true;
37 : :
38 [ - + - - ]: 45 : if (isarray == ECPG_ARRAY_VECTOR && c == '\0')
5183 meskes@postgresql.or 39 :UBC 0 : return true;
40 : :
5183 meskes@postgresql.or 41 :CBC 45 : return false;
42 : : }
43 : :
44 : : /* returns true if some garbage is found at the end of the scanned string */
45 : : static bool
2356 46 : 286 : 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 : : */
5183 52 [ + + ]: 286 : if (isarray == ECPG_ARRAY_NONE)
53 : : {
2356 54 [ + + - + : 276 : if (INFORMIX_MODE(compat) && **scan_length == '.')
- + ]
55 : : {
56 : : /* skip invalid characters */
57 : : do
58 : : {
2356 meskes@postgresql.or 59 :UBC 0 : (*scan_length)++;
2350 tgl@sss.pgh.pa.us 60 [ # # ]: 0 : } while (isdigit((unsigned char) **scan_length));
61 : : }
62 : :
2356 meskes@postgresql.or 63 [ + - - + ]:CBC 276 : if (**scan_length != ' ' && **scan_length != '\0')
5183 meskes@postgresql.or 64 :UBC 0 : return true;
65 : : }
2356 meskes@postgresql.or 66 [ - + - - :CBC 10 : else if (ECPG_IS_ARRAY(isarray) && !array_delimiter(isarray, **scan_length) && !array_boundary(isarray, **scan_length))
+ + - + ]
7463 meskes@postgresql.or 67 :UBC 0 : return true;
68 : :
7463 meskes@postgresql.or 69 :CBC 286 : 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
5185 80 : 8 : get_float8_infinity(void)
81 : : {
82 : : #ifdef INFINITY
83 : 8 : return (double) INFINITY;
84 : : #else
85 : : return (double) (HUGE_VAL * HUGE_VAL);
86 : : #endif
87 : : }
88 : :
89 : : static double
90 : 4 : get_float8_nan(void)
91 : : {
92 : : /* (double) NAN doesn't work on some NetBSD/MIPS releases */
93 : : #if defined(NAN) && !(defined(__NetBSD__) && defined(__mips__))
5161 bruce@momjian.us 94 : 4 : return (double) NAN;
95 : : #else
96 : : return (double) (0.0 / 0.0);
97 : : #endif
98 : : }
99 : :
100 : : static bool
5185 meskes@postgresql.or 101 : 45 : check_special_value(char *ptr, double *retval, char **endptr)
102 : : {
4492 peter_e@gmx.net 103 [ + + ]: 45 : if (pg_strncasecmp(ptr, "NaN", 3) == 0)
104 : : {
5185 meskes@postgresql.or 105 : 4 : *retval = get_float8_nan();
106 : 4 : *endptr = ptr + 3;
107 : 4 : return true;
108 : : }
4492 peter_e@gmx.net 109 [ + + ]: 41 : else if (pg_strncasecmp(ptr, "Infinity", 8) == 0)
110 : : {
5185 meskes@postgresql.or 111 : 4 : *retval = get_float8_infinity();
112 : 4 : *endptr = ptr + 8;
113 : 4 : return true;
114 : : }
4492 peter_e@gmx.net 115 [ + + ]: 37 : else if (pg_strncasecmp(ptr, "-Infinity", 9) == 0)
116 : : {
5185 meskes@postgresql.or 117 : 4 : *retval = -get_float8_infinity();
118 : 4 : *endptr = ptr + 9;
119 : 4 : return true;
120 : : }
121 : :
122 : 33 : return false;
123 : : }
124 : :
125 : : /* imported from src/backend/utils/adt/encode.c */
126 : :
127 : : unsigned
1882 128 : 35 : ecpg_hex_enc_len(unsigned srclen)
129 : : {
130 : 35 : return srclen << 1;
131 : : }
132 : :
133 : : unsigned
134 : 3 : ecpg_hex_dec_len(unsigned srclen)
135 : : {
136 : 3 : return srclen >> 1;
137 : : }
138 : :
139 : : static inline char
1207 bruce@momjian.us 140 : 9138 : 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 : 9138 : int res = -1;
153 : :
154 [ + - + - ]: 9138 : if (c > 0 && c < 127)
155 : 9138 : res = hexlookup[(unsigned char) c];
156 : :
157 : 9138 : return (char) res;
158 : : }
159 : :
160 : : static unsigned
161 : 9 : 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 : 9 : srcend = src + len;
170 : 9 : s = src;
171 : 9 : p = dst;
172 [ + + ]: 4578 : while (s < srcend)
173 : : {
174 [ + - + - : 4569 : if (*s == ' ' || *s == '\n' || *s == '\t' || *s == '\r')
+ - - + ]
175 : : {
1207 bruce@momjian.us 176 :UBC 0 : s++;
177 : 0 : continue;
178 : : }
1207 bruce@momjian.us 179 :CBC 4569 : v1 = get_hex(*s++) << 4;
180 [ - + ]: 4569 : if (s >= srcend)
1207 bruce@momjian.us 181 :UBC 0 : return -1;
182 : :
1207 bruce@momjian.us 183 :CBC 4569 : v2 = get_hex(*s++);
184 : 4569 : *p++ = v1 | v2;
185 : : }
186 : :
187 : 9 : return p - dst;
188 : : }
189 : :
190 : : unsigned
1882 meskes@postgresql.or 191 : 13 : ecpg_hex_encode(const char *src, unsigned len, char *dst)
192 : : {
193 : : static const char hextbl[] = "0123456789abcdef";
194 : 13 : const char *end = src + len;
195 : :
196 [ + + ]: 6669 : while (src < end)
197 : : {
198 : 6656 : *dst++ = hextbl[(*src >> 4) & 0xF];
199 : 6656 : *dst++ = hextbl[*src & 0xF];
200 : 6656 : src++;
201 : : }
202 : 13 : return len * 2;
203 : : }
204 : :
205 : : bool
6038 206 : 1430 : 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 : : {
7609 bruce@momjian.us 211 : 1430 : struct sqlca_t *sqlca = ECPGget_sqlca();
6402 212 : 1430 : char *pval = (char *) PQgetvalue(results, act_tuple, act_field);
213 : 1430 : int binary = PQfformat(results, act_field);
214 : 1430 : int size = PQgetlength(results, act_tuple, act_field);
215 : 1430 : int value_for_indicator = 0;
216 : : long log_offset;
217 : :
3226 meskes@postgresql.or 218 [ - + ]: 1430 : if (sqlca == NULL)
219 : : {
3226 meskes@postgresql.or 220 :UBC 0 : ecpg_raise(lineno, ECPG_OUT_OF_MEMORY,
221 : : ECPG_SQLSTATE_ECPG_OUT_OF_MEMORY, NULL);
2432 peter_e@gmx.net 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 : : */
6303 meskes@postgresql.or 229 [ + + ]:CBC 1430 : if (ecpg_internal_regression_mode)
6459 230 : 594 : log_offset = -1;
231 : : else
232 : 836 : log_offset = offset;
233 : :
5183 234 [ + + - + : 1430 : 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 */
5161 bruce@momjian.us 237 [ - + ]: 1430 : 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 : : */
5252 meskes@postgresql.or 243 :UBC 0 : ecpg_raise(lineno, ECPG_NOT_FOUND, ECPG_SQLSTATE_NO_DATA, NULL);
2432 peter_e@gmx.net 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 : : */
7599 meskes@postgresql.or 253 [ + + ]:CBC 1430 : if (PQgetisnull(results, act_tuple, act_field))
7586 254 : 48 : value_for_indicator = -1;
255 : :
256 [ + + + - : 1430 : switch (ind_type)
+ - ]
257 : : {
258 : 50 : case ECPGt_short:
259 : : case ECPGt_unsigned_short:
260 : 50 : *((short *) (ind + ind_offset * act_tuple)) = value_for_indicator;
261 : 50 : break;
262 : 80 : case ECPGt_int:
263 : : case ECPGt_unsigned_int:
264 : 80 : *((int *) (ind + ind_offset * act_tuple)) = value_for_indicator;
265 : 80 : break;
266 : 10 : case ECPGt_long:
267 : : case ECPGt_unsigned_long:
268 : 10 : *((long *) (ind + ind_offset * act_tuple)) = value_for_indicator;
269 : 10 : break;
7586 meskes@postgresql.or 270 :UBC 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;
7586 meskes@postgresql.or 274 :CBC 1290 : case ECPGt_NO_INDICATOR:
275 [ + + ]: 1290 : if (value_for_indicator == -1)
276 : : {
7598 277 [ + + ]: 18 : 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 : : */
7231 283 : 12 : ECPGset_noind_null(type, var + offset * act_tuple);
284 : : }
285 : : else
286 : : {
6038 287 : 6 : ecpg_raise(lineno, ECPG_MISSING_INDICATOR,
288 : : ECPG_SQLSTATE_NULL_VALUE_NO_INDICATOR_PARAMETER,
289 : : NULL);
2432 peter_e@gmx.net 290 : 6 : return false;
291 : : }
292 : : }
7586 meskes@postgresql.or 293 : 1284 : break;
7586 meskes@postgresql.or 294 :UBC 0 : default:
6038 295 : 0 : ecpg_raise(lineno, ECPG_UNSUPPORTED,
296 : : ECPG_SQLSTATE_ECPG_INTERNAL_ERROR,
297 : : ecpg_type_name(ind_type));
2432 peter_e@gmx.net 298 : 0 : return false;
299 : : break;
300 : : }
301 : :
7586 meskes@postgresql.or 302 [ + + ]:CBC 1424 : if (value_for_indicator == -1)
2432 peter_e@gmx.net 303 : 42 : return true;
304 : :
305 : : /* let's check if it really is an array if it should be one */
6808 meskes@postgresql.or 306 [ + + ]: 1382 : if (isarray == ECPG_ARRAY_ARRAY)
307 : : {
5252 308 [ - + ]: 6 : if (*pval != '{')
309 : : {
6038 meskes@postgresql.or 310 :UBC 0 : ecpg_raise(lineno, ECPG_DATA_NOT_ARRAY,
311 : : ECPG_SQLSTATE_DATATYPE_MISMATCH, NULL);
2432 peter_e@gmx.net 312 : 0 : return false;
313 : : }
314 : :
6808 meskes@postgresql.or 315 [ + + ]:CBC 6 : switch (type)
316 : : {
317 : 1 : case ECPGt_char:
318 : : case ECPGt_unsigned_char:
319 : : case ECPGt_varchar:
320 : : case ECPGt_string:
321 : 1 : break;
322 : :
323 : 5 : default:
324 : 5 : pval++;
325 : 5 : break;
326 : : }
327 : : }
328 : :
329 : : do
330 : : {
6662 331 [ + + ]: 1427 : if (binary)
332 : : {
5252 333 [ + + + - ]: 4 : if (varcharsize == 0 || varcharsize * offset >= size)
5218 tgl@sss.pgh.pa.us 334 : 4 : memcpy(var + offset * act_tuple, pval, size);
335 : : else
336 : : {
5218 tgl@sss.pgh.pa.us 337 :UBC 0 : memcpy(var + offset * act_tuple, pval, varcharsize * offset);
338 : :
5252 meskes@postgresql.or 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 : : }
5252 meskes@postgresql.or 366 :CBC 4 : pval += size;
367 : : }
368 : : else
369 : : {
6402 bruce@momjian.us 370 [ + - - - : 1423 : 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 : 241 : case ECPGt_short:
384 : : case ECPGt_int:
385 : : case ECPGt_long:
5252 meskes@postgresql.or 386 : 241 : res = strtol(pval, &scan_length, 10);
2356 387 [ - + ]: 241 : if (garbage_left(isarray, &scan_length, compat))
388 : : {
5252 meskes@postgresql.or 389 :UBC 0 : ecpg_raise(lineno, ECPG_INT_FORMAT,
390 : : ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
2432 peter_e@gmx.net 391 : 0 : return false;
392 : : }
5252 meskes@postgresql.or 393 [ + + + - ]:CBC 241 : pval = scan_length;
394 : :
395 : : switch (type)
396 : : {
6402 bruce@momjian.us 397 : 16 : case ECPGt_short:
398 : 16 : *((short *) (var + offset * act_tuple)) = (short) res;
399 : 16 : break;
400 : 212 : case ECPGt_int:
401 : 212 : *((int *) (var + offset * act_tuple)) = (int) res;
402 : 212 : break;
403 : 13 : case ECPGt_long:
404 : 13 : *((long *) (var + offset * act_tuple)) = (long) res;
405 : 13 : break;
6402 bruce@momjian.us 406 :UBC 0 : default:
407 : : /* Cannot happen */
408 : 0 : break;
409 : : }
6402 bruce@momjian.us 410 :CBC 241 : break;
411 : :
6402 bruce@momjian.us 412 :UBC 0 : case ECPGt_unsigned_short:
413 : : case ECPGt_unsigned_int:
414 : : case ECPGt_unsigned_long:
5252 meskes@postgresql.or 415 : 0 : ures = strtoul(pval, &scan_length, 10);
2356 416 [ # # ]: 0 : if (garbage_left(isarray, &scan_length, compat))
417 : : {
5252 418 : 0 : ecpg_raise(lineno, ECPG_UINT_FORMAT,
419 : : ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
2432 peter_e@gmx.net 420 : 0 : return false;
421 : : }
5252 meskes@postgresql.or 422 [ # # # # ]: 0 : pval = scan_length;
423 : :
424 : : switch (type)
425 : : {
6402 bruce@momjian.us 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:
5252 meskes@postgresql.or 442 : 0 : *((long long int *) (var + offset * act_tuple)) = strtoll(pval, &scan_length, 10);
2356 443 [ # # ]: 0 : if (garbage_left(isarray, &scan_length, compat))
444 : : {
5252 445 : 0 : ecpg_raise(lineno, ECPG_INT_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
2432 peter_e@gmx.net 446 : 0 : return false;
447 : : }
5252 meskes@postgresql.or 448 : 0 : pval = scan_length;
449 : :
6402 bruce@momjian.us 450 : 0 : break;
451 : :
452 : 0 : case ECPGt_unsigned_long_long:
5252 meskes@postgresql.or 453 : 0 : *((unsigned long long int *) (var + offset * act_tuple)) = strtoull(pval, &scan_length, 10);
2356 454 [ # # ]: 0 : if (garbage_left(isarray, &scan_length, compat))
455 : : {
5252 456 : 0 : ecpg_raise(lineno, ECPG_UINT_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
2432 peter_e@gmx.net 457 : 0 : return false;
458 : : }
5252 meskes@postgresql.or 459 : 0 : pval = scan_length;
460 : :
6402 bruce@momjian.us 461 : 0 : break;
462 : :
6402 bruce@momjian.us 463 :CBC 45 : case ECPGt_float:
464 : : case ECPGt_double:
5252 meskes@postgresql.or 465 [ + - - + ]: 45 : if (isarray && *pval == '"')
5185 meskes@postgresql.or 466 :UBC 0 : pval++;
467 : :
5185 meskes@postgresql.or 468 [ + + ]:CBC 45 : if (!check_special_value(pval, &dres, &scan_length))
5252 469 : 33 : dres = strtod(pval, &scan_length);
470 : :
471 [ + - - + ]: 45 : if (isarray && *scan_length == '"')
5252 meskes@postgresql.or 472 :UBC 0 : scan_length++;
473 : :
474 : : /* no special INFORMIX treatment for floats */
2355 meskes@postgresql.or 475 [ - + ]:CBC 45 : if (garbage_left(isarray, &scan_length, ECPG_COMPAT_PGSQL))
476 : : {
5252 meskes@postgresql.or 477 :UBC 0 : ecpg_raise(lineno, ECPG_FLOAT_FORMAT,
478 : : ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
2432 peter_e@gmx.net 479 : 0 : return false;
480 : : }
5252 meskes@postgresql.or 481 [ + + - ]:CBC 45 : pval = scan_length;
482 : :
483 : : switch (type)
484 : : {
6402 bruce@momjian.us 485 : 7 : case ECPGt_float:
486 : 7 : *((float *) (var + offset * act_tuple)) = dres;
487 : 7 : break;
488 : 38 : case ECPGt_double:
489 : 38 : *((double *) (var + offset * act_tuple)) = dres;
490 : 38 : break;
6402 bruce@momjian.us 491 :UBC 0 : default:
492 : : /* Cannot happen */
493 : 0 : break;
494 : : }
6402 bruce@momjian.us 495 :CBC 45 : break;
496 : :
497 : 12 : case ECPGt_bool:
5252 meskes@postgresql.or 498 [ + + + - ]: 12 : if (pval[0] == 'f' && pval[1] == '\0')
499 : : {
3132 500 : 5 : *((bool *) (var + offset * act_tuple)) = false;
4209 501 : 5 : pval++;
5252 502 : 5 : break;
503 : : }
504 [ + - + - ]: 7 : else if (pval[0] == 't' && pval[1] == '\0')
505 : : {
3132 506 : 7 : *((bool *) (var + offset * act_tuple)) = true;
4209 507 : 7 : pval++;
5252 508 : 7 : break;
509 : : }
5252 meskes@postgresql.or 510 [ # # # # ]:UBC 0 : else if (pval[0] == '\0' && PQgetisnull(results, act_tuple, act_field))
511 : : {
512 : : /* NULL is valid */
513 : 0 : break;
514 : : }
515 : :
6038 516 : 0 : ecpg_raise(lineno, ECPG_CONVERT_BOOL,
517 : : ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
2432 peter_e@gmx.net 518 : 0 : return false;
519 : : break;
520 : :
1882 meskes@postgresql.or 521 :CBC 9 : case ECPGt_bytea:
522 : : {
1357 michael@paquier.xyz 523 : 9 : struct ECPGgeneric_bytea *variable =
331 tgl@sss.pgh.pa.us 524 : 9 : (struct ECPGgeneric_bytea *) (var + offset * act_tuple);
525 : : long dst_size,
526 : : src_size,
527 : : dec_size;
528 : :
1882 meskes@postgresql.or 529 : 9 : dst_size = ecpg_hex_enc_len(varcharsize);
530 : 9 : src_size = size - 2; /* exclude backslash + 'x' */
531 : 9 : dec_size = src_size < dst_size ? src_size : dst_size;
532 : 9 : variable->len = hex_decode(pval + 2, dec_size, variable->arr);
533 : :
534 [ + + ]: 9 : if (dst_size < src_size)
535 : : {
536 [ - + - - : 3 : long rcv_size = ecpg_hex_dec_len(size - 2);
- ]
537 : :
538 : : /* truncation */
539 : : switch (ind_type)
540 : : {
1882 meskes@postgresql.or 541 :UBC 0 : case ECPGt_short:
542 : : case ECPGt_unsigned_short:
543 : 0 : *((short *) (ind + ind_offset * act_tuple)) = rcv_size;
544 : 0 : break;
1882 meskes@postgresql.or 545 :CBC 3 : case ECPGt_int:
546 : : case ECPGt_unsigned_int:
547 : 3 : *((int *) (ind + ind_offset * act_tuple)) = rcv_size;
548 : 3 : break;
1882 meskes@postgresql.or 549 :UBC 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 : : }
1882 meskes@postgresql.or 560 :CBC 3 : sqlca->sqlwarn[0] = sqlca->sqlwarn[1] = 'W';
561 : : }
562 : :
563 : 9 : pval += size;
564 : : }
565 : 9 : break;
566 : :
6402 bruce@momjian.us 567 : 1037 : case ECPGt_char:
568 : : case ECPGt_unsigned_char:
569 : : case ECPGt_string:
570 : : {
5161 571 : 1037 : 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 : : */
3631 meskes@postgresql.or 578 [ + + - + ]: 1037 : if (varcharsize == 0 && offset == sizeof(char *))
3631 bruce@momjian.us 579 :UBC 0 : str = *(char **) str;
580 : :
362 michael@paquier.xyz 581 [ + + ]:CBC 1037 : if (varcharsize > size)
582 : : {
583 : : /*
584 : : * compatibility mode, blank pad and null
585 : : * terminate char array
586 : : */
2223 meskes@postgresql.or 587 [ + + - + : 955 : if (ORACLE_MODE(compat) && (type == ECPGt_char || type == ECPGt_unsigned_char))
- - ]
588 : : {
589 : 9 : memset(str, ' ', varcharsize);
590 : 9 : memcpy(str, pval, size);
2180 tgl@sss.pgh.pa.us 591 : 9 : str[varcharsize - 1] = '\0';
592 : :
593 : : /*
594 : : * compatibility mode empty string gets -1
595 : : * indicator but no warning
596 : : */
597 [ + + ]: 9 : if (size == 0)
598 : : {
599 : : /* truncation */
600 : : switch (ind_type)
601 : : {
2223 meskes@postgresql.or 602 : 2 : case ECPGt_short:
603 : : case ECPGt_unsigned_short:
604 : 2 : *((short *) (ind + ind_offset * act_tuple)) = -1;
605 : 2 : break;
2223 meskes@postgresql.or 606 :UBC 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 : : }
622 : : }
623 : : else
624 : : {
2223 meskes@postgresql.or 625 :CBC 946 : strncpy(str, pval, size + 1);
626 : : }
627 : : /* do the rtrim() */
5364 628 [ + + ]: 955 : if (type == ECPGt_string)
629 : : {
5161 bruce@momjian.us 630 : 2 : char *last = str + size;
631 : :
5364 meskes@postgresql.or 632 [ + + + + : 13 : while (last > str && (*last == ' ' || *last == '\0'))
+ + ]
633 : : {
634 : 11 : *last = '\0';
635 : 11 : last--;
636 : : }
637 : : }
638 : : }
639 : : else
640 : : {
362 michael@paquier.xyz 641 : 82 : int charsize = varcharsize;
642 : :
643 : : /*
644 : : * assume that the caller provided storage exactly
645 : : * fit when varcharsize is zero.
646 : : */
647 [ + + ]: 82 : if (varcharsize == 0)
648 : 34 : charsize = size + 1;
649 : :
650 : 82 : strncpy(str, pval, charsize);
651 : :
652 : : /* compatibility mode, null terminate char array */
653 [ + + + + ]: 82 : if (ORACLE_MODE(compat) && (charsize - 1) < size)
654 : : {
2223 meskes@postgresql.or 655 [ - + - - ]: 3 : if (type == ECPGt_char || type == ECPGt_unsigned_char)
362 michael@paquier.xyz 656 : 3 : str[charsize - 1] = '\0';
657 : : }
658 : :
659 [ + + + + : 82 : if (charsize < size || (ORACLE_MODE(compat) && (charsize - 1) < size))
+ + ]
660 : : {
661 : : /* truncation */
662 : : switch (ind_type)
663 : : {
6402 bruce@momjian.us 664 : 3 : case ECPGt_short:
665 : : case ECPGt_unsigned_short:
666 : 3 : *((short *) (ind + ind_offset * act_tuple)) = size;
667 : 3 : break;
668 : 1 : case ECPGt_int:
669 : : case ECPGt_unsigned_int:
670 : 1 : *((int *) (ind + ind_offset * act_tuple)) = size;
671 : 1 : break;
6402 bruce@momjian.us 672 :UBC 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;
6402 bruce@momjian.us 680 :CBC 2 : default:
681 : 2 : break;
682 : : }
683 : 6 : sqlca->sqlwarn[0] = sqlca->sqlwarn[1] = 'W';
684 : : }
685 : : }
686 : 1037 : pval += size;
687 : : }
688 : 1037 : break;
689 : :
690 : 22 : case ECPGt_varchar:
691 : : {
692 : 22 : struct ECPGgeneric_varchar *variable =
331 tgl@sss.pgh.pa.us 693 : 22 : (struct ECPGgeneric_varchar *) (var + offset * act_tuple);
694 : :
6402 bruce@momjian.us 695 : 22 : variable->len = size;
696 [ - + ]: 22 : if (varcharsize == 0)
6402 bruce@momjian.us 697 :UBC 0 : strncpy(variable->arr, pval, variable->len);
698 : : else
699 : : {
6402 bruce@momjian.us 700 :CBC 22 : strncpy(variable->arr, pval, varcharsize);
701 : :
702 [ - + ]: 22 : if (variable->len > varcharsize)
703 : : {
704 : : /* truncation */
705 : : switch (ind_type)
706 : : {
6402 bruce@momjian.us 707 :UBC 0 : case ECPGt_short:
708 : : case ECPGt_unsigned_short:
3792 meskes@postgresql.or 709 : 0 : *((short *) (ind + ind_offset * act_tuple)) = variable->len;
6402 bruce@momjian.us 710 : 0 : break;
711 : 0 : case ECPGt_int:
712 : : case ECPGt_unsigned_int:
3792 meskes@postgresql.or 713 : 0 : *((int *) (ind + ind_offset * act_tuple)) = variable->len;
6402 bruce@momjian.us 714 : 0 : break;
715 : 0 : case ECPGt_long:
716 : : case ECPGt_unsigned_long:
3792 meskes@postgresql.or 717 : 0 : *((long *) (ind + ind_offset * act_tuple)) = variable->len;
6402 bruce@momjian.us 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 : : }
6402 bruce@momjian.us 731 :CBC 22 : pval += size;
732 : : }
733 : 22 : break;
734 : :
735 : 23 : case ECPGt_decimal:
736 : : case ECPGt_numeric:
3351 meskes@postgresql.or 737 [ + + + + : 97 : for (endptr = pval; *endptr && *endptr != ',' && *endptr != '}'; endptr++);
+ + ]
738 : 23 : endchar = *endptr;
739 : 23 : *endptr = '\0';
740 : 23 : nres = PGTYPESnumeric_from_asc(pval, &scan_length);
741 : 23 : *endptr = endchar;
742 : :
743 : : /* did we get an error? */
5252 744 [ - + ]: 23 : if (nres == NULL)
745 : : {
5252 meskes@postgresql.or 746 :UBC 0 : ecpg_log("ecpg_get_data on line %d: RESULT %s; errno %d\n",
3336 747 : 0 : lineno, pval, errno);
748 : :
5252 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);
2432 peter_e@gmx.net 762 : 0 : return false;
763 : : }
764 : : }
765 : : else
766 : : {
5252 meskes@postgresql.or 767 : 0 : ecpg_raise(lineno, ECPG_NUMERIC_FORMAT,
768 : : ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
2432 peter_e@gmx.net 769 : 0 : return false;
770 : : }
771 : : }
772 : : else
773 : : {
2356 meskes@postgresql.or 774 [ - + - - ]:CBC 23 : if (!isarray && garbage_left(isarray, &scan_length, compat))
775 : : {
5252 meskes@postgresql.or 776 :UBC 0 : free(nres);
777 : 0 : ecpg_raise(lineno, ECPG_NUMERIC_FORMAT,
778 : : ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
2432 peter_e@gmx.net 779 : 0 : return false;
780 : : }
781 : : }
5252 meskes@postgresql.or 782 :CBC 23 : pval = scan_length;
783 : :
6402 bruce@momjian.us 784 [ + + ]: 23 : if (type == ECPGt_numeric)
785 : 15 : PGTYPESnumeric_copy(nres, (numeric *) (var + offset * act_tuple));
786 : : else
787 : 8 : PGTYPESnumeric_to_decimal(nres, (decimal *) (var + offset * act_tuple));
788 : :
5309 meskes@postgresql.or 789 : 23 : PGTYPESnumeric_free(nres);
6402 bruce@momjian.us 790 : 23 : break;
791 : :
792 : 10 : case ECPGt_interval:
3351 meskes@postgresql.or 793 [ + - ]: 10 : if (*pval == '"')
794 : 10 : pval++;
795 : :
796 [ + - + - : 110 : for (endptr = pval; *endptr && *endptr != ',' && *endptr != '"' && *endptr != '}'; endptr++);
+ + + - ]
797 : 10 : endchar = *endptr;
798 : 10 : *endptr = '\0';
799 : 10 : ires = PGTYPESinterval_from_asc(pval, &scan_length);
800 : 10 : *endptr = endchar;
801 : :
802 : : /* did we get an error? */
5252 803 [ - + ]: 10 : if (ires == NULL)
804 : : {
5252 meskes@postgresql.or 805 :UBC 0 : ecpg_log("ecpg_get_data on line %d: RESULT %s; errno %d\n",
3336 806 : 0 : lineno, pval, errno);
807 : :
5252 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)
2432 peter_e@gmx.net 816 : 0 : return false;
817 : :
5252 meskes@postgresql.or 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);
2432 peter_e@gmx.net 824 : 0 : return false;
825 : : }
826 : : }
827 : : else
828 : : {
3351 meskes@postgresql.or 829 [ + - ]:CBC 10 : if (*scan_length == '"')
5252 830 : 10 : scan_length++;
831 : :
2356 832 [ - + - - ]: 10 : if (!isarray && garbage_left(isarray, &scan_length, compat))
833 : : {
5252 meskes@postgresql.or 834 :UBC 0 : free(ires);
835 : 0 : ecpg_raise(lineno, ECPG_INTERVAL_FORMAT,
836 : : ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
2432 peter_e@gmx.net 837 : 0 : return false;
838 : : }
839 : : }
5252 meskes@postgresql.or 840 :CBC 10 : pval = scan_length;
841 : :
6402 bruce@momjian.us 842 : 10 : PGTYPESinterval_copy(ires, (interval *) (var + offset * act_tuple));
843 : 10 : free(ires);
844 : 10 : break;
845 : :
846 : 11 : case ECPGt_date:
3351 meskes@postgresql.or 847 [ - + ]: 11 : if (*pval == '"')
3351 meskes@postgresql.or 848 :UBC 0 : pval++;
849 : :
3351 meskes@postgresql.or 850 [ + + + + :CBC 121 : for (endptr = pval; *endptr && *endptr != ',' && *endptr != '"' && *endptr != '}'; endptr++);
+ - + + ]
851 : 11 : endchar = *endptr;
852 : 11 : *endptr = '\0';
853 : 11 : ddres = PGTYPESdate_from_asc(pval, &scan_length);
854 : 11 : *endptr = endchar;
855 : :
856 : : /* did we get an error? */
5252 857 [ - + ]: 11 : if (errno != 0)
858 : : {
5252 meskes@postgresql.or 859 :UBC 0 : ecpg_log("ecpg_get_data on line %d: RESULT %s; errno %d\n",
3336 860 : 0 : lineno, pval, errno);
861 : :
5252 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);
2432 peter_e@gmx.net 874 : 0 : return false;
875 : : }
876 : : }
877 : : else
878 : : {
3351 meskes@postgresql.or 879 [ - + ]:CBC 11 : if (*scan_length == '"')
5252 meskes@postgresql.or 880 :UBC 0 : scan_length++;
881 : :
2356 meskes@postgresql.or 882 [ - + - - ]:CBC 11 : if (!isarray && garbage_left(isarray, &scan_length, compat))
883 : : {
5252 meskes@postgresql.or 884 :UBC 0 : ecpg_raise(lineno, ECPG_DATE_FORMAT,
885 : : ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
2432 peter_e@gmx.net 886 : 0 : return false;
887 : : }
888 : : }
889 : :
5252 meskes@postgresql.or 890 :CBC 11 : *((date *) (var + offset * act_tuple)) = ddres;
891 : 11 : pval = scan_length;
6402 bruce@momjian.us 892 : 11 : break;
893 : :
894 : 13 : case ECPGt_timestamp:
3351 meskes@postgresql.or 895 [ + + ]: 13 : if (*pval == '"')
896 : 10 : pval++;
897 : :
898 [ + + + - : 320 : for (endptr = pval; *endptr && *endptr != ',' && *endptr != '"' && *endptr != '}'; endptr++);
+ + + - ]
899 : 13 : endchar = *endptr;
900 : 13 : *endptr = '\0';
901 : 13 : tres = PGTYPEStimestamp_from_asc(pval, &scan_length);
902 : 13 : *endptr = endchar;
903 : :
904 : : /* did we get an error? */
5252 905 [ - + ]: 13 : if (errno != 0)
906 : : {
5252 meskes@postgresql.or 907 :UBC 0 : ecpg_log("ecpg_get_data on line %d: RESULT %s; errno %d\n",
3336 908 : 0 : lineno, pval, errno);
909 : :
5252 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);
2432 peter_e@gmx.net 922 : 0 : return false;
923 : : }
924 : : }
925 : : else
926 : : {
3351 meskes@postgresql.or 927 [ + + ]:CBC 13 : if (*scan_length == '"')
5252 928 : 10 : scan_length++;
929 : :
2356 930 [ - + - - ]: 13 : if (!isarray && garbage_left(isarray, &scan_length, compat))
931 : : {
5252 meskes@postgresql.or 932 :UBC 0 : ecpg_raise(lineno, ECPG_TIMESTAMP_FORMAT,
933 : : ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
2432 peter_e@gmx.net 934 : 0 : return false;
935 : : }
936 : : }
937 : :
5252 meskes@postgresql.or 938 :CBC 13 : *((timestamp *) (var + offset * act_tuple)) = tres;
939 : 13 : pval = scan_length;
6402 bruce@momjian.us 940 : 13 : break;
941 : :
6402 bruce@momjian.us 942 :UBC 0 : default:
6038 meskes@postgresql.or 943 : 0 : ecpg_raise(lineno, ECPG_UNSUPPORTED,
944 : : ECPG_SQLSTATE_ECPG_INTERNAL_ERROR,
945 : : ecpg_type_name(type));
2432 peter_e@gmx.net 946 : 0 : return false;
947 : : break;
948 : : }
5183 meskes@postgresql.or 949 [ + + - + ]:CBC 1423 : if (ECPG_IS_ARRAY(isarray))
950 : : {
6402 bruce@momjian.us 951 : 51 : bool string = false;
952 : :
953 : : /* set array to next entry */
954 : 51 : ++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 : : */
5183 meskes@postgresql.or 962 [ + + - + : 51 : for (; *pval != '\0' && (string || (!array_delimiter(isarray, *pval) && !array_boundary(isarray, *pval))); ++pval)
+ + - + ]
6402 bruce@momjian.us 963 [ # # ]:UBC 0 : if (*pval == '"')
964 : 0 : string = string ? false : true;
965 : :
5183 meskes@postgresql.or 966 [ + + ]:CBC 51 : if (array_delimiter(isarray, *pval))
6402 bruce@momjian.us 967 : 45 : ++pval;
968 : : }
969 : : }
4209 meskes@postgresql.or 970 [ + + + + ]: 1427 : } while (*pval != '\0' && !array_boundary(isarray, *pval));
971 : :
2432 peter_e@gmx.net 972 : 1382 : return true;
973 : : }
|