LCOV - code coverage report
Current view: top level - clients/odbc/driver - ODBCConvert.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 221 2146 10.3 %
Date: 2021-10-13 02:24:04 Functions: 6 13 46.2 %

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

Generated by: LCOV version 1.14