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