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
5744 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 == ' ')
5744 meskes@postgresql.or 26 :UBC 0 : return true;
27 : :
5744 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')
5744 meskes@postgresql.or 39 :UBC 0 : return true;
40 : :
5744 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
2917 46 : 289 : 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 : : */
5744 52 [ + + ]: 289 : if (isarray == ECPG_ARRAY_NONE)
53 : : {
2917 54 [ + + - + : 279 : if (INFORMIX_MODE(compat) && **scan_length == '.')
- + ]
55 : : {
56 : : /* skip invalid characters */
57 : : do
58 : : {
2917 meskes@postgresql.or 59 :UBC 0 : (*scan_length)++;
2911 tgl@sss.pgh.pa.us 60 [ # # ]: 0 : } while (isdigit((unsigned char) **scan_length));
61 : : }
62 : :
2917 meskes@postgresql.or 63 [ + - - + ]:CBC 279 : if (**scan_length != ' ' && **scan_length != '\0')
5744 meskes@postgresql.or 64 :UBC 0 : return true;
65 : : }
2917 meskes@postgresql.or 66 [ - + - - :CBC 10 : else if (ECPG_IS_ARRAY(isarray) && !array_delimiter(isarray, **scan_length) && !array_boundary(isarray, **scan_length))
+ + - + ]
8024 meskes@postgresql.or 67 :UBC 0 : return true;
68 : :
8024 meskes@postgresql.or 69 :CBC 289 : return false;
70 : : }
71 : :
72 : :
73 : : /*
74 : : * Portability wrappers borrowed from src/include/utils/float.h
75 : : */
76 : : static double
5746 77 : 8 : get_float8_infinity(void)
78 : : {
79 : 8 : return (double) INFINITY;
80 : : }
81 : :
82 : : static double
83 : 4 : get_float8_nan(void)
84 : : {
5722 bruce@momjian.us 85 : 4 : return (double) NAN;
86 : : }
87 : :
88 : :
89 : : static bool
5746 meskes@postgresql.or 90 : 45 : check_special_value(char *ptr, double *retval, char **endptr)
91 : : {
5053 peter_e@gmx.net 92 [ + + ]: 45 : if (pg_strncasecmp(ptr, "NaN", 3) == 0)
93 : : {
5746 meskes@postgresql.or 94 : 4 : *retval = get_float8_nan();
95 : 4 : *endptr = ptr + 3;
96 : 4 : return true;
97 : : }
5053 peter_e@gmx.net 98 [ + + ]: 41 : else if (pg_strncasecmp(ptr, "Infinity", 8) == 0)
99 : : {
5746 meskes@postgresql.or 100 : 4 : *retval = get_float8_infinity();
101 : 4 : *endptr = ptr + 8;
102 : 4 : return true;
103 : : }
5053 peter_e@gmx.net 104 [ + + ]: 37 : else if (pg_strncasecmp(ptr, "-Infinity", 9) == 0)
105 : : {
5746 meskes@postgresql.or 106 : 4 : *retval = -get_float8_infinity();
107 : 4 : *endptr = ptr + 9;
108 : 4 : return true;
109 : : }
110 : :
111 : 33 : return false;
112 : : }
113 : :
114 : : /* imported from src/backend/utils/adt/encode.c */
115 : :
116 : : unsigned
2443 117 : 35 : ecpg_hex_enc_len(unsigned srclen)
118 : : {
119 : 35 : return srclen << 1;
120 : : }
121 : :
122 : : unsigned
123 : 3 : ecpg_hex_dec_len(unsigned srclen)
124 : : {
125 : 3 : return srclen >> 1;
126 : : }
127 : :
128 : : static inline char
1768 bruce@momjian.us 129 : 9138 : 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 : 9138 : int res = -1;
142 : :
143 [ + - + - ]: 9138 : if (c > 0 && c < 127)
144 : 9138 : res = hexlookup[(unsigned char) c];
145 : :
146 : 9138 : return (char) res;
147 : : }
148 : :
149 : : static unsigned
150 : 9 : 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 : 9 : srcend = src + len;
159 : 9 : s = src;
160 : 9 : p = dst;
161 [ + + ]: 4578 : while (s < srcend)
162 : : {
163 [ + - + - : 4569 : if (*s == ' ' || *s == '\n' || *s == '\t' || *s == '\r')
+ - - + ]
164 : : {
1768 bruce@momjian.us 165 :UBC 0 : s++;
166 : 0 : continue;
167 : : }
1768 bruce@momjian.us 168 :CBC 4569 : v1 = get_hex(*s++) << 4;
169 [ - + ]: 4569 : if (s >= srcend)
1768 bruce@momjian.us 170 :UBC 0 : return -1;
171 : :
1768 bruce@momjian.us 172 :CBC 4569 : v2 = get_hex(*s++);
173 : 4569 : *p++ = v1 | v2;
174 : : }
175 : :
176 : 9 : return p - dst;
177 : : }
178 : :
179 : : unsigned
2443 meskes@postgresql.or 180 : 13 : ecpg_hex_encode(const char *src, unsigned len, char *dst)
181 : : {
182 : : static const char hextbl[] = "0123456789abcdef";
183 : 13 : const char *end = src + len;
184 : :
185 [ + + ]: 6669 : while (src < end)
186 : : {
187 : 6656 : *dst++ = hextbl[(*src >> 4) & 0xF];
188 : 6656 : *dst++ = hextbl[*src & 0xF];
189 : 6656 : src++;
190 : : }
191 : 13 : return len * 2;
192 : : }
193 : :
194 : : bool
6599 195 : 1433 : 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 : : {
8170 bruce@momjian.us 200 : 1433 : struct sqlca_t *sqlca = ECPGget_sqlca();
6963 201 : 1433 : char *pval = (char *) PQgetvalue(results, act_tuple, act_field);
202 : 1433 : int binary = PQfformat(results, act_field);
203 : 1433 : int size = PQgetlength(results, act_tuple, act_field);
204 : 1433 : int value_for_indicator = 0;
205 : : long log_offset;
206 : :
3787 meskes@postgresql.or 207 [ - + ]: 1433 : if (sqlca == NULL)
208 : : {
3787 meskes@postgresql.or 209 :UBC 0 : ecpg_raise(lineno, ECPG_OUT_OF_MEMORY,
210 : : ECPG_SQLSTATE_ECPG_OUT_OF_MEMORY, NULL);
2993 peter_e@gmx.net 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 : : */
6864 meskes@postgresql.or 218 [ + + ]:CBC 1433 : if (ecpg_internal_regression_mode)
7020 219 : 597 : log_offset = -1;
220 : : else
221 : 836 : log_offset = offset;
222 : :
5744 223 [ + + - + : 1433 : 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 */
5722 bruce@momjian.us 226 [ - + ]: 1433 : 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 : : */
5813 meskes@postgresql.or 232 :UBC 0 : ecpg_raise(lineno, ECPG_NOT_FOUND, ECPG_SQLSTATE_NO_DATA, NULL);
2993 peter_e@gmx.net 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 : : */
8160 meskes@postgresql.or 242 [ + + ]:CBC 1433 : if (PQgetisnull(results, act_tuple, act_field))
8147 243 : 48 : value_for_indicator = -1;
244 : :
245 [ + + + - : 1433 : switch (ind_type)
+ - ]
246 : : {
247 : 50 : case ECPGt_short:
248 : : case ECPGt_unsigned_short:
249 : 50 : *((short *) (ind + ind_offset * act_tuple)) = value_for_indicator;
250 : 50 : break;
251 : 80 : case ECPGt_int:
252 : : case ECPGt_unsigned_int:
253 : 80 : *((int *) (ind + ind_offset * act_tuple)) = value_for_indicator;
254 : 80 : break;
255 : 10 : case ECPGt_long:
256 : : case ECPGt_unsigned_long:
257 : 10 : *((long *) (ind + ind_offset * act_tuple)) = value_for_indicator;
258 : 10 : break;
8147 meskes@postgresql.or 259 :UBC 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;
8147 meskes@postgresql.or 263 :CBC 1293 : case ECPGt_NO_INDICATOR:
264 [ + + ]: 1293 : if (value_for_indicator == -1)
265 : : {
8159 266 [ + + ]: 18 : 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 : : */
7792 272 : 12 : ECPGset_noind_null(type, var + offset * act_tuple);
273 : : }
274 : : else
275 : : {
6599 276 : 6 : ecpg_raise(lineno, ECPG_MISSING_INDICATOR,
277 : : ECPG_SQLSTATE_NULL_VALUE_NO_INDICATOR_PARAMETER,
278 : : NULL);
2993 peter_e@gmx.net 279 : 6 : return false;
280 : : }
281 : : }
8147 meskes@postgresql.or 282 : 1287 : break;
8147 meskes@postgresql.or 283 :UBC 0 : default:
6599 284 : 0 : ecpg_raise(lineno, ECPG_UNSUPPORTED,
285 : : ECPG_SQLSTATE_ECPG_INTERNAL_ERROR,
286 : : ecpg_type_name(ind_type));
2993 peter_e@gmx.net 287 : 0 : return false;
288 : : break;
289 : : }
290 : :
8147 meskes@postgresql.or 291 [ + + ]:CBC 1427 : if (value_for_indicator == -1)
2993 peter_e@gmx.net 292 : 42 : return true;
293 : :
294 : : /* let's check if it really is an array if it should be one */
7369 meskes@postgresql.or 295 [ + + ]: 1385 : if (isarray == ECPG_ARRAY_ARRAY)
296 : : {
5813 297 [ - + ]: 6 : if (*pval != '{')
298 : : {
6599 meskes@postgresql.or 299 :UBC 0 : ecpg_raise(lineno, ECPG_DATA_NOT_ARRAY,
300 : : ECPG_SQLSTATE_DATATYPE_MISMATCH, NULL);
2993 peter_e@gmx.net 301 : 0 : return false;
302 : : }
303 : :
7369 meskes@postgresql.or 304 [ + + ]:CBC 6 : switch (type)
305 : : {
306 : 1 : case ECPGt_char:
307 : : case ECPGt_unsigned_char:
308 : : case ECPGt_varchar:
309 : : case ECPGt_string:
310 : 1 : break;
311 : :
312 : 5 : default:
313 : 5 : pval++;
314 : 5 : break;
315 : : }
316 : : }
317 : :
318 : : do
319 : : {
7223 320 [ + + ]: 1430 : if (binary)
321 : : {
5813 322 [ + + + - ]: 4 : if (varcharsize == 0 || varcharsize * offset >= size)
5779 tgl@sss.pgh.pa.us 323 : 4 : memcpy(var + offset * act_tuple, pval, size);
324 : : else
325 : : {
5779 tgl@sss.pgh.pa.us 326 :UBC 0 : memcpy(var + offset * act_tuple, pval, varcharsize * offset);
327 : :
5813 meskes@postgresql.or 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 : : }
5813 meskes@postgresql.or 355 :CBC 4 : pval += size;
356 : : }
357 : : else
358 : : {
6963 bruce@momjian.us 359 [ + - - - : 1426 : 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 : 244 : case ECPGt_short:
373 : : case ECPGt_int:
374 : : case ECPGt_long:
5813 meskes@postgresql.or 375 : 244 : res = strtol(pval, &scan_length, 10);
2917 376 [ - + ]: 244 : if (garbage_left(isarray, &scan_length, compat))
377 : : {
5813 meskes@postgresql.or 378 :UBC 0 : ecpg_raise(lineno, ECPG_INT_FORMAT,
379 : : ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
2993 peter_e@gmx.net 380 : 0 : return false;
381 : : }
5813 meskes@postgresql.or 382 :CBC 244 : pval = scan_length;
383 : :
6963 bruce@momjian.us 384 [ + + + - ]: 244 : switch (type)
385 : : {
386 : 16 : case ECPGt_short:
387 : 16 : *((short *) (var + offset * act_tuple)) = (short) res;
388 : 16 : break;
389 : 215 : case ECPGt_int:
390 : 215 : *((int *) (var + offset * act_tuple)) = (int) res;
391 : 215 : break;
392 : 13 : case ECPGt_long:
393 : 13 : *((long *) (var + offset * act_tuple)) = (long) res;
394 : 13 : break;
6963 bruce@momjian.us 395 :UBC 0 : default:
396 : : /* Cannot happen */
397 : 0 : break;
398 : : }
6963 bruce@momjian.us 399 :CBC 244 : break;
400 : :
6963 bruce@momjian.us 401 :UBC 0 : case ECPGt_unsigned_short:
402 : : case ECPGt_unsigned_int:
403 : : case ECPGt_unsigned_long:
5813 meskes@postgresql.or 404 : 0 : ures = strtoul(pval, &scan_length, 10);
2917 405 [ # # ]: 0 : if (garbage_left(isarray, &scan_length, compat))
406 : : {
5813 407 : 0 : ecpg_raise(lineno, ECPG_UINT_FORMAT,
408 : : ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
2993 peter_e@gmx.net 409 : 0 : return false;
410 : : }
5813 meskes@postgresql.or 411 : 0 : pval = scan_length;
412 : :
6963 bruce@momjian.us 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:
5813 meskes@postgresql.or 431 : 0 : *((long long int *) (var + offset * act_tuple)) = strtoll(pval, &scan_length, 10);
2917 432 [ # # ]: 0 : if (garbage_left(isarray, &scan_length, compat))
433 : : {
5813 434 : 0 : ecpg_raise(lineno, ECPG_INT_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
2993 peter_e@gmx.net 435 : 0 : return false;
436 : : }
5813 meskes@postgresql.or 437 : 0 : pval = scan_length;
438 : :
6963 bruce@momjian.us 439 : 0 : break;
440 : :
441 : 0 : case ECPGt_unsigned_long_long:
5813 meskes@postgresql.or 442 : 0 : *((unsigned long long int *) (var + offset * act_tuple)) = strtoull(pval, &scan_length, 10);
2917 443 [ # # ]: 0 : if (garbage_left(isarray, &scan_length, compat))
444 : : {
5813 445 : 0 : ecpg_raise(lineno, ECPG_UINT_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
2993 peter_e@gmx.net 446 : 0 : return false;
447 : : }
5813 meskes@postgresql.or 448 : 0 : pval = scan_length;
449 : :
6963 bruce@momjian.us 450 : 0 : break;
451 : :
6963 bruce@momjian.us 452 :CBC 45 : case ECPGt_float:
453 : : case ECPGt_double:
5813 meskes@postgresql.or 454 [ + - - + ]: 45 : if (isarray && *pval == '"')
5746 meskes@postgresql.or 455 :UBC 0 : pval++;
456 : :
5746 meskes@postgresql.or 457 [ + + ]:CBC 45 : if (!check_special_value(pval, &dres, &scan_length))
213 peter@eisentraut.org 458 : 33 : dres = strtod(pval, &scan_length);
459 : :
5813 meskes@postgresql.or 460 [ + - - + ]: 45 : if (isarray && *scan_length == '"')
5813 meskes@postgresql.or 461 :UBC 0 : scan_length++;
462 : :
463 : : /* no special INFORMIX treatment for floats */
2916 meskes@postgresql.or 464 [ - + ]:CBC 45 : if (garbage_left(isarray, &scan_length, ECPG_COMPAT_PGSQL))
465 : : {
5813 meskes@postgresql.or 466 :UBC 0 : ecpg_raise(lineno, ECPG_FLOAT_FORMAT,
467 : : ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
2993 peter_e@gmx.net 468 : 0 : return false;
469 : : }
5813 meskes@postgresql.or 470 :CBC 45 : pval = scan_length;
471 : :
6963 bruce@momjian.us 472 [ + + - ]: 45 : switch (type)
473 : : {
474 : 7 : case ECPGt_float:
475 : 7 : *((float *) (var + offset * act_tuple)) = dres;
476 : 7 : break;
477 : 38 : case ECPGt_double:
478 : 38 : *((double *) (var + offset * act_tuple)) = dres;
479 : 38 : break;
6963 bruce@momjian.us 480 :UBC 0 : default:
481 : : /* Cannot happen */
482 : 0 : break;
483 : : }
6963 bruce@momjian.us 484 :CBC 45 : break;
485 : :
486 : 12 : case ECPGt_bool:
5813 meskes@postgresql.or 487 [ + + + - ]: 12 : if (pval[0] == 'f' && pval[1] == '\0')
488 : : {
3693 489 : 5 : *((bool *) (var + offset * act_tuple)) = false;
4770 490 : 5 : pval++;
5813 491 : 5 : break;
492 : : }
493 [ + - + - ]: 7 : else if (pval[0] == 't' && pval[1] == '\0')
494 : : {
3693 495 : 7 : *((bool *) (var + offset * act_tuple)) = true;
4770 496 : 7 : pval++;
5813 497 : 7 : break;
498 : : }
5813 meskes@postgresql.or 499 [ # # # # ]:UBC 0 : else if (pval[0] == '\0' && PQgetisnull(results, act_tuple, act_field))
500 : : {
501 : : /* NULL is valid */
502 : 0 : break;
503 : : }
504 : :
6599 505 : 0 : ecpg_raise(lineno, ECPG_CONVERT_BOOL,
506 : : ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
2993 peter_e@gmx.net 507 : 0 : return false;
508 : : break;
509 : :
2443 meskes@postgresql.or 510 :CBC 9 : case ECPGt_bytea:
511 : : {
1918 michael@paquier.xyz 512 : 9 : struct ECPGgeneric_bytea *variable =
892 tgl@sss.pgh.pa.us 513 : 9 : (struct ECPGgeneric_bytea *) (var + offset * act_tuple);
514 : : long dst_size,
515 : : src_size,
516 : : dec_size;
517 : :
2443 meskes@postgresql.or 518 : 9 : dst_size = ecpg_hex_enc_len(varcharsize);
519 : 9 : src_size = size - 2; /* exclude backslash + 'x' */
520 : 9 : dec_size = src_size < dst_size ? src_size : dst_size;
521 : 9 : variable->len = hex_decode(pval + 2, dec_size, variable->arr);
522 : :
523 [ + + ]: 9 : if (dst_size < src_size)
524 : : {
525 : 3 : long rcv_size = ecpg_hex_dec_len(size - 2);
526 : :
527 : : /* truncation */
528 [ - + - - : 3 : switch (ind_type)
- ]
529 : : {
2443 meskes@postgresql.or 530 :UBC 0 : case ECPGt_short:
531 : : case ECPGt_unsigned_short:
532 : 0 : *((short *) (ind + ind_offset * act_tuple)) = rcv_size;
533 : 0 : break;
2443 meskes@postgresql.or 534 :CBC 3 : case ECPGt_int:
535 : : case ECPGt_unsigned_int:
536 : 3 : *((int *) (ind + ind_offset * act_tuple)) = rcv_size;
537 : 3 : break;
2443 meskes@postgresql.or 538 :UBC 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 : : }
2443 meskes@postgresql.or 549 :CBC 3 : sqlca->sqlwarn[0] = sqlca->sqlwarn[1] = 'W';
550 : : }
551 : :
552 : 9 : pval += size;
553 : : }
554 : 9 : break;
555 : :
6963 bruce@momjian.us 556 : 1037 : case ECPGt_char:
557 : : case ECPGt_unsigned_char:
558 : : case ECPGt_string:
559 : : {
5722 560 : 1037 : 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 : : */
4192 meskes@postgresql.or 567 [ + + - + ]: 1037 : if (varcharsize == 0 && offset == sizeof(char *))
4192 bruce@momjian.us 568 :UBC 0 : str = *(char **) str;
569 : :
923 michael@paquier.xyz 570 [ + + ]:CBC 1037 : if (varcharsize > size)
571 : : {
572 : : /*
573 : : * compatibility mode, blank pad and null
574 : : * terminate char array
575 : : */
2784 meskes@postgresql.or 576 [ + + - + : 955 : if (ORACLE_MODE(compat) && (type == ECPGt_char || type == ECPGt_unsigned_char))
- - ]
577 : : {
578 : 9 : memset(str, ' ', varcharsize);
579 : 9 : memcpy(str, pval, size);
2741 tgl@sss.pgh.pa.us 580 : 9 : str[varcharsize - 1] = '\0';
581 : :
582 : : /*
583 : : * compatibility mode empty string gets -1
584 : : * indicator but no warning
585 : : */
586 [ + + ]: 9 : if (size == 0)
587 : : {
588 : : /* truncation */
2784 meskes@postgresql.or 589 [ + - - - : 2 : switch (ind_type)
- ]
590 : : {
591 : 2 : case ECPGt_short:
592 : : case ECPGt_unsigned_short:
593 : 2 : *((short *) (ind + ind_offset * act_tuple)) = -1;
594 : 2 : break;
2784 meskes@postgresql.or 595 :UBC 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 : : {
2784 meskes@postgresql.or 614 :CBC 946 : strncpy(str, pval, size + 1);
615 : : }
616 : : /* do the rtrim() */
5925 617 [ + + ]: 955 : if (type == ECPGt_string)
618 : : {
5722 bruce@momjian.us 619 : 2 : char *last = str + size;
620 : :
5925 meskes@postgresql.or 621 [ + + + + : 13 : while (last > str && (*last == ' ' || *last == '\0'))
+ + ]
622 : : {
623 : 11 : *last = '\0';
624 : 11 : last--;
625 : : }
626 : : }
627 : : }
628 : : else
629 : : {
923 michael@paquier.xyz 630 : 82 : int charsize = varcharsize;
631 : :
632 : : /*
633 : : * assume that the caller provided storage exactly
634 : : * fit when varcharsize is zero.
635 : : */
636 [ + + ]: 82 : if (varcharsize == 0)
637 : 34 : charsize = size + 1;
638 : :
639 : 82 : strncpy(str, pval, charsize);
640 : :
641 : : /* compatibility mode, null terminate char array */
642 [ + + + + ]: 82 : if (ORACLE_MODE(compat) && (charsize - 1) < size)
643 : : {
2784 meskes@postgresql.or 644 [ - + - - ]: 3 : if (type == ECPGt_char || type == ECPGt_unsigned_char)
923 michael@paquier.xyz 645 : 3 : str[charsize - 1] = '\0';
646 : : }
647 : :
648 [ + + + + : 82 : if (charsize < size || (ORACLE_MODE(compat) && (charsize - 1) < size))
+ + ]
649 : : {
650 : : /* truncation */
6963 bruce@momjian.us 651 [ + + - - : 6 : switch (ind_type)
+ ]
652 : : {
653 : 3 : case ECPGt_short:
654 : : case ECPGt_unsigned_short:
655 : 3 : *((short *) (ind + ind_offset * act_tuple)) = size;
656 : 3 : break;
657 : 1 : case ECPGt_int:
658 : : case ECPGt_unsigned_int:
659 : 1 : *((int *) (ind + ind_offset * act_tuple)) = size;
660 : 1 : break;
6963 bruce@momjian.us 661 :UBC 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;
6963 bruce@momjian.us 669 :CBC 2 : default:
670 : 2 : break;
671 : : }
672 : 6 : sqlca->sqlwarn[0] = sqlca->sqlwarn[1] = 'W';
673 : : }
674 : : }
675 : 1037 : pval += size;
676 : : }
677 : 1037 : break;
678 : :
679 : 22 : case ECPGt_varchar:
680 : : {
681 : 22 : struct ECPGgeneric_varchar *variable =
892 tgl@sss.pgh.pa.us 682 : 22 : (struct ECPGgeneric_varchar *) (var + offset * act_tuple);
683 : :
6963 bruce@momjian.us 684 : 22 : variable->len = size;
685 [ - + ]: 22 : if (varcharsize == 0)
6963 bruce@momjian.us 686 :UBC 0 : strncpy(variable->arr, pval, variable->len);
687 : : else
688 : : {
6963 bruce@momjian.us 689 :CBC 22 : strncpy(variable->arr, pval, varcharsize);
690 : :
691 [ - + ]: 22 : if (variable->len > varcharsize)
692 : : {
693 : : /* truncation */
6963 bruce@momjian.us 694 [ # # # # :UBC 0 : switch (ind_type)
# ]
695 : : {
696 : 0 : case ECPGt_short:
697 : : case ECPGt_unsigned_short:
4353 meskes@postgresql.or 698 : 0 : *((short *) (ind + ind_offset * act_tuple)) = variable->len;
6963 bruce@momjian.us 699 : 0 : break;
700 : 0 : case ECPGt_int:
701 : : case ECPGt_unsigned_int:
4353 meskes@postgresql.or 702 : 0 : *((int *) (ind + ind_offset * act_tuple)) = variable->len;
6963 bruce@momjian.us 703 : 0 : break;
704 : 0 : case ECPGt_long:
705 : : case ECPGt_unsigned_long:
4353 meskes@postgresql.or 706 : 0 : *((long *) (ind + ind_offset * act_tuple)) = variable->len;
6963 bruce@momjian.us 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 : : }
6963 bruce@momjian.us 720 :CBC 22 : pval += size;
721 : : }
722 : 22 : break;
723 : :
724 : 23 : case ECPGt_decimal:
725 : : case ECPGt_numeric:
3912 meskes@postgresql.or 726 [ + + + + : 97 : for (endptr = pval; *endptr && *endptr != ',' && *endptr != '}'; endptr++);
+ + ]
727 : 23 : endchar = *endptr;
728 : 23 : *endptr = '\0';
729 : 23 : nres = PGTYPESnumeric_from_asc(pval, &scan_length);
730 : 23 : *endptr = endchar;
731 : :
732 : : /* did we get an error? */
5813 733 [ - + ]: 23 : if (nres == NULL)
734 : : {
5813 meskes@postgresql.or 735 :UBC 0 : ecpg_log("ecpg_get_data on line %d: RESULT %s; errno %d\n",
3897 736 : 0 : lineno, pval, errno);
737 : :
5813 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);
2993 peter_e@gmx.net 751 : 0 : return false;
752 : : }
753 : : }
754 : : else
755 : : {
5813 meskes@postgresql.or 756 : 0 : ecpg_raise(lineno, ECPG_NUMERIC_FORMAT,
757 : : ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
2993 peter_e@gmx.net 758 : 0 : return false;
759 : : }
760 : : }
761 : : else
762 : : {
2917 meskes@postgresql.or 763 [ - + - - ]:CBC 23 : if (!isarray && garbage_left(isarray, &scan_length, compat))
764 : : {
5813 meskes@postgresql.or 765 :UBC 0 : free(nres);
766 : 0 : ecpg_raise(lineno, ECPG_NUMERIC_FORMAT,
767 : : ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
2993 peter_e@gmx.net 768 : 0 : return false;
769 : : }
770 : : }
5813 meskes@postgresql.or 771 :CBC 23 : pval = scan_length;
772 : :
6963 bruce@momjian.us 773 [ + + ]: 23 : if (type == ECPGt_numeric)
774 : 15 : PGTYPESnumeric_copy(nres, (numeric *) (var + offset * act_tuple));
775 : : else
776 : 8 : PGTYPESnumeric_to_decimal(nres, (decimal *) (var + offset * act_tuple));
777 : :
5870 meskes@postgresql.or 778 : 23 : PGTYPESnumeric_free(nres);
6963 bruce@momjian.us 779 : 23 : break;
780 : :
781 : 10 : case ECPGt_interval:
3912 meskes@postgresql.or 782 [ + - ]: 10 : if (*pval == '"')
783 : 10 : pval++;
784 : :
785 [ + - + - : 110 : for (endptr = pval; *endptr && *endptr != ',' && *endptr != '"' && *endptr != '}'; endptr++);
+ + + - ]
786 : 10 : endchar = *endptr;
787 : 10 : *endptr = '\0';
788 : 10 : ires = PGTYPESinterval_from_asc(pval, &scan_length);
789 : 10 : *endptr = endchar;
790 : :
791 : : /* did we get an error? */
5813 792 [ - + ]: 10 : if (ires == NULL)
793 : : {
5813 meskes@postgresql.or 794 :UBC 0 : ecpg_log("ecpg_get_data on line %d: RESULT %s; errno %d\n",
3897 795 : 0 : lineno, pval, errno);
796 : :
5813 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)
2993 peter_e@gmx.net 805 : 0 : return false;
806 : :
5813 meskes@postgresql.or 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);
2993 peter_e@gmx.net 813 : 0 : return false;
814 : : }
815 : : }
816 : : else
817 : : {
3912 meskes@postgresql.or 818 [ + - ]:CBC 10 : if (*scan_length == '"')
5813 819 : 10 : scan_length++;
820 : :
2917 821 [ - + - - ]: 10 : if (!isarray && garbage_left(isarray, &scan_length, compat))
822 : : {
5813 meskes@postgresql.or 823 :UBC 0 : free(ires);
824 : 0 : ecpg_raise(lineno, ECPG_INTERVAL_FORMAT,
825 : : ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
2993 peter_e@gmx.net 826 : 0 : return false;
827 : : }
828 : : }
5813 meskes@postgresql.or 829 :CBC 10 : pval = scan_length;
830 : :
6963 bruce@momjian.us 831 : 10 : PGTYPESinterval_copy(ires, (interval *) (var + offset * act_tuple));
832 : 10 : free(ires);
833 : 10 : break;
834 : :
835 : 11 : case ECPGt_date:
3912 meskes@postgresql.or 836 [ - + ]: 11 : if (*pval == '"')
3912 meskes@postgresql.or 837 :UBC 0 : pval++;
838 : :
3912 meskes@postgresql.or 839 [ + + + + :CBC 121 : for (endptr = pval; *endptr && *endptr != ',' && *endptr != '"' && *endptr != '}'; endptr++);
+ - + + ]
840 : 11 : endchar = *endptr;
841 : 11 : *endptr = '\0';
842 : 11 : ddres = PGTYPESdate_from_asc(pval, &scan_length);
843 : 11 : *endptr = endchar;
844 : :
845 : : /* did we get an error? */
5813 846 [ - + ]: 11 : if (errno != 0)
847 : : {
5813 meskes@postgresql.or 848 :UBC 0 : ecpg_log("ecpg_get_data on line %d: RESULT %s; errno %d\n",
3897 849 : 0 : lineno, pval, errno);
850 : :
5813 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);
2993 peter_e@gmx.net 863 : 0 : return false;
864 : : }
865 : : }
866 : : else
867 : : {
3912 meskes@postgresql.or 868 [ - + ]:CBC 11 : if (*scan_length == '"')
5813 meskes@postgresql.or 869 :UBC 0 : scan_length++;
870 : :
2917 meskes@postgresql.or 871 [ - + - - ]:CBC 11 : if (!isarray && garbage_left(isarray, &scan_length, compat))
872 : : {
5813 meskes@postgresql.or 873 :UBC 0 : ecpg_raise(lineno, ECPG_DATE_FORMAT,
874 : : ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
2993 peter_e@gmx.net 875 : 0 : return false;
876 : : }
877 : : }
878 : :
5813 meskes@postgresql.or 879 :CBC 11 : *((date *) (var + offset * act_tuple)) = ddres;
880 : 11 : pval = scan_length;
6963 bruce@momjian.us 881 : 11 : break;
882 : :
883 : 13 : case ECPGt_timestamp:
3912 meskes@postgresql.or 884 [ + + ]: 13 : if (*pval == '"')
885 : 10 : pval++;
886 : :
887 [ + + + - : 320 : for (endptr = pval; *endptr && *endptr != ',' && *endptr != '"' && *endptr != '}'; endptr++);
+ + + - ]
888 : 13 : endchar = *endptr;
889 : 13 : *endptr = '\0';
890 : 13 : tres = PGTYPEStimestamp_from_asc(pval, &scan_length);
891 : 13 : *endptr = endchar;
892 : :
893 : : /* did we get an error? */
5813 894 [ - + ]: 13 : if (errno != 0)
895 : : {
5813 meskes@postgresql.or 896 :UBC 0 : ecpg_log("ecpg_get_data on line %d: RESULT %s; errno %d\n",
3897 897 : 0 : lineno, pval, errno);
898 : :
5813 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);
2993 peter_e@gmx.net 911 : 0 : return false;
912 : : }
913 : : }
914 : : else
915 : : {
3912 meskes@postgresql.or 916 [ + + ]:CBC 13 : if (*scan_length == '"')
5813 917 : 10 : scan_length++;
918 : :
2917 919 [ - + - - ]: 13 : if (!isarray && garbage_left(isarray, &scan_length, compat))
920 : : {
5813 meskes@postgresql.or 921 :UBC 0 : ecpg_raise(lineno, ECPG_TIMESTAMP_FORMAT,
922 : : ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
2993 peter_e@gmx.net 923 : 0 : return false;
924 : : }
925 : : }
926 : :
5813 meskes@postgresql.or 927 :CBC 13 : *((timestamp *) (var + offset * act_tuple)) = tres;
928 : 13 : pval = scan_length;
6963 bruce@momjian.us 929 : 13 : break;
930 : :
6963 bruce@momjian.us 931 :UBC 0 : default:
6599 meskes@postgresql.or 932 : 0 : ecpg_raise(lineno, ECPG_UNSUPPORTED,
933 : : ECPG_SQLSTATE_ECPG_INTERNAL_ERROR,
934 : : ecpg_type_name(type));
2993 peter_e@gmx.net 935 : 0 : return false;
936 : : break;
937 : : }
5744 meskes@postgresql.or 938 [ + + - + ]:CBC 1426 : if (ECPG_IS_ARRAY(isarray))
939 : : {
6963 bruce@momjian.us 940 : 51 : bool string = false;
941 : :
942 : : /* set array to next entry */
943 : 51 : ++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 : : */
5744 meskes@postgresql.or 951 [ + + - + : 51 : for (; *pval != '\0' && (string || (!array_delimiter(isarray, *pval) && !array_boundary(isarray, *pval))); ++pval)
+ + - + ]
6963 bruce@momjian.us 952 [ # # ]:UBC 0 : if (*pval == '"')
953 : 0 : string = string ? false : true;
954 : :
5744 meskes@postgresql.or 955 [ + + ]:CBC 51 : if (array_delimiter(isarray, *pval))
6963 bruce@momjian.us 956 : 45 : ++pval;
957 : : }
958 : : }
4770 meskes@postgresql.or 959 [ + + + + ]: 1430 : } while (*pval != '\0' && !array_boundary(isarray, *pval));
960 : :
2993 peter_e@gmx.net 961 : 1385 : return true;
962 : : }
|