Line data Source code
1 : /*
2 : * SPDX-License-Identifier: MPL-2.0
3 : *
4 : * This Source Code Form is subject to the terms of the Mozilla Public
5 : * License, v. 2.0. If a copy of the MPL was not distributed with this
6 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 : *
8 : * Copyright 2024, 2025 MonetDB Foundation;
9 : * Copyright August 2008 - 2023 MonetDB B.V.;
10 : * Copyright 1997 - July 2008 CWI.
11 : */
12 :
13 : #include "ODBCGlobal.h"
14 : #include "ODBCStmt.h"
15 : #include "ODBCUtil.h"
16 : #include <time.h>
17 : #ifdef HAVE_STRINGS_H
18 : #include <strings.h> /* for strncasecmp */
19 : #endif
20 : #include <float.h> /* for FLT_MAX */
21 :
22 : #ifdef HAVE_HGE
23 : #define MAXBIGNUM10 (((uhge) UINT64_C(0x1999999999999999) << 64) | ((uhge) UINT64_C(0x9999999999999999)))
24 : #define MAXBIGNUMLAST '5'
25 : #else
26 : #define MAXBIGNUM10 (UINT64_MAX / 10)
27 : #define MAXBIGNUMLAST ('0' + (int) (UINT64_MAX % 10))
28 : #endif
29 :
30 : #define space(c) ((c) == ' ' || (c) == '\t')
31 :
32 : typedef struct {
33 : uint8_t precision; /* total number of digits */
34 : int8_t scale; /* how far to shift decimal point (>
35 : * 0: shift left, i.e. number has
36 : * fraction; < 0: shift right,
37 : * i.e. multiply with power of 10) */
38 : uint8_t sign; /* 1 pos, 0 neg */
39 : #ifdef HAVE_HGE
40 : uhge val; /* the value (128 bits) */
41 : #else
42 : uint64_t val; /* the value (64 bits) */
43 : #endif
44 : } bignum_t;
45 :
46 : /* Parse a number and store in a bignum_t.
47 : * 1 is returned if all is well;
48 : * 2 is returned if there is loss of precision (i.e. overflow of the value);
49 : * 0 is returned if the string is not a number, or if scale doesn't fit.
50 : */
51 : static int
52 5255 : parseint(const char *data, bignum_t *nval)
53 : {
54 5255 : int fraction = 0; /* inside the fractional part */
55 5255 : int scale = 0;
56 5255 : int overflow = 0;
57 :
58 5255 : nval->val = 0;
59 5255 : nval->precision = 0;
60 5255 : scale = 0;
61 5255 : while (space(*data))
62 0 : data++;
63 5255 : if (*data == '-') {
64 564 : nval->sign = 0;
65 564 : data++;
66 : } else {
67 4691 : nval->sign = 1;
68 4691 : if (*data == '+')
69 0 : data++;
70 : }
71 17599 : while (*data && *data != 'e' && *data != 'E' && !space(*data)) {
72 12344 : if (*data == '.')
73 : fraction = 1;
74 12304 : else if (isdigit((unsigned char) *data)) {
75 12304 : if (overflow ||
76 12304 : nval->val > MAXBIGNUM10 ||
77 0 : (nval->val == MAXBIGNUM10 &&
78 : *data > MAXBIGNUMLAST)) {
79 0 : overflow = 1;
80 0 : if (!fraction)
81 0 : scale--;
82 : } else {
83 12304 : nval->precision++;
84 12304 : if (fraction)
85 149 : scale++;
86 12304 : nval->val *= 10;
87 12304 : nval->val += *data - '0';
88 : }
89 : } else
90 : return 0;
91 12344 : data++;
92 : }
93 5255 : if (*data == 'e' || *data == 'E') {
94 0 : char *p;
95 0 : long i;
96 :
97 0 : i = strtol(data, &p, 10);
98 0 : if (p == data || *p)
99 0 : return 0;
100 0 : scale -= i;
101 : /* normalize scale */
102 0 : while (scale > 0 && nval->val % 10 == 0) {
103 0 : scale--;
104 0 : nval->val /= 10;
105 : }
106 0 : while (scale < 0 && nval->val <= MAXBIGNUM10) {
107 0 : scale++;
108 0 : nval->val *= 10;
109 : }
110 : }
111 5255 : if (scale < -128 || scale > 127)
112 : return 0;
113 5255 : nval->scale = scale;
114 5255 : while (space(*data))
115 0 : data++;
116 5255 : if (*data)
117 : return 0;
118 5255 : return 1 + overflow;
119 : }
120 :
121 : static int
122 32 : parsesecondinterval(bignum_t *nval, SQL_INTERVAL_STRUCT *ival, int type)
123 : {
124 32 : unsigned int f = 1;
125 32 : int ivalscale = 0;
126 :
127 : /* convert value to second */
128 32 : switch (type) {
129 0 : case SQL_INTERVAL_DAY: /* SQL_C_INTERVAL_DAY */
130 0 : nval->val *= 24;
131 : /* fall through */
132 0 : case SQL_INTERVAL_HOUR: /* SQL_C_INTERVAL_HOUR */
133 : case SQL_INTERVAL_DAY_TO_HOUR: /* SQL_C_INTERVAL_DAY_TO_HOUR */
134 0 : nval->val *= 60;
135 : /* fall through */
136 0 : case SQL_INTERVAL_MINUTE: /* SQL_C_INTERVAL_MINUTE */
137 : case SQL_INTERVAL_HOUR_TO_MINUTE: /* SQL_C_INTERVAL_HOUR_TO_MINUTE */
138 : case SQL_INTERVAL_DAY_TO_MINUTE: /* SQL_C_INTERVAL_DAY_TO_MINUTE */
139 0 : nval->val *= 60;
140 : /* fall through */
141 : case SQL_INTERVAL_SECOND: /* SQL_C_INTERVAL_SECOND */
142 : case SQL_INTERVAL_MINUTE_TO_SECOND: /* SQL_C_INTERVAL_MINUTE_TO_SECOND */
143 : case SQL_INTERVAL_HOUR_TO_SECOND: /* SQL_C_INTERVAL_HOUR_TO_SECOND */
144 : case SQL_INTERVAL_DAY_TO_SECOND: /* SQL_C_INTERVAL_DAY_TO_SECOND */
145 32 : break;
146 : default:
147 0 : assert(0);
148 : }
149 32 : ival->intval.day_second.fraction = 0;
150 128 : while (nval->scale > 0) {
151 96 : if (f < 1000000000) {
152 96 : ivalscale++;
153 96 : ival->intval.day_second.fraction += (SQLUINTEGER) ((nval->val % 10) * f);
154 96 : f *= 10;
155 : }
156 96 : nval->val /= 10;
157 96 : nval->scale--;
158 : }
159 32 : ival->interval_type = SQL_IS_DAY_TO_SECOND;
160 32 : ival->interval_sign = !nval->sign;
161 32 : ival->intval.day_second.second = (SQLUINTEGER) (nval->val % 60);
162 32 : nval->val /= 60;
163 32 : ival->intval.day_second.minute = (SQLUINTEGER) (nval->val % 60);
164 32 : nval->val /= 60;
165 32 : ival->intval.day_second.hour = (SQLUINTEGER) (nval->val % 24);
166 32 : nval->val /= 24;
167 32 : ival->intval.day_second.day = (SQLUINTEGER) nval->val;
168 32 : return ivalscale;
169 : }
170 :
171 : static void
172 9 : parsemonthinterval(bignum_t *nval, SQL_INTERVAL_STRUCT *ival, int type)
173 : {
174 : /* convert value to months */
175 9 : switch (type) {
176 0 : case SQL_INTERVAL_YEAR: /* SQL_C_INTERVAL_YEAR */
177 0 : nval->val *= 12;
178 : case SQL_INTERVAL_YEAR_TO_MONTH: /* SQL_C_INTERVAL_YEAR_TO_MONTH */
179 : case SQL_INTERVAL_MONTH: /* SQL_C_INTERVAL_MONTH */
180 : break;
181 : default:
182 0 : assert(0);
183 : }
184 : /* ignore fraction */
185 9 : while (nval->scale > 0) {
186 0 : nval->scale--;
187 0 : nval->val /= 10;
188 : }
189 9 : ival->interval_type = SQL_IS_YEAR_TO_MONTH;
190 9 : ival->interval_sign = !nval->sign;
191 9 : ival->intval.year_month.year = (SQLUINTEGER) (nval->val / 12);
192 9 : ival->intval.year_month.month = (SQLUINTEGER) (nval->val % 12);
193 9 : }
194 :
195 : static short monthlengths[] = {
196 : 0, /* dummy */
197 : 31, /* Jan */
198 : 29, /* Feb */
199 : 31, /* Mar */
200 : 30, /* Apr */
201 : 31, /* May */
202 : 30, /* Jun */
203 : 31, /* Jul */
204 : 31, /* Aug */
205 : 30, /* Sep */
206 : 31, /* Oct */
207 : 30, /* Nov */
208 : 31, /* Dec */
209 : };
210 :
211 : #define isLeap(y) ((y) % 4 == 0 && ((y) % 100 != 0 || (y) % 400 == 0))
212 :
213 : static int
214 2003 : parsedate(const char *data, DATE_STRUCT *dval)
215 : {
216 2003 : int n;
217 :
218 2003 : *dval = (DATE_STRUCT) {0};
219 2003 : while (space(*data))
220 0 : data++;
221 2003 : if (sscanf(data, "{d '%hd-%hu-%hu'}%n",
222 2003 : &dval->year, &dval->month, &dval->day, &n) < 3 &&
223 2003 : sscanf(data, "%hd-%hu-%hu%n",
224 : &dval->year, &dval->month, &dval->day, &n) < 3)
225 : return 0;
226 2003 : if (dval->month == 0 || dval->month > 12 ||
227 2003 : dval->day == 0 || dval->day > monthlengths[dval->month] ||
228 169 : (dval->month == 2 && !isLeap(dval->year) && dval->day == 29))
229 : return 0;
230 2003 : data += n;
231 2003 : while (space(*data))
232 0 : data++;
233 2003 : if (*data)
234 : return 0;
235 : return 1;
236 : }
237 :
238 : static int
239 2003 : parsetime(const char *data, TIME_STRUCT *tval)
240 : {
241 2003 : int n;
242 2003 : int braces;
243 :
244 2003 : *tval = (TIME_STRUCT) {0};
245 2003 : while (space(*data))
246 0 : data++;
247 2003 : if (sscanf(data, "{t '%hu:%hu:%hu%n",
248 2003 : &tval->hour, &tval->minute, &tval->second, &n) < 3 &&
249 2003 : sscanf(data, "%hu:%hu:%hu%n",
250 : &tval->hour, &tval->minute, &tval->second, &n) < 3)
251 : return 0;
252 : /* seconds can go up to 61(!) because of leap seconds */
253 2003 : if (tval->hour > 23 || tval->minute > 59 || tval->second > 61)
254 : return 0;
255 2003 : braces = *data == '{';
256 2003 : data += n;
257 2003 : n = 1; /* tentative return value */
258 2003 : if (*data == '.') {
259 0 : while (*++data && isdigit((unsigned char) *data))
260 : ;
261 0 : n = 2; /* indicate loss of precision */
262 : }
263 2003 : if (*data == '+' || *data == '-') {
264 : /* time zone (which we ignore) */
265 0 : short tzhour, tzmin;
266 0 : int i;
267 :
268 0 : if (sscanf(data, "%hd:%hd%n", &tzhour, &tzmin, &i) < 2)
269 0 : return 0;
270 0 : data += i;
271 0 : tzmin = tzhour < 0 ? tzhour * 60 - tzmin : tzhour * 60 + tzmin;
272 0 : (void) tzhour;
273 0 : (void) tzmin;
274 : }
275 2003 : if (braces && *data++ != '\'' && *data++ != '}')
276 : return 0;
277 2003 : while (space(*data))
278 0 : data++;
279 2003 : if (*data)
280 : return 0;
281 2003 : return n;
282 : }
283 :
284 : static int
285 3 : parsetimestamp(const char *data, TIMESTAMP_STRUCT *tsval)
286 : {
287 3 : int n;
288 3 : int braces;
289 :
290 3 : *tsval = (TIMESTAMP_STRUCT) {0};
291 3 : while (space(*data))
292 0 : data++;
293 3 : if (sscanf(data, "{TS '%hd-%hu-%hu %hu:%hu:%hu%n",
294 : &tsval->year, &tsval->month, &tsval->day,
295 3 : &tsval->hour, &tsval->minute, &tsval->second, &n) < 6 &&
296 3 : sscanf(data, "%hd-%hu-%hu %hu:%hu:%hu%n",
297 : &tsval->year, &tsval->month, &tsval->day,
298 : &tsval->hour, &tsval->minute, &tsval->second, &n) < 6)
299 : return 0;
300 3 : if (tsval->month == 0 || tsval->month > 12 ||
301 3 : tsval->day == 0 || tsval->day > monthlengths[tsval->month] ||
302 1 : (tsval->month == 2 && !isLeap(tsval->year) && tsval->day == 29) ||
303 3 : tsval->hour > 23 || tsval->minute > 59 || tsval->second > 61)
304 : return 0;
305 3 : braces = *data == '{';
306 3 : tsval->fraction = 0;
307 3 : data += n;
308 3 : n = 1000000000;
309 3 : if (*data == '.') {
310 21 : while (*++data && isdigit((unsigned char) *data)) {
311 18 : n /= 10;
312 18 : tsval->fraction += (*data - '0') * n;
313 : }
314 : }
315 3 : if (*data == '+' || *data == '-') {
316 : /* time zone (which we ignore) */
317 0 : short tzhour, tzmin;
318 0 : int i;
319 :
320 0 : if (sscanf(data, "%hd:%hd%n", &tzhour, &tzmin, &i) < 2)
321 0 : return 0;
322 0 : data += i;
323 0 : tzmin = tzhour < 0 ? tzhour * 60 - tzmin : tzhour * 60 + tzmin;
324 0 : (void) tzhour;
325 0 : (void) tzmin;
326 : }
327 3 : if (braces && *data++ != '\'' && *data++ != '}')
328 : return 0;
329 3 : while (space(*data))
330 0 : data++;
331 3 : if (*data)
332 : return 0;
333 3 : if (n == 0)
334 0 : return 2; /* fractional digits truncated */
335 : return 1;
336 : }
337 :
338 : static int
339 2006 : parsedouble(const char *data, double *fval)
340 : {
341 2006 : char *p;
342 :
343 2006 : while (space(*data))
344 0 : data++;
345 2006 : errno = 0;
346 2006 : *fval = strtod(data, &p);
347 2006 : if (p == NULL || p == data || errno == ERANGE)
348 : return 0;
349 2006 : while (space(*p))
350 0 : p++;
351 2006 : if (*p)
352 : return 0;
353 : return 1;
354 : }
355 :
356 : static SQLSMALLINT
357 0 : ODBCDefaultType(ODBCDescRec *rec)
358 : {
359 0 : switch (rec->sql_desc_concise_type) {
360 : case SQL_CHAR:
361 : case SQL_VARCHAR:
362 : case SQL_LONGVARCHAR:
363 : case SQL_DECIMAL:
364 : case SQL_NUMERIC:
365 : case SQL_GUID:
366 : return SQL_C_CHAR;
367 0 : case SQL_WCHAR:
368 : case SQL_WVARCHAR:
369 : case SQL_WLONGVARCHAR:
370 0 : return SQL_C_WCHAR;
371 0 : case SQL_BIT:
372 0 : return SQL_C_BIT;
373 0 : case SQL_TINYINT:
374 0 : return rec->sql_desc_unsigned ? SQL_C_UTINYINT : SQL_C_STINYINT;
375 0 : case SQL_SMALLINT:
376 0 : return rec->sql_desc_unsigned ? SQL_C_USHORT : SQL_C_SSHORT;
377 0 : case SQL_INTEGER:
378 0 : return rec->sql_desc_unsigned ? SQL_C_ULONG : SQL_C_SLONG;
379 0 : case SQL_BIGINT:
380 0 : return rec->sql_desc_unsigned ? SQL_C_UBIGINT : SQL_C_SBIGINT;
381 0 : case SQL_HUGEINT: /* for now, try to treat as BIGINT */
382 0 : return rec->sql_desc_unsigned ? SQL_C_UBIGINT : SQL_C_SBIGINT;
383 0 : case SQL_REAL:
384 0 : return SQL_C_FLOAT;
385 0 : case SQL_FLOAT:
386 : case SQL_DOUBLE:
387 0 : return SQL_C_DOUBLE;
388 0 : case SQL_BINARY:
389 : case SQL_VARBINARY:
390 : case SQL_LONGVARBINARY:
391 0 : return SQL_C_BINARY;
392 0 : case SQL_TYPE_DATE:
393 0 : return SQL_C_TYPE_DATE;
394 0 : case SQL_TYPE_TIME:
395 0 : return SQL_C_TYPE_TIME;
396 0 : case SQL_TYPE_TIMESTAMP:
397 0 : return SQL_C_TYPE_TIMESTAMP;
398 0 : case SQL_INTERVAL_YEAR:
399 0 : return SQL_C_INTERVAL_YEAR;
400 0 : case SQL_INTERVAL_MONTH:
401 0 : return SQL_C_INTERVAL_MONTH;
402 0 : case SQL_INTERVAL_YEAR_TO_MONTH:
403 0 : return SQL_C_INTERVAL_YEAR_TO_MONTH;
404 0 : case SQL_INTERVAL_DAY:
405 0 : return SQL_C_INTERVAL_DAY;
406 0 : case SQL_INTERVAL_HOUR:
407 0 : return SQL_C_INTERVAL_HOUR;
408 0 : case SQL_INTERVAL_MINUTE:
409 0 : return SQL_C_INTERVAL_MINUTE;
410 0 : case SQL_INTERVAL_SECOND:
411 0 : return SQL_C_INTERVAL_SECOND;
412 0 : case SQL_INTERVAL_DAY_TO_HOUR:
413 0 : return SQL_C_INTERVAL_DAY_TO_HOUR;
414 0 : case SQL_INTERVAL_DAY_TO_MINUTE:
415 0 : return SQL_C_INTERVAL_DAY_TO_MINUTE;
416 0 : case SQL_INTERVAL_DAY_TO_SECOND:
417 0 : return SQL_C_INTERVAL_DAY_TO_SECOND;
418 0 : case SQL_INTERVAL_HOUR_TO_MINUTE:
419 0 : return SQL_C_INTERVAL_HOUR_TO_MINUTE;
420 0 : case SQL_INTERVAL_HOUR_TO_SECOND:
421 0 : return SQL_C_INTERVAL_HOUR_TO_SECOND;
422 0 : case SQL_INTERVAL_MINUTE_TO_SECOND:
423 0 : return SQL_C_INTERVAL_MINUTE_TO_SECOND;
424 : }
425 0 : return 0;
426 : }
427 :
428 : static SQLRETURN
429 0 : parseoptionalbracketednumber(char **svalp,
430 : SQLLEN *slenp,
431 : int *val1p,
432 : int *val2p)
433 : {
434 0 : char *sval = *svalp;
435 0 : SQLLEN slen = *slenp;
436 0 : char *eptr;
437 0 : long val;
438 :
439 0 : while (slen > 0 && isspace((unsigned char) *sval)) {
440 0 : slen--;
441 0 : sval++;
442 : }
443 0 : if (slen == 0 || *sval != '(') {
444 : /* don't touch *valp, it contains the default */
445 : return SQL_SUCCESS;
446 : }
447 0 : slen--;
448 0 : sval++;
449 0 : while (slen > 0 && isspace((unsigned char) *sval)) {
450 0 : slen--;
451 0 : sval++;
452 : }
453 : /* make sure there is a closing parenthesis in the string:
454 : * this makes the calls to strtol safe */
455 : {
456 0 : SQLLEN i;
457 :
458 0 : for (eptr = sval, i = slen; i > 0 && *eptr != ')'; i--, eptr++)
459 : ;
460 0 : if (i == 0)
461 : return SQL_ERROR;
462 : }
463 0 : if (slen > 0 && (*sval == '+' || *sval == '-'))
464 : return SQL_ERROR;
465 0 : val = strtol(sval, &eptr, 10);
466 0 : if (eptr == sval)
467 : return SQL_ERROR;
468 0 : slen -= (int) (eptr - sval);
469 0 : sval = eptr;
470 0 : *val1p = (int) val;
471 0 : while (slen > 0 && isspace((unsigned char) *sval)) {
472 0 : slen--;
473 0 : sval++;
474 : }
475 0 : if (val2p != NULL && slen > 0 && *sval == ',') {
476 0 : slen--;
477 0 : sval++;
478 0 : while (slen > 0 && isspace((unsigned char) *sval)) {
479 0 : slen--;
480 0 : sval++;
481 : }
482 0 : if (slen > 0 && (*sval == '+' || *sval == '-'))
483 : return SQL_ERROR;
484 0 : val = strtol(sval, &eptr, 10);
485 0 : if (eptr == sval)
486 : return SQL_ERROR;
487 0 : slen -= (int) (eptr - sval);
488 0 : sval = eptr;
489 0 : *val2p = (int) val;
490 : }
491 :
492 0 : if (slen == 0 || *sval != ')')
493 : return SQL_ERROR;
494 0 : slen--;
495 0 : sval++;
496 0 : *svalp = sval;
497 0 : *slenp = slen;
498 0 : return SQL_SUCCESS;
499 : }
500 :
501 : static SQLRETURN
502 0 : parsemonthintervalstring(char **svalp,
503 : SQLLEN *slenp,
504 : SQL_INTERVAL_STRUCT *ival)
505 : {
506 0 : char *sval = *svalp;
507 0 : SQLLEN slen = slenp ? *slenp : (SQLLEN) strlen(sval);
508 0 : char *eptr;
509 0 : long val1 = -1, val2 = -1;
510 0 : SQLLEN leadingprecision;
511 :
512 0 : *ival = (SQL_INTERVAL_STRUCT) {
513 : .interval_type = SQL_IS_YEAR, /* anything will do */
514 : };
515 0 : if (slen < 8 || strncasecmp(sval, "interval", 8) != 0)
516 : return SQL_ERROR;
517 0 : sval += 8;
518 0 : slen -= 8;
519 0 : if (slen == 0 || !isspace((unsigned char) *sval))
520 : return SQL_ERROR;
521 0 : while (slen > 0 && isspace((unsigned char) *sval)) {
522 0 : slen--;
523 0 : sval++;
524 : }
525 0 : if (slen > 0 && *sval == '-') {
526 0 : slen--;
527 0 : sval++;
528 0 : ival->interval_sign = SQL_TRUE;
529 : } else
530 : ival->interval_sign = SQL_FALSE;
531 0 : if (slen == 0 || *sval != '\'')
532 : return SQL_ERROR;
533 0 : slen--;
534 0 : sval++;
535 : /* make sure there is another quote in the string: this makes
536 : * the calls to strtol safe */
537 0 : for (eptr = sval, leadingprecision = slen;
538 0 : leadingprecision > 0 && *eptr != '\'';
539 0 : leadingprecision--, eptr++)
540 : ;
541 0 : if (leadingprecision == 0)
542 : return SQL_ERROR;
543 0 : if (*sval == '+' || *sval == '-')
544 : return SQL_ERROR;
545 0 : val1 = strtol(sval, &eptr, 10);
546 0 : if (eptr == sval)
547 : return SQL_ERROR;
548 0 : leadingprecision = (SQLLEN) (eptr - sval);
549 0 : slen -= leadingprecision;
550 0 : sval = eptr;
551 0 : while (isspace((unsigned char) *sval)) {
552 0 : slen--;
553 0 : sval++;
554 : }
555 0 : if (*sval == '-') {
556 0 : slen--;
557 0 : sval++;
558 0 : while (isspace((unsigned char) *sval)) {
559 0 : slen--;
560 0 : sval++;
561 : }
562 0 : if (*sval == '+' || *sval == '-')
563 : return SQL_ERROR;
564 0 : val2 = strtol(sval, &eptr, 10);
565 0 : if (eptr == sval)
566 : return SQL_ERROR;
567 0 : if (eptr - sval > 2)
568 : return SQL_ERROR;
569 0 : slen -= (int) (eptr - sval);
570 0 : sval = eptr;
571 0 : while (isspace((unsigned char) *sval)) {
572 0 : slen--;
573 0 : sval++;
574 : }
575 0 : if (val2 >= 12)
576 : return SQL_ERROR;
577 : }
578 0 : if (*sval != '\'')
579 : return SQL_ERROR;
580 0 : slen--;
581 0 : sval++;
582 0 : if (slen == 0 || !isspace((unsigned char) *sval))
583 : return SQL_ERROR;
584 0 : while (slen > 0 && isspace((unsigned char) *sval)) {
585 0 : slen--;
586 0 : sval++;
587 : }
588 0 : if (slen >= 4 && strncasecmp(sval, "year", 4) == 0) {
589 0 : int p = 2;
590 :
591 0 : slen -= 4;
592 0 : sval += 4;
593 0 : if (parseoptionalbracketednumber(&sval, &slen, &p, NULL) == SQL_ERROR)
594 0 : return SQL_ERROR;
595 0 : if (leadingprecision > p)
596 : return SQL_ERROR;
597 0 : ival->intval.year_month.year = val1;
598 0 : if (val2 == -1) {
599 0 : ival->interval_type = SQL_IS_YEAR;
600 0 : ival->intval.year_month.month = 0;
601 : } else {
602 0 : ival->interval_type = SQL_IS_YEAR_TO_MONTH;
603 0 : ival->intval.year_month.month = val2;
604 : }
605 0 : if (slen > 0 && isspace((unsigned char) *sval)) {
606 0 : while (slen > 0 && isspace((unsigned char) *sval)) {
607 0 : slen--;
608 0 : sval++;
609 : }
610 0 : if (slen > 2 && strncasecmp(sval, "to", 2) == 0) {
611 0 : slen -= 2;
612 0 : sval += 2;
613 0 : if (val2 == -1)
614 : return SQL_ERROR;
615 0 : if (slen == 0 || !isspace((unsigned char) *sval))
616 : return SQL_ERROR;
617 0 : while (slen > 0 && isspace((unsigned char) *sval)) {
618 0 : slen--;
619 0 : sval++;
620 : }
621 0 : if (slen >= 5 && strncasecmp(sval, "month", 5) == 0) {
622 0 : slen -= 5;
623 0 : sval += 5;
624 0 : while (slen > 0 && isspace((unsigned char) *sval)) {
625 0 : slen--;
626 0 : sval++;
627 : }
628 : } else
629 : return SQL_ERROR;
630 : }
631 : }
632 0 : if (slen > 0)
633 : return SQL_ERROR;
634 0 : } else if (slen >= 5 && strncasecmp(sval, "month", 5) == 0) {
635 0 : int p = 2;
636 :
637 0 : slen -= 5;
638 0 : sval += 5;
639 0 : if (parseoptionalbracketednumber(&sval, &slen, &p, NULL) == SQL_ERROR)
640 0 : return SQL_ERROR;
641 0 : if (leadingprecision > p)
642 : return SQL_ERROR;
643 0 : while (slen > 0 && isspace((unsigned char) *sval)) {
644 0 : slen--;
645 0 : sval++;
646 : }
647 0 : if (slen != 0)
648 : return SQL_ERROR;
649 0 : ival->interval_type = SQL_IS_MONTH;
650 0 : ival->intval.year_month.year = val1 / 12;
651 0 : ival->intval.year_month.month = val1 % 12;
652 : } else
653 : return SQL_ERROR;
654 :
655 : return SQL_SUCCESS;
656 : }
657 :
658 : static SQLRETURN
659 0 : parsesecondintervalstring(char **svalp,
660 : SQLLEN *slenp,
661 : SQL_INTERVAL_STRUCT *ival,
662 : int *secprecp)
663 : {
664 0 : char *sval = *svalp;
665 0 : SQLLEN slen = slenp ? *slenp : (SQLLEN) strlen(sval);
666 0 : char *eptr;
667 0 : SQLLEN leadingprecision;
668 0 : int secondprecision = 0;
669 0 : unsigned v1, v2, v3, v4;
670 0 : int n;
671 :
672 0 : *ival = (SQL_INTERVAL_STRUCT) {
673 : .interval_type = SQL_IS_YEAR, /* anything will do */
674 : };
675 0 : if (slen < 8 || strncasecmp(sval, "interval", 8) != 0)
676 : return SQL_ERROR;
677 0 : sval += 8;
678 0 : slen -= 8;
679 0 : if (slen == 0 || !isspace((unsigned char) *sval))
680 : return SQL_ERROR;
681 0 : while (slen > 0 && isspace((unsigned char) *sval)) {
682 0 : slen--;
683 0 : sval++;
684 : }
685 0 : if (slen > 0 && *sval == '-') {
686 0 : slen--;
687 0 : sval++;
688 0 : ival->interval_sign = SQL_TRUE;
689 : } else
690 : ival->interval_sign = SQL_FALSE;
691 0 : if (slen == 0 || *sval != '\'')
692 : return SQL_ERROR;
693 0 : slen--;
694 0 : sval++;
695 : /* make sure there is another quote in the string: this makes
696 : * the calls to sscanf safe */
697 0 : for (eptr = sval, leadingprecision = slen;
698 0 : leadingprecision > 0 && *eptr != '\'';
699 0 : leadingprecision--, eptr++)
700 : ;
701 0 : if (leadingprecision == 0)
702 : return SQL_ERROR;
703 0 : if (*sval == '+' || *sval == '-')
704 : return SQL_ERROR;
705 : /* note that the first bit is a bogus comparison (sval does
706 : * not start with '-', so is not negative) but this keeps the
707 : * compiler happy */
708 0 : if (strtol(sval, &eptr, 10) < 0 || /* we parse the actual value again later */
709 0 : eptr == sval)
710 : return SQL_ERROR;
711 0 : leadingprecision = (int) (eptr - sval);
712 :
713 0 : ival->interval_type = (SQLINTERVAL)0; /* unknown as yet */
714 0 : ival->intval.day_second.day = 0;
715 0 : ival->intval.day_second.hour = 0;
716 0 : ival->intval.day_second.minute = 0;
717 0 : ival->intval.day_second.second = 0;
718 0 : ival->intval.day_second.fraction = 0;
719 0 : if (sscanf(sval, "%u %2u:%2u:%2u%n", &v1, &v2, &v3, &v4, &n) >= 4) {
720 0 : ival->interval_type = SQL_IS_DAY_TO_SECOND;
721 0 : if (v2 >= 24 || v3 >= 60 || v4 >= 60)
722 : return SQL_ERROR;
723 0 : ival->intval.day_second.day = v1;
724 0 : ival->intval.day_second.hour = v2;
725 0 : ival->intval.day_second.minute = v3;
726 0 : ival->intval.day_second.second = v4;
727 0 : sval += n;
728 0 : slen -= n;
729 0 : } else if (sscanf(sval, "%u %2u:%2u%n", &v1, &v2, &v3, &n) >= 3) {
730 0 : ival->interval_type = SQL_IS_DAY_TO_MINUTE;
731 0 : if (v2 >= 24 || v3 >= 60)
732 : return SQL_ERROR;
733 0 : ival->intval.day_second.day = v1;
734 0 : ival->intval.day_second.hour = v2;
735 0 : ival->intval.day_second.minute = v3;
736 0 : sval += n;
737 0 : slen -= n;
738 0 : } else if (sscanf(sval, "%u %2u%n", &v1, &v2, &n) >= 2) {
739 0 : ival->interval_type = SQL_IS_DAY_TO_HOUR;
740 0 : if (v2 >= 60)
741 : return SQL_ERROR;
742 0 : ival->intval.day_second.day = v1;
743 0 : ival->intval.day_second.hour = v2;
744 0 : sval += n;
745 0 : slen -= n;
746 0 : } else if (sscanf(sval, "%u:%2u:%2u%n", &v1, &v2, &v3, &n) >= 3) {
747 0 : ival->interval_type = SQL_IS_HOUR_TO_SECOND;
748 0 : if (v2 >= 60 || v3 >= 60)
749 : return SQL_ERROR;
750 0 : ival->intval.day_second.day = v1 / 24;
751 0 : ival->intval.day_second.hour = v1 % 24;
752 0 : ival->intval.day_second.minute = v2;
753 0 : ival->intval.day_second.second = v3;
754 0 : sval += n;
755 0 : slen -= n;
756 0 : } else if (sscanf(sval, "%u:%2u%n", &v1, &v2, &n) >= 2) {
757 0 : sval += n;
758 0 : slen -= n;
759 0 : if (*sval == '.') {
760 0 : ival->interval_type = SQL_IS_MINUTE_TO_SECOND;
761 0 : if (v2 >= 60)
762 : return SQL_ERROR;
763 0 : ival->intval.day_second.day = v1 / (24 * 60);
764 0 : ival->intval.day_second.hour = (v1 / 60) % 24;
765 0 : ival->intval.day_second.minute = v1 % 60;
766 0 : ival->intval.day_second.second = v2;
767 : }
768 0 : n = 2; /* two valid values */
769 0 : } else if (sscanf(sval, "%u%n", &v1, &n) >= 1) {
770 0 : sval += n;
771 0 : slen -= n;
772 0 : if (*sval == '.') {
773 0 : ival->interval_type = SQL_IS_SECOND;
774 0 : ival->intval.day_second.day = v1 / (24 * 60 * 60);
775 0 : ival->intval.day_second.hour = (v1 / (60 * 60)) % 24;
776 0 : ival->intval.day_second.minute = (v1 / 60) % 60;
777 0 : ival->intval.day_second.second = v1 % 60;
778 : }
779 0 : n = 1; /* one valid value */
780 : }
781 0 : if (*sval == '.') {
782 0 : if (ival->interval_type != SQL_IS_SECOND &&
783 0 : ival->interval_type != SQL_IS_MINUTE_TO_SECOND &&
784 0 : ival->interval_type != SQL_IS_HOUR_TO_SECOND &&
785 : ival->interval_type != SQL_IS_DAY_TO_SECOND)
786 : return SQL_ERROR;
787 0 : sval++;
788 0 : slen--;
789 0 : secondprecision = 0;
790 0 : while (isdigit((unsigned char) *sval)) {
791 0 : if (secondprecision < 9) {
792 0 : secondprecision++;
793 0 : ival->intval.day_second.fraction *= 10;
794 0 : ival->intval.day_second.fraction += *sval - '0';
795 : }
796 0 : sval++;
797 0 : slen--;
798 : }
799 : }
800 0 : while (slen > 0 && isspace((unsigned char) *sval)) {
801 0 : slen--;
802 0 : sval++;
803 : }
804 0 : if (*sval != '\'')
805 : return SQL_ERROR;
806 0 : slen--;
807 0 : sval++;
808 0 : if (slen == 0 || !isspace((unsigned char) *sval))
809 : return SQL_ERROR;
810 0 : while (slen > 0 && isspace((unsigned char) *sval)) {
811 0 : slen--;
812 0 : sval++;
813 : }
814 :
815 0 : if (slen >= 3 && strncasecmp(sval, "day", 3) == 0) {
816 0 : sval += 3;
817 0 : slen -= 3;
818 0 : if (ival->interval_type == 0 && n == 1) {
819 0 : ival->interval_type = SQL_IS_DAY;
820 0 : ival->intval.day_second.day = v1;
821 : }
822 0 : if (ival->interval_type != SQL_IS_DAY &&
823 0 : ival->interval_type != SQL_IS_DAY_TO_HOUR &&
824 0 : ival->interval_type != SQL_IS_DAY_TO_MINUTE &&
825 : ival->interval_type != SQL_IS_DAY_TO_SECOND)
826 : return SQL_ERROR;
827 0 : } else if (slen >= 4 && strncasecmp(sval, "hour", 4) == 0) {
828 0 : slen -= 4;
829 0 : sval += 4;
830 0 : if (ival->interval_type == 0) {
831 0 : if (n == 1) {
832 0 : ival->interval_type = SQL_IS_HOUR;
833 0 : ival->intval.day_second.day = v1 / 24;
834 0 : ival->intval.day_second.hour = v1 % 24;
835 : } else {
836 0 : assert(n == 2);
837 0 : ival->interval_type = SQL_IS_HOUR_TO_MINUTE;
838 0 : if (v2 >= 60)
839 : return SQL_ERROR;
840 0 : ival->intval.day_second.day = v1 / 24;
841 0 : ival->intval.day_second.hour = v1 % 24;
842 0 : ival->intval.day_second.minute = v2;
843 : }
844 : }
845 0 : if (ival->interval_type != SQL_IS_HOUR &&
846 0 : ival->interval_type != SQL_IS_HOUR_TO_MINUTE &&
847 : ival->interval_type != SQL_IS_HOUR_TO_SECOND)
848 : return SQL_ERROR;
849 0 : } else if (slen >= 6 && strncasecmp(sval, "minute", 6) == 0) {
850 0 : slen -= 6;
851 0 : sval += 6;
852 0 : if (ival->interval_type == 0) {
853 0 : if (n == 1) {
854 0 : ival->interval_type = SQL_IS_MINUTE;
855 0 : ival->intval.day_second.day = v1 / (24 * 60);
856 0 : ival->intval.day_second.hour = (v1 / 60) % 24;
857 0 : ival->intval.day_second.minute = v1 % 60;
858 : } else {
859 0 : assert(n == 2);
860 0 : ival->interval_type = SQL_IS_MINUTE_TO_SECOND;
861 0 : if (v2 >= 60)
862 : return SQL_ERROR;
863 0 : ival->intval.day_second.day = v1 / (24 * 60);
864 0 : ival->intval.day_second.hour = (v1 / 60) % 24;
865 0 : ival->intval.day_second.minute = v1 % 60;
866 0 : ival->intval.day_second.second = v2;
867 : }
868 : }
869 0 : if (ival->interval_type != SQL_IS_MINUTE &&
870 : ival->interval_type != SQL_IS_MINUTE_TO_SECOND)
871 : return SQL_ERROR;
872 0 : } else if (slen >= 6 && strncasecmp(sval, "second", 6) == 0) {
873 0 : slen -= 6;
874 0 : sval += 6;
875 0 : if (ival->interval_type == 0) {
876 0 : if (n == 1) {
877 0 : ival->interval_type = SQL_IS_SECOND;
878 0 : ival->intval.day_second.day = v1 / (24 * 60 * 60);
879 0 : ival->intval.day_second.hour = (v1 / (60 * 60)) % 24;
880 0 : ival->intval.day_second.minute = (v1 / 60) % 60;
881 0 : ival->intval.day_second.second = v1 % 60;
882 : }
883 : }
884 0 : if (ival->interval_type != SQL_IS_SECOND)
885 : return SQL_ERROR;
886 : }
887 : {
888 0 : int p = 2;
889 0 : int q = 6;
890 :
891 0 : if (parseoptionalbracketednumber(&sval, &slen, &p, ival->interval_type == SQL_IS_SECOND ? &q : NULL) == SQL_ERROR)
892 0 : return SQL_ERROR;
893 0 : if (leadingprecision > p)
894 : return SQL_ERROR;
895 0 : if (ival->interval_type == SQL_IS_SECOND && secondprecision > q)
896 : return SQL_ERROR;
897 : }
898 0 : if (slen > 0 && isspace((unsigned char) *sval)) {
899 0 : while (slen > 0 && isspace((unsigned char) *sval)) {
900 0 : slen--;
901 0 : sval++;
902 : }
903 0 : if (slen > 2 && strncasecmp(sval, "to", 2) == 0) {
904 0 : slen -= 2;
905 0 : sval += 2;
906 0 : if (slen == 0 || !isspace((unsigned char) *sval))
907 : return SQL_ERROR;
908 0 : while (slen > 0 && isspace((unsigned char) *sval)) {
909 0 : slen--;
910 0 : sval++;
911 : }
912 0 : if (slen >= 4 && strncasecmp(sval, "hour", 4) == 0) {
913 0 : slen -= 4;
914 0 : sval += 4;
915 0 : if (ival->interval_type != SQL_IS_DAY_TO_HOUR)
916 : return SQL_ERROR;
917 0 : } else if (slen >= 6 && strncasecmp(sval, "minute", 6) == 0) {
918 0 : slen -= 6;
919 0 : sval += 6;
920 0 : if (ival->interval_type != SQL_IS_DAY_TO_MINUTE &&
921 : ival->interval_type != SQL_IS_HOUR_TO_MINUTE)
922 : return SQL_ERROR;
923 0 : } else if (slen >= 6 && strncasecmp(sval, "second", 6) == 0) {
924 0 : int p = 6;
925 :
926 0 : slen -= 6;
927 0 : sval += 6;
928 0 : if (ival->interval_type != SQL_IS_DAY_TO_SECOND &&
929 0 : ival->interval_type != SQL_IS_HOUR_TO_SECOND &&
930 : ival->interval_type != SQL_IS_MINUTE_TO_SECOND)
931 0 : return SQL_ERROR;
932 0 : while (slen > 0 && isspace((unsigned char) *sval)) {
933 0 : slen--;
934 0 : sval++;
935 : }
936 0 : if (parseoptionalbracketednumber(&sval, &slen, &p, NULL) == SQL_ERROR)
937 : return SQL_ERROR;
938 0 : if (p < secondprecision)
939 : return SQL_ERROR;
940 : } else
941 : return SQL_ERROR;
942 0 : while (slen > 0 && isspace((unsigned char) *sval)) {
943 0 : slen--;
944 0 : sval++;
945 : }
946 : }
947 : }
948 0 : if (slen > 0)
949 : return SQL_ERROR;
950 0 : *secprecp = secondprecision;
951 0 : return SQL_SUCCESS;
952 : }
953 :
954 : SQLRETURN
955 16573 : ODBCFetch(ODBCStmt *stmt,
956 : SQLUSMALLINT col,
957 : SQLSMALLINT type,
958 : SQLPOINTER ptr,
959 : SQLLEN buflen,
960 : SQLLEN *lenp,
961 : SQLLEN *nullp,
962 : SQLSMALLINT precision,
963 : SQLSMALLINT scale,
964 : SQLINTEGER datetime_interval_precision,
965 : SQLLEN offset,
966 : SQLULEN row)
967 : {
968 16573 : char *data;
969 16573 : size_t datalen;
970 16573 : SQLSMALLINT sql_type;
971 16573 : SQLUINTEGER maxdatetimeval;
972 16573 : ODBCDesc *ard, *ird;
973 16573 : ODBCDescRec *irdrec, *ardrec;
974 16573 : SQLINTEGER bind_type;
975 :
976 : /* various interpretations of the input data */
977 16573 : bignum_t nval;
978 16573 : SQL_INTERVAL_STRUCT ival;
979 16573 : int ivalprec = 0; /* interval second precision */
980 16573 : int i;
981 16573 : DATE_STRUCT dval;
982 16573 : TIME_STRUCT tval;
983 16573 : TIMESTAMP_STRUCT tsval;
984 16573 : double fval = 0;
985 :
986 : /* staging variables for output data */
987 16573 : SQL_NUMERIC_STRUCT nmval;
988 16573 : SQL_INTERVAL_STRUCT ivval;
989 :
990 16573 : assert(ptr != NULL);
991 :
992 16573 : ird = stmt->ImplRowDescr;
993 16573 : ard = stmt->ApplRowDescr;
994 :
995 16573 : if (col == 0 || col > ird->sql_desc_count) {
996 : /* Invalid descriptor index */
997 0 : addStmtError(stmt, "07009", NULL, 0);
998 0 : return SQL_ERROR;
999 : }
1000 16573 : bind_type = ard->sql_desc_bind_type;
1001 16573 : irdrec = &ird->descRec[col];
1002 16573 : ardrec = col <= ard->sql_desc_count ? &ard->descRec[col] : NULL;
1003 16573 : sql_type = irdrec->sql_desc_concise_type;
1004 :
1005 16573 : if (offset > 0)
1006 0 : ptr = (SQLPOINTER) ((char *) ptr + offset);
1007 :
1008 16573 : if (lenp)
1009 6559 : lenp = (SQLLEN *) ((char *) lenp + offset + row * (bind_type == SQL_BIND_BY_COLUMN ? (SQLINTEGER) sizeof(*lenp) : bind_type));
1010 16573 : if (nullp)
1011 6559 : nullp = (SQLLEN *) ((char *) nullp + offset + row * (bind_type == SQL_BIND_BY_COLUMN ? (SQLINTEGER) sizeof(*nullp) : bind_type));
1012 :
1013 : /* translate default type */
1014 : /* note, type can't be SQL_ARD_TYPE since when this function
1015 : * is called from SQLFetch, type is already the ARD concise
1016 : * type, and when it is called from SQLGetData, it has already
1017 : * been translated */
1018 :
1019 16573 : if (type == SQL_C_DEFAULT)
1020 0 : type = ODBCDefaultType(irdrec);
1021 :
1022 16573 : if (precision == UNAFFECTED ||
1023 16573 : scale == UNAFFECTED ||
1024 : datetime_interval_precision == UNAFFECTED) {
1025 6563 : if (ardrec) {
1026 0 : if (precision == UNAFFECTED)
1027 0 : precision = ardrec->sql_desc_precision;
1028 0 : if (scale == UNAFFECTED)
1029 0 : scale = ardrec->sql_desc_scale;
1030 0 : if (datetime_interval_precision == UNAFFECTED)
1031 0 : datetime_interval_precision = ardrec->sql_desc_datetime_interval_precision;
1032 : } else {
1033 6563 : if (precision == UNAFFECTED)
1034 6563 : precision = type == SQL_C_NUMERIC ? 10 : 6;
1035 6563 : if (scale == UNAFFECTED)
1036 6563 : scale = 0;
1037 6563 : if (datetime_interval_precision == UNAFFECTED)
1038 6563 : datetime_interval_precision = 2;
1039 : }
1040 : }
1041 16573 : i = datetime_interval_precision;
1042 16573 : maxdatetimeval = 1;
1043 29699 : while (i-- > 0)
1044 13126 : maxdatetimeval *= 10;
1045 :
1046 16573 : data = mapi_fetch_field(stmt->hdl, col - 1);
1047 16573 : if (mapi_error(stmt->Dbc->mid)) {
1048 : /* General error */
1049 0 : addStmtError(stmt, "HY000", mapi_error_str(stmt->Dbc->mid), 0);
1050 0 : return SQL_ERROR;
1051 : }
1052 16573 : if (nullp)
1053 6559 : *nullp = SQL_NULL_DATA;
1054 16573 : if (lenp)
1055 6559 : *lenp = SQL_NULL_DATA;
1056 16573 : if (data == NULL) {
1057 1233 : if (nullp == NULL) {
1058 : /* Indicator variable required but not supplied */
1059 0 : addStmtError(stmt, "22002", NULL, 0);
1060 0 : return SQL_ERROR;
1061 : }
1062 : return SQL_SUCCESS;
1063 : }
1064 15340 : datalen = mapi_fetch_field_len(stmt->hdl, col - 1);
1065 :
1066 : /* first convert to internal (binary) format */
1067 :
1068 : /* see SQLExecute.c for possible types */
1069 15340 : switch (sql_type) {
1070 5255 : case SQL_DECIMAL:
1071 : case SQL_NUMERIC:
1072 : case SQL_TINYINT:
1073 : case SQL_SMALLINT:
1074 : case SQL_INTEGER:
1075 : case SQL_BIGINT:
1076 : case SQL_HUGEINT:
1077 : case SQL_INTERVAL_YEAR:
1078 : case SQL_INTERVAL_YEAR_TO_MONTH:
1079 : case SQL_INTERVAL_MONTH:
1080 : case SQL_INTERVAL_DAY:
1081 : case SQL_INTERVAL_DAY_TO_HOUR:
1082 : case SQL_INTERVAL_DAY_TO_MINUTE:
1083 : case SQL_INTERVAL_DAY_TO_SECOND:
1084 : case SQL_INTERVAL_HOUR:
1085 : case SQL_INTERVAL_HOUR_TO_MINUTE:
1086 : case SQL_INTERVAL_HOUR_TO_SECOND:
1087 : case SQL_INTERVAL_MINUTE:
1088 : case SQL_INTERVAL_MINUTE_TO_SECOND:
1089 : case SQL_INTERVAL_SECOND:
1090 5255 : switch (parseint(data, &nval)) {
1091 0 : case 0:
1092 : /* shouldn't happen: getting here means SQL
1093 : * server told us a value was of a certain
1094 : * type, but in reality it wasn't. */
1095 : /* Invalid character value for cast specification */
1096 0 : addStmtError(stmt, "22018", NULL, 0);
1097 0 : return SQL_ERROR;
1098 0 : case 2:
1099 : /* hugeint that doesn't fit into a bigint */
1100 : /* Numeric value out of range */
1101 0 : addStmtError(stmt, "22003", NULL, 0);
1102 0 : return SQL_ERROR;
1103 : }
1104 :
1105 : /* interval types are transferred as ints but need to
1106 : * be converted to the internal interval formats */
1107 5255 : switch (sql_type) {
1108 9 : case SQL_INTERVAL_YEAR:
1109 : case SQL_INTERVAL_YEAR_TO_MONTH:
1110 : case SQL_INTERVAL_MONTH:
1111 9 : parsemonthinterval(&nval, &ival, SQL_INTERVAL_MONTH);
1112 9 : break;
1113 32 : case SQL_INTERVAL_DAY:
1114 : case SQL_INTERVAL_DAY_TO_HOUR:
1115 : case SQL_INTERVAL_DAY_TO_MINUTE:
1116 : case SQL_INTERVAL_DAY_TO_SECOND:
1117 : case SQL_INTERVAL_HOUR:
1118 : case SQL_INTERVAL_HOUR_TO_MINUTE:
1119 : case SQL_INTERVAL_HOUR_TO_SECOND:
1120 : case SQL_INTERVAL_MINUTE:
1121 : case SQL_INTERVAL_MINUTE_TO_SECOND:
1122 : case SQL_INTERVAL_SECOND:
1123 32 : ivalprec = parsesecondinterval(&nval, &ival, SQL_INTERVAL_SECOND);
1124 32 : break;
1125 : default:
1126 : break;
1127 : }
1128 : break;
1129 2006 : case SQL_DOUBLE:
1130 : case SQL_FLOAT:
1131 : case SQL_REAL:
1132 2006 : if (!parsedouble(data, &fval)) {
1133 : /* Invalid character value for cast specification */
1134 0 : addStmtError(stmt, "22018", NULL, 0);
1135 0 : return SQL_ERROR;
1136 : }
1137 : break;
1138 147 : case SQL_BIT:
1139 147 : nval.precision = 1;
1140 147 : nval.scale = 0;
1141 147 : nval.sign = 1;
1142 147 : while (datalen != 0 && space(*data)) {
1143 0 : data++;
1144 0 : datalen--;
1145 : }
1146 147 : if (datalen >= 4 && strncasecmp(data, "true", 4) == 0) {
1147 145 : data += 4;
1148 145 : datalen -= 4;
1149 145 : nval.val = 1;
1150 2 : } else if (datalen >= 5 && strncasecmp(data, "false", 5) == 0) {
1151 2 : data += 5;
1152 2 : datalen -= 5;
1153 2 : nval.val = 0;
1154 : } else {
1155 : /* Invalid character value for cast specification */
1156 0 : addStmtError(stmt, "22018", NULL, 0);
1157 0 : return SQL_ERROR;
1158 : }
1159 147 : while (datalen != 0 && space(*data)) {
1160 0 : data++;
1161 0 : datalen--;
1162 : }
1163 147 : if (datalen != 0) {
1164 : /* Invalid character value for cast specification */
1165 0 : addStmtError(stmt, "22018", NULL, 0);
1166 0 : return SQL_ERROR;
1167 : }
1168 : break;
1169 2003 : case SQL_TYPE_DATE:
1170 2003 : if (!parsedate(data, &dval)) {
1171 : /* Invalid character value for cast specification */
1172 0 : addStmtError(stmt, "22018", NULL, 0);
1173 0 : return SQL_ERROR;
1174 : }
1175 : break;
1176 2003 : case SQL_TYPE_TIME:
1177 2003 : if (!parsetime(data, &tval)) {
1178 : /* Invalid character value for cast specification */
1179 0 : addStmtError(stmt, "22018", NULL, 0);
1180 0 : return SQL_ERROR;
1181 : }
1182 : break;
1183 3 : case SQL_TYPE_TIMESTAMP:
1184 3 : if (!parsetimestamp(data, &tsval)) {
1185 : /* Invalid character value for cast specification */
1186 0 : addStmtError(stmt, "22018", NULL, 0);
1187 0 : return SQL_ERROR;
1188 : }
1189 : break;
1190 : case SQL_GUID:
1191 : /* nothing special to do here */
1192 : default:
1193 : /* any other type can only be converted to SQL_C_CHAR */
1194 : break;
1195 : }
1196 :
1197 : /* then convert to desired format */
1198 :
1199 15340 : switch (type) {
1200 6244 : case SQL_C_CHAR:
1201 : case SQL_C_WCHAR:
1202 : {
1203 6244 : SQLPOINTER origptr;
1204 6244 : SQLLEN origbuflen;
1205 6244 : SQLLEN *origlenp;
1206 6244 : SQLLEN sz;
1207 :
1208 6244 : if (buflen < 0) {
1209 : /* Invalid string or buffer length */
1210 0 : addStmtError(stmt, "HY090", NULL, 0);
1211 0 : return SQL_ERROR;
1212 : }
1213 6244 : if (ardrec && row > 0)
1214 0 : ptr = (SQLPOINTER) ((char *) ptr + row * (bind_type == SQL_BIND_BY_COLUMN ? ardrec->sql_desc_octet_length : bind_type));
1215 :
1216 : /* if SQL_C_WCHAR is requested, first convert to UTF-8
1217 : * (SQL_C_CHAR), and at the end convert to WCHAR */
1218 6244 : origptr = ptr;
1219 :
1220 6244 : origbuflen = buflen;
1221 6244 : origlenp = lenp;
1222 6244 : if (type == SQL_C_WCHAR) {
1223 : /* allocate temporary space */
1224 391 : switch (sql_type) {
1225 391 : case SQL_CHAR:
1226 : case SQL_VARCHAR:
1227 : case SQL_LONGVARCHAR:
1228 : case SQL_WCHAR:
1229 : case SQL_WVARCHAR:
1230 : case SQL_WLONGVARCHAR:
1231 : case SQL_BINARY:
1232 : case SQL_VARBINARY:
1233 : case SQL_LONGVARBINARY:
1234 : case SQL_GUID:
1235 : /* this is certainly enough for strings */
1236 391 : buflen = (SQLLEN) datalen + 1;
1237 391 : ptr = NULL;
1238 391 : break;
1239 0 : default:
1240 : /* should be enough for most types */
1241 0 : buflen = 511;
1242 0 : ptr = malloc(buflen);
1243 0 : if (ptr == NULL) {
1244 : /* Memory allocation error */
1245 0 : addStmtError(stmt, "HY001", NULL, 0);
1246 0 : return SQL_ERROR;
1247 : }
1248 : break;
1249 : }
1250 : lenp = NULL;
1251 : }
1252 6244 : switch (sql_type) {
1253 0 : case SQL_BINARY:
1254 : case SQL_VARBINARY:
1255 : case SQL_LONGVARBINARY:
1256 0 : if (buflen > 0 && (buflen & 1) == 0) {
1257 : /* return even number of bytes + NULL
1258 : * (i.e. buflen must be odd) */
1259 0 : buflen--;
1260 : }
1261 : /* fall through */
1262 : default:
1263 : case SQL_CHAR:
1264 : case SQL_VARCHAR:
1265 : case SQL_LONGVARCHAR:
1266 : case SQL_WCHAR:
1267 : case SQL_WVARCHAR:
1268 : case SQL_WLONGVARCHAR:
1269 : case SQL_GUID:
1270 3917 : if (irdrec->already_returned < 0)
1271 3911 : irdrec->already_returned = 0;
1272 6 : else if ((size_t) irdrec->already_returned >= datalen) {
1273 : /* no more data to return */
1274 0 : if (type == SQL_C_WCHAR && ptr)
1275 0 : free(ptr);
1276 0 : return SQL_NO_DATA;
1277 : }
1278 3917 : data += irdrec->already_returned;
1279 3917 : datalen -= (size_t) irdrec->already_returned;
1280 3917 : if (ptr) {
1281 7052 : copyString(data, datalen, ptr, buflen, lenp,
1282 : SQLLEN, addStmtError, stmt,
1283 : return SQL_ERROR);
1284 : }
1285 3917 : if (datalen < (size_t) buflen)
1286 3916 : irdrec->already_returned += datalen;
1287 : else
1288 1 : irdrec->already_returned += buflen - 1;
1289 : break;
1290 2318 : case SQL_TINYINT:
1291 : case SQL_SMALLINT:
1292 : case SQL_INTEGER:
1293 : case SQL_BIGINT:
1294 : case SQL_HUGEINT:
1295 2318 : sz = snprintf((char *) ptr, buflen, "%s", data);
1296 2318 : if (sz < 0 || sz >= buflen) {
1297 : /* Numeric value out of range */
1298 0 : addStmtError(stmt, "22003", NULL, 0);
1299 :
1300 0 : if (type == SQL_C_WCHAR)
1301 0 : free(ptr);
1302 0 : return SQL_ERROR;
1303 : }
1304 2318 : if (lenp)
1305 2318 : *lenp = sz;
1306 : break;
1307 9 : case SQL_DECIMAL:
1308 : case SQL_NUMERIC:
1309 : case SQL_BIT: {
1310 9 : uint64_t f;
1311 9 : int n;
1312 :
1313 9 : data = (char *) ptr;
1314 :
1315 62 : for (n = 0, f = 1; n < nval.scale; n++)
1316 53 : f *= 10;
1317 : #ifdef HAVE_HGE
1318 9 : uhge v = nval.val / f;
1319 9 : if (v > UINT64_MAX) {
1320 : /* Numeric value out of range */
1321 0 : addStmtError(stmt, "22003", NULL, 0);
1322 :
1323 0 : if (type == SQL_C_WCHAR)
1324 0 : free(ptr);
1325 0 : return SQL_ERROR;
1326 : }
1327 18 : sz = snprintf(data, buflen, "%s%" PRIu64,
1328 9 : nval.sign ? "" : "-", (uint64_t) v);
1329 : #else
1330 : sz = snprintf(data, buflen, "%s%" PRIu64,
1331 : nval.sign ? "" : "-",
1332 : (uint64_t) (nval.val / f));
1333 : #endif
1334 9 : if (sz < 0 || sz >= buflen) {
1335 : /* Numeric value out of range */
1336 0 : addStmtError(stmt, "22003", NULL, 0);
1337 :
1338 0 : if (type == SQL_C_WCHAR)
1339 0 : free(ptr);
1340 0 : return SQL_ERROR;
1341 : }
1342 9 : if (lenp)
1343 9 : *lenp = sz;
1344 9 : if (nval.scale > 0) {
1345 8 : data += sz;
1346 8 : buflen -= sz;
1347 8 : if (lenp)
1348 8 : *lenp += nval.scale + 1;
1349 8 : if (buflen > 2)
1350 8 : sz = (SQLLEN) snprintf(data, buflen, ".%0*" PRIu64, nval.scale, (uint64_t) (nval.val % f));
1351 8 : if (buflen <= 2 || sz < 0 || sz >= buflen) {
1352 0 : data[buflen - 1] = 0;
1353 : /* String data, right-truncated */
1354 0 : addStmtError(stmt, "01004", NULL, 0);
1355 : }
1356 : }
1357 : break;
1358 : }
1359 0 : case SQL_DOUBLE:
1360 : case SQL_FLOAT:
1361 : case SQL_REAL: {
1362 0 : data = (char *) ptr;
1363 :
1364 0 : for (i = 4; i < 18; i++) {
1365 0 : sz = (SQLLEN) snprintf(data, buflen, "%.*g", i, fval);
1366 0 : if (sz < 0 || sz >= buflen) {
1367 0 : data[buflen - 1] = 0;
1368 0 : if (i == 0) {
1369 : /* Numeric value out
1370 : * of range */
1371 : addStmtError(stmt, "22003", NULL, 0);
1372 :
1373 : if (type == SQL_C_WCHAR)
1374 : free(ptr);
1375 : return SQL_ERROR;
1376 : }
1377 : /* current precision (i) doesn't fit,
1378 : * but previous did, so use that */
1379 0 : snprintf(data, buflen, "%.*g", i - 1, fval);
1380 : /* max space that would have
1381 : * been needed */
1382 0 : sz = (SQLLEN) strlen(data) + 17 - i;
1383 : /* String data, right-truncated */
1384 0 : addStmtError(stmt, "01004", NULL, 0);
1385 0 : break;
1386 : }
1387 0 : if (fval == strtod(data, NULL))
1388 : break;
1389 : }
1390 0 : if (lenp)
1391 0 : *lenp = sz;
1392 : break;
1393 : }
1394 0 : case SQL_TYPE_DATE:
1395 0 : if (buflen < 11) {
1396 : /* Numeric value out of range */
1397 0 : addStmtError(stmt, "22003", NULL, 0);
1398 :
1399 0 : if (type == SQL_C_WCHAR)
1400 0 : free(ptr);
1401 0 : return SQL_ERROR;
1402 : }
1403 0 : data = (char *) ptr;
1404 :
1405 0 : sz = snprintf(data, buflen, "%04u-%02u-%02u",
1406 0 : (unsigned int) dval.year,
1407 0 : (unsigned int) dval.month,
1408 0 : (unsigned int) dval.day);
1409 0 : if (sz < 0 || sz >= buflen) {
1410 0 : data[buflen - 1] = 0;
1411 : /* String data, right-truncated */
1412 0 : addStmtError(stmt, "01004", NULL, 0);
1413 : }
1414 0 : if (lenp)
1415 0 : *lenp = sz;
1416 : break;
1417 0 : case SQL_TYPE_TIME:
1418 0 : if (buflen < 9) {
1419 : /* Numeric value out of range */
1420 0 : addStmtError(stmt, "22003", NULL, 0);
1421 :
1422 0 : if (type == SQL_C_WCHAR)
1423 0 : free(ptr);
1424 0 : return SQL_ERROR;
1425 : }
1426 0 : data = (char *) ptr;
1427 :
1428 0 : sz = snprintf(data, buflen, "%02u:%02u:%02u",
1429 0 : (unsigned int) tval.hour,
1430 0 : (unsigned int) tval.minute,
1431 0 : (unsigned int) tval.second);
1432 0 : if (sz < 0 || sz >= buflen) {
1433 0 : data[buflen - 1] = 0;
1434 : /* String data, right-truncated */
1435 0 : addStmtError(stmt, "01004", NULL, 0);
1436 : }
1437 0 : if (lenp)
1438 0 : *lenp = sz;
1439 : break;
1440 0 : case SQL_TYPE_TIMESTAMP:
1441 0 : data = (char *) ptr;
1442 :
1443 0 : sz = snprintf(data, buflen,
1444 : "%04u-%02u-%02u %02u:%02u:%02u",
1445 0 : (unsigned int) tsval.year,
1446 0 : (unsigned int) tsval.month,
1447 0 : (unsigned int) tsval.day,
1448 0 : (unsigned int) tsval.hour,
1449 0 : (unsigned int) tsval.minute,
1450 0 : (unsigned int) tsval.second);
1451 0 : if (sz < 0 || sz >= buflen) {
1452 : /* Numeric value out of range */
1453 0 : addStmtError(stmt, "22003", NULL, 0);
1454 :
1455 0 : if (type == SQL_C_WCHAR)
1456 0 : free(ptr);
1457 0 : return SQL_ERROR;
1458 : }
1459 0 : if (lenp)
1460 0 : *lenp = sz;
1461 0 : if (tsval.fraction) {
1462 0 : int fscale = 9;
1463 :
1464 0 : data += sz;
1465 0 : buflen += sz;
1466 0 : while (tsval.fraction % 10 == 0) {
1467 0 : tsval.fraction /= 10;
1468 0 : fscale--;
1469 : }
1470 0 : if (lenp)
1471 0 : *lenp += fscale + 1;
1472 0 : if (buflen > 2)
1473 0 : sz = snprintf(data, buflen, ".%0*u",
1474 : fscale, (unsigned int) tsval.fraction);
1475 0 : if (buflen <= 2 || sz < 0 || sz >= buflen) {
1476 0 : data[buflen - 1] = 0;
1477 : /* String data, right-truncated */
1478 0 : addStmtError(stmt, "01004", NULL, 0);
1479 : }
1480 : }
1481 : break;
1482 0 : case SQL_INTERVAL_YEAR:
1483 0 : sz = snprintf((char *) ptr, buflen,
1484 : "INTERVAL %s'%u' YEAR",
1485 0 : ival.interval_sign ? "-" : "",
1486 0 : (unsigned int) ival.intval.year_month.year);
1487 :
1488 0 : if (sz < 0 || sz >= buflen) {
1489 : /* Numeric value out of range */
1490 0 : addStmtError(stmt, "22003", NULL, 0);
1491 :
1492 0 : if (type == SQL_C_WCHAR)
1493 0 : free(ptr);
1494 0 : return SQL_ERROR;
1495 : }
1496 0 : if (lenp)
1497 0 : *lenp = sz;
1498 : break;
1499 0 : case SQL_INTERVAL_YEAR_TO_MONTH:
1500 0 : sz = snprintf((char *) ptr, buflen,
1501 : "INTERVAL %s'%u-%02u' YEAR TO MONTH",
1502 0 : ival.interval_sign ? "-" : "",
1503 0 : (unsigned int) ival.intval.year_month.year,
1504 0 : (unsigned int) ival.intval.year_month.month);
1505 :
1506 0 : if (sz < 0 || sz >= buflen) {
1507 : /* Numeric value out of range */
1508 0 : addStmtError(stmt, "22003", NULL, 0);
1509 :
1510 0 : if (type == SQL_C_WCHAR)
1511 0 : free(ptr);
1512 0 : return SQL_ERROR;
1513 : }
1514 0 : if (lenp)
1515 0 : *lenp = sz;
1516 : break;
1517 0 : case SQL_INTERVAL_MONTH:
1518 0 : sz = snprintf((char *) ptr, buflen,
1519 : "INTERVAL %s'%u' MONTH",
1520 0 : ival.interval_sign ? "-" : "",
1521 0 : (unsigned int) (12 * ival.intval.year_month.year +
1522 0 : ival.intval.year_month.month));
1523 :
1524 0 : if (sz < 0 || sz >= buflen) {
1525 : /* Numeric value out of range */
1526 0 : addStmtError(stmt, "22003", NULL, 0);
1527 :
1528 0 : if (type == SQL_C_WCHAR)
1529 0 : free(ptr);
1530 0 : return SQL_ERROR;
1531 : }
1532 0 : if (lenp)
1533 0 : *lenp = sz;
1534 : break;
1535 0 : case SQL_INTERVAL_DAY:
1536 0 : sz = snprintf((char *) ptr, buflen,
1537 : "INTERVAL %s'%u' DAY",
1538 0 : ival.interval_sign ? "-" : "",
1539 0 : (unsigned int) ival.intval.day_second.day);
1540 :
1541 0 : if (sz < 0 || sz >= buflen) {
1542 : /* Numeric value out of range */
1543 0 : addStmtError(stmt, "22003", NULL, 0);
1544 :
1545 0 : if (type == SQL_C_WCHAR)
1546 0 : free(ptr);
1547 0 : return SQL_ERROR;
1548 : }
1549 0 : if (lenp)
1550 0 : *lenp = sz;
1551 : break;
1552 0 : case SQL_INTERVAL_DAY_TO_HOUR:
1553 0 : sz = snprintf((char *) ptr, buflen,
1554 : "INTERVAL %s'%u %02u' DAY TO HOUR",
1555 0 : ival.interval_sign ? "-" : "",
1556 0 : (unsigned int) ival.intval.day_second.day,
1557 0 : (unsigned int) ival.intval.day_second.hour);
1558 :
1559 0 : if (sz < 0 || sz >= buflen) {
1560 : /* Numeric value out of range */
1561 0 : addStmtError(stmt, "22003", NULL, 0);
1562 :
1563 0 : if (type == SQL_C_WCHAR)
1564 0 : free(ptr);
1565 0 : return SQL_ERROR;
1566 : }
1567 0 : if (lenp)
1568 0 : *lenp = sz;
1569 : break;
1570 0 : case SQL_INTERVAL_DAY_TO_MINUTE:
1571 0 : sz = snprintf((char *) ptr, buflen,
1572 : "INTERVAL %s'%u %02u:%02u' DAY TO MINUTE",
1573 0 : ival.interval_sign ? "-" : "",
1574 0 : (unsigned int) ival.intval.day_second.day,
1575 0 : (unsigned int) ival.intval.day_second.hour,
1576 0 : (unsigned int) ival.intval.day_second.minute);
1577 :
1578 0 : if (sz < 0 || sz >= buflen) {
1579 : /* Numeric value out of range */
1580 0 : addStmtError(stmt, "22003", NULL, 0);
1581 :
1582 0 : if (type == SQL_C_WCHAR)
1583 0 : free(ptr);
1584 0 : return SQL_ERROR;
1585 : }
1586 0 : if (lenp)
1587 0 : *lenp = sz;
1588 : break;
1589 0 : case SQL_INTERVAL_DAY_TO_SECOND: {
1590 0 : int w;
1591 :
1592 0 : data = (char *) ptr;
1593 :
1594 0 : w = 14; /* space needed for "'DAY TO SECOND" */
1595 :
1596 0 : sz = snprintf(data, buflen, "INTERVAL %s'%u %02u:%02u:%02u",
1597 0 : ival.interval_sign ? "-" : "",
1598 0 : (unsigned int) ival.intval.day_second.day,
1599 0 : (unsigned int) ival.intval.day_second.hour,
1600 0 : (unsigned int) ival.intval.day_second.minute,
1601 0 : (unsigned int) ival.intval.day_second.second);
1602 0 : if (sz < 0 || sz + w >= buflen) {
1603 : /* Numeric value out of range */
1604 0 : addStmtError(stmt, "22003", NULL, 0);
1605 :
1606 0 : if (type == SQL_C_WCHAR)
1607 0 : free(ptr);
1608 0 : return SQL_ERROR;
1609 : }
1610 0 : data += sz;
1611 0 : buflen -= sz;
1612 :
1613 0 : if (lenp)
1614 0 : *lenp = sz;
1615 0 : if (ivalprec > 0) {
1616 0 : if (lenp)
1617 0 : *lenp += ivalprec + 1;
1618 0 : if (buflen > w + 2)
1619 0 : sz = snprintf(data, buflen, ".%0*u", ivalprec, (unsigned int) ival.intval.day_second.fraction);
1620 0 : if (buflen <= w + 2 || sz < 0 || sz + w >= buflen) {
1621 0 : sz = buflen - w - 1;
1622 : /* String data, right-truncated */
1623 0 : addStmtError(stmt, "01004", NULL, 0);
1624 : }
1625 0 : data += sz;
1626 0 : buflen -= sz;
1627 : }
1628 : /* this should now fit */
1629 0 : sz = snprintf(data, buflen, "' DAY TO SECOND");
1630 0 : if (lenp && sz > 0)
1631 0 : *lenp += sz;
1632 : break;
1633 : }
1634 0 : case SQL_INTERVAL_HOUR:
1635 0 : sz = snprintf((char *) ptr, buflen,
1636 : "INTERVAL %s'%u' HOUR",
1637 0 : ival.interval_sign ? "-" : "",
1638 0 : (unsigned) (24 * ival.intval.day_second.day +
1639 0 : ival.intval.day_second.hour));
1640 :
1641 0 : if (sz < 0 || sz >= buflen) {
1642 : /* Numeric value out of range */
1643 0 : addStmtError(stmt, "22003", NULL, 0);
1644 :
1645 0 : if (type == SQL_C_WCHAR)
1646 0 : free(ptr);
1647 0 : return SQL_ERROR;
1648 : }
1649 0 : if (lenp)
1650 0 : *lenp = sz;
1651 : break;
1652 0 : case SQL_INTERVAL_HOUR_TO_MINUTE:
1653 0 : sz = snprintf((char *) ptr, buflen,
1654 : "INTERVAL %s'%u:%02u' HOUR TO MINUTE",
1655 0 : ival.interval_sign ? "-" : "",
1656 0 : (unsigned) (24 * ival.intval.day_second.day +
1657 0 : ival.intval.day_second.hour),
1658 0 : (unsigned int) ival.intval.day_second.minute);
1659 :
1660 0 : if (sz < 0 || sz >= buflen) {
1661 : /* Numeric value out of range */
1662 0 : addStmtError(stmt, "22003", NULL, 0);
1663 :
1664 0 : if (type == SQL_C_WCHAR)
1665 0 : free(ptr);
1666 0 : return SQL_ERROR;
1667 : }
1668 0 : if (lenp)
1669 0 : *lenp = sz;
1670 : break;
1671 0 : case SQL_INTERVAL_HOUR_TO_SECOND: {
1672 0 : int w;
1673 :
1674 0 : data = (char *) ptr;
1675 :
1676 0 : w = 15; /* space needed for "'HOUR TO SECOND" */
1677 :
1678 0 : sz = snprintf(data, buflen, "INTERVAL %s'%u:%02u:%02u",
1679 0 : ival.interval_sign ? "-" : "",
1680 0 : (unsigned) (24 * ival.intval.day_second.day +
1681 0 : ival.intval.day_second.hour),
1682 0 : (unsigned int) ival.intval.day_second.minute,
1683 0 : (unsigned int) ival.intval.day_second.second);
1684 0 : if (sz < 0 || sz + w >= buflen) {
1685 : /* Numeric value out of range */
1686 0 : addStmtError(stmt, "22003", NULL, 0);
1687 :
1688 0 : if (type == SQL_C_WCHAR)
1689 0 : free(ptr);
1690 0 : return SQL_ERROR;
1691 : }
1692 0 : data += sz;
1693 0 : buflen -= sz;
1694 :
1695 0 : if (lenp)
1696 0 : *lenp = sz;
1697 0 : if (ivalprec > 0) {
1698 0 : if (lenp)
1699 0 : *lenp += ivalprec + 1;
1700 0 : if (buflen > w + 2)
1701 0 : sz = snprintf(data, buflen, ".%0*u", ivalprec, (unsigned int) ival.intval.day_second.fraction);
1702 0 : if (buflen <= w + 2 || sz < 0 || sz + w >= buflen) {
1703 0 : sz = buflen - w - 1;
1704 : /* String data, right-truncated */
1705 0 : addStmtError(stmt, "01004", NULL, 0);
1706 : }
1707 0 : data += sz;
1708 0 : buflen -= sz;
1709 : }
1710 : /* this should now fit */
1711 0 : sz = snprintf(data, buflen, "' HOUR TO SECOND");
1712 0 : if (lenp && sz > 0)
1713 0 : *lenp += sz;
1714 : break;
1715 : }
1716 0 : case SQL_INTERVAL_MINUTE:
1717 0 : sz = snprintf((char *) ptr, buflen,
1718 : "INTERVAL %s'%u' MINUTE",
1719 0 : ival.interval_sign ? "-" : "",
1720 0 : (unsigned) (60 * (24 * ival.intval.day_second.day +
1721 0 : ival.intval.day_second.hour) +
1722 0 : ival.intval.day_second.minute));
1723 :
1724 0 : if (sz < 0 || sz >= buflen) {
1725 : /* Numeric value out of range */
1726 0 : addStmtError(stmt, "22003", NULL, 0);
1727 :
1728 0 : if (type == SQL_C_WCHAR)
1729 0 : free(ptr);
1730 0 : return SQL_ERROR;
1731 : }
1732 0 : if (lenp)
1733 0 : *lenp = sz;
1734 : break;
1735 0 : case SQL_INTERVAL_MINUTE_TO_SECOND: {
1736 0 : int w;
1737 :
1738 0 : data = (char *) ptr;
1739 :
1740 0 : w = 17; /* space needed for "'MINUTE TO SECOND" */
1741 :
1742 0 : sz = snprintf(data, buflen, "INTERVAL %s'%u:%02u",
1743 0 : ival.interval_sign ? "-" : "",
1744 0 : (unsigned) (60 * (24 * ival.intval.day_second.day +
1745 0 : ival.intval.day_second.hour) +
1746 0 : ival.intval.day_second.minute),
1747 0 : (unsigned int) ival.intval.day_second.second);
1748 0 : if (sz < 0 || sz + w >= buflen) {
1749 : /* Numeric value out of range */
1750 0 : addStmtError(stmt, "22003", NULL, 0);
1751 :
1752 0 : if (type == SQL_C_WCHAR)
1753 0 : free(ptr);
1754 0 : return SQL_ERROR;
1755 : }
1756 0 : data += sz;
1757 0 : buflen -= sz;
1758 :
1759 0 : if (lenp)
1760 0 : *lenp = sz;
1761 0 : if (ivalprec > 0) {
1762 0 : if (lenp)
1763 0 : *lenp += ivalprec + 1;
1764 0 : if (buflen > w + 2)
1765 0 : sz = snprintf(data, buflen, ".%0*u", ivalprec, (unsigned int) ival.intval.day_second.fraction);
1766 0 : if (buflen <= w + 2 || sz < 0 || sz + w >= buflen) {
1767 0 : sz = buflen - w - 1;
1768 : /* String data, right-truncated */
1769 0 : addStmtError(stmt, "01004", NULL, 0);
1770 : }
1771 0 : data += sz;
1772 0 : buflen -= sz;
1773 : }
1774 : /* this should now fit */
1775 0 : sz = snprintf(data, buflen, "' MINUTE TO SECOND");
1776 0 : if (lenp && sz > 0)
1777 0 : *lenp += sz;
1778 : break;
1779 : }
1780 0 : case SQL_INTERVAL_SECOND: {
1781 0 : int w;
1782 :
1783 0 : data = (char *) ptr;
1784 :
1785 0 : w = 7; /* space needed for "'SECOND" */
1786 :
1787 0 : sz = snprintf(data, buflen, "INTERVAL %s'%u",
1788 0 : ival.interval_sign ? "-" : "",
1789 0 : (unsigned) (60 * (60 * (24 * ival.intval.day_second.day +
1790 0 : ival.intval.day_second.hour) +
1791 0 : ival.intval.day_second.minute) +
1792 0 : ival.intval.day_second.second));
1793 0 : if (sz < 0 || sz + w >= buflen) {
1794 : /* Numeric value out of range */
1795 0 : addStmtError(stmt, "22003", NULL, 0);
1796 :
1797 0 : if (type == SQL_C_WCHAR)
1798 0 : free(ptr);
1799 0 : return SQL_ERROR;
1800 : }
1801 0 : data += sz;
1802 0 : buflen -= sz;
1803 :
1804 0 : if (lenp)
1805 0 : *lenp = sz;
1806 0 : if (ivalprec > 0) {
1807 0 : if (lenp)
1808 0 : *lenp += ivalprec + 1;
1809 0 : if (buflen > w + 2)
1810 0 : sz = snprintf(data, buflen, ".%0*u", ivalprec, (unsigned int) ival.intval.day_second.fraction);
1811 0 : if (buflen <= w + 2 || sz < 0 || sz + w >= buflen) {
1812 0 : sz = buflen - w - 1;
1813 : /* String data, right-truncated */
1814 0 : addStmtError(stmt, "01004", NULL, 0);
1815 : }
1816 0 : data += sz;
1817 0 : buflen -= sz;
1818 : }
1819 : /* this should now fit */
1820 0 : sz = snprintf(data, buflen, "' SECOND");
1821 0 : if (lenp && sz > 0)
1822 0 : *lenp += sz;
1823 : break;
1824 : }
1825 : }
1826 6244 : if (type == SQL_C_WCHAR) {
1827 391 : SQLSMALLINT n;
1828 391 : size_t i;
1829 :
1830 391 : if (ptr) {
1831 0 : ODBCutf82wchar((SQLCHAR *) ptr, SQL_NTS,
1832 : (SQLWCHAR *) origptr,
1833 0 : origbuflen / sizeof(SQLWCHAR),
1834 : &n, &i);
1835 0 : free(ptr);
1836 : } else {
1837 391 : ODBCutf82wchar((SQLCHAR *) data, SQL_NTS,
1838 : (SQLWCHAR *) origptr,
1839 391 : origbuflen / sizeof(SQLWCHAR),
1840 : &n, &i);
1841 : }
1842 : #ifdef ODBCDEBUG
1843 391 : ODBCLOG("Writing %d bytes to %p\n",
1844 : (int) (n * sizeof(SQLWCHAR)),
1845 : origptr);
1846 : #endif
1847 :
1848 391 : if (origlenp)
1849 391 : *origlenp = n * sizeof(SQLWCHAR); /* # of bytes, not chars */
1850 391 : irdrec->already_returned -= datalen;
1851 391 : irdrec->already_returned += i;
1852 391 : if (i < datalen) {
1853 : /* String data, right-truncated */
1854 6 : addStmtError(stmt, "01004", NULL, 0);
1855 : }
1856 : }
1857 : #ifdef ODBCDEBUG
1858 : else
1859 5853 : ODBCLOG("Writing %zu bytes to %p\n", strlen(ptr), ptr);
1860 : #endif
1861 15340 : break;
1862 : }
1863 2 : case SQL_C_BINARY: {
1864 2 : if (buflen < 0) {
1865 : /* Invalid string or buffer length */
1866 0 : addStmtError(stmt, "HY090", NULL, 0);
1867 0 : return SQL_ERROR;
1868 : }
1869 2 : if (ardrec && row > 0)
1870 0 : ptr = (SQLPOINTER) ((char *) ptr + row * (bind_type == SQL_BIND_BY_COLUMN ? ardrec->sql_desc_octet_length : bind_type));
1871 :
1872 2 : switch (sql_type) {
1873 0 : case SQL_CHAR:
1874 : case SQL_VARCHAR:
1875 : case SQL_WCHAR:
1876 : case SQL_WVARCHAR:
1877 : case SQL_DECIMAL:
1878 : case SQL_NUMERIC:
1879 : case SQL_TINYINT:
1880 : case SQL_SMALLINT:
1881 : case SQL_INTEGER:
1882 : case SQL_BIGINT:
1883 : case SQL_HUGEINT:
1884 : case SQL_REAL:
1885 : case SQL_DOUBLE:
1886 : case SQL_FLOAT:
1887 : case SQL_BIT:
1888 : case SQL_TYPE_DATE:
1889 : case SQL_TYPE_TIME:
1890 : case SQL_TYPE_TIMESTAMP:
1891 : case SQL_INTERVAL_YEAR:
1892 : case SQL_INTERVAL_YEAR_TO_MONTH:
1893 : case SQL_INTERVAL_MONTH:
1894 : case SQL_INTERVAL_DAY:
1895 : case SQL_INTERVAL_DAY_TO_HOUR:
1896 : case SQL_INTERVAL_DAY_TO_MINUTE:
1897 : case SQL_INTERVAL_DAY_TO_SECOND:
1898 : case SQL_INTERVAL_HOUR:
1899 : case SQL_INTERVAL_HOUR_TO_MINUTE:
1900 : case SQL_INTERVAL_HOUR_TO_SECOND:
1901 : case SQL_INTERVAL_MINUTE:
1902 : case SQL_INTERVAL_MINUTE_TO_SECOND:
1903 : case SQL_INTERVAL_SECOND:
1904 : default:
1905 : /* Restricted data type attribute violation */
1906 0 : addStmtError(stmt, "07006", NULL, 0);
1907 0 : return SQL_ERROR;
1908 : case SQL_BINARY:
1909 : case SQL_VARBINARY:
1910 : case SQL_LONGVARBINARY:
1911 2 : break;
1912 : }
1913 2 : if (irdrec->already_returned < 0)
1914 2 : irdrec->already_returned = 0;
1915 0 : else if ((size_t) irdrec->already_returned >= datalen) {
1916 : /* no more data to return */
1917 : return SQL_NO_DATA;
1918 : }
1919 2 : data += irdrec->already_returned;
1920 2 : datalen -= irdrec->already_returned;
1921 :
1922 2 : size_t k;
1923 2 : SQLLEN j;
1924 2 : unsigned char *p = ptr;
1925 :
1926 84 : for (k = 0, j = 0; k < datalen && j < buflen; k++) {
1927 82 : unsigned int n;
1928 :
1929 82 : if (isdigit((unsigned char) data[k]))
1930 43 : n = data[k] - '0';
1931 39 : else if ('A' <= data[k] && data[k] <= 'F')
1932 39 : n = data[k] - 'A' + 10;
1933 0 : else if ('a' <= data[k] && data[k] <= 'f')
1934 0 : n = data[k] - 'a' + 10;
1935 : else {
1936 : /* should not happen: not a hex character */
1937 : /* General error */
1938 0 : addStmtError(stmt, "HY000", "Unexpected data from server", 0);
1939 0 : if (type == SQL_C_WCHAR)
1940 : free(ptr);
1941 0 : return SQL_ERROR;
1942 : }
1943 82 : if (k & 1) {
1944 41 : p[j] |= n;
1945 41 : j++;
1946 : } else {
1947 41 : p[j] = n << 4;
1948 : }
1949 : }
1950 2 : if (k & 1) {
1951 : /* should not happen: uneven length */
1952 : /* General error */
1953 0 : addStmtError(stmt, "HY000", "Unexpected data from server", 0);
1954 0 : if (type == SQL_C_WCHAR)
1955 : free(ptr);
1956 0 : return SQL_ERROR;
1957 : }
1958 2 : irdrec->already_returned += k;
1959 2 : if (lenp)
1960 2 : *lenp = datalen / 2;
1961 2 : if (k < datalen) {
1962 : /* String data, right-truncated */
1963 0 : addStmtError(stmt, "01004", NULL, 0);
1964 : }
1965 : break;
1966 : }
1967 147 : case SQL_C_BIT:
1968 147 : if (ardrec && row > 0)
1969 0 : ptr = (SQLPOINTER) ((char *) ptr + row * (bind_type == SQL_BIND_BY_COLUMN ? (SQLINTEGER) sizeof(unsigned char) : bind_type));
1970 :
1971 147 : if (lenp)
1972 147 : *lenp = 1;
1973 147 : switch (sql_type) {
1974 0 : case SQL_CHAR:
1975 : case SQL_VARCHAR:
1976 : case SQL_WCHAR:
1977 : case SQL_WVARCHAR:
1978 0 : if (!parsedouble(data, &fval)) {
1979 : /* Invalid character value for cast
1980 : specification */
1981 0 : addStmtError(stmt, "22018", NULL, 0);
1982 0 : return SQL_ERROR;
1983 : }
1984 : /* fall through */
1985 : case SQL_REAL:
1986 : case SQL_DOUBLE:
1987 : case SQL_FLOAT:
1988 0 : if (fval < 0 || fval >= 2) {
1989 : /* Numeric value out of range */
1990 0 : addStmtError(stmt, "22003", NULL, 0);
1991 0 : return SQL_ERROR;
1992 : }
1993 0 : WriteData(ptr, fval >= 1, unsigned char);
1994 :
1995 0 : if (fval != 0 && fval != 1) {
1996 : /* Fractional truncation */
1997 0 : addStmtError(stmt, "01S07", NULL, 0);
1998 : }
1999 : break;
2000 147 : case SQL_DECIMAL:
2001 : case SQL_NUMERIC:
2002 : case SQL_TINYINT:
2003 : case SQL_SMALLINT:
2004 : case SQL_INTEGER:
2005 : case SQL_BIGINT:
2006 : case SQL_HUGEINT:
2007 : case SQL_BIT: {
2008 147 : int truncated = nval.scale > 0;
2009 :
2010 147 : while (nval.scale > 0) {
2011 0 : nval.val /= 10;
2012 0 : nval.scale--;
2013 : }
2014 : /* -0 is ok, but -1 or -0.5 isn't */
2015 147 : if (nval.val > 1 || (!nval.sign && (nval.val == 1 || truncated))) {
2016 : /* Numeric value out of range */
2017 0 : addStmtError(stmt, "22003", NULL, 0);
2018 0 : return SQL_ERROR;
2019 : }
2020 147 : WriteData(ptr, (unsigned char) nval.val, unsigned char);
2021 :
2022 147 : if (truncated) {
2023 : /* Fractional truncation */
2024 0 : addStmtError(stmt, "01S07", NULL, 0);
2025 : }
2026 : break;
2027 : }
2028 0 : default:
2029 : /* Restricted data type attribute violation */
2030 0 : addStmtError(stmt, "07006", NULL, 0);
2031 0 : return SQL_ERROR;
2032 : }
2033 : break;
2034 2887 : case SQL_C_STINYINT:
2035 : case SQL_C_TINYINT:
2036 : case SQL_C_SSHORT:
2037 : case SQL_C_SHORT:
2038 : case SQL_C_SLONG:
2039 : case SQL_C_LONG:
2040 : case SQL_C_SBIGINT: {
2041 2887 : uint64_t maxval = 1;
2042 :
2043 2887 : switch (type) {
2044 3 : case SQL_C_STINYINT:
2045 : case SQL_C_TINYINT:
2046 3 : maxval <<= 7;
2047 3 : if (lenp)
2048 3 : *lenp = sizeof(signed char);
2049 3 : if (ardrec && row > 0)
2050 0 : ptr = (SQLPOINTER) ((char *) ptr + row * (bind_type == SQL_BIND_BY_COLUMN ? (SQLINTEGER) sizeof(signed char) : bind_type));
2051 : break;
2052 2013 : case SQL_C_SSHORT:
2053 : case SQL_C_SHORT:
2054 2013 : maxval <<= 15;
2055 2013 : if (lenp)
2056 3 : *lenp = sizeof(short);
2057 2013 : if (ardrec && row > 0)
2058 0 : ptr = (SQLPOINTER) ((char *) ptr + row * (bind_type == SQL_BIND_BY_COLUMN ? (SQLINTEGER) sizeof(short) : bind_type));
2059 : break;
2060 868 : case SQL_C_SLONG:
2061 : case SQL_C_LONG:
2062 868 : maxval <<= 31;
2063 868 : if (lenp)
2064 864 : *lenp = sizeof(int);
2065 868 : if (ardrec && row > 0)
2066 0 : ptr = (SQLPOINTER) ((char *) ptr + row * (bind_type == SQL_BIND_BY_COLUMN ? (SQLINTEGER) sizeof(int) : bind_type));
2067 : break;
2068 3 : case SQL_C_SBIGINT:
2069 3 : maxval <<= 63;
2070 3 : if (lenp)
2071 3 : *lenp = sizeof(SQLBIGINT);
2072 3 : if (ardrec && row > 0)
2073 0 : ptr = (SQLPOINTER) ((char *) ptr + row * (bind_type == SQL_BIND_BY_COLUMN ? (SQLINTEGER) sizeof(SQLBIGINT) : bind_type));
2074 : break;
2075 : }
2076 2887 : switch (sql_type) {
2077 0 : case SQL_CHAR:
2078 : case SQL_VARCHAR:
2079 : case SQL_WCHAR:
2080 : case SQL_WVARCHAR:
2081 : case SQL_DOUBLE:
2082 : case SQL_FLOAT:
2083 : case SQL_REAL:
2084 : /* reparse double and float, parse char */
2085 0 : if (!parseint(data, &nval)) {
2086 : /* Invalid character value for cast
2087 : * specification */
2088 0 : addStmtError(stmt, "22018", NULL, 0);
2089 0 : return SQL_ERROR;
2090 : }
2091 : /* fall through */
2092 : case SQL_DECIMAL:
2093 : case SQL_NUMERIC:
2094 : case SQL_TINYINT:
2095 : case SQL_SMALLINT:
2096 : case SQL_INTEGER:
2097 : case SQL_BIGINT:
2098 : case SQL_HUGEINT:
2099 : case SQL_BIT: {
2100 2887 : int truncated = nval.scale > 0;
2101 :
2102 : /* scale is normalized, so if negative, number
2103 : * is too large even for SQLUBIGINT */
2104 2887 : while (nval.scale > 0) {
2105 0 : nval.val /= 10;
2106 0 : nval.scale--;
2107 : }
2108 2887 : if (nval.scale < 0 || nval.val > maxval || (nval.val == maxval && nval.sign)) {
2109 : /* Numeric value out of range */
2110 0 : addStmtError(stmt, "22003", NULL, 0);
2111 0 : return SQL_ERROR;
2112 : }
2113 2887 : if (truncated) {
2114 : /* Fractional truncation */
2115 0 : addStmtError(stmt, "01S07", NULL, 0);
2116 : }
2117 :
2118 2887 : switch (type) {
2119 3 : case SQL_C_STINYINT:
2120 : case SQL_C_TINYINT:
2121 3 : WriteData(ptr, nval.sign ? (signed char) nval.val : -(signed char) nval.val, signed char);
2122 3 : break;
2123 2013 : case SQL_C_SSHORT:
2124 : case SQL_C_SHORT:
2125 2013 : WriteData(ptr, nval.sign ? (short) nval.val : -(short) nval.val, short);
2126 2013 : break;
2127 868 : case SQL_C_SLONG:
2128 : case SQL_C_LONG:
2129 868 : WriteData(ptr, nval.sign ? (int) nval.val : -(int) nval.val, int);
2130 868 : break;
2131 3 : case SQL_C_SBIGINT:
2132 3 : WriteData(ptr, nval.sign ? (SQLBIGINT) nval.val : -(SQLBIGINT) nval.val, SQLBIGINT);
2133 3 : break;
2134 : }
2135 : break;
2136 : }
2137 0 : default:
2138 : /* Restricted data type attribute violation */
2139 0 : addStmtError(stmt, "07006", NULL, 0);
2140 0 : return SQL_ERROR;
2141 : }
2142 : break;
2143 : }
2144 0 : case SQL_C_UTINYINT:
2145 : case SQL_C_USHORT:
2146 : case SQL_C_ULONG:
2147 : case SQL_C_UBIGINT: {
2148 0 : uint64_t maxval = 1;
2149 :
2150 0 : switch (type) {
2151 0 : case SQL_C_UTINYINT:
2152 0 : maxval <<= 8;
2153 0 : if (lenp)
2154 0 : *lenp = sizeof(unsigned char);
2155 0 : if (ardrec && row > 0)
2156 0 : ptr = (SQLPOINTER) ((char *) ptr + row * (bind_type == SQL_BIND_BY_COLUMN ? (SQLINTEGER) sizeof(unsigned char) : bind_type));
2157 : break;
2158 0 : case SQL_C_USHORT:
2159 0 : maxval <<= 16;
2160 0 : if (lenp)
2161 0 : *lenp = sizeof(unsigned short);
2162 0 : if (ardrec && row > 0)
2163 0 : ptr = (SQLPOINTER) ((char *) ptr + row * (bind_type == SQL_BIND_BY_COLUMN ? (SQLINTEGER) sizeof(unsigned short) : bind_type));
2164 : break;
2165 0 : case SQL_C_ULONG:
2166 0 : maxval <<= 32;
2167 0 : if (lenp)
2168 0 : *lenp = sizeof(unsigned int);
2169 0 : if (ardrec && row > 0)
2170 0 : ptr = (SQLPOINTER) ((char *) ptr + row * (bind_type == SQL_BIND_BY_COLUMN ? (SQLINTEGER) sizeof(unsigned int) : bind_type));
2171 : break;
2172 0 : case SQL_C_UBIGINT:
2173 0 : if (lenp)
2174 0 : *lenp = sizeof(SQLUBIGINT);
2175 0 : if (ardrec && row > 0)
2176 0 : ptr = (SQLPOINTER) ((char *) ptr + row * (bind_type == SQL_BIND_BY_COLUMN ? (SQLINTEGER) sizeof(SQLUBIGINT) : bind_type));
2177 : break;
2178 : }
2179 0 : maxval--;
2180 0 : switch (sql_type) {
2181 0 : case SQL_CHAR:
2182 : case SQL_VARCHAR:
2183 : case SQL_WCHAR:
2184 : case SQL_WVARCHAR:
2185 : case SQL_DOUBLE:
2186 : case SQL_FLOAT:
2187 : case SQL_REAL:
2188 : /* reparse double and float, parse char */
2189 0 : if (!parseint(data, &nval)) {
2190 : /* Invalid character value for cast
2191 : * specification */
2192 0 : addStmtError(stmt, "22018", NULL, 0);
2193 0 : return SQL_ERROR;
2194 : }
2195 : /* fall through */
2196 : case SQL_DECIMAL:
2197 : case SQL_NUMERIC:
2198 : case SQL_TINYINT:
2199 : case SQL_SMALLINT:
2200 : case SQL_INTEGER:
2201 : case SQL_BIGINT:
2202 : case SQL_HUGEINT:
2203 : case SQL_BIT: {
2204 0 : int truncated = nval.scale > 0;
2205 :
2206 : /* scale is normalized, so if negative, number
2207 : * is too large even for SQLUBIGINT */
2208 0 : while (nval.scale > 0) {
2209 0 : nval.val /= 10;
2210 0 : nval.scale--;
2211 : }
2212 0 : if (nval.scale < 0 || !nval.sign || (maxval != 0 && nval.val >= maxval)) {
2213 : /* Numeric value out of range */
2214 0 : addStmtError(stmt, "22003", NULL, 0);
2215 0 : return SQL_ERROR;
2216 : }
2217 0 : if (truncated) {
2218 : /* Fractional truncation */
2219 0 : addStmtError(stmt, "01S07", NULL, 0);
2220 : }
2221 :
2222 0 : switch (type) {
2223 0 : case SQL_C_UTINYINT:
2224 0 : WriteData(ptr, (unsigned char) nval.val, unsigned char);
2225 0 : break;
2226 0 : case SQL_C_USHORT:
2227 0 : WriteData(ptr, (unsigned short) nval.val, unsigned short);
2228 0 : break;
2229 0 : case SQL_C_ULONG:
2230 0 : WriteData(ptr, (unsigned int) nval.val, unsigned int);
2231 0 : break;
2232 0 : case SQL_C_UBIGINT:
2233 0 : WriteData(ptr, (SQLUBIGINT) nval.val, SQLUBIGINT);
2234 0 : break;
2235 : }
2236 : break;
2237 : }
2238 0 : default:
2239 : /* Restricted data type attribute violation */
2240 0 : addStmtError(stmt, "07006", NULL, 0);
2241 0 : return SQL_ERROR;
2242 : }
2243 : break;
2244 : }
2245 0 : case SQL_C_NUMERIC:
2246 0 : if (ardrec && row > 0)
2247 0 : ptr = (SQLPOINTER) ((char *) ptr + row * (bind_type == SQL_BIND_BY_COLUMN ? (SQLINTEGER) sizeof(SQL_NUMERIC_STRUCT) : bind_type));
2248 :
2249 0 : switch (sql_type) {
2250 0 : case SQL_CHAR:
2251 : case SQL_VARCHAR:
2252 : case SQL_WCHAR:
2253 : case SQL_WVARCHAR:
2254 : case SQL_DOUBLE:
2255 : case SQL_FLOAT:
2256 : case SQL_REAL:
2257 : /* reparse double and float, parse char */
2258 0 : if (!(i = parseint(data, &nval))) {
2259 : /* Invalid character value for cast
2260 : * specification */
2261 0 : addStmtError(stmt, "22018", NULL, 0);
2262 0 : return SQL_ERROR;
2263 : }
2264 0 : if (i == 2) {
2265 : /* Fractional truncation */
2266 0 : addStmtError(stmt, "01S07", NULL, 0);
2267 : }
2268 :
2269 : /* fall through */
2270 : case SQL_DECIMAL:
2271 : case SQL_NUMERIC:
2272 : case SQL_TINYINT:
2273 : case SQL_SMALLINT:
2274 : case SQL_INTEGER:
2275 : case SQL_BIGINT:
2276 : case SQL_HUGEINT:
2277 : case SQL_BIT:
2278 0 : while (nval.precision > precision) {
2279 0 : nval.val /= 10;
2280 0 : nval.scale--;
2281 0 : nval.precision--;
2282 : }
2283 0 : while (nval.scale < scale) {
2284 0 : nval.val *= 10;
2285 0 : nval.scale++;
2286 : }
2287 0 : while (nval.scale > scale) {
2288 0 : nval.val /= 10;
2289 0 : nval.scale--;
2290 0 : nval.precision--;
2291 : }
2292 0 : nmval = (SQL_NUMERIC_STRUCT) {
2293 0 : .precision = nval.precision,
2294 : .scale = nval.scale,
2295 0 : .sign = nval.sign,
2296 : };
2297 0 : for (i = 0; i < SQL_MAX_NUMERIC_LEN; i++) {
2298 0 : nmval.val[i] = (SQLCHAR) (nval.val & 0xFF);
2299 0 : nval.val >>= 8;
2300 : }
2301 0 : WriteData(ptr, nmval, SQL_NUMERIC_STRUCT);
2302 0 : if (lenp)
2303 0 : *lenp = sizeof(SQL_NUMERIC_STRUCT);
2304 : break;
2305 0 : default:
2306 : /* Restricted data type attribute violation */
2307 0 : addStmtError(stmt, "07006", NULL, 0);
2308 0 : return SQL_ERROR;
2309 : }
2310 : break;
2311 2006 : case SQL_C_FLOAT:
2312 : case SQL_C_DOUBLE:
2313 2006 : switch (sql_type) {
2314 0 : case SQL_CHAR:
2315 : case SQL_VARCHAR:
2316 : case SQL_WCHAR:
2317 : case SQL_WVARCHAR:
2318 0 : if (!parsedouble(data, &fval)) {
2319 : /* Invalid character value for cast
2320 : * specification */
2321 0 : addStmtError(stmt, "22018", NULL, 0);
2322 0 : return SQL_ERROR;
2323 : }
2324 : break;
2325 : case SQL_DOUBLE:
2326 : case SQL_FLOAT:
2327 : case SQL_REAL:
2328 : break;
2329 0 : case SQL_DECIMAL:
2330 : case SQL_NUMERIC:
2331 : case SQL_TINYINT:
2332 : case SQL_SMALLINT:
2333 : case SQL_INTEGER:
2334 : case SQL_BIGINT:
2335 : case SQL_HUGEINT:
2336 : case SQL_BIT:
2337 0 : fval = (double) (int64_t) nval.val;
2338 0 : i = 1;
2339 0 : while (nval.scale > 0) {
2340 0 : nval.scale--;
2341 0 : i *= 10;
2342 : }
2343 0 : fval /= (double) i;
2344 0 : i = 1;
2345 0 : while (nval.scale < 0) {
2346 0 : nval.scale++;
2347 0 : i *= 10;
2348 : }
2349 0 : fval *= (double) i;
2350 0 : if (!nval.sign)
2351 0 : fval = -fval;
2352 : break;
2353 0 : default:
2354 : /* Restricted data type attribute violation */
2355 0 : addStmtError(stmt, "07006", NULL, 0);
2356 0 : return SQL_ERROR;
2357 : }
2358 2006 : if (type == SQL_C_FLOAT) {
2359 3 : if (ardrec && row > 0)
2360 0 : ptr = (SQLPOINTER) ((char *) ptr + row * (bind_type == SQL_BIND_BY_COLUMN ? (SQLINTEGER) sizeof(float) : bind_type));
2361 3 : if (fval < -FLT_MAX || fval > FLT_MAX) {
2362 : /* Numeric value out of range */
2363 0 : addStmtError(stmt, "22003", NULL, 0);
2364 0 : return SQL_ERROR;
2365 : }
2366 3 : WriteData(ptr, (float) fval, float);
2367 3 : if (lenp)
2368 3 : *lenp = sizeof(float);
2369 : } else {
2370 2003 : if (ardrec && row > 0)
2371 0 : ptr = (SQLPOINTER) ((char *) ptr + row * (bind_type == SQL_BIND_BY_COLUMN ? (SQLINTEGER) sizeof(double) : bind_type));
2372 2003 : WriteData(ptr, fval, double);
2373 :
2374 2003 : if (lenp)
2375 3 : *lenp = sizeof(double);
2376 : }
2377 : break;
2378 2003 : case SQL_C_TYPE_DATE:
2379 2003 : if (ardrec && row > 0)
2380 0 : ptr = (SQLPOINTER) ((char *) ptr + row * (bind_type == SQL_BIND_BY_COLUMN ? (SQLINTEGER) sizeof(DATE_STRUCT) : bind_type));
2381 :
2382 2003 : i = 1;
2383 2003 : switch (sql_type) {
2384 0 : case SQL_CHAR:
2385 : case SQL_VARCHAR:
2386 : case SQL_WCHAR:
2387 : case SQL_WVARCHAR:
2388 0 : i = parsetimestamp(data, &tsval);
2389 : /* fall through */
2390 : case SQL_TYPE_TIMESTAMP: /* note i==1 unless we fell through */
2391 0 : if (i) {
2392 0 : if (tsval.hour || tsval.minute || tsval.second || tsval.fraction || i == 2) {
2393 : /* Fractional truncation */
2394 0 : addStmtError(stmt, "01S07", NULL, 0);
2395 : }
2396 0 : dval = (DATE_STRUCT) {
2397 0 : .year = tsval.year,
2398 0 : .month = tsval.month,
2399 0 : .day = tsval.day,
2400 : };
2401 0 : } else if (!parsedate(data, &dval)) {
2402 : /* Invalid character value for cast
2403 : * specification */
2404 0 : addStmtError(stmt, "22018", NULL, 0);
2405 0 : return SQL_ERROR;
2406 : }
2407 : /* fall through */
2408 : case SQL_TYPE_DATE:
2409 2003 : WriteData(ptr, dval, DATE_STRUCT);
2410 2003 : break;
2411 0 : default:
2412 : /* Restricted data type attribute violation */
2413 0 : addStmtError(stmt, "07006", NULL, 0);
2414 0 : return SQL_ERROR;
2415 : }
2416 2003 : if (lenp)
2417 3 : *lenp = sizeof(DATE_STRUCT);
2418 : break;
2419 2003 : case SQL_C_TYPE_TIME:
2420 2003 : if (ardrec && row > 0)
2421 0 : ptr = (SQLPOINTER) ((char *) ptr + row * (bind_type == SQL_BIND_BY_COLUMN ? (SQLINTEGER) sizeof(TIME_STRUCT) : bind_type));
2422 :
2423 2003 : i = 1;
2424 2003 : switch (sql_type) {
2425 0 : case SQL_CHAR:
2426 : case SQL_VARCHAR:
2427 : case SQL_WCHAR:
2428 : case SQL_WVARCHAR:
2429 0 : i = parsetimestamp(data, &tsval);
2430 : /* fall through */
2431 : case SQL_TYPE_TIMESTAMP: /* note i==1 unless we fell through */
2432 0 : if (i) {
2433 0 : if (tsval.fraction || i == 2) {
2434 : /* Fractional truncation */
2435 0 : addStmtError(stmt, "01S07", NULL, 0);
2436 : }
2437 0 : tval.hour = tsval.hour;
2438 0 : tval.minute = tsval.minute;
2439 0 : tval.second = tsval.second;
2440 0 : } else if (!parsetime(data, &tval)) {
2441 : /* Invalid character value for cast
2442 : * specification */
2443 0 : addStmtError(stmt, "22018", NULL, 0);
2444 0 : return SQL_ERROR;
2445 : }
2446 : /* fall through */
2447 : case SQL_TYPE_TIME:
2448 2003 : WriteData(ptr, tval, TIME_STRUCT);
2449 2003 : break;
2450 0 : default:
2451 : /* Restricted data type attribute violation */
2452 0 : addStmtError(stmt, "07006", NULL, 0);
2453 0 : return SQL_ERROR;
2454 : }
2455 2003 : if (lenp)
2456 3 : *lenp = sizeof(TIME_STRUCT);
2457 : break;
2458 3 : case SQL_C_TYPE_TIMESTAMP:
2459 3 : if (ardrec && row > 0)
2460 0 : ptr = (SQLPOINTER) ((char *) ptr + row * (bind_type == SQL_BIND_BY_COLUMN ? (SQLINTEGER) sizeof(TIMESTAMP_STRUCT) : bind_type));
2461 :
2462 3 : i = 1;
2463 3 : switch (sql_type) {
2464 0 : case SQL_CHAR:
2465 : case SQL_VARCHAR:
2466 : case SQL_WCHAR:
2467 : case SQL_WVARCHAR:
2468 0 : i = parsetimestamp(data, &tsval);
2469 0 : if (i == 0) {
2470 0 : i = parsetime(data, &tval);
2471 0 : if (i) {
2472 0 : struct tm tm;
2473 0 : time_t t;
2474 :
2475 : case SQL_TYPE_TIME:
2476 0 : (void) time(&t);
2477 0 : tm = (struct tm) {0};
2478 : #ifdef HAVE_LOCALTIME_R
2479 0 : (void) localtime_r(&t, &tm);
2480 : #else
2481 : tm = *localtime(&t);
2482 : #endif
2483 0 : tsval = (TIMESTAMP_STRUCT) {
2484 0 : .year = tm.tm_year + 1900,
2485 0 : .month = tm.tm_mon + 1,
2486 0 : .day = tm.tm_mday,
2487 0 : .hour = tval.hour,
2488 0 : .minute = tval.minute,
2489 0 : .second = tval.second,
2490 : .fraction = 0,
2491 : };
2492 : } else {
2493 0 : i = parsedate(data, &dval);
2494 0 : if (i) {
2495 : case SQL_TYPE_DATE:
2496 0 : tsval = (TIMESTAMP_STRUCT) {
2497 0 : .year = dval.year,
2498 0 : .month = dval.month,
2499 0 : .day = dval.day,
2500 : .hour = 0,
2501 : .minute = 0,
2502 : .second = 0,
2503 : .fraction = 0,
2504 : };
2505 : } else {
2506 : /* Invalid character
2507 : * value for cast
2508 : * specification */
2509 0 : addStmtError(stmt, "22018", NULL, 0);
2510 0 : return SQL_ERROR;
2511 : }
2512 : }
2513 : }
2514 : /* fall through */
2515 : case SQL_TYPE_TIMESTAMP: /* note i==1 unless we fell through */
2516 3 : WriteData(ptr, tsval, TIMESTAMP_STRUCT);
2517 3 : break;
2518 0 : default:
2519 : /* Restricted data type attribute violation */
2520 0 : addStmtError(stmt, "07006", NULL, 0);
2521 0 : return SQL_ERROR;
2522 : }
2523 3 : if (lenp)
2524 3 : *lenp = sizeof(TIMESTAMP_STRUCT);
2525 : break;
2526 9 : case SQL_C_INTERVAL_YEAR:
2527 : case SQL_C_INTERVAL_MONTH:
2528 : case SQL_C_INTERVAL_YEAR_TO_MONTH:
2529 9 : if (ardrec && row > 0)
2530 0 : ptr = (SQLPOINTER) ((char *) ptr + row * (bind_type == SQL_BIND_BY_COLUMN ? (SQLINTEGER) sizeof(SQL_INTERVAL_STRUCT) : bind_type));
2531 :
2532 9 : switch (sql_type) {
2533 0 : case SQL_CHAR:
2534 : case SQL_VARCHAR:
2535 : case SQL_WCHAR:
2536 : case SQL_WVARCHAR:
2537 0 : if (parsemonthintervalstring(&data, NULL, &ival) == SQL_ERROR) {
2538 : /* Invalid character value for cast
2539 : * specification */
2540 0 : addStmtError(stmt, "22018", NULL, 0);
2541 0 : return SQL_ERROR;
2542 : }
2543 : break;
2544 0 : case SQL_DECIMAL:
2545 : case SQL_NUMERIC:
2546 : case SQL_TINYINT:
2547 : case SQL_SMALLINT:
2548 : case SQL_INTEGER:
2549 : case SQL_BIGINT:
2550 : case SQL_HUGEINT:
2551 0 : parsemonthinterval(&nval, &ival, type);
2552 0 : break;
2553 : case SQL_INTERVAL_YEAR:
2554 : case SQL_INTERVAL_YEAR_TO_MONTH:
2555 : case SQL_INTERVAL_MONTH:
2556 : break;
2557 0 : default:
2558 : /* Restricted data type attribute violation */
2559 0 : addStmtError(stmt, "07006", NULL, 0);
2560 0 : return SQL_ERROR;
2561 : }
2562 9 : ivval = (SQL_INTERVAL_STRUCT) {
2563 9 : .interval_sign = ival.interval_sign,
2564 : .intval.year_month.year = 0,
2565 : .intval.year_month.month = 0,
2566 : };
2567 9 : switch (type) {
2568 3 : case SQL_C_INTERVAL_YEAR:
2569 3 : ivval.interval_type = SQL_IS_YEAR;
2570 3 : if ((ivval.intval.year_month.year = ival.intval.year_month.year) >= maxdatetimeval) {
2571 : /* Interval field overflow */
2572 0 : addStmtError(stmt, "22015", NULL, 0);
2573 0 : return SQL_ERROR;
2574 : }
2575 3 : if (ival.intval.year_month.month) {
2576 : /* Fractional truncation */
2577 0 : addStmtError(stmt, "01S07", NULL, 0);
2578 : }
2579 : break;
2580 3 : case SQL_C_INTERVAL_MONTH:
2581 3 : ivval.interval_type = SQL_IS_MONTH;
2582 3 : if ((ivval.intval.year_month.month = ival.intval.year_month.month + 12 * ival.intval.year_month.year) >= maxdatetimeval) {
2583 : /* Interval field overflow */
2584 0 : addStmtError(stmt, "22015", NULL, 0);
2585 0 : return SQL_ERROR;
2586 : }
2587 : break;
2588 3 : case SQL_C_INTERVAL_YEAR_TO_MONTH:
2589 3 : ivval.interval_type = SQL_IS_YEAR_TO_MONTH;
2590 3 : if ((ivval.intval.year_month.year = ival.intval.year_month.year) >= maxdatetimeval) {
2591 : /* Interval field overflow */
2592 0 : addStmtError(stmt, "22015", NULL, 0);
2593 0 : return SQL_ERROR;
2594 : }
2595 3 : ivval.intval.year_month.month = ival.intval.year_month.month;
2596 3 : break;
2597 : }
2598 9 : WriteData(ptr, ivval, SQL_INTERVAL_STRUCT);
2599 9 : if (lenp)
2600 9 : *lenp = sizeof(SQL_INTERVAL_STRUCT);
2601 : break;
2602 32 : case SQL_C_INTERVAL_DAY:
2603 : case SQL_C_INTERVAL_HOUR:
2604 : case SQL_C_INTERVAL_MINUTE:
2605 : case SQL_C_INTERVAL_SECOND:
2606 : case SQL_C_INTERVAL_DAY_TO_HOUR:
2607 : case SQL_C_INTERVAL_DAY_TO_MINUTE:
2608 : case SQL_C_INTERVAL_DAY_TO_SECOND:
2609 : case SQL_C_INTERVAL_HOUR_TO_MINUTE:
2610 : case SQL_C_INTERVAL_HOUR_TO_SECOND:
2611 : case SQL_C_INTERVAL_MINUTE_TO_SECOND:
2612 32 : if (ardrec && row > 0)
2613 0 : ptr = (SQLPOINTER) ((char *) ptr + row * (bind_type == SQL_BIND_BY_COLUMN ? (SQLINTEGER) sizeof(SQL_INTERVAL_STRUCT) : bind_type));
2614 :
2615 32 : switch (sql_type) {
2616 0 : case SQL_CHAR:
2617 : case SQL_VARCHAR:
2618 : case SQL_WCHAR:
2619 : case SQL_WVARCHAR:
2620 0 : if (parsesecondintervalstring(&data, NULL, &ival, &ivalprec) == SQL_ERROR) {
2621 : /* Invalid character value for cast
2622 : * specification */
2623 0 : addStmtError(stmt, "22018", NULL, 0);
2624 0 : return SQL_ERROR;
2625 : }
2626 : break;
2627 0 : case SQL_DECIMAL:
2628 : case SQL_NUMERIC:
2629 : case SQL_TINYINT:
2630 : case SQL_SMALLINT:
2631 : case SQL_INTEGER:
2632 : case SQL_BIGINT:
2633 : case SQL_HUGEINT:
2634 0 : ivalprec = parsesecondinterval(&nval, &ival, type);
2635 0 : break;
2636 : case SQL_INTERVAL_DAY:
2637 : case SQL_INTERVAL_DAY_TO_HOUR:
2638 : case SQL_INTERVAL_DAY_TO_MINUTE:
2639 : case SQL_INTERVAL_DAY_TO_SECOND:
2640 : case SQL_INTERVAL_HOUR:
2641 : case SQL_INTERVAL_HOUR_TO_MINUTE:
2642 : case SQL_INTERVAL_HOUR_TO_SECOND:
2643 : case SQL_INTERVAL_MINUTE:
2644 : case SQL_INTERVAL_MINUTE_TO_SECOND:
2645 : case SQL_INTERVAL_SECOND:
2646 : break;
2647 0 : default:
2648 : /* Restricted data type attribute violation */
2649 0 : addStmtError(stmt, "07006", NULL, 0);
2650 0 : return SQL_ERROR;
2651 : }
2652 32 : ivval = (SQL_INTERVAL_STRUCT) {
2653 32 : .interval_sign = ival.interval_sign,
2654 : .intval.day_second.day = 0,
2655 : .intval.day_second.hour = 0,
2656 : .intval.day_second.minute = 0,
2657 : .intval.day_second.second = 0,
2658 : .intval.day_second.fraction = 0,
2659 : };
2660 32 : switch (type) {
2661 5 : case SQL_C_INTERVAL_DAY:
2662 5 : ivval.interval_type = SQL_IS_DAY;
2663 5 : if ((ivval.intval.day_second.day = ival.intval.day_second.day) >= maxdatetimeval) {
2664 : /* Interval field overflow */
2665 0 : addStmtError(stmt, "22015", NULL, 0);
2666 0 : return SQL_ERROR;
2667 : }
2668 5 : if (ival.intval.day_second.hour || ival.intval.day_second.minute || ival.intval.day_second.second || ival.intval.day_second.fraction) {
2669 : /* Fractional truncation */
2670 0 : addStmtError(stmt, "01S07", NULL, 0);
2671 : }
2672 : break;
2673 3 : case SQL_C_INTERVAL_HOUR:
2674 3 : ivval.interval_type = SQL_IS_HOUR;
2675 3 : if ((ivval.intval.day_second.hour = ival.intval.day_second.hour + 24 * ival.intval.day_second.day) >= maxdatetimeval) {
2676 : /* Interval field overflow */
2677 0 : addStmtError(stmt, "22015", NULL, 0);
2678 0 : return SQL_ERROR;
2679 : }
2680 3 : if (ival.intval.day_second.minute || ival.intval.day_second.second || ival.intval.day_second.fraction) {
2681 : /* Fractional truncation */
2682 0 : addStmtError(stmt, "01S07", NULL, 0);
2683 : }
2684 : break;
2685 3 : case SQL_C_INTERVAL_MINUTE:
2686 3 : ivval.interval_type = SQL_IS_MINUTE;
2687 3 : if ((ivval.intval.day_second.minute = ival.intval.day_second.minute + 60 * (ival.intval.day_second.hour + 24 * ival.intval.day_second.day)) >= maxdatetimeval) {
2688 : /* Interval field overflow */
2689 0 : addStmtError(stmt, "22015", NULL, 0);
2690 0 : return SQL_ERROR;
2691 : }
2692 3 : if (ival.intval.day_second.second || ival.intval.day_second.fraction) {
2693 : /* Fractional truncation */
2694 0 : addStmtError(stmt, "01S07", NULL, 0);
2695 : }
2696 : break;
2697 3 : case SQL_C_INTERVAL_SECOND:
2698 3 : ivval.interval_type = SQL_IS_SECOND;
2699 3 : if ((ivval.intval.day_second.second = ival.intval.day_second.second + 60 * (ival.intval.day_second.minute + 60 * (ival.intval.day_second.hour + 24 * ival.intval.day_second.day))) >= maxdatetimeval) {
2700 : /* Interval field overflow */
2701 0 : addStmtError(stmt, "22015", NULL, 0);
2702 0 : return SQL_ERROR;
2703 : }
2704 3 : ivval.intval.day_second.fraction = ival.intval.day_second.fraction;
2705 3 : break;
2706 3 : case SQL_C_INTERVAL_DAY_TO_HOUR:
2707 3 : ivval.interval_type = SQL_IS_DAY_TO_HOUR;
2708 3 : if ((ivval.intval.day_second.day = ival.intval.day_second.day) >= maxdatetimeval) {
2709 : /* Interval field overflow */
2710 0 : addStmtError(stmt, "22015", NULL, 0);
2711 0 : return SQL_ERROR;
2712 : }
2713 3 : ivval.intval.day_second.hour = ival.intval.day_second.hour;
2714 3 : if (ival.intval.day_second.minute || ival.intval.day_second.second || ival.intval.day_second.fraction) {
2715 : /* Fractional truncation */
2716 0 : addStmtError(stmt, "01S07", NULL, 0);
2717 : }
2718 : break;
2719 3 : case SQL_C_INTERVAL_DAY_TO_MINUTE:
2720 3 : ivval.interval_type = SQL_IS_DAY_TO_MINUTE;
2721 3 : if ((ivval.intval.day_second.day = ival.intval.day_second.day) >= maxdatetimeval) {
2722 : /* Interval field overflow */
2723 0 : addStmtError(stmt, "22015", NULL, 0);
2724 0 : return SQL_ERROR;
2725 : }
2726 3 : ivval.intval.day_second.hour = ival.intval.day_second.hour;
2727 3 : ivval.intval.day_second.minute = ival.intval.day_second.minute;
2728 3 : if (ival.intval.day_second.second || ival.intval.day_second.fraction) {
2729 : /* Fractional truncation */
2730 0 : addStmtError(stmt, "01S07", NULL, 0);
2731 : }
2732 : break;
2733 3 : case SQL_C_INTERVAL_DAY_TO_SECOND:
2734 3 : ivval.interval_type = SQL_IS_DAY_TO_SECOND;
2735 3 : if ((ivval.intval.day_second.day = ival.intval.day_second.day) >= maxdatetimeval) {
2736 : /* Interval field overflow */
2737 0 : addStmtError(stmt, "22015", NULL, 0);
2738 0 : return SQL_ERROR;
2739 : }
2740 3 : ivval.intval.day_second.hour = ival.intval.day_second.hour;
2741 3 : ivval.intval.day_second.minute = ival.intval.day_second.minute;
2742 3 : ivval.intval.day_second.second = ival.intval.day_second.second;
2743 3 : ivval.intval.day_second.fraction = ival.intval.day_second.fraction;
2744 3 : break;
2745 3 : case SQL_C_INTERVAL_HOUR_TO_MINUTE:
2746 3 : ivval.interval_type = SQL_IS_HOUR_TO_MINUTE;
2747 3 : if ((ivval.intval.day_second.hour = ival.intval.day_second.hour + 24 * ival.intval.day_second.day) >= maxdatetimeval) {
2748 : /* Interval field overflow */
2749 0 : addStmtError(stmt, "22015", NULL, 0);
2750 0 : return SQL_ERROR;
2751 : }
2752 3 : ivval.intval.day_second.minute = ival.intval.day_second.minute;
2753 3 : if (ival.intval.day_second.second || ival.intval.day_second.fraction) {
2754 : /* Fractional truncation */
2755 0 : addStmtError(stmt, "01S07", NULL, 0);
2756 : }
2757 : break;
2758 3 : case SQL_C_INTERVAL_HOUR_TO_SECOND:
2759 3 : ivval.interval_type = SQL_IS_HOUR_TO_SECOND;
2760 3 : if ((ivval.intval.day_second.hour = ival.intval.day_second.hour + 24 * ival.intval.day_second.day) >= maxdatetimeval) {
2761 : /* Interval field overflow */
2762 0 : addStmtError(stmt, "22015", NULL, 0);
2763 0 : return SQL_ERROR;
2764 : }
2765 3 : ivval.intval.day_second.minute = ival.intval.day_second.minute;
2766 3 : ivval.intval.day_second.second = ival.intval.day_second.second;
2767 3 : ivval.intval.day_second.fraction = ival.intval.day_second.fraction;
2768 3 : break;
2769 3 : case SQL_C_INTERVAL_MINUTE_TO_SECOND:
2770 3 : ivval.interval_type = SQL_IS_MINUTE_TO_SECOND;
2771 3 : if ((ivval.intval.day_second.minute = ival.intval.day_second.minute + 60 * (ival.intval.day_second.hour + 24 * ival.intval.day_second.day)) >= maxdatetimeval) {
2772 : /* Interval field overflow */
2773 0 : addStmtError(stmt, "22015", NULL, 0);
2774 0 : return SQL_ERROR;
2775 : }
2776 3 : ivval.intval.day_second.second = ival.intval.day_second.second;
2777 3 : ivval.intval.day_second.fraction = ival.intval.day_second.fraction;
2778 3 : break;
2779 : }
2780 32 : if (ivval.intval.day_second.fraction) {
2781 32 : while (ivalprec < precision) {
2782 24 : ivalprec++;
2783 24 : ivval.intval.day_second.fraction *= 10;
2784 : }
2785 8 : while (ivalprec > precision) {
2786 0 : ivalprec--;
2787 0 : if (stmt->Error == NULL &&
2788 0 : ivval.intval.day_second.fraction % 10 != 0) {
2789 : /* Fractional truncation */
2790 0 : addStmtError(stmt, "01S07", NULL, 0);
2791 : }
2792 0 : ivval.intval.day_second.fraction /= 10;
2793 : }
2794 : }
2795 32 : WriteData(ptr, ivval, SQL_INTERVAL_STRUCT);
2796 32 : if (lenp)
2797 32 : *lenp = sizeof(SQL_INTERVAL_STRUCT);
2798 : break;
2799 4 : case SQL_C_GUID:
2800 4 : if (datalen != 36) {
2801 : /* Restricted data type attribute violation */
2802 0 : addStmtError(stmt, "07006", NULL, 0);
2803 0 : return SQL_ERROR;
2804 : }
2805 : #ifdef ODBCDEBUG
2806 4 : ODBCLOG("Writing 16 bytes to %p\n", ptr);
2807 : #endif
2808 4 : SQLGUID su;
2809 4 : sscanf(data,
2810 : "%8"SCNx32
2811 : "-%4"SCNx16
2812 : "-%4"SCNx16
2813 : "-%2"SCNx8"%2"SCNx8
2814 : "-%2"SCNx8"%2"SCNx8"%2"SCNx8"%2"SCNx8"%2"SCNx8"%2"SCNx8,
2815 : &su.Data1, &su.Data2, &su.Data3,
2816 : &su.Data4[0], &su.Data4[1],
2817 : &su.Data4[2], &su.Data4[3], &su.Data4[4], &su.Data4[5], &su.Data4[6], &su.Data4[7]);
2818 4 : WriteData(ptr, su, SQLGUID);
2819 4 : if (lenp)
2820 4 : *lenp = sizeof(SQLGUID);
2821 : break;
2822 0 : default:
2823 : /* Invalid application buffer type */
2824 0 : addStmtError(stmt, "HY003", NULL, 0);
2825 0 : return SQL_ERROR;
2826 : }
2827 15340 : return stmt->Error ? SQL_SUCCESS_WITH_INFO : SQL_SUCCESS;
2828 : }
2829 :
2830 : #define assign(buf,bufpos,buflen,value,stmt) \
2831 : do { \
2832 : if (bufpos >= buflen) { \
2833 : char *b = realloc(buf, buflen += 1024); \
2834 : if (b == NULL) { \
2835 : free(buf); \
2836 : if (ctype == SQL_C_WCHAR && sval) \
2837 : free(sval); \
2838 : /* Memory allocation error */ \
2839 : addStmtError(stmt, "HY001", NULL, 0); \
2840 : return SQL_ERROR; \
2841 : } \
2842 : buf = b; \
2843 : } \
2844 : buf[bufpos++] = (value); \
2845 : } while (0)
2846 : #define assigns(buf,bufpos,buflen,value,stmt) \
2847 : do { \
2848 : size_t _len = strlen(value); \
2849 : size_t _i; \
2850 : while (bufpos + _len >= buflen) { \
2851 : char *b = realloc(buf, buflen += 1024); \
2852 : if (b == NULL) { \
2853 : free(buf); \
2854 : if (ctype == SQL_C_WCHAR && sval) \
2855 : free(sval); \
2856 : /* Memory allocation error */ \
2857 : addStmtError(stmt, "HY001", NULL, 0); \
2858 : return SQL_ERROR; \
2859 : } \
2860 : buf = b; \
2861 : } \
2862 : for (_i = 0; _i < _len; _i++) \
2863 : buf[bufpos++] = (value)[_i]; \
2864 : } while (0)
2865 :
2866 : SQLRETURN
2867 10004 : ODBCStore(ODBCStmt *stmt,
2868 : SQLUSMALLINT param,
2869 : SQLLEN offset,
2870 : SQLULEN row,
2871 : char **bufp,
2872 : size_t *bufposp,
2873 : size_t *buflenp,
2874 : const char *sep)
2875 : {
2876 10004 : ODBCDescRec *ipdrec, *apdrec;
2877 10004 : SQLPOINTER ptr;
2878 10004 : SQLLEN *strlen_or_ind_ptr;
2879 10004 : SQLINTEGER bind_type;
2880 10004 : SQLSMALLINT ctype, sqltype;
2881 10004 : char *sval = NULL;
2882 10004 : SQLLEN slen = 0;
2883 10004 : bignum_t nval;
2884 10004 : double fval = 0.0;
2885 10004 : DATE_STRUCT dval;
2886 10004 : TIME_STRUCT tval;
2887 10004 : TIMESTAMP_STRUCT tsval;
2888 10004 : int ivalprec = 0; /* interval second precision */
2889 10004 : SQL_INTERVAL_STRUCT ival;
2890 10004 : SQLGUID u;
2891 10004 : char *buf = *bufp;
2892 10004 : size_t bufpos = *bufposp;
2893 10004 : size_t buflen = *buflenp;
2894 10004 : char data[256];
2895 10004 : int i;
2896 :
2897 10004 : assert(param <= stmt->ImplParamDescr->sql_desc_count);
2898 10004 : assert(param <= stmt->ApplParamDescr->sql_desc_count);
2899 10004 : ipdrec = stmt->ImplParamDescr->descRec + param;
2900 10004 : apdrec = stmt->ApplParamDescr->descRec + param;
2901 :
2902 10004 : bind_type = stmt->ApplParamDescr->sql_desc_bind_type;
2903 10004 : ptr = apdrec->sql_desc_data_ptr;
2904 10004 : if (ptr && offset)
2905 0 : ptr = (SQLPOINTER) ((char *) ptr + offset + row * (bind_type == SQL_BIND_BY_COLUMN ? (SQLINTEGER) sizeof(SQLPOINTER) : bind_type));
2906 10004 : strlen_or_ind_ptr = apdrec->sql_desc_indicator_ptr;
2907 10004 : if (strlen_or_ind_ptr && offset)
2908 0 : strlen_or_ind_ptr = (SQLLEN *) ((char *) strlen_or_ind_ptr + offset + row * (bind_type == SQL_BIND_BY_COLUMN ? (SQLINTEGER) sizeof(SQLINTEGER) : bind_type));
2909 10004 : if (ptr == NULL &&
2910 0 : (strlen_or_ind_ptr == NULL || *strlen_or_ind_ptr != SQL_NULL_DATA)) {
2911 : /* COUNT field incorrect */
2912 0 : addStmtError(stmt, "07002", NULL, 0);
2913 0 : return SQL_ERROR;
2914 : }
2915 :
2916 10004 : ctype = apdrec->sql_desc_concise_type;
2917 10004 : sqltype = ipdrec->sql_desc_concise_type;
2918 10004 : if (ctype == SQL_C_DEFAULT)
2919 0 : ctype = ODBCDefaultType(ipdrec);
2920 :
2921 10004 : switch (ctype) {
2922 0 : case SQL_C_TINYINT:
2923 0 : ctype = apdrec->sql_desc_unsigned ? SQL_C_UTINYINT : SQL_C_STINYINT;
2924 : break;
2925 0 : case SQL_C_SHORT:
2926 0 : ctype = apdrec->sql_desc_unsigned ? SQL_C_USHORT : SQL_C_SSHORT;
2927 : break;
2928 2 : case SQL_C_LONG:
2929 2 : ctype = apdrec->sql_desc_unsigned ? SQL_C_ULONG : SQL_C_SLONG;
2930 : break;
2931 : default:
2932 : break;
2933 : }
2934 :
2935 28010 : assigns(buf, bufpos, buflen, sep, stmt);
2936 10004 : *bufp = buf;
2937 :
2938 10004 : if (strlen_or_ind_ptr != NULL && *strlen_or_ind_ptr == SQL_NULL_DATA) {
2939 0 : assigns(buf, bufpos, buflen, "NULL", stmt);
2940 0 : *bufp = buf;
2941 0 : *bufposp = bufpos;
2942 0 : *buflenp = buflen;
2943 0 : return SQL_SUCCESS;
2944 : }
2945 :
2946 10004 : strlen_or_ind_ptr = apdrec->sql_desc_octet_length_ptr;
2947 10004 : if (strlen_or_ind_ptr && offset)
2948 0 : strlen_or_ind_ptr = (SQLLEN *) ((char *) strlen_or_ind_ptr + offset + row * (bind_type == SQL_BIND_BY_COLUMN ? (SQLINTEGER) sizeof(SQLINTEGER) : bind_type));
2949 :
2950 10004 : switch (ctype) {
2951 2000 : case SQL_C_CHAR:
2952 : case SQL_C_BINARY:
2953 2000 : slen = strlen_or_ind_ptr ? *strlen_or_ind_ptr : SQL_NTS;
2954 2000 : sval = (char *) ptr;
2955 2000 : fixODBCstring(sval, slen, SQLLEN, addStmtError, stmt, return SQL_ERROR);
2956 : break;
2957 2 : case SQL_C_WCHAR:
2958 2 : slen = strlen_or_ind_ptr ? *strlen_or_ind_ptr : SQL_NTS;
2959 2 : if (slen > 0)
2960 2 : slen /= 2; /* convert from bytes to characters */
2961 2 : fixWcharIn((SQLWCHAR *) ptr, slen, char, sval, addStmtError, stmt, return SQL_ERROR);
2962 2 : if (sval == NULL) {
2963 0 : sval = strdup("");
2964 0 : if (sval == NULL) {
2965 0 : addStmtError(stmt, "HY001", NULL, 0);
2966 0 : return SQL_ERROR;
2967 : }
2968 : }
2969 2 : slen = strlen(sval);
2970 2 : break;
2971 0 : case SQL_C_BIT:
2972 0 : nval.precision = 1;
2973 0 : nval.scale = 0;
2974 0 : nval.sign = 1;
2975 0 : nval.val = * (SQLCHAR *) ptr != 0;
2976 0 : break;
2977 0 : case SQL_C_STINYINT:
2978 0 : nval.precision = 1;
2979 0 : nval.scale = 0;
2980 0 : if (* (SQLSCHAR *) ptr < 0) {
2981 0 : nval.sign = 0;
2982 0 : nval.val = - * (SQLSCHAR *) ptr;
2983 : } else {
2984 0 : nval.sign = 1;
2985 0 : nval.val = * (SQLSCHAR *) ptr;
2986 : }
2987 : break;
2988 0 : case SQL_C_UTINYINT:
2989 0 : nval.precision = 1;
2990 0 : nval.scale = 0;
2991 0 : nval.sign = 1;
2992 0 : nval.val = * (SQLCHAR *) ptr;
2993 0 : break;
2994 2000 : case SQL_C_SSHORT:
2995 2000 : nval.precision = 1;
2996 2000 : nval.scale = 0;
2997 2000 : if (* (SQLSMALLINT *) ptr < 0) {
2998 0 : nval.sign = 0;
2999 0 : nval.val = - * (SQLSMALLINT *) ptr;
3000 : } else {
3001 2000 : nval.sign = 1;
3002 2000 : nval.val = * (SQLSMALLINT *) ptr;
3003 : }
3004 : break;
3005 0 : case SQL_C_USHORT:
3006 0 : nval.precision = 1;
3007 0 : nval.scale = 0;
3008 0 : nval.sign = 1;
3009 0 : nval.val = * (SQLUSMALLINT *) ptr;
3010 0 : break;
3011 2 : case SQL_C_SLONG:
3012 2 : nval.precision = 1;
3013 2 : nval.scale = 0;
3014 2 : if (* (SQLINTEGER *) ptr < 0) {
3015 0 : nval.sign = 0;
3016 0 : nval.val = - * (SQLINTEGER *) ptr;
3017 : } else {
3018 2 : nval.sign = 1;
3019 2 : nval.val = * (SQLINTEGER *) ptr;
3020 : }
3021 : break;
3022 0 : case SQL_C_ULONG:
3023 0 : nval.precision = 1;
3024 0 : nval.scale = 0;
3025 0 : nval.sign = 1;
3026 0 : nval.val = * (SQLUINTEGER *) ptr;
3027 0 : break;
3028 0 : case SQL_C_SBIGINT:
3029 0 : nval.precision = 1;
3030 0 : nval.scale = 0;
3031 0 : if (* (SQLBIGINT *) ptr < 0) {
3032 0 : nval.sign = 0;
3033 0 : nval.val = - * (SQLBIGINT *) ptr;
3034 : } else {
3035 0 : nval.sign = 1;
3036 0 : nval.val = * (SQLBIGINT *) ptr;
3037 : }
3038 : break;
3039 0 : case SQL_C_UBIGINT:
3040 0 : nval.precision = 1;
3041 0 : nval.scale = 0;
3042 0 : nval.sign = 1;
3043 0 : nval.val = * (SQLUBIGINT *) ptr;
3044 0 : break;
3045 0 : case SQL_C_NUMERIC:
3046 0 : nval.precision = (uint8_t) apdrec->sql_desc_precision;
3047 0 : nval.scale = (int8_t) apdrec->sql_desc_scale;
3048 0 : nval.sign = ((SQL_NUMERIC_STRUCT *) ptr)->sign;
3049 0 : nval.val = 0;
3050 0 : for (i = 0; i < SQL_MAX_NUMERIC_LEN; i++)
3051 0 : nval.val |= (uint64_t) ((SQL_NUMERIC_STRUCT *) ptr)->val[i] << (i * 8);
3052 : break;
3053 0 : case SQL_C_FLOAT:
3054 0 : fval = * (SQLREAL *) ptr;
3055 0 : break;
3056 2000 : case SQL_C_DOUBLE:
3057 2000 : fval = * (SQLDOUBLE *) ptr;
3058 2000 : break;
3059 2000 : case SQL_C_TYPE_DATE:
3060 2000 : dval = * (SQL_DATE_STRUCT *) ptr;
3061 2000 : break;
3062 2000 : case SQL_C_TYPE_TIME:
3063 2000 : tval = * (SQL_TIME_STRUCT *) ptr;
3064 2000 : break;
3065 0 : case SQL_C_TYPE_TIMESTAMP:
3066 0 : tsval = * (SQL_TIMESTAMP_STRUCT *) ptr;
3067 0 : break;
3068 0 : case SQL_C_INTERVAL_YEAR:
3069 0 : ival.interval_type = SQL_IS_YEAR;
3070 0 : ival.interval_sign = ((SQL_INTERVAL_STRUCT *) ptr)->interval_sign;
3071 0 : ival.intval.year_month.year = ((SQL_INTERVAL_STRUCT *) ptr)->intval.year_month.year;
3072 0 : ival.intval.year_month.month = 0;
3073 0 : break;
3074 0 : case SQL_C_INTERVAL_MONTH:
3075 0 : ival.interval_type = SQL_IS_MONTH;
3076 0 : ival.interval_sign = ((SQL_INTERVAL_STRUCT *) ptr)->interval_sign;
3077 0 : ival.intval.year_month.year = 0;
3078 0 : ival.intval.year_month.month = ((SQL_INTERVAL_STRUCT *) ptr)->intval.year_month.month;
3079 0 : break;
3080 0 : case SQL_C_INTERVAL_YEAR_TO_MONTH:
3081 0 : ival.interval_type = SQL_IS_YEAR_TO_MONTH;
3082 0 : ival.interval_sign = ((SQL_INTERVAL_STRUCT *) ptr)->interval_sign;
3083 0 : ival.intval.year_month.year = ((SQL_INTERVAL_STRUCT *) ptr)->intval.year_month.year;
3084 0 : ival.intval.year_month.month = ((SQL_INTERVAL_STRUCT *) ptr)->intval.year_month.month;
3085 0 : break;
3086 0 : case SQL_C_INTERVAL_DAY:
3087 0 : ival.interval_type = SQL_IS_DAY;
3088 0 : ival.interval_sign = ((SQL_INTERVAL_STRUCT *) ptr)->interval_sign;
3089 0 : ival.intval.day_second.day = ((SQL_INTERVAL_STRUCT *) ptr)->intval.day_second.day;
3090 0 : ival.intval.day_second.hour = 0;
3091 0 : ival.intval.day_second.minute = 0;
3092 0 : ival.intval.day_second.second = 0;
3093 0 : ival.intval.day_second.fraction = 0;
3094 0 : break;
3095 0 : case SQL_C_INTERVAL_HOUR:
3096 0 : ival.interval_type = SQL_IS_HOUR;
3097 0 : ival.interval_sign = ((SQL_INTERVAL_STRUCT *) ptr)->interval_sign;
3098 0 : ival.intval.day_second.day = 0;
3099 0 : ival.intval.day_second.hour = ((SQL_INTERVAL_STRUCT *) ptr)->intval.day_second.hour;
3100 0 : ival.intval.day_second.minute = 0;
3101 0 : ival.intval.day_second.second = 0;
3102 0 : ival.intval.day_second.fraction = 0;
3103 0 : break;
3104 0 : case SQL_C_INTERVAL_MINUTE:
3105 0 : ival.interval_type = SQL_IS_MINUTE;
3106 0 : ival.interval_sign = ((SQL_INTERVAL_STRUCT *) ptr)->interval_sign;
3107 0 : ival.intval.day_second.day = 0;
3108 0 : ival.intval.day_second.hour = 0;
3109 0 : ival.intval.day_second.minute = ((SQL_INTERVAL_STRUCT *) ptr)->intval.day_second.minute;
3110 0 : ival.intval.day_second.second = 0;
3111 0 : ival.intval.day_second.fraction = 0;
3112 0 : break;
3113 0 : case SQL_C_INTERVAL_SECOND:
3114 0 : ival.interval_type = SQL_IS_SECOND;
3115 0 : ival.interval_sign = ((SQL_INTERVAL_STRUCT *) ptr)->interval_sign;
3116 0 : ival.intval.day_second.day = 0;
3117 0 : ival.intval.day_second.hour = 0;
3118 0 : ival.intval.day_second.minute = 0;
3119 0 : ival.intval.day_second.second = ((SQL_INTERVAL_STRUCT *) ptr)->intval.day_second.second;
3120 0 : ival.intval.day_second.fraction = ((SQL_INTERVAL_STRUCT *) ptr)->intval.day_second.fraction;
3121 0 : ivalprec = apdrec->sql_desc_precision;
3122 0 : break;
3123 0 : case SQL_C_INTERVAL_DAY_TO_HOUR:
3124 0 : ival.interval_type = SQL_IS_DAY_TO_HOUR;
3125 0 : ival.interval_sign = ((SQL_INTERVAL_STRUCT *) ptr)->interval_sign;
3126 0 : ival.intval.day_second.day = ((SQL_INTERVAL_STRUCT *) ptr)->intval.day_second.day;
3127 0 : ival.intval.day_second.hour = ((SQL_INTERVAL_STRUCT *) ptr)->intval.day_second.hour;
3128 0 : ival.intval.day_second.minute = 0;
3129 0 : ival.intval.day_second.second = 0;
3130 0 : ival.intval.day_second.fraction = 0;
3131 0 : break;
3132 0 : case SQL_C_INTERVAL_DAY_TO_MINUTE:
3133 0 : ival.interval_type = SQL_IS_DAY_TO_MINUTE;
3134 0 : ival.interval_sign = ((SQL_INTERVAL_STRUCT *) ptr)->interval_sign;
3135 0 : ival.intval.day_second.day = ((SQL_INTERVAL_STRUCT *) ptr)->intval.day_second.day;
3136 0 : ival.intval.day_second.hour = ((SQL_INTERVAL_STRUCT *) ptr)->intval.day_second.hour;
3137 0 : ival.intval.day_second.minute = ((SQL_INTERVAL_STRUCT *) ptr)->intval.day_second.minute;
3138 0 : ival.intval.day_second.second = 0;
3139 0 : ival.intval.day_second.fraction = 0;
3140 0 : break;
3141 0 : case SQL_C_INTERVAL_DAY_TO_SECOND:
3142 0 : ival.interval_type = SQL_IS_DAY_TO_SECOND;
3143 0 : ival.interval_sign = ((SQL_INTERVAL_STRUCT *) ptr)->interval_sign;
3144 0 : ival.intval.day_second.day = ((SQL_INTERVAL_STRUCT *) ptr)->intval.day_second.day;
3145 0 : ival.intval.day_second.hour = ((SQL_INTERVAL_STRUCT *) ptr)->intval.day_second.hour;
3146 0 : ival.intval.day_second.minute = ((SQL_INTERVAL_STRUCT *) ptr)->intval.day_second.minute;
3147 0 : ival.intval.day_second.second = ((SQL_INTERVAL_STRUCT *) ptr)->intval.day_second.second;
3148 0 : ival.intval.day_second.fraction = ((SQL_INTERVAL_STRUCT *) ptr)->intval.day_second.fraction;
3149 0 : ivalprec = apdrec->sql_desc_precision;
3150 0 : break;
3151 0 : case SQL_C_INTERVAL_HOUR_TO_MINUTE:
3152 0 : ival.interval_type = SQL_IS_HOUR_TO_MINUTE;
3153 0 : ival.interval_sign = ((SQL_INTERVAL_STRUCT *) ptr)->interval_sign;
3154 0 : ival.intval.day_second.day = 0;
3155 0 : ival.intval.day_second.hour = ((SQL_INTERVAL_STRUCT *) ptr)->intval.day_second.hour;
3156 0 : ival.intval.day_second.minute = ((SQL_INTERVAL_STRUCT *) ptr)->intval.day_second.minute;
3157 0 : ival.intval.day_second.second = 0;
3158 0 : ival.intval.day_second.fraction = 0;
3159 0 : break;
3160 0 : case SQL_C_INTERVAL_HOUR_TO_SECOND:
3161 0 : ival.interval_type = SQL_IS_HOUR_TO_SECOND;
3162 0 : ival.interval_sign = ((SQL_INTERVAL_STRUCT *) ptr)->interval_sign;
3163 0 : ival.intval.day_second.day = 0;
3164 0 : ival.intval.day_second.hour = ((SQL_INTERVAL_STRUCT *) ptr)->intval.day_second.hour;
3165 0 : ival.intval.day_second.minute = ((SQL_INTERVAL_STRUCT *) ptr)->intval.day_second.minute;
3166 0 : ival.intval.day_second.second = ((SQL_INTERVAL_STRUCT *) ptr)->intval.day_second.second;
3167 0 : ival.intval.day_second.fraction = ((SQL_INTERVAL_STRUCT *) ptr)->intval.day_second.fraction;
3168 0 : ivalprec = apdrec->sql_desc_precision;
3169 0 : break;
3170 0 : case SQL_C_INTERVAL_MINUTE_TO_SECOND:
3171 0 : ival.interval_type = SQL_IS_MINUTE_TO_SECOND;
3172 0 : ival.interval_sign = ((SQL_INTERVAL_STRUCT *) ptr)->interval_sign;
3173 0 : ival.intval.day_second.day = 0;
3174 0 : ival.intval.day_second.hour = 0;
3175 0 : ival.intval.day_second.minute = ((SQL_INTERVAL_STRUCT *) ptr)->intval.day_second.minute;
3176 0 : ival.intval.day_second.second = ((SQL_INTERVAL_STRUCT *) ptr)->intval.day_second.second;
3177 0 : ival.intval.day_second.fraction = ((SQL_INTERVAL_STRUCT *) ptr)->intval.day_second.fraction;
3178 0 : ivalprec = apdrec->sql_desc_precision;
3179 0 : break;
3180 : case SQL_C_GUID:
3181 : break;
3182 : }
3183 :
3184 : /* just the types supported by the server */
3185 10004 : switch (sqltype) {
3186 2002 : case SQL_CHAR:
3187 : case SQL_VARCHAR:
3188 : case SQL_LONGVARCHAR:
3189 : case SQL_WCHAR:
3190 : case SQL_WVARCHAR:
3191 : case SQL_WLONGVARCHAR:
3192 2002 : assign(buf, bufpos, buflen, 'r', stmt); /* RAW string */
3193 2002 : assign(buf, bufpos, buflen, '\'', stmt);
3194 2002 : switch (ctype) {
3195 : case SQL_C_CHAR:
3196 : case SQL_C_WCHAR:
3197 : case SQL_C_BINARY:
3198 32901 : for (i = 0; i < slen; i++) {
3199 30899 : unsigned char c = (unsigned char) sval[i];
3200 :
3201 30899 : if (c == 0)
3202 : break;
3203 30899 : if (c == '\'')
3204 0 : assign(buf, bufpos, buflen, '\'', stmt);
3205 30899 : assign(buf, bufpos, buflen, c, stmt);
3206 : }
3207 : break;
3208 0 : case SQL_C_BIT:
3209 0 : if (nval.val)
3210 0 : assigns(buf, bufpos, buflen, "true", stmt);
3211 : else
3212 0 : assigns(buf, bufpos, buflen, "false", stmt);
3213 : break;
3214 : case SQL_C_STINYINT:
3215 : case SQL_C_UTINYINT:
3216 : case SQL_C_SSHORT:
3217 : case SQL_C_USHORT:
3218 : case SQL_C_SLONG:
3219 : case SQL_C_ULONG:
3220 : case SQL_C_SBIGINT:
3221 : case SQL_C_UBIGINT:
3222 : case SQL_C_NUMERIC: {
3223 : int f, n;
3224 :
3225 0 : for (n = 0, f = 1; n < nval.scale; n++)
3226 0 : f *= 10;
3227 0 : snprintf(data, sizeof(data), "%s%" PRIu64, nval.sign ? "" : "-", (uint64_t) (nval.val / f));
3228 0 : assigns(buf, bufpos, buflen, data, stmt);
3229 0 : if (nval.scale > 0) {
3230 0 : snprintf(data, sizeof(data), ".%0*" PRIu64, nval.scale, (uint64_t) (nval.val % f));
3231 0 : assigns(buf, bufpos, buflen, data, stmt);
3232 : }
3233 : break;
3234 : }
3235 : case SQL_C_FLOAT:
3236 : case SQL_C_DOUBLE: {
3237 0 : for (i = 0; i < 18; i++) {
3238 0 : snprintf(data, sizeof(data), "%.*g", i, fval);
3239 0 : if (fval == strtod(data, NULL))
3240 : break;
3241 : }
3242 0 : assigns(buf, bufpos, buflen, data, stmt);
3243 : break;
3244 : }
3245 0 : case SQL_C_TYPE_DATE:
3246 0 : snprintf(data, sizeof(data), "%04d-%02u-%02u",
3247 0 : (int) dval.year,
3248 0 : (unsigned int) dval.month,
3249 0 : (unsigned int) dval.day);
3250 0 : assigns(buf, bufpos, buflen, data, stmt);
3251 : break;
3252 0 : case SQL_C_TYPE_TIME:
3253 0 : snprintf(data, sizeof(data), "%02u:%02u:%02u",
3254 0 : (unsigned int) tval.hour,
3255 0 : (unsigned int) tval.minute,
3256 0 : (unsigned int) tval.second);
3257 0 : assigns(buf, bufpos, buflen, data, stmt);
3258 : break;
3259 0 : case SQL_C_TYPE_TIMESTAMP:
3260 0 : snprintf(data, sizeof(data),
3261 : "%04d-%02u-%02u %02u:%02u:%02u",
3262 0 : (int) tsval.year,
3263 0 : (unsigned int) tsval.month,
3264 0 : (unsigned int) tsval.day,
3265 0 : (unsigned int) tsval.hour,
3266 0 : (unsigned int) tsval.minute,
3267 0 : (unsigned int) tsval.second);
3268 0 : assigns(buf, bufpos, buflen, data, stmt);
3269 0 : if (tsval.fraction) {
3270 0 : snprintf(data, sizeof(data), ".%09u", (unsigned int) tsval.fraction);
3271 : /* remove trailing zeros */
3272 0 : for (i = 9; i > 0 && data[i] == '0'; i--)
3273 0 : data[i] = 0;
3274 0 : assigns(buf, bufpos, buflen, data, stmt);
3275 : }
3276 : break;
3277 0 : case SQL_C_INTERVAL_YEAR:
3278 0 : snprintf(data, sizeof(data), "%s%0*u", ival.interval_sign ? "-" : "", (int) apdrec->sql_desc_datetime_interval_precision, (unsigned int) ival.intval.year_month.year);
3279 0 : assigns(buf, bufpos, buflen, data, stmt);
3280 : break;
3281 0 : case SQL_C_INTERVAL_MONTH:
3282 0 : snprintf(data, sizeof(data), "%s%0*u", ival.interval_sign ? "-" : "", (int) apdrec->sql_desc_datetime_interval_precision, (unsigned int) ival.intval.year_month.month);
3283 0 : assigns(buf, bufpos, buflen, data, stmt);
3284 : break;
3285 0 : case SQL_C_INTERVAL_YEAR_TO_MONTH:
3286 0 : snprintf(data, sizeof(data), "%s%0*u-%02u", ival.interval_sign ? "-" : "", (int) apdrec->sql_desc_datetime_interval_precision, (unsigned int) ival.intval.year_month.year, (unsigned int) ival.intval.year_month.month);
3287 0 : assigns(buf, bufpos, buflen, data, stmt);
3288 : break;
3289 0 : case SQL_C_INTERVAL_DAY:
3290 0 : snprintf(data, sizeof(data), "%s%0*u", ival.interval_sign ? "-" : "", (int) apdrec->sql_desc_datetime_interval_precision, (unsigned int) ival.intval.day_second.day);
3291 0 : assigns(buf, bufpos, buflen, data, stmt);
3292 : break;
3293 0 : case SQL_C_INTERVAL_HOUR:
3294 0 : snprintf(data, sizeof(data), "%s%0*u", ival.interval_sign ? "-" : "", (int) apdrec->sql_desc_datetime_interval_precision, (unsigned int) ival.intval.day_second.hour);
3295 0 : assigns(buf, bufpos, buflen, data, stmt);
3296 : break;
3297 0 : case SQL_C_INTERVAL_MINUTE:
3298 0 : snprintf(data, sizeof(data), "%s%0*u", ival.interval_sign ? "-" : "", (int) apdrec->sql_desc_datetime_interval_precision, (unsigned int) ival.intval.day_second.minute);
3299 0 : assigns(buf, bufpos, buflen, data, stmt);
3300 : break;
3301 0 : case SQL_C_INTERVAL_SECOND:
3302 0 : snprintf(data, sizeof(data), "%s%0*u", ival.interval_sign ? "-" : "", (int) apdrec->sql_desc_datetime_interval_precision, (unsigned int) ival.intval.day_second.second);
3303 0 : assigns(buf, bufpos, buflen, data, stmt);
3304 : /* if ivalprec > 16, the digits that are used by
3305 : * the server are all 0, so we don't need to
3306 : * write them */
3307 0 : if (ival.intval.day_second.fraction && ivalprec > 0 && ivalprec < 17) {
3308 0 : snprintf(data, sizeof(data), ".%0*u", ivalprec, (unsigned int) ival.intval.day_second.fraction);
3309 0 : assigns(buf, bufpos, buflen, data, stmt);
3310 : }
3311 : break;
3312 0 : case SQL_C_INTERVAL_DAY_TO_HOUR:
3313 0 : snprintf(data, sizeof(data), "%s%0*u %02u", ival.interval_sign ? "-" : "", (int) apdrec->sql_desc_datetime_interval_precision, (unsigned int) ival.intval.day_second.day, (unsigned int) ival.intval.day_second.hour);
3314 0 : assigns(buf, bufpos, buflen, data, stmt);
3315 : break;
3316 0 : case SQL_C_INTERVAL_DAY_TO_MINUTE:
3317 0 : snprintf(data, sizeof(data), "%s%0*u %02u:%02u", ival.interval_sign ? "-" : "", (int) apdrec->sql_desc_datetime_interval_precision, (unsigned int) ival.intval.day_second.day, (unsigned int) ival.intval.day_second.hour, (unsigned int) ival.intval.day_second.minute);
3318 0 : assigns(buf, bufpos, buflen, data, stmt);
3319 : break;
3320 0 : case SQL_C_INTERVAL_DAY_TO_SECOND:
3321 0 : snprintf(data, sizeof(data), "%s%0*u %02u:%02u:%02u", ival.interval_sign ? "-" : "", (int) apdrec->sql_desc_datetime_interval_precision, (unsigned int) ival.intval.day_second.day, (unsigned int) ival.intval.day_second.hour, (unsigned int) ival.intval.day_second.minute, (unsigned int) ival.intval.day_second.second);
3322 0 : assigns(buf, bufpos, buflen, data, stmt);
3323 0 : if (ival.intval.day_second.fraction && ivalprec > 0 && ivalprec < 17) {
3324 0 : snprintf(data, sizeof(data), ".%0*u", ivalprec, (unsigned int) ival.intval.day_second.fraction);
3325 0 : assigns(buf, bufpos, buflen, data, stmt);
3326 : }
3327 : break;
3328 0 : case SQL_C_INTERVAL_HOUR_TO_MINUTE:
3329 0 : snprintf(data, sizeof(data), "%s%0*u:%02u", ival.interval_sign ? "-" : "", (int) apdrec->sql_desc_datetime_interval_precision, (unsigned int) ival.intval.day_second.hour, (unsigned int) ival.intval.day_second.minute);
3330 0 : assigns(buf, bufpos, buflen, data, stmt);
3331 : break;
3332 0 : case SQL_C_INTERVAL_HOUR_TO_SECOND:
3333 0 : snprintf(data, sizeof(data), "%s%0*u:%02u:%02u", ival.interval_sign ? "-" : "", (int) apdrec->sql_desc_datetime_interval_precision, (unsigned int) ival.intval.day_second.hour, (unsigned int) ival.intval.day_second.minute, (unsigned int) ival.intval.day_second.second);
3334 0 : assigns(buf, bufpos, buflen, data, stmt);
3335 0 : if (ival.intval.day_second.fraction && ivalprec > 0 && ivalprec < 17) {
3336 0 : snprintf(data, sizeof(data), ".%0*u", ivalprec, (unsigned int) ival.intval.day_second.fraction);
3337 0 : assigns(buf, bufpos, buflen, data, stmt);
3338 : }
3339 : break;
3340 0 : case SQL_C_INTERVAL_MINUTE_TO_SECOND:
3341 0 : snprintf(data, sizeof(data), "%s%0*u:%02u", ival.interval_sign ? "-" : "", (int) apdrec->sql_desc_datetime_interval_precision, (unsigned int) ival.intval.day_second.minute, (unsigned int) ival.intval.day_second.second);
3342 0 : assigns(buf, bufpos, buflen, data, stmt);
3343 0 : if (ival.intval.day_second.fraction && ivalprec > 0 && ivalprec < 17) {
3344 0 : snprintf(data, sizeof(data), ".%0*u", ivalprec, (unsigned int) ival.intval.day_second.fraction);
3345 0 : assigns(buf, bufpos, buflen, data, stmt);
3346 : }
3347 : break;
3348 0 : case SQL_C_GUID:
3349 0 : u = *(SQLGUID *)ptr;
3350 0 : snprintf(data, sizeof(data),
3351 : "%08"PRIx32"-%04"PRIx16"-%04"PRIx16
3352 : "-%02"PRIx8"%02"PRIx8
3353 : "-%02"PRIx8"%02"PRIx8"%02"PRIx8
3354 : "%02"PRIx8"%02"PRIx8"%02"PRIx8,
3355 : u.Data1, u.Data2, u.Data3,
3356 : u.Data4[0], u.Data4[1],
3357 : u.Data4[2], u.Data4[3],
3358 : u.Data4[4], u.Data4[5],
3359 : u.Data4[6], u.Data4[7]);
3360 0 : break;
3361 : }
3362 2002 : assign(buf, bufpos, buflen, '\'', stmt);
3363 2002 : break;
3364 0 : case SQL_BINARY:
3365 : case SQL_VARBINARY:
3366 : case SQL_LONGVARBINARY:
3367 0 : switch (ctype) {
3368 : case SQL_C_CHAR:
3369 : case SQL_C_BINARY:
3370 0 : assigns(buf, bufpos, buflen, "blob '", stmt);
3371 0 : for (i = 0; i < slen; i++) {
3372 0 : unsigned char c = (unsigned char) sval[i];
3373 :
3374 0 : assign(buf, bufpos, buflen, "0123456789ABCDEF"[c >> 4], stmt);
3375 0 : assign(buf, bufpos, buflen, "0123456789ABCDEF"[c & 0xF], stmt);
3376 : }
3377 0 : assign(buf, bufpos, buflen, '\'', stmt);
3378 0 : break;
3379 0 : default:
3380 : /* Restricted data type attribute violation */
3381 0 : addStmtError(stmt, "07006", NULL, 0);
3382 0 : goto failure;
3383 : }
3384 0 : break;
3385 2000 : case SQL_TYPE_DATE:
3386 2000 : i = 1;
3387 2000 : switch (ctype) {
3388 0 : case SQL_C_CHAR:
3389 : case SQL_C_WCHAR:
3390 : case SQL_C_BINARY:
3391 0 : i = parsetimestamp(sval, &tsval);
3392 : /* fall through */
3393 : case SQL_C_TYPE_TIMESTAMP:
3394 0 : if (i) {
3395 0 : if (tsval.hour || tsval.minute || tsval.second || tsval.fraction || i == 2) {
3396 : /* Datetime field overflow */
3397 0 : addStmtError(stmt, "22008", NULL, 0);
3398 : }
3399 0 : dval = (DATE_STRUCT) {
3400 0 : .year = tsval.year,
3401 0 : .month = tsval.month,
3402 0 : .day = tsval.day,
3403 : };
3404 0 : } else if (!parsedate(sval, &dval)) {
3405 : /* Invalid character value for cast
3406 : * specification */
3407 0 : addStmtError(stmt, "22018", NULL, 0);
3408 0 : goto failure;
3409 : }
3410 : /* fall through */
3411 : case SQL_C_TYPE_DATE:
3412 2000 : snprintf(data, sizeof(data), "DATE '%u-%02u-%02u'",
3413 2000 : (unsigned int) dval.year,
3414 2000 : (unsigned int) dval.month,
3415 2000 : (unsigned int) dval.day);
3416 38000 : assigns(buf, bufpos, buflen, data, stmt);
3417 : break;
3418 0 : default:
3419 : /* Restricted data type attribute violation */
3420 0 : addStmtError(stmt, "07006", NULL, 0);
3421 0 : goto failure;
3422 : }
3423 : break;
3424 2000 : case SQL_TYPE_TIME:
3425 2000 : i = 1;
3426 2000 : switch (ctype) {
3427 0 : case SQL_C_CHAR:
3428 : case SQL_C_WCHAR:
3429 : case SQL_C_BINARY:
3430 0 : i = parsetimestamp(sval, &tsval);
3431 : /* fall through */
3432 : case SQL_C_TYPE_TIMESTAMP:
3433 0 : if (i) {
3434 0 : if (tsval.fraction || i == 2) {
3435 : /* Datetime field overflow */
3436 0 : addStmtError(stmt, "22008", NULL, 0);
3437 : }
3438 0 : tval = (TIME_STRUCT) {
3439 0 : .hour = tsval.hour,
3440 0 : .minute = tsval.minute,
3441 0 : .second = tsval.second,
3442 : };
3443 0 : } else if (!parsetime(sval, &tval)) {
3444 : /* Invalid character value for cast
3445 : * specification */
3446 0 : addStmtError(stmt, "22018", NULL, 0);
3447 0 : goto failure;
3448 : }
3449 : /* fall through */
3450 : case SQL_C_TYPE_TIME:
3451 2000 : snprintf(data, sizeof(data), "TIME '%u:%02u:%02u'",
3452 2000 : (unsigned int) tval.hour,
3453 2000 : (unsigned int) tval.minute,
3454 2000 : (unsigned int) tval.second);
3455 32000 : assigns(buf, bufpos, buflen, data, stmt);
3456 : break;
3457 0 : default:
3458 : /* Restricted data type attribute violation */
3459 0 : addStmtError(stmt, "07006", NULL, 0);
3460 0 : goto failure;
3461 : }
3462 : break;
3463 0 : case SQL_TYPE_TIMESTAMP:
3464 0 : switch (ctype) {
3465 0 : case SQL_C_CHAR:
3466 : case SQL_C_WCHAR:
3467 : case SQL_C_BINARY:
3468 0 : i = parsetimestamp(sval, &tsval);
3469 0 : if (i == 0) {
3470 0 : i = parsetime(sval, &tval);
3471 0 : if (i) {
3472 0 : struct tm tm;
3473 0 : time_t t;
3474 :
3475 : case SQL_C_TYPE_TIME:
3476 0 : (void) time(&t);
3477 0 : tm = (struct tm) {0};
3478 : #ifdef HAVE_LOCALTIME_R
3479 0 : (void) localtime_r(&t, &tm);
3480 : #else
3481 : tm = *localtime(&t);
3482 : #endif
3483 0 : tsval = (TIMESTAMP_STRUCT) {
3484 0 : .year = tm.tm_year + 1900,
3485 0 : .month = tm.tm_mon + 1,
3486 0 : .day = tm.tm_mday,
3487 0 : .hour = tval.hour,
3488 0 : .minute = tval.minute,
3489 0 : .second = tval.second,
3490 : .fraction = 0,
3491 : };
3492 : } else {
3493 0 : i = parsedate(sval, &dval);
3494 0 : if (i) {
3495 : case SQL_TYPE_DATE:
3496 0 : tsval = (TIMESTAMP_STRUCT) {
3497 0 : .year = dval.year,
3498 0 : .month = dval.month,
3499 0 : .day = dval.day,
3500 : .hour = 0,
3501 : .minute = 0,
3502 : .second = 0,
3503 : .fraction = 0,
3504 : };
3505 : } else {
3506 : /* Invalid character
3507 : * value for cast
3508 : * specification */
3509 0 : addStmtError(stmt, "22018", NULL, 0);
3510 0 : goto failure;
3511 : }
3512 : }
3513 : }
3514 : /* fall through */
3515 : case SQL_C_TYPE_TIMESTAMP:
3516 0 : snprintf(data, sizeof(data),
3517 : "TIMESTAMP '%u-%02u-%02u %02u:%02u:%02u",
3518 0 : (unsigned int) tsval.year,
3519 0 : (unsigned int) tsval.month,
3520 0 : (unsigned int) tsval.day,
3521 0 : (unsigned int) tsval.hour,
3522 0 : (unsigned int) tsval.minute,
3523 0 : (unsigned int) tsval.second);
3524 0 : assigns(buf, bufpos, buflen, data, stmt);
3525 0 : if (tsval.fraction) {
3526 0 : snprintf(data, sizeof(data), ".%09u", (unsigned int) tsval.fraction);
3527 0 : assigns(buf, bufpos, buflen, data, stmt);
3528 : }
3529 0 : assign(buf, bufpos, buflen, '\'', stmt);
3530 0 : break;
3531 0 : default:
3532 : /* Restricted data type attribute violation */
3533 0 : addStmtError(stmt, "07006", NULL, 0);
3534 0 : goto failure;
3535 : }
3536 0 : break;
3537 0 : case SQL_INTERVAL_MONTH:
3538 : case SQL_INTERVAL_YEAR:
3539 : case SQL_INTERVAL_YEAR_TO_MONTH:
3540 0 : switch (ctype) {
3541 0 : case SQL_C_CHAR:
3542 : case SQL_C_WCHAR:
3543 : case SQL_C_BINARY:
3544 0 : if (parsemonthintervalstring(&sval, &slen, &ival) == SQL_ERROR) {
3545 : /* Invalid character value for cast
3546 : * specification */
3547 0 : addStmtError(stmt, "22018", NULL, 0);
3548 0 : goto failure;
3549 : }
3550 : break;
3551 0 : case SQL_C_BIT:
3552 : case SQL_C_STINYINT:
3553 : case SQL_C_UTINYINT:
3554 : case SQL_C_TINYINT:
3555 : case SQL_C_SSHORT:
3556 : case SQL_C_USHORT:
3557 : case SQL_C_SHORT:
3558 : case SQL_C_SLONG:
3559 : case SQL_C_ULONG:
3560 : case SQL_C_LONG:
3561 : case SQL_C_SBIGINT:
3562 : case SQL_C_UBIGINT:
3563 : case SQL_C_NUMERIC:
3564 0 : parsemonthinterval(&nval, &ival, sqltype);
3565 0 : break;
3566 : case SQL_C_INTERVAL_YEAR:
3567 : case SQL_C_INTERVAL_MONTH:
3568 : case SQL_C_INTERVAL_YEAR_TO_MONTH:
3569 : break;
3570 0 : default:
3571 : /* Restricted data type attribute violation */
3572 0 : addStmtError(stmt, "07006", NULL, 0);
3573 0 : goto failure;
3574 : }
3575 0 : switch (ival.interval_type) {
3576 0 : case SQL_IS_YEAR:
3577 0 : snprintf(data, sizeof(data), "INTERVAL %s'%u' YEAR", ival.interval_sign ? "" : "- ", (unsigned int) ival.intval.year_month.year);
3578 0 : break;
3579 0 : case SQL_IS_MONTH:
3580 0 : snprintf(data, sizeof(data), "INTERVAL %s'%u' MONTH", ival.interval_sign ? "" : "- ", (unsigned int) ival.intval.year_month.month);
3581 0 : break;
3582 0 : case SQL_IS_YEAR_TO_MONTH:
3583 0 : snprintf(data, sizeof(data), "INTERVAL %s'%u-%u' YEAR TO MONTH", ival.interval_sign ? "" : "- ", (unsigned int) ival.intval.year_month.year, (unsigned int) ival.intval.year_month.month);
3584 0 : break;
3585 : default:
3586 : /* cannot happen */
3587 : break;
3588 : }
3589 0 : assigns(buf, bufpos, buflen, data, stmt);
3590 : break;
3591 0 : case SQL_INTERVAL_DAY:
3592 : case SQL_INTERVAL_HOUR:
3593 : case SQL_INTERVAL_MINUTE:
3594 : case SQL_INTERVAL_SECOND:
3595 : case SQL_INTERVAL_DAY_TO_HOUR:
3596 : case SQL_INTERVAL_DAY_TO_MINUTE:
3597 : case SQL_INTERVAL_DAY_TO_SECOND:
3598 : case SQL_INTERVAL_HOUR_TO_MINUTE:
3599 : case SQL_INTERVAL_HOUR_TO_SECOND:
3600 : case SQL_INTERVAL_MINUTE_TO_SECOND:
3601 0 : switch (ctype) {
3602 0 : case SQL_C_CHAR:
3603 : case SQL_C_WCHAR:
3604 : case SQL_C_BINARY:
3605 0 : if (parsesecondintervalstring(&sval, &slen, &ival, &ivalprec) == SQL_ERROR) {
3606 : /* Invalid character value for cast
3607 : * specification */
3608 0 : addStmtError(stmt, "22018", NULL, 0);
3609 0 : goto failure;
3610 : }
3611 : break;
3612 0 : case SQL_C_BIT:
3613 : case SQL_C_STINYINT:
3614 : case SQL_C_UTINYINT:
3615 : case SQL_C_TINYINT:
3616 : case SQL_C_SSHORT:
3617 : case SQL_C_USHORT:
3618 : case SQL_C_SHORT:
3619 : case SQL_C_SLONG:
3620 : case SQL_C_ULONG:
3621 : case SQL_C_LONG:
3622 : case SQL_C_SBIGINT:
3623 : case SQL_C_UBIGINT:
3624 : case SQL_C_NUMERIC:
3625 0 : parsesecondinterval(&nval, &ival, sqltype);
3626 0 : break;
3627 : case SQL_C_INTERVAL_DAY:
3628 : case SQL_C_INTERVAL_HOUR:
3629 : case SQL_C_INTERVAL_MINUTE:
3630 : case SQL_C_INTERVAL_SECOND:
3631 : case SQL_C_INTERVAL_DAY_TO_HOUR:
3632 : case SQL_C_INTERVAL_DAY_TO_MINUTE:
3633 : case SQL_C_INTERVAL_DAY_TO_SECOND:
3634 : case SQL_C_INTERVAL_HOUR_TO_MINUTE:
3635 : case SQL_C_INTERVAL_HOUR_TO_SECOND:
3636 : case SQL_C_INTERVAL_MINUTE_TO_SECOND:
3637 : break;
3638 0 : default:
3639 : /* Restricted data type attribute violation */
3640 0 : addStmtError(stmt, "07006", NULL, 0);
3641 0 : goto failure;
3642 : }
3643 0 : snprintf(data, sizeof(data), "INTERVAL %s'%u %u:%u:%u", ival.interval_sign ? "" : "- ", (unsigned int) ival.intval.day_second.day, (unsigned int) ival.intval.day_second.hour, (unsigned int) ival.intval.day_second.minute, (unsigned int) ival.intval.day_second.second);
3644 0 : assigns(buf, bufpos, buflen, data, stmt);
3645 0 : assigns(buf, bufpos, buflen, "' DAY TO SECOND", stmt);
3646 : break;
3647 2002 : case SQL_DECIMAL:
3648 : case SQL_NUMERIC:
3649 : case SQL_SMALLINT:
3650 : case SQL_INTEGER:
3651 : case SQL_BIGINT:
3652 : case SQL_HUGEINT:
3653 : case SQL_BIT:
3654 : /* first convert to nval (if not already done) */
3655 2002 : switch (ctype) {
3656 : case SQL_C_FLOAT:
3657 : case SQL_C_DOUBLE:
3658 0 : for (i = 0; i < 18; i++) {
3659 0 : snprintf(data, sizeof(data), "%.*g", i, fval);
3660 0 : if (fval == strtod(data, NULL))
3661 : break;
3662 : }
3663 0 : sval = data;
3664 : /* fall through */
3665 0 : case SQL_C_CHAR:
3666 : case SQL_C_WCHAR:
3667 : case SQL_C_BINARY:
3668 : /* parse character data, reparse floating
3669 : * point number */
3670 0 : if (!parseint(sval, &nval)) {
3671 : /* Invalid character value for cast
3672 : * specification */
3673 0 : addStmtError(stmt, "22018", NULL, 0);
3674 0 : goto failure;
3675 : }
3676 : /* fall through */
3677 : case SQL_C_BIT:
3678 : case SQL_C_STINYINT:
3679 : case SQL_C_UTINYINT:
3680 : case SQL_C_TINYINT:
3681 : case SQL_C_SSHORT:
3682 : case SQL_C_USHORT:
3683 : case SQL_C_SHORT:
3684 : case SQL_C_SLONG:
3685 : case SQL_C_ULONG:
3686 : case SQL_C_LONG:
3687 : case SQL_C_SBIGINT:
3688 : case SQL_C_UBIGINT:
3689 : case SQL_C_NUMERIC:
3690 : break;
3691 0 : case SQL_C_INTERVAL_YEAR:
3692 0 : nval.precision = 0;
3693 0 : nval.scale = 0;
3694 0 : nval.sign = !ival.interval_sign;
3695 0 : nval.val = ival.intval.year_month.year;
3696 0 : break;
3697 0 : case SQL_C_INTERVAL_MONTH:
3698 0 : nval.precision = 0;
3699 0 : nval.scale = 0;
3700 0 : nval.sign = !ival.interval_sign;
3701 0 : nval.val = 12 * ival.intval.year_month.year + ival.intval.year_month.month;
3702 0 : break;
3703 0 : case SQL_C_INTERVAL_DAY:
3704 0 : nval.precision = 0;
3705 0 : nval.scale = 0;
3706 0 : nval.sign = !ival.interval_sign;
3707 0 : nval.val = ival.intval.day_second.day;
3708 0 : break;
3709 0 : case SQL_C_INTERVAL_HOUR:
3710 0 : nval.precision = 0;
3711 0 : nval.scale = 0;
3712 0 : nval.sign = !ival.interval_sign;
3713 0 : nval.val = 24 * ival.intval.day_second.day + ival.intval.day_second.hour;
3714 0 : break;
3715 0 : case SQL_C_INTERVAL_MINUTE:
3716 0 : nval.precision = 0;
3717 0 : nval.scale = 0;
3718 0 : nval.sign = !ival.interval_sign;
3719 0 : nval.val = 60 * (24 * ival.intval.day_second.day + ival.intval.day_second.hour) + ival.intval.day_second.minute;
3720 0 : break;
3721 0 : case SQL_C_INTERVAL_SECOND:
3722 0 : nval.precision = 0;
3723 0 : nval.scale = 0;
3724 0 : nval.sign = !ival.interval_sign;
3725 0 : nval.val = 60 * (60 * (24 * ival.intval.day_second.day + ival.intval.day_second.hour) + ival.intval.day_second.minute) + ival.intval.day_second.second;
3726 0 : if (ival.intval.day_second.fraction && ivalprec > 0) {
3727 0 : for (i = 0; i < ivalprec; i++) {
3728 0 : nval.val *= 10;
3729 0 : nval.scale++;
3730 : }
3731 0 : nval.val += ival.intval.day_second.fraction;
3732 : }
3733 : break;
3734 0 : default:
3735 : /* Restricted data type attribute violation */
3736 0 : addStmtError(stmt, "07006", NULL, 0);
3737 0 : goto failure;
3738 : }
3739 : /* now store value contained in nval */
3740 : {
3741 2002 : int f = 1;
3742 :
3743 2002 : for (i = 0; i < nval.scale; i++)
3744 0 : f *= 10;
3745 2002 : if (sqltype == SQL_BIT) {
3746 0 : switch (nval.val / f) {
3747 : case 0:
3748 0 : assigns(buf, bufpos, buflen, "false", stmt);
3749 : break;
3750 : case 1:
3751 0 : assigns(buf, bufpos, buflen, "true", stmt);
3752 : break;
3753 0 : default:
3754 : /* Numeric value out of range */
3755 0 : addStmtError(stmt, "22003", NULL, 0);
3756 0 : goto failure;
3757 : }
3758 0 : if (f > 1 && nval.val % f) {
3759 : /* String data, right truncation */
3760 0 : addStmtError(stmt, "22001", NULL, 0);
3761 : }
3762 : } else {
3763 2002 : snprintf(data, sizeof(data), "%s%" PRIu64, nval.sign ? "" : "-", (uint64_t) (nval.val / f));
3764 10896 : assigns(buf, bufpos, buflen, data, stmt);
3765 2002 : if (nval.scale > 0) {
3766 0 : switch (sqltype) {
3767 0 : case SQL_DECIMAL:
3768 : case SQL_NUMERIC:
3769 0 : snprintf(data, sizeof(data), ".%0*" PRIu64, nval.scale, (uint64_t) (nval.val % f));
3770 0 : assigns(buf, bufpos, buflen, data, stmt);
3771 : break;
3772 0 : default:
3773 : /* Fractional truncation */
3774 0 : addStmtError(stmt, "01S07", NULL, 0);
3775 0 : break;
3776 : }
3777 : } else {
3778 2002 : for (i = nval.scale; i < 0; i++)
3779 0 : assign(buf, bufpos, buflen, '0', stmt);
3780 : }
3781 : }
3782 : }
3783 : break;
3784 2000 : case SQL_REAL:
3785 : case SQL_DOUBLE:
3786 : case SQL_FLOAT:
3787 2000 : switch (ctype) {
3788 0 : case SQL_C_CHAR:
3789 : case SQL_C_WCHAR:
3790 : case SQL_C_BINARY:
3791 0 : if (!parsedouble(sval, &fval)) {
3792 : /* Invalid character value for cast specification */
3793 0 : addStmtError(stmt, "22018", NULL, 0);
3794 0 : goto failure;
3795 : }
3796 : break;
3797 0 : case SQL_C_BIT:
3798 : case SQL_C_STINYINT:
3799 : case SQL_C_UTINYINT:
3800 : case SQL_C_TINYINT:
3801 : case SQL_C_SSHORT:
3802 : case SQL_C_USHORT:
3803 : case SQL_C_SHORT:
3804 : case SQL_C_SLONG:
3805 : case SQL_C_ULONG:
3806 : case SQL_C_LONG:
3807 : case SQL_C_SBIGINT:
3808 : case SQL_C_UBIGINT:
3809 : case SQL_C_NUMERIC:
3810 0 : fval = (double) (int64_t) nval.val;
3811 0 : i = 1;
3812 0 : while (nval.scale > 0) {
3813 0 : nval.scale--;
3814 0 : i *= 10;
3815 : }
3816 0 : fval /= (double) i;
3817 0 : i = 1;
3818 0 : while (nval.scale < 0) {
3819 0 : nval.scale++;
3820 0 : i *= 10;
3821 : }
3822 0 : fval *= (double) i;
3823 0 : if (!nval.sign)
3824 0 : fval = -fval;
3825 : break;
3826 : case SQL_C_FLOAT:
3827 : case SQL_C_DOUBLE:
3828 : break;
3829 0 : case SQL_C_INTERVAL_YEAR:
3830 0 : fval = (double) ival.intval.year_month.year;
3831 0 : if (ival.interval_sign)
3832 0 : fval = -fval;
3833 : break;
3834 0 : case SQL_C_INTERVAL_MONTH:
3835 0 : fval = (double) (12 * ival.intval.year_month.year + ival.intval.year_month.month);
3836 0 : if (ival.interval_sign)
3837 0 : fval = -fval;
3838 : break;
3839 0 : case SQL_C_INTERVAL_DAY:
3840 0 : fval = (double) ival.intval.day_second.day;
3841 0 : if (ival.interval_sign)
3842 0 : fval = -fval;
3843 : break;
3844 0 : case SQL_C_INTERVAL_HOUR:
3845 0 : fval = (double) (24 * ival.intval.day_second.day + ival.intval.day_second.hour);
3846 0 : if (ival.interval_sign)
3847 0 : fval = -fval;
3848 : break;
3849 0 : case SQL_C_INTERVAL_MINUTE:
3850 0 : fval = (double) (60 * (24 * ival.intval.day_second.day + ival.intval.day_second.hour) + ival.intval.day_second.minute);
3851 0 : if (ival.interval_sign)
3852 0 : fval = -fval;
3853 : break;
3854 0 : case SQL_C_INTERVAL_SECOND:
3855 0 : fval = (double) (60 * (60 * (24 * ival.intval.day_second.day + ival.intval.day_second.hour) + ival.intval.day_second.minute) + ival.intval.day_second.second);
3856 0 : if (ival.intval.day_second.fraction && ivalprec > 0) {
3857 : int f = 1;
3858 :
3859 0 : for (i = 0; i < ivalprec; i++)
3860 0 : f *= 10;
3861 0 : fval += ival.intval.day_second.fraction / (double) f;
3862 : }
3863 0 : if (ival.interval_sign)
3864 0 : fval = -fval;
3865 : break;
3866 0 : default:
3867 : /* Restricted data type attribute violation */
3868 0 : addStmtError(stmt, "07006", NULL, 0);
3869 0 : goto failure;
3870 : }
3871 6161 : for (i = 1; i < 18; i++) {
3872 6161 : snprintf(data, sizeof(data), "%.*e", i, fval);
3873 6161 : if (fval == strtod(data, NULL))
3874 : break;
3875 : }
3876 22161 : assigns(buf, bufpos, buflen, data, stmt);
3877 : break;
3878 0 : case SQL_GUID:
3879 0 : switch (ctype) {
3880 0 : case SQL_C_CHAR:
3881 : case SQL_C_WCHAR:
3882 0 : if (slen != 36) {
3883 : /* not sure this is the correct error */
3884 : /* Invalid character value for cast
3885 : * specification */
3886 0 : addStmtError(stmt, "22018", NULL, 0);
3887 0 : goto failure;
3888 : }
3889 0 : if (sval[strspn(sval, "0123456789abcdefABCDEF-")] != 0) {
3890 : /* not sure this is the correct error */
3891 : /* Invalid character value for cast
3892 : * specification */
3893 0 : addStmtError(stmt, "22018", NULL, 0);
3894 0 : goto failure;
3895 : }
3896 0 : snprintf(data, sizeof(data), "%.36s", sval);
3897 0 : break;
3898 0 : case SQL_C_GUID:
3899 0 : u = *(SQLGUID *)ptr;
3900 0 : snprintf(data, sizeof(data),
3901 : "UUID '"
3902 : "%08"PRIx32"-%04"PRIx16"-%04"PRIx16
3903 : "-%02"PRIx8"%02"PRIx8
3904 : "-%02"PRIx8"%02"PRIx8"%02"PRIx8
3905 : "%02"PRIx8"%02"PRIx8"%02"PRIx8
3906 : "'",
3907 : u.Data1, u.Data2, u.Data3,
3908 : u.Data4[0], u.Data4[1],
3909 : u.Data4[2], u.Data4[3],
3910 : u.Data4[4], u.Data4[5],
3911 : u.Data4[6], u.Data4[7]);
3912 0 : break;
3913 0 : default:
3914 : /* Restricted data type attribute violation */
3915 0 : addStmtError(stmt, "07006", NULL, 0);
3916 0 : goto failure;
3917 : }
3918 0 : assigns(buf, bufpos, buflen, data, stmt);
3919 : break;
3920 : }
3921 10004 : if (ctype == SQL_C_WCHAR)
3922 2 : free(sval);
3923 10004 : *bufp = buf;
3924 10004 : *bufposp = bufpos;
3925 10004 : *buflenp = buflen;
3926 10004 : return SQL_SUCCESS;
3927 :
3928 0 : failure:
3929 0 : if (ctype == SQL_C_WCHAR)
3930 0 : free(sval);
3931 : return SQL_ERROR;
3932 : }
|