LCOV - code coverage report
Current view: top level - clients/odbc/driver - ODBCUtil.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 186 878 21.2 %
Date: 2024-11-15 19:37:45 Functions: 14 18 77.8 %

          Line data    Source code
       1             : /*
       2             :  * SPDX-License-Identifier: MPL-2.0
       3             :  *
       4             :  * This Source Code Form is subject to the terms of the Mozilla Public
       5             :  * License, v. 2.0.  If a copy of the MPL was not distributed with this
       6             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       7             :  *
       8             :  * Copyright 2024 MonetDB Foundation;
       9             :  * Copyright August 2008 - 2023 MonetDB B.V.;
      10             :  * Copyright 1997 - July 2008 CWI.
      11             :  */
      12             : 
      13             : /*
      14             :  * This code was created by Peter Harvey (mostly during Christmas 98/99).
      15             :  * This code is LGPL. Please ensure that this message remains in future
      16             :  * distributions and uses of this code (that's about all I get out of it).
      17             :  * - Peter Harvey pharvey@codebydesign.com
      18             :  *
      19             :  * This file has been modified for the MonetDB project.  See the file
      20             :  * Copyright in this directory for more information.
      21             :  */
      22             : 
      23             : /**********************************************
      24             :  * ODBCUtil.c
      25             :  *
      26             :  * Description:
      27             :  * This file contains utility functions for
      28             :  * the ODBC driver implementation.
      29             :  *
      30             :  * Author: Martin van Dinther, Sjoerd Mullender
      31             :  * Date  : 30 aug 2002
      32             :  *
      33             :  **********************************************/
      34             : 
      35             : #include "ODBCUtil.h"
      36             : #include "ODBCDbc.h"
      37             : #include <float.h>
      38             : #include "mutf8.h"
      39             : 
      40             : 
      41             : #ifdef WIN32
      42             : /* Windows seems to need this */
      43             : BOOL WINAPI
      44             : DllMain(HINSTANCE hinstDLL, DWORD reason, LPVOID reserved)
      45             : {
      46             : #ifdef ODBCDEBUG
      47             :         ODBCLOG("DllMain %ld (MonetDB %s)\n", (long) reason, MONETDB_VERSION);
      48             : #endif
      49             :         (void) hinstDLL;
      50             :         (void) reason;
      51             :         (void) reserved;
      52             : 
      53             :         return TRUE;
      54             : }
      55             : #endif
      56             : 
      57             : /*
      58             :  * Utility function to duplicate an ODBC string (with a length
      59             :  * specified, may not be null terminated) to a normal C string (null
      60             :  * terminated).
      61             :  *
      62             :  * Precondition: inStr != NULL
      63             :  * Postcondition: returns a newly allocated null terminated string.
      64             :  */
      65             : char *
      66        1036 : dupODBCstring(const SQLCHAR *inStr, size_t length)
      67             : {
      68        1036 :         char *tmp = (char *) malloc((length + 1) * sizeof(char));
      69             : 
      70        1036 :         if (tmp == NULL)
      71             :                 return NULL;
      72        1036 :         strcpy_len(tmp, (const char *) inStr, length + 1);
      73        1036 :         return tmp;
      74             : }
      75             : 
      76             : /* Convert a SQLWCHAR (UTF-16 encoded string) to UTF-8.  On success,
      77             :    clears the location pointed to by errmsg and returns NULL or a
      78             :    newly allocated buffer.  On error, assigns a string with an error
      79             :    message to the location pointed to by errmsg and returns NULL.
      80             :    The first two arguments describe the input string in the normal
      81             :    ODBC fashion.
      82             : */
      83             : SQLCHAR *
      84          18 : ODBCwchar2utf8(const SQLWCHAR *src, SQLLEN length, const char **errmsg)
      85             : {
      86          18 :         size_t i = 0;
      87          18 :         SQLLEN j = 0;
      88          18 :         uint32_t c;
      89          18 :         SQLCHAR *dest;
      90             : 
      91          18 :         if (errmsg)
      92          18 :                 *errmsg = NULL;
      93          18 :         if (src == NULL || length == SQL_NULL_DATA)
      94             :                 return NULL;
      95          18 :         if (length == SQL_NTS) {
      96             :                 /* a very large (positive) number that fits in SQLLEN */
      97             :                 length = (SQLLEN) (~(SQLULEN)0 >> 1);
      98          10 :         } else if (length < 0) {
      99           0 :                 if (errmsg)
     100           0 :                         *errmsg = "Invalid length parameter";
     101           0 :                 return NULL;
     102             :         }
     103          18 :         if (src[j] == 0xFEFF)
     104           0 :                 j++;
     105         514 :         while (j < length && src[j]) {
     106         496 :                 if (src[j] <= 0x7F) {
     107         491 :                         i += 1;
     108           5 :                 } else if (src[j] <= 0x7FF) {
     109           4 :                         i += 2;
     110           1 :                 } else if (
     111             : #if SIZEOF_SQLWCHAR == 2
     112             :                         (src[j] & 0xFC00) != 0xD800
     113             : #else
     114             :                         src[j] <= 0xFFFF
     115             : #endif
     116             :                         ) {
     117           0 :                         if ((src[j] & 0xF800) == 0xD800) {
     118           0 :                                 if (errmsg)
     119           0 :                                         *errmsg = "Illegal surrogate";
     120           0 :                                 return NULL;
     121             :                         }
     122           0 :                         i += 3;
     123             :                 } else {
     124             : #if SIZEOF_SQLWCHAR == 2
     125             :                         /* (src[j] & 0xFC00) == 0xD800, i.e. high surrogate */
     126           1 :                         if ((src[j+1] & 0xFC00) != 0xDC00) {
     127           0 :                                 if (errmsg)
     128           0 :                                         *errmsg = "Illegal surrogate";
     129           0 :                                 return NULL;
     130             :                         }
     131           1 :                         j++;
     132             : #else
     133             :                         c = src[j+0];
     134             :                         if (c > 0x10FFFF || (c & 0x1FF800) == 0xD800) {
     135             :                                 if (errmsg)
     136             :                                         *errmsg = "Illegal wide character value";
     137             :                                 return NULL;
     138             :                         }
     139             : #endif
     140           1 :                         i += 4;
     141             :                 }
     142         496 :                 j++;
     143             :         }
     144          18 :         length = j;     /* figured out the real length (might not change) */
     145          18 :         dest = malloc((i + 1) * sizeof(SQLCHAR));
     146          18 :         if (dest == NULL)
     147             :                 return NULL;
     148             :         i = 0;
     149             :         j = 0;
     150             :         if (src[j] == 0xFEFF)
     151             :                 j++;
     152         514 :         while (j < length) {
     153         496 :                 if (src[j] <= 0x7F) {
     154         491 :                         dest[i++] = (SQLCHAR) src[j];
     155           5 :                 } else if (src[j] <= 0x7FF) {
     156           4 :                         dest[i++] = 0xC0 | (src[j] >> 6);
     157           4 :                         dest[i++] = 0x80 | (src[j] & 0x3F);
     158           1 :                 } else if (
     159             : #if SIZEOF_SQLWCHAR == 2
     160             :                         (src[j] & 0xFC00) != 0xD800
     161             : #else
     162             :                         src[j] <= 0xFFFF
     163             : #endif
     164             :                         ) {
     165           0 :                         dest[i++] = 0xE0 | (src[j] >> 12);
     166           0 :                         dest[i++] = 0x80 | ((src[j] >> 6) & 0x3F);
     167           0 :                         dest[i++] = 0x80 | (src[j] & 0x3F);
     168             :                 } else {
     169             : #if SIZEOF_SQLWCHAR == 2
     170           1 :                         c = ((src[j+0] & 0x03FF) + 0x40) << 10
     171           1 :                                 | (src[j+1] & 0x03FF);
     172           1 :                         j++;
     173             : #else
     174             :                         c = src[j+0];
     175             : #endif
     176           1 :                         dest[i++] = 0xF0 | (c >> 18);
     177           1 :                         dest[i++] = 0x80 | ((c >> 12) & 0x3F);
     178           1 :                         dest[i++] = 0x80 | ((c >> 6) & 0x3F);
     179           1 :                         dest[i++] = 0x80 | (c & 0x3F);
     180             :                 }
     181         496 :                 j++;
     182             :         }
     183          18 :         dest[i] = 0;
     184          18 :         return dest;
     185             : }
     186             : 
     187             : /* Convert a UTF-8 encoded string to UTF-16 (SQLWCHAR).  On success
     188             :    returns NULL, on error returns a string with an error message.  The
     189             :    first two arguments describe the input, the next three arguments
     190             :    describe the output, both in the normal ODBC fashion.
     191             :    The last argument is the count of the number of input bytes
     192             :    actually converted to the output. */
     193             : const char *
     194         495 : ODBCutf82wchar(const SQLCHAR *src,
     195             :                SQLINTEGER length,
     196             :                SQLWCHAR *buf,
     197             :                SQLLEN buflen,
     198             :                SQLSMALLINT *buflenout,
     199             :                size_t *consumed)
     200             : {
     201         495 :         SQLLEN i = 0;
     202         495 :         SQLINTEGER j = 0;
     203             : 
     204         495 :         if (buf == NULL)
     205             :                 buflen = 0;
     206         494 :         else if (buflen == 0)
     207           1 :                 buf = NULL;
     208             : 
     209         495 :         if (src == NULL || length == SQL_NULL_DATA) {
     210           0 :                 if (buflen > 0)
     211           0 :                         buf[0] = 0;
     212           0 :                 if (buflenout)
     213           0 :                         *buflenout = 0;
     214           0 :                 if (consumed)
     215           0 :                         *consumed = 0;
     216           0 :                 return NULL;
     217             :         }
     218         495 :         if (length == SQL_NTS)
     219             :                 length = (SQLINTEGER) (~(SQLUINTEGER)0 >> 1);
     220         104 :         else if (length < 0)
     221             :                 return "Invalid length parameter";
     222             : 
     223         495 :         uint32_t state = 0, codepoint = 0;
     224       68946 :         while (j < length && i + 1 < buflen && src[j]) {
     225       68451 :                 switch (decode(&state, &codepoint, (uint8_t) src[j++])) {
     226       68443 :                 case UTF8_ACCEPT:
     227             : #if SIZEOF_SQLWCHAR == 2
     228       68443 :                         if (codepoint <= 0xFFFF) {
     229       68442 :                                 buf[i++] = (SQLWCHAR) codepoint;
     230             :                         } else {
     231           1 :                                 buf[i++] = (SQLWCHAR) (0xD7C0 + (codepoint >> 10));
     232           1 :                                 buf[i++] = (SQLWCHAR) (0xDC00 + (codepoint & 0x3FF));
     233             :                         }
     234             : #else
     235             :                         buf[i++] = (SQLWCHAR) codepoint;
     236             : #endif
     237             :                         break;
     238             :                 case UTF8_REJECT:
     239             :                         return "Illegal code point";
     240             :                 default:
     241             :                         break;
     242             :                 }
     243             :         }
     244         495 :         if (buflen > 0)
     245         494 :                 buf[i] = 0;
     246         495 :         if (consumed)
     247         391 :                 *consumed = (size_t) j;
     248       11396 :         while (j < length && src[j]) {
     249       10901 :                 switch (decode(&state, &codepoint, (uint8_t) src[j++])) {
     250       10901 :                 case UTF8_ACCEPT:
     251             : #if SIZEOF_SQLWCHAR == 2
     252       10901 :                         if (codepoint <= 0xFFFF) {
     253       10901 :                                 i++;
     254             :                         } else {
     255           0 :                                 i += 2;
     256             :                         }
     257             : #else
     258             :                         i++;
     259             : #endif
     260             :                         break;
     261             :                 case UTF8_REJECT:
     262             :                         return "Illegal code point";
     263             :                 default:
     264             :                         break;
     265             :                 }
     266             :         }
     267         495 :         if (buflenout)
     268         475 :                 *buflenout = (SQLSMALLINT) i;
     269             :         return NULL;
     270             : }
     271             : 
     272             : /*
     273             :  * Translate an ODBC-compatible query to one that the SQL server
     274             :  * understands.
     275             :  *
     276             :  * Precondition: query != NULL
     277             :  * Postcondition: returns a newly allocated null terminated string.
     278             :  */
     279             : /*
     280             :   Escape sequences:
     281             :   {d 'yyyy-mm-dd'}
     282             :   {t 'hh:mm:ss'}
     283             :   {ts 'yyyy-mm-dd hh:mm:ss[.f...]'}
     284             :   {interval ...}
     285             :   {guid 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'}
     286             :   {fn scalar-function}
     287             :   {escape 'escape-character'}
     288             :   {oj outer-join}
     289             :   where outer-join is:
     290             :         table-reference {LEFT|RIGHT|FULL} OUTER JOIN
     291             :         {table-reference | outer-join} ON search condition
     292             :   {[?=]call procedure-name[([parameter][,[parameter]]...)]}
     293             :  */
     294             : 
     295             : static struct scalars {
     296             :         const char *name;
     297             :         int nargs;
     298             :         const char *repl;
     299             : } scalars[] = {
     300             :         {
     301             :                 .name = "abs",
     302             :                 .nargs = 1,
     303             :                 .repl = "sys.\"abs\"",
     304             :         },
     305             :         {
     306             :                 .name = "acos",
     307             :                 .nargs = 1,
     308             :                 .repl = "sys.\"acos\"",
     309             :         },
     310             :         {
     311             :                 .name = "ascii",
     312             :                 .nargs = 1,
     313             :                 .repl = "sys.\"ascii\"",
     314             :         },
     315             :         {
     316             :                 .name = "asin",
     317             :                 .nargs = 1,
     318             :                 .repl = "sys.\"asin\"",
     319             :         },
     320             :         {
     321             :                 .name = "atan",
     322             :                 .nargs = 1,
     323             :                 .repl = "sys.\"atan\"",
     324             :         },
     325             :         {
     326             :                 .name = "atan2",
     327             :                 .nargs = 2,
     328             :                 .repl = "sys.\"atan\"", /* note: not atan2 */
     329             :         },
     330             :         {
     331             :                 .name = "bit_length",
     332             :                 .nargs = 1,
     333             :                 .repl = NULL,
     334             :         },
     335             :         {
     336             :                 .name = "ceiling",
     337             :                 .nargs = 1,
     338             :                 .repl = "sys.\"ceiling\"",
     339             :         },
     340             :         {
     341             :                 .name = "char",
     342             :                 .nargs = 1,
     343             :                 .repl = "sys.\"code\"",
     344             :         },
     345             :         {
     346             :                 .name = "character_length",
     347             :                 .nargs = 1,
     348             :                 .repl = "sys.\"character_length\"",
     349             :         },
     350             :         {
     351             :                 .name = "char_length",
     352             :                 .nargs = 1,
     353             :                 .repl = "sys.\"char_length\"",
     354             :         },
     355             :         {
     356             :                 .name = "concat",
     357             :                 .nargs = 2,
     358             :                 .repl = "sys.\"concat\"",
     359             :         },
     360             :         {
     361             :                 /* second argument is an ODBC type name that also gets
     362             :                  * translated.  Note: convert is implemented in the
     363             :                  * parser */
     364             :                 .name = "convert",
     365             :                 .nargs = 2,
     366             :                 .repl = NULL,
     367             :         },
     368             :         {
     369             :                 .name = "cos",
     370             :                 .nargs = 1,
     371             :                 .repl = "sys.\"cos\"",
     372             :         },
     373             :         {
     374             :                 .name = "cot",
     375             :                 .nargs = 1,
     376             :                 .repl = "sys.\"cot\"",
     377             :         },
     378             :         {
     379             :                 .name = "curdate",
     380             :                 .nargs = 0,
     381             :                 .repl = "sys.\"curdate\"",
     382             :         },
     383             :         {
     384             :                 .name = "current_date",
     385             :                 .nargs = 0,
     386             :                 .repl = "sys.\"current_date\"",
     387             :         },
     388             :         {
     389             :                 .name = "current_time",
     390             :                 .nargs = 0,
     391             :                 .repl = "sys.\"current_time\"",
     392             :         },
     393             :         {
     394             :                 .name = "current_time",
     395             :                 .nargs = 1,
     396             :                 .repl = NULL,
     397             :         },
     398             :         {
     399             :                 .name = "current_timestamp",
     400             :                 .nargs = 0,
     401             :                 .repl = "sys.\"current_timestamp\"",
     402             :         },
     403             :         {
     404             :                 .name = "current_timestamp",
     405             :                 .nargs = 1,
     406             :                 .repl = NULL,
     407             :         },
     408             :         {
     409             :                 .name = "curtime",
     410             :                 .nargs = 0,
     411             :                 .repl = "sys.\"curtime\"",
     412             :         },
     413             :         {
     414             :                 .name = "database",
     415             :                 .nargs = 0,
     416             :                 .repl = NULL,
     417             :         },
     418             :         {
     419             :                 .name = "dayname",
     420             :                 .nargs = 1,
     421             :                 .repl = NULL,
     422             :         },
     423             :         {
     424             :                 .name = "dayofmonth",
     425             :                 .nargs = 1,
     426             :                 .repl = "sys.\"dayofmonth\"",
     427             :         },
     428             :         {
     429             :                 .name = "dayofweek",
     430             :                 .nargs = 1,
     431             :                 .repl = "sys.\"dayofweek\"",
     432             :         },
     433             :         {
     434             :                 .name = "dayofyear",
     435             :                 .nargs = 1,
     436             :                 .repl = "sys.\"dayofyear\"",
     437             :         },
     438             :         {
     439             :                 .name = "degrees",
     440             :                 .nargs = 1,
     441             :                 .repl = "sys.\"degrees\"",
     442             :         },
     443             :         {
     444             :                 .name = "difference",
     445             :                 .nargs = 2,
     446             :                 .repl = "sys.\"difference\"",
     447             :         },
     448             :         {
     449             :                 .name = "exp",
     450             :                 .nargs = 1,
     451             :                 .repl = "sys.\"exp\"",
     452             :         },
     453             :         {
     454             :                 .name = "extract",
     455             :                 .nargs = 1,
     456             :                 .repl = "EXTRACT", /* include "X FROM " in argument */
     457             :         },
     458             :         {
     459             :                 .name = "floor",
     460             :                 .nargs = 1,
     461             :                 .repl = "sys.\"floor\"",
     462             :         },
     463             :         {
     464             :                 .name = "hour",
     465             :                 .nargs = 1,
     466             :                 .repl = "sys.\"hour\"",
     467             :         },
     468             :         {
     469             :                 .name = "ifnull",
     470             :                 .nargs = 2,
     471             :                 .repl = "sys.\"coalesce\"",
     472             :         },
     473             :         {
     474             :                 .name = "insert",
     475             :                 .nargs = 4,
     476             :                 .repl = "sys.\"insert\"",
     477             :         },
     478             :         {
     479             :                 .name = "lcase",
     480             :                 .nargs = 1,
     481             :                 .repl = "sys.\"lcase\"",
     482             :         },
     483             :         {
     484             :                 .name = "left",
     485             :                 .nargs = 2,
     486             :                 .repl = "sys.\"left\"",
     487             :         },
     488             :         {
     489             :                 .name = "length",
     490             :                 .nargs = 1,
     491             :                 .repl = "sys.\"length\"",
     492             :         },
     493             :         {
     494             :                 .name = "locate",
     495             :                 .nargs = 2,
     496             :                 .repl = "sys.\"locate\"",
     497             :         },
     498             :         {
     499             :                 .name = "locate",
     500             :                 .nargs = 3,
     501             :                 .repl = "sys.\"locate\"",
     502             :         },
     503             :         {
     504             :                 .name = "log10",
     505             :                 .nargs = 1,
     506             :                 .repl = "sys.\"log10\"",
     507             :         },
     508             :         {
     509             :                 .name = "log",
     510             :                 .nargs = 1,
     511             :                 .repl = "sys.\"log\"",
     512             :         },
     513             :         {
     514             :                 .name = "ltrim",
     515             :                 .nargs = 1,
     516             :                 .repl = "sys.\"ltrim\"",
     517             :         },
     518             :         {
     519             :                 .name = "minute",
     520             :                 .nargs = 1,
     521             :                 .repl = "sys.\"minute\"",
     522             :         },
     523             :         {
     524             :                 .name = "mod",
     525             :                 .nargs = 2,
     526             :                 .repl = "sys.\"mod\"",
     527             :         },
     528             :         {
     529             :                 .name = "month",
     530             :                 .nargs = 1,
     531             :                 .repl = "sys.\"month\"",
     532             :         },
     533             :         {
     534             :                 .name = "monthname",
     535             :                 .nargs = 1,
     536             :                 .repl = NULL,
     537             :         },
     538             :         {
     539             :                 .name = "now",
     540             :                 .nargs = 0,
     541             :                 .repl = "sys.\"now\"",
     542             :         },
     543             :         {
     544             :                 .name = "octet_length",
     545             :                 .nargs = 1,
     546             :                 .repl = "sys.\"octet_length\"",
     547             :         },
     548             :         {
     549             :                 .name = "pi",
     550             :                 .nargs = 0,
     551             :                 .repl = "sys.\"pi\"",
     552             :         },
     553             :         {
     554             :                 .name = "position",
     555             :                 .nargs = 1,
     556             :                  /* includes " IN str" in first argument. Note:
     557             :                   * POSITION is implemented in the parser. */
     558             :                 .repl = "position",
     559             :         },
     560             :         {
     561             :                 .name = "power",
     562             :                 .nargs = 2,
     563             :                 .repl = "sys.\"power\"",
     564             :         },
     565             :         {
     566             :                 .name = "quarter",
     567             :                 .nargs = 1,
     568             :                 .repl = "sys.\"quarter\"",
     569             :         },
     570             :         {
     571             :                 .name = "radians",
     572             :                 .nargs = 1,
     573             :                 .repl = "sys.\"radians\"",
     574             :         },
     575             :         {
     576             :                 .name = "rand",
     577             :                 .nargs = 0,
     578             :                 .repl = "sys.\"rand\"",
     579             :         },
     580             :         {
     581             :                 .name = "rand",
     582             :                 .nargs = 1,
     583             :                 .repl = "sys.\"rand\"",
     584             :         },
     585             :         {
     586             :                 .name = "repeat",
     587             :                 .nargs = 2,
     588             :                 .repl = "sys.\"repeat\"",
     589             :         },
     590             :         {
     591             :                 .name = "replace",
     592             :                 .nargs = 3,
     593             :                 .repl = "sys.\"replace\"",
     594             :         },
     595             :         {
     596             :                 .name = "right",
     597             :                 .nargs = 2,
     598             :                 .repl = "sys.\"right\"",
     599             :         },
     600             :         {
     601             :                 .name = "round",
     602             :                 .nargs = 2,
     603             :                 .repl = "sys.\"round\"",
     604             :         },
     605             :         {
     606             :                 .name = "rtrim",
     607             :                 .nargs = 1,
     608             :                 .repl = "sys.\"rtrim\"",
     609             :         },
     610             :         {
     611             :                 .name = "second",
     612             :                 .nargs = 1,
     613             :                 .repl = "sys.\"second\"",
     614             :         },
     615             :         {
     616             :                 .name = "sign",
     617             :                 .nargs = 1,
     618             :                 .repl = "sys.\"sign\"",
     619             :         },
     620             :         {
     621             :                 .name = "sin",
     622             :                 .nargs = 1,
     623             :                 .repl = "sys.\"sin\"",
     624             :         },
     625             :         {
     626             :                 .name = "soundex",
     627             :                 .nargs = 1,
     628             :                 .repl = "sys.\"soundex\"",
     629             :         },
     630             :         {
     631             :                 .name = "space",
     632             :                 .nargs = 1,
     633             :                 .repl = "sys.\"space\"",
     634             :         },
     635             :         {
     636             :                 .name = "sqrt",
     637             :                 .nargs = 1,
     638             :                 .repl = "sys.\"sqrt\"",
     639             :         },
     640             :         {
     641             :                 .name = "substring",
     642             :                 .nargs = 3,
     643             :                 .repl = "sys.\"substring\"",
     644             :         },
     645             :         {
     646             :                 .name = "tan",
     647             :                 .nargs = 1,
     648             :                 .repl = "sys.\"tan\"",
     649             :         },
     650             :         {
     651             :                 .name = "timestampadd",
     652             :                 .nargs = 3,
     653             :                 .repl = NULL,
     654             :         },
     655             :         {
     656             :                 .name = "timestampdiff",
     657             :                 .nargs = 3,
     658             :                 .repl = NULL,
     659             :         },
     660             :         {
     661             :                 .name = "truncate",
     662             :                 .nargs = 2,
     663             :                 .repl = "sys.\"ms_trunc\"",
     664             :         },
     665             :         {
     666             :                 .name = "ucase",
     667             :                 .nargs = 1,
     668             :                 .repl = "sys.\"ucase\"",
     669             :         },
     670             :         {
     671             :                 .name = "user",
     672             :                 .nargs = 0,
     673             :                 .repl = NULL,
     674             :         },
     675             :         {
     676             :                 .name = "week",
     677             :                 .nargs = 1,
     678             :                 .repl = "sys.\"week\"",
     679             :         },
     680             :         {
     681             :                 .name = "year",
     682             :                 .nargs = 1,
     683             :                 .repl = "sys.\"year\"",
     684             :         },
     685             :         {
     686             :                 0               /* sentinel */
     687             :         },
     688             : };
     689             : 
     690             : static struct convert {
     691             :         const char *odbc;
     692             :         const char *server;
     693             : } convert[] = {
     694             :         {
     695             :                 .odbc =  "SQL_BIGINT",
     696             :                 .server = "bigint",
     697             :         },
     698             :         {
     699             :                 .odbc =  "SQL_BINARY",
     700             :                 .server = "binary large object",
     701             :         },
     702             :         {
     703             :                 .odbc =  "SQL_BIT",
     704             :                 .server = "boolean",
     705             :         },
     706             :         {
     707             :                 .odbc =  "SQL_CHAR",
     708             :                 .server = "character",
     709             :         },
     710             :         {
     711             :                 .odbc =  "SQL_DATE",
     712             :                 .server = "date",
     713             :         },
     714             :         {
     715             :                 .odbc = "SQL_DECIMAL",
     716             :                 .server = "decimal(18,7)",
     717             :         },
     718             :         {
     719             :                 .odbc =  "SQL_DOUBLE",
     720             :                 .server = "double",
     721             :         },
     722             :         {
     723             :                 .odbc =  "SQL_FLOAT",
     724             :                 .server = "float",
     725             :         },
     726             :         {
     727             :                 .odbc =  "SQL_GUID",
     728             :                 .server = "uuid",
     729             :         },
     730             :         {
     731             :                 .odbc =  "SQL_HUGEINT",
     732             :                 .server = "hugeint",
     733             :         },
     734             :         {
     735             :                 .odbc =  "SQL_INTEGER",
     736             :                 .server = "integer",
     737             :         },
     738             :         {
     739             :                 .odbc =  "SQL_INTERVAL_DAY_TO_HOUR",
     740             :                 .server = "interval day to hour",
     741             :         },
     742             :         {
     743             :                 .odbc =  "SQL_INTERVAL_DAY_TO_MINUTE",
     744             :                 .server = "interval day to minute",
     745             :         },
     746             :         {
     747             :                 .odbc =  "SQL_INTERVAL_DAY_TO_SECOND",
     748             :                 .server = "interval day to second",
     749             :         },
     750             :         {
     751             :                 .odbc =  "SQL_INTERVAL_DAY",
     752             :                 .server = "interval day",
     753             :         },
     754             :         {
     755             :                 .odbc =  "SQL_INTERVAL_HOUR_TO_MINUTE",
     756             :                 .server = "interval hour to minute",
     757             :         },
     758             :         {
     759             :                 .odbc =  "SQL_INTERVAL_HOUR_TO_SECOND",
     760             :                 .server = "interval hour to second",
     761             :         },
     762             :         {
     763             :                 .odbc =  "SQL_INTERVAL_HOUR",
     764             :                 .server = "interval hour",
     765             :         },
     766             :         {
     767             :                 .odbc =  "SQL_INTERVAL_MINUTE_TO_SECOND",
     768             :                 .server = "interval minute to second",
     769             :         },
     770             :         {
     771             :                 .odbc =  "SQL_INTERVAL_MINUTE",
     772             :                 .server = "interval minute",
     773             :         },
     774             :         {
     775             :                 .odbc =  "SQL_INTERVAL_MONTH",
     776             :                 .server = "interval month",
     777             :         },
     778             :         {
     779             :                 .odbc =  "SQL_INTERVAL_SECOND",
     780             :                 .server = "interval second",
     781             :         },
     782             :         {
     783             :                 .odbc =  "SQL_INTERVAL_YEAR_TO_MONTH",
     784             :                 .server = "interval year to month",
     785             :         },
     786             :         {
     787             :                 .odbc =  "SQL_INTERVAL_YEAR",
     788             :                 .server = "interval year",
     789             :         },
     790             :         {
     791             :                 .odbc =  "SQL_LONGVARBINARY",
     792             :                 .server = "binary large object",
     793             :         },
     794             :         {
     795             :                 .odbc =  "SQL_LONGVARCHAR",
     796             :                 .server = "character large object",
     797             :         },
     798             :         {
     799             :                 .odbc = "SQL_NUMERIC",
     800             :                 .server = "numeric(18,7)",
     801             :         },
     802             :         {
     803             :                 .odbc =  "SQL_REAL",
     804             :                 .server = "real",
     805             :         },
     806             :         {
     807             :                 .odbc =  "SQL_SMALLINT",
     808             :                 .server = "smallint",
     809             :         },
     810             :         {
     811             :                 .odbc =  "SQL_TIMESTAMP",
     812             :                 .server = "timestamp",
     813             :         },
     814             :         {
     815             :                 .odbc =  "SQL_TIME",
     816             :                 .server = "time",
     817             :         },
     818             :         {
     819             :                 .odbc =  "SQL_TINYINT",
     820             :                 .server = "tinyint",
     821             :         },
     822             :         {
     823             :                 .odbc =  "SQL_VARBINARY",
     824             :                 .server = "binary large object",
     825             :         },
     826             :         {
     827             :                 .odbc =  "SQL_VARCHAR",
     828             :                 .server = "character varying",
     829             :         },
     830             :         {
     831             :                 .odbc =  "SQL_WCHAR",
     832             :                 .server = "character",
     833             :         },
     834             :         {
     835             :                 .odbc =  "SQL_WLONGVARCHAR",
     836             :                 .server = "character large object",
     837             :         },
     838             :         {
     839             :                 .odbc =  "SQL_WVARCHAR",
     840             :                 .server = "character varying",
     841             :         },
     842             :         {
     843             :                 0               /* sentinel */
     844             :         },
     845             : };
     846             : 
     847             : char *
     848         112 : ODBCTranslateSQL(ODBCDbc *dbc, const SQLCHAR *query, size_t length, SQLULEN noscan)
     849             : {
     850             :         /* we only need to read limited amounts of data into these
     851             :          * buffers (timestamp, interval, function name), so 128 bytes is
     852             :          * plenty long enough */
     853         112 :         char buf[128], buf2[128];
     854             : 
     855             :         /* From Jun2023 release (11.47) the mserver5 SQL parser supports all
     856             :          * ODBC escape sequences, so no scanning or translation is required here.
     857             :          */
     858         112 :         if (dbc->minor >= 47)
     859             :                 noscan = SQL_NOSCAN_ON;
     860             : 
     861           0 :         if (noscan != SQL_NOSCAN_ON) {
     862             :                 char *nquery;
     863             :                 bool quoted = false, rawstring = false, dquoted = false;
     864             : 
     865           0 :                 for (size_t i = 0; i < length; i++) {
     866           0 :                         if (quoted && query[i] == '\\') {
     867           0 :                                 i++;
     868           0 :                                 continue;
     869             :                         }
     870           0 :                         if (quoted || rawstring) {
     871           0 :                                 if (query[i] == '\'')
     872           0 :                                         quoted = rawstring = false;
     873           0 :                                 continue;
     874             :                         }
     875           0 :                         if (dquoted) {
     876           0 :                                 if (query[i] == '"')
     877           0 :                                         dquoted = false;
     878           0 :                                 continue;
     879             :                         }
     880           0 :                         if (query[i] == '\'') {
     881           0 :                                 if (dbc->raw_strings ?
     882           0 :                                     (i > 0 &&
     883           0 :                                      query[i - 1] != 'e' &&
     884             :                                      query[i - 1] != 'E') :
     885           0 :                                     (i > 0 &&
     886           0 :                                      (query[i - 1] == 'r' ||
     887             :                                       query[i - 1] == 'R')))
     888             :                                         rawstring = true;
     889             :                                 else
     890             :                                         quoted = true;
     891           0 :                                 continue;
     892             :                         }
     893           0 :                         if (query[i] == '"') {
     894           0 :                                 dquoted = true;
     895           0 :                                 continue;
     896             :                         }
     897           0 :                         if (query[i] != '{')
     898           0 :                                 continue;
     899           0 :                         size_t n = 0;
     900           0 :                         if (sscanf((const char *) query + i, "{ ts '%127[0-9:. -]' }%zn", buf, &n) >= 1 && n > 0) {
     901           0 :                                 char *rest = ODBCTranslateSQL(dbc, query + i + n, length - i - n, noscan);
     902           0 :                                 size_t len = strlen(buf) + strlen(rest);
     903           0 :                                 nquery = malloc(i + len + 13);
     904           0 :                                 snprintf(nquery, i + len + 13,
     905             :                                          "%.*sTIMESTAMP '%s'%s",
     906             :                                          (int) i, query, buf, rest);
     907           0 :                                 free(rest);
     908           0 :                                 return nquery;
     909             :                         }
     910           0 :                         if (sscanf((const char *) query + i, "{ t '%127[0-9:]' }%zn", buf, &n) >= 1 && n > 0) {
     911           0 :                                 char *rest = ODBCTranslateSQL(dbc, query + i + n, length - i - n, noscan);
     912           0 :                                 size_t len = strlen(buf) + strlen(rest);
     913           0 :                                 nquery = malloc(i + len + 8);
     914           0 :                                 snprintf(nquery, i + len + 8,
     915             :                                          "%.*sTIME '%s'%s",
     916             :                                          (int) i, query, buf, rest);
     917           0 :                                 free(rest);
     918           0 :                                 return nquery;
     919             :                         }
     920           0 :                         if (sscanf((const char *) query + i, "{ d '%127[0-9-]' }%zn", buf, &n) >= 1 && n > 0) {
     921           0 :                                 char *rest = ODBCTranslateSQL(dbc, query + i + n, length - i - n, noscan);
     922           0 :                                 size_t len = strlen(buf) + strlen(rest);
     923           0 :                                 nquery = malloc(i + len + 8);
     924           0 :                                 snprintf(nquery, i + len + 8,
     925             :                                          "%.*sDATE '%s'%s",
     926             :                                          (int) i, query, buf, rest);
     927           0 :                                 free(rest);
     928           0 :                                 return nquery;
     929             :                         }
     930           0 :                         if (sscanf((const char *) query + i, "{ guid '%127[0-9a-fA-F-]' }%zn", buf, &n) >= 1 && n > 0) {
     931           0 :                                 char *rest = ODBCTranslateSQL(dbc, query + i + n, length - i - n, noscan);
     932           0 :                                 size_t len = strlen(buf) + strlen(rest);
     933           0 :                                 nquery = malloc(i + len + 8);
     934           0 :                                 snprintf(nquery, i + len + 8,
     935             :                                          "%.*sUUID '%s'%s",
     936             :                                          (int) i, query, buf, rest);
     937           0 :                                 free(rest);
     938           0 :                                 return nquery;
     939             :                         }
     940           0 :                         if (sscanf((const char *) query + i, "{ escape '%127[^']' }%zn", buf, &n) >= 1 && n > 0) {
     941           0 :                                 char *rest = ODBCTranslateSQL(dbc, query + i + n, length - i - n, noscan);
     942           0 :                                 size_t len = strlen(buf) + strlen(rest);
     943           0 :                                 nquery = malloc(i + len + 10);
     944           0 :                                 snprintf(nquery, i + len + 10,
     945             :                                          "%.*sESCAPE '%s'%s",
     946             :                                          (int) i, query, buf, rest);
     947           0 :                                 free(rest);
     948           0 :                                 return nquery;
     949             :                         }
     950           0 :                         if (sscanf((const char *) query + i, "{ interval '%127[^']' %127[a-zA-Z ] }%zn", buf, buf2, &n) >= 2 && n > 0) {
     951           0 :                                 char *rest = ODBCTranslateSQL(dbc, query + i + n, length - i - n, noscan);
     952           0 :                                 size_t len = strlen(buf) + strlen(buf2) + strlen(rest);
     953           0 :                                 nquery = malloc(i + len + 14);
     954           0 :                                 snprintf(nquery, i + len + 14,
     955             :                                          "%.*sINTERVAL '%s' %s %s",
     956             :                                          (int) i, query, buf, buf2, rest);
     957           0 :                                 free(rest);
     958           0 :                                 return nquery;
     959             :                         }
     960           0 :                         if (sscanf((const char *) query + i, "{ interval + '%127[^']' %127[a-zA-Z ] }%zn", buf, buf2, &n) >= 2 && n > 0) {
     961           0 :                                 char *rest = ODBCTranslateSQL(dbc, query + i + n, length - i - n, noscan);
     962           0 :                                 size_t len = strlen(buf) + strlen(buf2) + strlen(rest);
     963           0 :                                 nquery = malloc(i + len + 15);
     964           0 :                                 snprintf(nquery, i + len + 15,
     965             :                                          "%.*sINTERVAL +'%s' %s %s",
     966             :                                          (int) i, query, buf, buf2, rest);
     967           0 :                                 free(rest);
     968           0 :                                 return nquery;
     969             :                         }
     970           0 :                         if (sscanf((const char *) query + i, "{ interval - '%127[^']' %127[a-zA-Z ] }%zn", buf, buf2, &n) >= 2 && n > 0) {
     971           0 :                                 char *rest = ODBCTranslateSQL(dbc, query + i + n, length - i - n, noscan);
     972           0 :                                 size_t len = strlen(buf) + strlen(buf2) + strlen(rest);
     973           0 :                                 nquery = malloc(i + len + 15);
     974           0 :                                 snprintf(nquery, i + len + 15,
     975             :                                          "%.*sINTERVAL -'%s' %s %s",
     976             :                                          (int) i, query, buf, buf2, rest);
     977           0 :                                 free(rest);
     978           0 :                                 return nquery;
     979             :                         }
     980           0 :                         if (sscanf((const char *) query + i, "{ oj %zn", &n) >= 0 && n > 0) {
     981           0 :                                 char *rest = ODBCTranslateSQL(dbc, query + i + n, length - i - n, noscan);
     982           0 :                                 for (size_t j = 0; rest[j]; j++) {
     983           0 :                                         if (quoted && rest[j] == '\\') {
     984           0 :                                                 j++;
     985           0 :                                                 continue;
     986             :                                         }
     987           0 :                                         if (quoted || rawstring) {
     988           0 :                                                 if (rest[j] == '\'')
     989           0 :                                                         quoted = rawstring = false;
     990           0 :                                                 continue;
     991             :                                         }
     992           0 :                                         if (dquoted) {
     993           0 :                                                 if (rest[j] == '"')
     994           0 :                                                         dquoted = false;
     995           0 :                                                 continue;
     996             :                                         }
     997           0 :                                         if (rest[j] == '\'') {
     998           0 :                                                 if (dbc->raw_strings ?
     999           0 :                                                     (j > 0 &&
    1000           0 :                                                      rest[j - 1] != 'e' &&
    1001             :                                                      rest[j - 1] != 'E') :
    1002           0 :                                                     (j > 0 &&
    1003           0 :                                                      (rest[j - 1] == 'r' ||
    1004             :                                                       rest[j - 1] == 'R')))
    1005             :                                                         rawstring = true;
    1006             :                                                 else
    1007             :                                                         quoted = true;
    1008           0 :                                                 continue;
    1009             :                                         }
    1010           0 :                                         if (rest[j] == '"') {
    1011           0 :                                                 dquoted = true;
    1012           0 :                                                 continue;
    1013             :                                         }
    1014           0 :                                         if (rest[j] == '}') {
    1015           0 :                                                 size_t len = strlen(rest);
    1016           0 :                                                 nquery = malloc(i + len + 2);
    1017           0 :                                                 snprintf(nquery, i + len + 2,
    1018             :                                                          "%.*s %.*s %s",
    1019             :                                                          (int) i, query,
    1020             :                                                          (int) j, rest,
    1021           0 :                                                          rest + j + 1);
    1022           0 :                                                 free(rest);
    1023           0 :                                                 return nquery;
    1024             :                                         }
    1025             :                                 }
    1026           0 :                                 free(rest);
    1027           0 :                                 continue;
    1028             :                         }
    1029           0 :                         if (sscanf((const char *) query + i, "{ call %zn", &n) >= 0 && n > 0) {
    1030           0 :                                 char *rest = ODBCTranslateSQL(dbc, query + i + n, length - i - n, noscan);
    1031           0 :                                 for (size_t j = 0; rest[j]; j++) {
    1032           0 :                                         if (quoted && rest[j] == '\\') {
    1033           0 :                                                 j++;
    1034           0 :                                                 continue;
    1035             :                                         }
    1036           0 :                                         if (quoted || rawstring) {
    1037           0 :                                                 if (rest[j] == '\'')
    1038           0 :                                                         quoted = rawstring = false;
    1039           0 :                                                 continue;
    1040             :                                         }
    1041           0 :                                         if (dquoted) {
    1042           0 :                                                 if (rest[j] == '"')
    1043           0 :                                                         dquoted = false;
    1044           0 :                                                 continue;
    1045             :                                         }
    1046           0 :                                         if (rest[j] == '\'') {
    1047           0 :                                                 if (dbc->raw_strings ?
    1048           0 :                                                     (j > 0 &&
    1049           0 :                                                      rest[j - 1] != 'e' &&
    1050             :                                                      rest[j - 1] != 'E') :
    1051           0 :                                                     (j > 0 &&
    1052           0 :                                                      (rest[j - 1] == 'r' ||
    1053             :                                                       rest[j - 1] == 'R')))
    1054             :                                                         rawstring = true;
    1055             :                                                 else
    1056             :                                                         quoted = true;
    1057           0 :                                                 continue;
    1058             :                                         }
    1059           0 :                                         if (rest[j] == '"') {
    1060           0 :                                                 dquoted = true;
    1061           0 :                                                 continue;
    1062             :                                         }
    1063           0 :                                         if (rest[j] == '}') {
    1064           0 :                                                 size_t len = strlen(rest);
    1065           0 :                                                 nquery = malloc(i + len + 6);
    1066           0 :                                                 snprintf(nquery, i + len + 6,
    1067             :                                                          "%.*sCALL %.*s %s",
    1068             :                                                          (int) i, query,
    1069             :                                                          (int) j, rest,
    1070           0 :                                                          rest + j + 1);
    1071           0 :                                                 free(rest);
    1072           0 :                                                 return nquery;
    1073             :                                         }
    1074             :                                 }
    1075           0 :                                 free(rest);
    1076           0 :                                 continue;
    1077             :                         }
    1078           0 :                         if (sscanf((const char *) query + i, "{ fn %127[a-zA-Z0-9_] ( %zn", buf, &n) >= 1 && n > 0) {
    1079           0 :                                 char *rest = ODBCTranslateSQL(dbc, query + i + n, length - i - n, noscan);
    1080           0 :                                 size_t arglen = 0;
    1081           0 :                                 size_t lastarg = 0;
    1082           0 :                                 int nargs = 0;
    1083           0 :                                 int nparen = 1;
    1084           0 :                                 bool seenarg = false;
    1085             : 
    1086           0 :                                 for (size_t j = 0; rest[j] && nargs < 5; j++) {
    1087           0 :                                         if (quoted && rest[j] == '\\') {
    1088           0 :                                                 j++;
    1089           0 :                                                 continue;
    1090             :                                         }
    1091           0 :                                         if (quoted || rawstring) {
    1092           0 :                                                 if (rest[j] == '\'')
    1093           0 :                                                         quoted = rawstring = false;
    1094           0 :                                                 continue;
    1095             :                                         }
    1096           0 :                                         if (dquoted) {
    1097           0 :                                                 if (rest[j] == '"')
    1098           0 :                                                         dquoted = false;
    1099           0 :                                                 continue;
    1100             :                                         }
    1101           0 :                                         if (rest[j] == '\'') {
    1102           0 :                                                 seenarg = true;
    1103           0 :                                                 if (dbc->raw_strings ?
    1104           0 :                                                     (j > 0 &&
    1105           0 :                                                      rest[j - 1] != 'e' &&
    1106             :                                                      rest[j - 1] != 'E') :
    1107           0 :                                                     (j > 0 &&
    1108           0 :                                                      (rest[j - 1] == 'r' ||
    1109             :                                                       rest[j - 1] == 'R')))
    1110             :                                                         rawstring = true;
    1111             :                                                 else
    1112             :                                                         quoted = true;
    1113           0 :                                                 continue;
    1114             :                                         }
    1115           0 :                                         if (rest[j] == '"') {
    1116           0 :                                                 seenarg = true;
    1117           0 :                                                 dquoted = true;
    1118           0 :                                                 continue;
    1119             :                                         }
    1120           0 :                                         if (rest[j] == '(') {
    1121           0 :                                                 seenarg = true;
    1122           0 :                                                 nparen++;
    1123           0 :                                                 continue;
    1124             :                                         }
    1125           0 :                                         if (nparen > 1) {
    1126           0 :                                                 if (rest[j] == ')')
    1127           0 :                                                         nparen--;
    1128           0 :                                                 continue;
    1129             :                                         }
    1130           0 :                                         if (rest[j] == ',') {
    1131           0 :                                                 if (!seenarg)
    1132             :                                                         break;
    1133           0 :                                                 nargs++;
    1134           0 :                                                 seenarg = false;
    1135           0 :                                                 continue;
    1136             :                                         }
    1137           0 :                                         if (rest[j] == ')') {
    1138           0 :                                                 if (--nparen < 0)
    1139             :                                                         break;
    1140           0 :                                                 arglen = j;
    1141           0 :                                                 if (seenarg)
    1142           0 :                                                         nargs++;
    1143           0 :                                                 else if (nargs > 0)
    1144             :                                                         break;
    1145           0 :                                                 seenarg = false;
    1146           0 :                                                 continue;
    1147             :                                         }
    1148           0 :                                         if (rest[j] == '}') {
    1149           0 :                                                 if (nparen != 0 || seenarg)
    1150             :                                                         break;
    1151           0 :                                                 for (struct scalars *func = scalars; func->name; func++) {
    1152           0 :                                                         if (strcasecmp(func->name, buf) == 0 && func->nargs == nargs) {
    1153           0 :                                                                 const char *repl = func->repl;
    1154           0 :                                                                 const char *repl2 = "";
    1155           0 :                                                                 const char *repl3 = "";
    1156           0 :                                                                 const char *p1 = "(";
    1157           0 :                                                                 const char *p2 = ")";
    1158           0 :                                                                 const char *quote = "";
    1159           0 :                                                                 size_t repl3len = 0;
    1160           0 :                                                                 if (repl == NULL) {
    1161           0 :                                                                         if (strcmp(func->name, "user") == 0) {
    1162           0 :                                                                                 repl = msetting_string(dbc->settings, MP_USER);
    1163           0 :                                                                                 p1 = p2 = "";
    1164           0 :                                                                                 quote = "'";
    1165           0 :                                                                         } else if (strcmp(func->name, "database") == 0) {
    1166           0 :                                                                                 repl = msetting_string(dbc->settings, MP_DATABASE);
    1167           0 :                                                                                 p1 = p2 = "";
    1168           0 :                                                                                 quote = "'";
    1169           0 :                                                                         } else if (strcmp(func->name, "convert") == 0) {
    1170           0 :                                                                                 repl = "convert";
    1171           0 :                                                                                 for (struct convert *c = convert; c->odbc; c++) {
    1172           0 :                                                                                         if (strncasecmp(rest + lastarg, c->odbc, strlen(c->odbc)) == 0) {
    1173           0 :                                                                                                 repl2 = c->server;
    1174           0 :                                                                                                 repl3len = arglen - lastarg - strlen(c->odbc);
    1175           0 :                                                                                                 repl3 = rest + lastarg + strlen(c->odbc);
    1176           0 :                                                                                                 arglen = lastarg;
    1177           0 :                                                                                                 break;
    1178             :                                                                                         }
    1179             :                                                                                 }
    1180             :                                                                         }
    1181           0 :                                                                         if (repl == NULL)
    1182             :                                                                                 break;
    1183             :                                                                 }
    1184           0 :                                                                 size_t l = i + strlen(repl) + 2 + arglen + strlen(rest) - j + 1 + strlen(repl2) + repl3len;
    1185           0 :                                                                 nquery = malloc(l);
    1186           0 :                                                                 snprintf(nquery, l, "%.*s%s%s%s%s%.*s%s%.*s%s%s", (int) i, query, quote, repl, quote, p1, (int) arglen, rest, repl2, (int) repl3len, repl3, p2, rest + j + 1);
    1187           0 :                                                                 free(rest);
    1188           0 :                                                                 return nquery;
    1189             :                                                         }
    1190             :                                                 }
    1191             :                                                 break;
    1192             :                                         }
    1193           0 :                                         if (!seenarg && !isspace((unsigned char) rest[j])) {
    1194           0 :                                                 lastarg = j;
    1195           0 :                                                 seenarg = true;
    1196             :                                         }
    1197             :                                 }
    1198           0 :                                 free(rest);
    1199           0 :                                 continue;
    1200             :                         }
    1201             :                 }
    1202             :         }
    1203         112 :         return dupODBCstring(query, length);
    1204             : }
    1205             : 
    1206             : char *
    1207          87 : ODBCParseOA(const char *tab, const char *col, const char *arg, size_t len)
    1208             : {
    1209          87 :         size_t i;
    1210          87 :         char *res;
    1211          87 :         const char *s;
    1212             : 
    1213             :         /* count length, counting ' and \ double */
    1214         722 :         for (i = 0, s = arg; s < arg + len; i++, s++) {
    1215         635 :                 if (*s == '\'' || *s == '\\')
    1216           0 :                         i++;
    1217             :         }
    1218          87 :         i += strlen(tab) + strlen(col) + 10; /* ""."" = '' */
    1219          87 :         res = malloc(i + 1);
    1220          87 :         if (res == NULL)
    1221             :                 return NULL;
    1222          87 :         snprintf(res, i, "\"%s\".\"%s\" = '", tab, col);
    1223         722 :         for (i = strlen(res), s = arg; s < arg + len; s++) {
    1224         635 :                 if (*s == '\'' || *s == '\\')
    1225           0 :                         res[i++] = *s;
    1226         635 :                 res[i++] = *s;
    1227             :         }
    1228          87 :         res[i++] = '\'';
    1229          87 :         res[i] = 0;
    1230          87 :         return res;
    1231             : }
    1232             : 
    1233             : char *
    1234          66 : ODBCParsePV(const char *tab, const char *col, const char *arg, size_t len, const ODBCDbc *dbc)
    1235             : {
    1236          66 :         size_t i;
    1237          66 :         char *res;
    1238          66 :         const char *s;
    1239             : 
    1240             :         /* count length, counting ' and \ double */
    1241         357 :         for (i = 0, s = arg; s < arg + len; i++, s++) {
    1242         291 :                 if (*s == '\'' || *s == '\\')
    1243           0 :                         i++;
    1244             :         }
    1245          66 :         i += strlen(tab) + strlen(col) + 25; /* ""."" like '' escape r'\' */
    1246          66 :         res = malloc(i + 1);
    1247          66 :         if (res == NULL)
    1248             :                 return NULL;
    1249          66 :         snprintf(res, i, "\"%s\".\"%s\" like '", tab, col);
    1250         357 :         for (i = strlen(res), s = arg; s < arg + len; s++) {
    1251         291 :                 if (*s == '\'' || *s == '\\')
    1252           0 :                         res[i++] = *s;
    1253         291 :                 res[i++] = *s;
    1254             :         }
    1255             :         /* raw strings prefix syntax is only supported by servers since Jun2020 (11.37) */
    1256          66 :         if (dbc->major == 11 && dbc->minor >= 37) {
    1257             :                 s = "' escape r'\\'";
    1258             :         } else {
    1259           0 :                 s = "' escape '\\\\'";
    1260             :         }
    1261         924 :         for (; *s; s++)
    1262         858 :                 res[i++] = *s;
    1263          66 :         res[i] = 0;
    1264          66 :         return res;
    1265             : }
    1266             : 
    1267             : char *
    1268           0 : ODBCParseID(const char *tab, const char *col, const char *arg, size_t len)
    1269             : {
    1270           0 :         size_t i;
    1271           0 :         char *res;
    1272           0 :         const char *s;
    1273           0 :         int fold = 1;
    1274             : 
    1275           0 :         while (len > 0 && (arg[--len] == ' ' || arg[len] == '\t'))
    1276             :                 ;
    1277           0 :         len++;
    1278           0 :         if (len >= 2 && *arg == '"' && arg[len - 1] == '"') {
    1279           0 :                 arg++;
    1280           0 :                 len -= 2;
    1281           0 :                 fold = 0;
    1282             :         }
    1283             : 
    1284           0 :         for (i = 0, s = arg; s < arg + len; i++, s++) {
    1285           0 :                 if (*s == '\'' || *s == '\\')
    1286           0 :                         i++;
    1287             :         }
    1288           0 :         i += strlen(tab) + strlen(col) + 10; /* ""."" = '' */
    1289           0 :         if (fold)
    1290           0 :                 i += 14;        /* 2 times upper() */
    1291           0 :         res = malloc(i + 1);
    1292           0 :         if (res == NULL)
    1293             :                 return NULL;
    1294           0 :         if (fold)
    1295           0 :                 snprintf(res, i, "upper(\"%s\".\"%s\") = upper('", tab, col);
    1296             :         else
    1297           0 :                 snprintf(res, i, "\"%s\".\"%s\" = '", tab, col);
    1298           0 :         for (i = strlen(res); len != 0; len--, arg++) {
    1299           0 :                 if (*arg == '\'' || *arg == '\\')
    1300           0 :                         res[i++] = *arg;
    1301           0 :                 res[i++] = *arg;
    1302             :         }
    1303           0 :         res[i++] = '\'';
    1304           0 :         if (fold)
    1305           0 :                 res[i++] = ')';
    1306           0 :         res[i] = 0;
    1307           0 :         return res;
    1308             : }
    1309             : 
    1310             : struct sql_types ODBC_sql_types[] = {
    1311             :         {
    1312             :                 .concise_type = SQL_CHAR,
    1313             :                 .type = SQL_CHAR,
    1314             :                 .datetime_interval_precision = UNAFFECTED,
    1315             :                 .length = 1,
    1316             :                 .scale = UNAFFECTED,
    1317             :                 .fixed = SQL_FALSE,
    1318             :         },
    1319             :         {
    1320             :                 .concise_type = SQL_VARCHAR,
    1321             :                 .type = SQL_VARCHAR,
    1322             :                 .datetime_interval_precision = UNAFFECTED,
    1323             :                 .length = 1,
    1324             :                 .scale = UNAFFECTED,
    1325             :                 .fixed = SQL_FALSE,
    1326             :         },
    1327             :         {
    1328             :                 .concise_type = SQL_LONGVARCHAR,
    1329             :                 .type = SQL_LONGVARCHAR,
    1330             :                 .precision = UNAFFECTED,
    1331             :                 .datetime_interval_precision = UNAFFECTED,
    1332             :                 .length = UNAFFECTED,
    1333             :                 .scale = UNAFFECTED,
    1334             :                 .fixed = SQL_FALSE,
    1335             :         },
    1336             :         {
    1337             :                 .concise_type = SQL_WCHAR,
    1338             :                 .type = SQL_WCHAR,
    1339             :                 .precision = UNAFFECTED,
    1340             :                 .datetime_interval_precision = UNAFFECTED,
    1341             :                 .length = UNAFFECTED,
    1342             :                 .scale = UNAFFECTED,
    1343             :                 .fixed = SQL_FALSE,
    1344             :         },
    1345             :         {
    1346             :                 .concise_type = SQL_WVARCHAR,
    1347             :                 .type = SQL_WVARCHAR,
    1348             :                 .precision = UNAFFECTED,
    1349             :                 .datetime_interval_precision = UNAFFECTED,
    1350             :                 .length = UNAFFECTED,
    1351             :                 .scale = UNAFFECTED,
    1352             :                 .fixed = SQL_FALSE,
    1353             :         },
    1354             :         {
    1355             :                 .concise_type = SQL_WLONGVARCHAR,
    1356             :                 .type = SQL_WLONGVARCHAR,
    1357             :                 .precision = UNAFFECTED,
    1358             :                 .datetime_interval_precision = UNAFFECTED,
    1359             :                 .length = UNAFFECTED,
    1360             :                 .scale = UNAFFECTED,
    1361             :                 .fixed = SQL_FALSE,
    1362             :         },
    1363             :         {
    1364             :                 .concise_type = SQL_DECIMAL,
    1365             :                 .type = SQL_DECIMAL,
    1366             :                 .precision = 17,
    1367             :                 .datetime_interval_precision = UNAFFECTED,
    1368             :                 .length = UNAFFECTED,
    1369             :                 .radix = 10,
    1370             :                 .fixed = SQL_TRUE,
    1371             :         },
    1372             :         {
    1373             :                 .concise_type = SQL_NUMERIC,
    1374             :                 .type = SQL_NUMERIC,
    1375             :                 .precision = 17,
    1376             :                 .datetime_interval_precision = UNAFFECTED,
    1377             :                 .length = UNAFFECTED,
    1378             :                 .radix = 10,
    1379             :                 .fixed = SQL_TRUE,
    1380             :         },
    1381             :         {
    1382             :                 .concise_type = SQL_BIT,
    1383             :                 .type = SQL_BIT,
    1384             :                 .precision = UNAFFECTED,
    1385             :                 .datetime_interval_precision = UNAFFECTED,
    1386             :                 .length = UNAFFECTED,
    1387             :                 .scale = UNAFFECTED,
    1388             :                 .fixed = SQL_FALSE,
    1389             :         },
    1390             :         {
    1391             :                 .concise_type = SQL_TINYINT,
    1392             :                 .type = SQL_TINYINT,
    1393             :                 .precision = UNAFFECTED,
    1394             :                 .datetime_interval_precision = UNAFFECTED,
    1395             :                 .length = UNAFFECTED,
    1396             :                 .scale = UNAFFECTED,
    1397             :                 .radix = 10,
    1398             :                 .fixed = SQL_TRUE,
    1399             :         },
    1400             :         {
    1401             :                 .concise_type = SQL_SMALLINT,
    1402             :                 .type = SQL_SMALLINT,
    1403             :                 .precision = UNAFFECTED,
    1404             :                 .datetime_interval_precision = UNAFFECTED,
    1405             :                 .length = UNAFFECTED,
    1406             :                 .scale = UNAFFECTED,
    1407             :                 .radix = 10,
    1408             :                 .fixed = SQL_TRUE,
    1409             :         },
    1410             :         {
    1411             :                 .concise_type = SQL_INTEGER,
    1412             :                 .type = SQL_INTEGER,
    1413             :                 .precision = UNAFFECTED,
    1414             :                 .datetime_interval_precision = UNAFFECTED,
    1415             :                 .length = UNAFFECTED,
    1416             :                 .scale = UNAFFECTED,
    1417             :                 .radix = 10,
    1418             :                 .fixed = SQL_TRUE,
    1419             :         },
    1420             :         {
    1421             :                 .concise_type = SQL_BIGINT,
    1422             :                 .type = SQL_BIGINT,
    1423             :                 .precision = UNAFFECTED,
    1424             :                 .datetime_interval_precision = UNAFFECTED,
    1425             :                 .length = UNAFFECTED,
    1426             :                 .scale = UNAFFECTED,
    1427             :                 .radix = 10,
    1428             :                 .fixed = SQL_TRUE,
    1429             :         },
    1430             :         {
    1431             :                 .concise_type = SQL_HUGEINT,
    1432             :                 .type = SQL_HUGEINT,
    1433             :                 .precision = UNAFFECTED,
    1434             :                 .datetime_interval_precision = UNAFFECTED,
    1435             :                 .length = UNAFFECTED,
    1436             :                 .scale = UNAFFECTED,
    1437             :                 .radix = 10,
    1438             :                 .fixed = SQL_TRUE,
    1439             :         },
    1440             :         {
    1441             :                 .concise_type = SQL_REAL,
    1442             :                 .type = SQL_REAL,
    1443             :                 .precision = FLT_MANT_DIG,
    1444             :                 .datetime_interval_precision = UNAFFECTED,
    1445             :                 .length = UNAFFECTED,
    1446             :                 .scale = UNAFFECTED,
    1447             :                 .radix = 2,
    1448             :                 .fixed = SQL_FALSE,
    1449             :         },
    1450             :         {
    1451             :                 .concise_type = SQL_FLOAT,
    1452             :                 .type = SQL_FLOAT,
    1453             :                 .precision = DBL_MANT_DIG,
    1454             :                 .datetime_interval_precision = UNAFFECTED,
    1455             :                 .length = UNAFFECTED,
    1456             :                 .scale = UNAFFECTED,
    1457             :                 .radix = 2,
    1458             :                 .fixed = SQL_FALSE,
    1459             :         },
    1460             :         {
    1461             :                 .concise_type = SQL_DOUBLE,
    1462             :                 .type = SQL_DOUBLE,
    1463             :                 .precision = DBL_MANT_DIG,
    1464             :                 .datetime_interval_precision = UNAFFECTED,
    1465             :                 .length = UNAFFECTED,
    1466             :                 .scale = UNAFFECTED,
    1467             :                 .radix = 2,
    1468             :                 .fixed = SQL_FALSE,
    1469             :         },
    1470             :         {
    1471             :                 .concise_type = SQL_BINARY,
    1472             :                 .type = SQL_BINARY,
    1473             :                 .datetime_interval_precision = UNAFFECTED,
    1474             :                 .length = 1,
    1475             :                 .scale = UNAFFECTED,
    1476             :                 .fixed = SQL_FALSE,
    1477             :         },
    1478             :         {
    1479             :                 .concise_type = SQL_VARBINARY,
    1480             :                 .type = SQL_VARBINARY,
    1481             :                 .datetime_interval_precision = UNAFFECTED,
    1482             :                 .length = 1,
    1483             :                 .scale = UNAFFECTED,
    1484             :                 .fixed = SQL_FALSE,
    1485             :         },
    1486             :         {
    1487             :                 .concise_type = SQL_LONGVARBINARY,
    1488             :                 .type = SQL_LONGVARBINARY,
    1489             :                 .precision = UNAFFECTED,
    1490             :                 .datetime_interval_precision = UNAFFECTED,
    1491             :                 .length = UNAFFECTED,
    1492             :                 .scale = UNAFFECTED,
    1493             :                 .fixed = SQL_FALSE,
    1494             :         },
    1495             :         {
    1496             :                 .concise_type = SQL_GUID,
    1497             :                 .type = SQL_GUID,
    1498             :                 .precision = UNAFFECTED,
    1499             :                 .datetime_interval_precision = UNAFFECTED,
    1500             :                 .length = UNAFFECTED,
    1501             :                 .scale = UNAFFECTED,
    1502             :                 .fixed = SQL_FALSE,
    1503             :         },
    1504             :         {
    1505             :                 .concise_type = SQL_TYPE_DATE,
    1506             :                 .type = SQL_DATETIME,
    1507             :                 .code = SQL_CODE_DATE,
    1508             :                 .datetime_interval_precision = UNAFFECTED,
    1509             :                 .length = UNAFFECTED,
    1510             :                 .scale = UNAFFECTED,
    1511             :                 .fixed = SQL_FALSE,
    1512             :         },
    1513             :         {
    1514             :                 .concise_type = SQL_TYPE_TIME,
    1515             :                 .type = SQL_DATETIME,
    1516             :                 .code = SQL_CODE_TIME,
    1517             :                 .datetime_interval_precision = UNAFFECTED,
    1518             :                 .length = UNAFFECTED,
    1519             :                 .scale = UNAFFECTED,
    1520             :                 .fixed = SQL_FALSE,
    1521             :         },
    1522             :         {
    1523             :                 .concise_type = SQL_TYPE_TIMESTAMP,
    1524             :                 .type = SQL_DATETIME,
    1525             :                 .code = SQL_CODE_TIMESTAMP,
    1526             :                 .precision = 6,
    1527             :                 .datetime_interval_precision = UNAFFECTED,
    1528             :                 .length = UNAFFECTED,
    1529             :                 .scale = UNAFFECTED,
    1530             :                 .fixed = SQL_FALSE,
    1531             :         },
    1532             :         {
    1533             :                 .concise_type = SQL_INTERVAL_MONTH,
    1534             :                 .type = SQL_INTERVAL,
    1535             :                 .code = SQL_CODE_MONTH,
    1536             :                 .datetime_interval_precision = 2,
    1537             :                 .length = UNAFFECTED,
    1538             :                 .scale = UNAFFECTED,
    1539             :                 .fixed = SQL_FALSE,
    1540             :         },
    1541             :         {
    1542             :                 .concise_type = SQL_INTERVAL_YEAR,
    1543             :                 .type = SQL_INTERVAL,
    1544             :                 .code = SQL_CODE_YEAR,
    1545             :                 .datetime_interval_precision = 2,
    1546             :                 .length = UNAFFECTED,
    1547             :                 .scale = UNAFFECTED,
    1548             :                 .fixed = SQL_FALSE,
    1549             :         },
    1550             :         {
    1551             :                 .concise_type = SQL_INTERVAL_YEAR_TO_MONTH,
    1552             :                 .type = SQL_INTERVAL,
    1553             :                 .code = SQL_CODE_YEAR_TO_MONTH,
    1554             :                 .datetime_interval_precision = 2,
    1555             :                 .length = UNAFFECTED,
    1556             :                 .scale = UNAFFECTED,
    1557             :                 .fixed = SQL_FALSE,
    1558             :         },
    1559             :         {
    1560             :                 .concise_type = SQL_INTERVAL_DAY,
    1561             :                 .type = SQL_INTERVAL,
    1562             :                 .code = SQL_CODE_DAY,
    1563             :                 .datetime_interval_precision = 2,
    1564             :                 .length = UNAFFECTED,
    1565             :                 .scale = UNAFFECTED,
    1566             :                 .fixed = SQL_FALSE,
    1567             :         },
    1568             :         {
    1569             :                 .concise_type = SQL_INTERVAL_HOUR,
    1570             :                 .type = SQL_INTERVAL,
    1571             :                 .code = SQL_CODE_HOUR,
    1572             :                 .datetime_interval_precision = 2,
    1573             :                 .length = UNAFFECTED,
    1574             :                 .scale = UNAFFECTED,
    1575             :                 .fixed = SQL_FALSE,
    1576             :         },
    1577             :         {
    1578             :                 .concise_type = SQL_INTERVAL_MINUTE,
    1579             :                 .type = SQL_INTERVAL,
    1580             :                 .code = SQL_CODE_MINUTE,
    1581             :                 .datetime_interval_precision = 2,
    1582             :                 .length = UNAFFECTED,
    1583             :                 .scale = UNAFFECTED,
    1584             :                 .fixed = SQL_FALSE,
    1585             :         },
    1586             :         {
    1587             :                 .concise_type = SQL_INTERVAL_SECOND,
    1588             :                 .type = SQL_INTERVAL,
    1589             :                 .code = SQL_CODE_SECOND,
    1590             :                 .precision = 6,
    1591             :                 .datetime_interval_precision = 2,
    1592             :                 .length = UNAFFECTED,
    1593             :                 .scale = UNAFFECTED,
    1594             :                 .fixed = SQL_FALSE,
    1595             :         },
    1596             :         {
    1597             :                 .concise_type = SQL_INTERVAL_DAY_TO_HOUR,
    1598             :                 .type = SQL_INTERVAL,
    1599             :                 .code = SQL_CODE_DAY_TO_HOUR,
    1600             :                 .datetime_interval_precision = 2,
    1601             :                 .length = UNAFFECTED,
    1602             :                 .scale = UNAFFECTED,
    1603             :                 .fixed = SQL_FALSE,
    1604             :         },
    1605             :         {
    1606             :                 .concise_type = SQL_INTERVAL_DAY_TO_MINUTE,
    1607             :                 .type = SQL_INTERVAL,
    1608             :                 .code = SQL_CODE_DAY_TO_MINUTE,
    1609             :                 .datetime_interval_precision = 2,
    1610             :                 .length = UNAFFECTED,
    1611             :                 .scale = UNAFFECTED,
    1612             :                 .fixed = SQL_FALSE,
    1613             :         },
    1614             :         {
    1615             :                 .concise_type = SQL_INTERVAL_DAY_TO_SECOND,
    1616             :                 .type = SQL_INTERVAL,
    1617             :                 .code = SQL_CODE_DAY_TO_SECOND,
    1618             :                 .precision = 6,
    1619             :                 .datetime_interval_precision = 2,
    1620             :                 .length = UNAFFECTED,
    1621             :                 .scale = UNAFFECTED,
    1622             :                 .fixed = SQL_FALSE,
    1623             :         },
    1624             :         {
    1625             :                 .concise_type = SQL_INTERVAL_HOUR_TO_MINUTE,
    1626             :                 .type = SQL_INTERVAL,
    1627             :                 .code = SQL_CODE_HOUR_TO_MINUTE,
    1628             :                 .datetime_interval_precision = 2,
    1629             :                 .length = UNAFFECTED,
    1630             :                 .scale = UNAFFECTED,
    1631             :                 .fixed = SQL_FALSE,
    1632             :         },
    1633             :         {
    1634             :                 .concise_type = SQL_INTERVAL_HOUR_TO_SECOND,
    1635             :                 .type = SQL_INTERVAL,
    1636             :                 .code = SQL_CODE_HOUR_TO_SECOND,
    1637             :                 .precision = 6,
    1638             :                 .datetime_interval_precision = 2,
    1639             :                 .length = UNAFFECTED,
    1640             :                 .scale = UNAFFECTED,
    1641             :                 .fixed = SQL_FALSE,
    1642             :         },
    1643             :         {
    1644             :                 .concise_type = SQL_INTERVAL_MINUTE_TO_SECOND,
    1645             :                 .type = SQL_INTERVAL,
    1646             :                 .code = SQL_CODE_MINUTE_TO_SECOND,
    1647             :                 .precision = 6,
    1648             :                 .datetime_interval_precision = 2,
    1649             :                 .length = UNAFFECTED,
    1650             :                 .scale = UNAFFECTED,
    1651             :                 .fixed = SQL_FALSE,
    1652             :         },
    1653             :         {
    1654             :                 0               /* sentinel */
    1655             :         },
    1656             : };
    1657             : 
    1658             : struct sql_types ODBC_c_types[] = {
    1659             :         {
    1660             :                 .concise_type = SQL_C_CHAR,
    1661             :                 .type = SQL_C_CHAR,
    1662             :                 .datetime_interval_precision = UNAFFECTED,
    1663             :                 .length = 1,
    1664             :                 .scale = UNAFFECTED,
    1665             :                 .fixed = SQL_FALSE,
    1666             :         },
    1667             :         {
    1668             :                 .concise_type = SQL_C_WCHAR,
    1669             :                 .type = SQL_C_WCHAR,
    1670             :                 .precision = UNAFFECTED,
    1671             :                 .datetime_interval_precision = UNAFFECTED,
    1672             :                 .length = UNAFFECTED,
    1673             :                 .scale = UNAFFECTED,
    1674             :                 .fixed = SQL_FALSE,
    1675             :         },
    1676             :         {
    1677             :                 .concise_type = SQL_C_BIT,
    1678             :                 .type = SQL_C_BIT,
    1679             :                 .precision = UNAFFECTED,
    1680             :                 .datetime_interval_precision = UNAFFECTED,
    1681             :                 .length = UNAFFECTED,
    1682             :                 .scale = UNAFFECTED,
    1683             :                 .fixed = SQL_FALSE,
    1684             :         },
    1685             :         {
    1686             :                 .concise_type = SQL_C_NUMERIC,
    1687             :                 .type = SQL_C_NUMERIC,
    1688             :                 .precision = 17,
    1689             :                 .datetime_interval_precision = UNAFFECTED,
    1690             :                 .length = UNAFFECTED,
    1691             :                 .radix = 10,
    1692             :                 .fixed = SQL_TRUE,
    1693             :         },
    1694             :         {
    1695             :                 .concise_type = SQL_C_STINYINT,
    1696             :                 .type = SQL_C_STINYINT,
    1697             :                 .precision = UNAFFECTED,
    1698             :                 .datetime_interval_precision = UNAFFECTED,
    1699             :                 .length = UNAFFECTED,
    1700             :                 .scale = UNAFFECTED,
    1701             :                 .radix = 10,
    1702             :                 .fixed = SQL_TRUE,
    1703             :         },
    1704             :         {
    1705             :                 .concise_type = SQL_C_UTINYINT,
    1706             :                 .type = SQL_C_UTINYINT,
    1707             :                 .precision = UNAFFECTED,
    1708             :                 .datetime_interval_precision = UNAFFECTED,
    1709             :                 .length = UNAFFECTED,
    1710             :                 .scale = UNAFFECTED,
    1711             :                 .radix = 10,
    1712             :                 .fixed = SQL_TRUE,
    1713             :         },
    1714             :         {
    1715             :                 .concise_type = SQL_C_TINYINT,
    1716             :                 .type = SQL_C_TINYINT,
    1717             :                 .precision = UNAFFECTED,
    1718             :                 .datetime_interval_precision = UNAFFECTED,
    1719             :                 .length = UNAFFECTED,
    1720             :                 .scale = UNAFFECTED,
    1721             :                 .radix = 10,
    1722             :                 .fixed = SQL_TRUE,
    1723             :         },
    1724             :         {
    1725             :                 .concise_type = SQL_C_SBIGINT,
    1726             :                 .type = SQL_C_SBIGINT,
    1727             :                 .precision = UNAFFECTED,
    1728             :                 .datetime_interval_precision = UNAFFECTED,
    1729             :                 .length = UNAFFECTED,
    1730             :                 .scale = UNAFFECTED,
    1731             :                 .radix = 10,
    1732             :                 .fixed = SQL_TRUE,
    1733             :         },
    1734             :         {
    1735             :                 .concise_type = SQL_C_UBIGINT,
    1736             :                 .type = SQL_C_UBIGINT,
    1737             :                 .precision = UNAFFECTED,
    1738             :                 .datetime_interval_precision = UNAFFECTED,
    1739             :                 .length = UNAFFECTED,
    1740             :                 .scale = UNAFFECTED,
    1741             :                 .radix = 10,
    1742             :                 .fixed = SQL_TRUE,
    1743             :         },
    1744             :         {
    1745             :                 .concise_type = SQL_C_SSHORT,
    1746             :                 .type = SQL_C_SSHORT,
    1747             :                 .precision = UNAFFECTED,
    1748             :                 .datetime_interval_precision = UNAFFECTED,
    1749             :                 .length = UNAFFECTED,
    1750             :                 .scale = UNAFFECTED,
    1751             :                 .radix = 10,
    1752             :                 .fixed = SQL_TRUE,
    1753             :         },
    1754             :         {
    1755             :                 .concise_type = SQL_C_USHORT,
    1756             :                 .type = SQL_C_USHORT,
    1757             :                 .precision = UNAFFECTED,
    1758             :                 .datetime_interval_precision = UNAFFECTED,
    1759             :                 .length = UNAFFECTED,
    1760             :                 .scale = UNAFFECTED,
    1761             :                 .radix = 10,
    1762             :                 .fixed = SQL_TRUE,
    1763             :         },
    1764             :         {
    1765             :                 .concise_type = SQL_C_SHORT,
    1766             :                 .type = SQL_C_SHORT,
    1767             :                 .precision = UNAFFECTED,
    1768             :                 .datetime_interval_precision = UNAFFECTED,
    1769             :                 .length = UNAFFECTED,
    1770             :                 .scale = UNAFFECTED,
    1771             :                 .radix = 10,
    1772             :                 .fixed = SQL_TRUE,
    1773             :         },
    1774             :         {
    1775             :                 .concise_type = SQL_C_SLONG,
    1776             :                 .type = SQL_C_SLONG,
    1777             :                 .precision = UNAFFECTED,
    1778             :                 .datetime_interval_precision = UNAFFECTED,
    1779             :                 .length = UNAFFECTED,
    1780             :                 .scale = UNAFFECTED,
    1781             :                 .radix = 10,
    1782             :                 .fixed = SQL_TRUE,
    1783             :         },
    1784             :         {
    1785             :                 .concise_type = SQL_C_ULONG,
    1786             :                 .type = SQL_C_ULONG,
    1787             :                 .precision = UNAFFECTED,
    1788             :                 .datetime_interval_precision = UNAFFECTED,
    1789             :                 .length = UNAFFECTED,
    1790             :                 .scale = UNAFFECTED,
    1791             :                 .radix = 10,
    1792             :                 .fixed = SQL_TRUE,
    1793             :         },
    1794             :         {
    1795             :                 .concise_type = SQL_C_LONG,
    1796             :                 .type = SQL_C_LONG,
    1797             :                 .precision = UNAFFECTED,
    1798             :                 .datetime_interval_precision = UNAFFECTED,
    1799             :                 .length = UNAFFECTED,
    1800             :                 .scale = UNAFFECTED,
    1801             :                 .radix = 10,
    1802             :                 .fixed = SQL_TRUE,
    1803             :         },
    1804             :         {
    1805             :                 .concise_type = SQL_C_FLOAT,
    1806             :                 .type = SQL_C_FLOAT,
    1807             :                 .precision = FLT_MANT_DIG,
    1808             :                 .datetime_interval_precision = UNAFFECTED,
    1809             :                 .length = UNAFFECTED,
    1810             :                 .scale = UNAFFECTED,
    1811             :                 .radix = 2,
    1812             :                 .fixed = SQL_FALSE,
    1813             :         },
    1814             :         {
    1815             :                 .concise_type = SQL_C_DOUBLE,
    1816             :                 .type = SQL_C_DOUBLE,
    1817             :                 .precision = DBL_MANT_DIG,
    1818             :                 .datetime_interval_precision = UNAFFECTED,
    1819             :                 .length = UNAFFECTED,
    1820             :                 .scale = UNAFFECTED,
    1821             :                 .radix = 2,
    1822             :                 .fixed = SQL_FALSE,
    1823             :         },
    1824             :         {
    1825             :                 .concise_type = SQL_C_BINARY,
    1826             :                 .type = SQL_C_BINARY,
    1827             :                 .precision = UNAFFECTED,
    1828             :                 .datetime_interval_precision = UNAFFECTED,
    1829             :                 .length = UNAFFECTED,
    1830             :                 .scale = UNAFFECTED,
    1831             :                 .fixed = SQL_FALSE,
    1832             :         },
    1833             :         {
    1834             :                 .concise_type = SQL_C_TYPE_DATE,
    1835             :                 .type = SQL_DATETIME,
    1836             :                 .code = SQL_CODE_DATE,
    1837             :                 .datetime_interval_precision = UNAFFECTED,
    1838             :                 .length = UNAFFECTED,
    1839             :                 .scale = UNAFFECTED,
    1840             :                 .fixed = SQL_FALSE,
    1841             :         },
    1842             :         {
    1843             :                 .concise_type = SQL_C_TYPE_TIME,
    1844             :                 .type = SQL_DATETIME,
    1845             :                 .code = SQL_CODE_TIME,
    1846             :                 .datetime_interval_precision = UNAFFECTED,
    1847             :                 .length = UNAFFECTED,
    1848             :                 .scale = UNAFFECTED,
    1849             :                 .fixed = SQL_FALSE,
    1850             :         },
    1851             :         {
    1852             :                 .concise_type = SQL_C_TYPE_TIMESTAMP,
    1853             :                 .type = SQL_DATETIME,
    1854             :                 .code = SQL_CODE_TIMESTAMP,
    1855             :                 .precision = 6,
    1856             :                 .datetime_interval_precision = UNAFFECTED,
    1857             :                 .length = UNAFFECTED,
    1858             :                 .scale = UNAFFECTED,
    1859             :                 .fixed = SQL_FALSE,
    1860             :         },
    1861             :         {
    1862             :                 .concise_type = SQL_C_INTERVAL_MONTH,
    1863             :                 .type = SQL_INTERVAL,
    1864             :                 .code = SQL_CODE_MONTH,
    1865             :                 .precision = UNAFFECTED,
    1866             :                 .datetime_interval_precision = 2,
    1867             :                 .length = UNAFFECTED,
    1868             :                 .scale = UNAFFECTED,
    1869             :                 .fixed = SQL_FALSE,
    1870             :         },
    1871             :         {
    1872             :                 .concise_type = SQL_C_INTERVAL_YEAR,
    1873             :                 .type = SQL_INTERVAL,
    1874             :                 .code = SQL_CODE_YEAR,
    1875             :                 .precision = UNAFFECTED,
    1876             :                 .datetime_interval_precision = 2,
    1877             :                 .length = UNAFFECTED,
    1878             :                 .scale = UNAFFECTED,
    1879             :                 .fixed = SQL_FALSE,
    1880             :         },
    1881             :         {
    1882             :                 .concise_type = SQL_C_INTERVAL_YEAR_TO_MONTH,
    1883             :                 .type = SQL_INTERVAL,
    1884             :                 .code = SQL_CODE_YEAR_TO_MONTH,
    1885             :                 .precision = UNAFFECTED,
    1886             :                 .datetime_interval_precision = 2,
    1887             :                 .length = UNAFFECTED,
    1888             :                 .scale = UNAFFECTED,
    1889             :                 .fixed = SQL_FALSE,
    1890             :         },
    1891             :         {
    1892             :                 .concise_type = SQL_C_INTERVAL_DAY,
    1893             :                 .type = SQL_INTERVAL,
    1894             :                 .code = SQL_CODE_DAY,
    1895             :                 .precision = UNAFFECTED,
    1896             :                 .datetime_interval_precision = 2,
    1897             :                 .length = UNAFFECTED,
    1898             :                 .scale = UNAFFECTED,
    1899             :                 .fixed = SQL_FALSE,
    1900             :         },
    1901             :         {
    1902             :                 .concise_type = SQL_C_INTERVAL_HOUR,
    1903             :                 .type = SQL_INTERVAL,
    1904             :                 .code = SQL_CODE_HOUR,
    1905             :                 .precision = UNAFFECTED,
    1906             :                 .datetime_interval_precision = 2,
    1907             :                 .length = UNAFFECTED,
    1908             :                 .scale = UNAFFECTED,
    1909             :                 .fixed = SQL_FALSE,
    1910             :         },
    1911             :         {
    1912             :                 .concise_type = SQL_C_INTERVAL_MINUTE,
    1913             :                 .type = SQL_INTERVAL,
    1914             :                 .code = SQL_CODE_MINUTE,
    1915             :                 .precision = UNAFFECTED,
    1916             :                 .datetime_interval_precision = 2,
    1917             :                 .length = UNAFFECTED,
    1918             :                 .scale = UNAFFECTED,
    1919             :                 .fixed = SQL_FALSE,
    1920             :         },
    1921             :         {
    1922             :                 .concise_type = SQL_C_INTERVAL_SECOND,
    1923             :                 .type = SQL_INTERVAL,
    1924             :                 .code = SQL_CODE_SECOND,
    1925             :                 .precision = UNAFFECTED,
    1926             :                 .datetime_interval_precision = 6,
    1927             :                 .length = UNAFFECTED,
    1928             :                 .scale = UNAFFECTED,
    1929             :                 .fixed = SQL_FALSE,
    1930             :         },
    1931             :         {
    1932             :                 .concise_type = SQL_C_INTERVAL_DAY_TO_HOUR,
    1933             :                 .type = SQL_INTERVAL,
    1934             :                 .code = SQL_CODE_DAY_TO_HOUR,
    1935             :                 .precision = UNAFFECTED,
    1936             :                 .datetime_interval_precision = 2,
    1937             :                 .length = UNAFFECTED,
    1938             :                 .scale = UNAFFECTED,
    1939             :                 .fixed = SQL_FALSE,
    1940             :         },
    1941             :         {
    1942             :                 .concise_type = SQL_C_INTERVAL_DAY_TO_MINUTE,
    1943             :                 .type = SQL_INTERVAL,
    1944             :                 .code = SQL_CODE_DAY_TO_MINUTE,
    1945             :                 .precision = UNAFFECTED,
    1946             :                 .datetime_interval_precision = 2,
    1947             :                 .length = UNAFFECTED,
    1948             :                 .scale = UNAFFECTED,
    1949             :                 .fixed = SQL_FALSE,
    1950             :         },
    1951             :         {
    1952             :                 .concise_type = SQL_C_INTERVAL_DAY_TO_SECOND,
    1953             :                 .type = SQL_INTERVAL,
    1954             :                 .code = SQL_CODE_DAY_TO_SECOND,
    1955             :                 .precision = UNAFFECTED,
    1956             :                 .datetime_interval_precision = 6,
    1957             :                 .length = UNAFFECTED,
    1958             :                 .scale = UNAFFECTED,
    1959             :                 .fixed = SQL_FALSE,
    1960             :         },
    1961             :         {
    1962             :                 .concise_type = SQL_C_INTERVAL_HOUR_TO_MINUTE,
    1963             :                 .type = SQL_INTERVAL,
    1964             :                 .code = SQL_CODE_HOUR_TO_MINUTE,
    1965             :                 .precision = UNAFFECTED,
    1966             :                 .datetime_interval_precision = 2,
    1967             :                 .length = UNAFFECTED,
    1968             :                 .scale = UNAFFECTED,
    1969             :                 .fixed = SQL_FALSE,
    1970             :         },
    1971             :         {
    1972             :                 .concise_type = SQL_C_INTERVAL_HOUR_TO_SECOND,
    1973             :                 .type = SQL_INTERVAL,
    1974             :                 .code = SQL_CODE_HOUR_TO_SECOND,
    1975             :                 .precision = UNAFFECTED,
    1976             :                 .datetime_interval_precision = 6,
    1977             :                 .length = UNAFFECTED,
    1978             :                 .scale = UNAFFECTED,
    1979             :                 .fixed = SQL_FALSE,
    1980             :         },
    1981             :         {
    1982             :                 .concise_type = SQL_C_INTERVAL_MINUTE_TO_SECOND,
    1983             :                 .type = SQL_INTERVAL,
    1984             :                 .code = SQL_CODE_MINUTE_TO_SECOND,
    1985             :                 .precision = UNAFFECTED,
    1986             :                 .datetime_interval_precision = 6,
    1987             :                 .length = UNAFFECTED,
    1988             :                 .scale = UNAFFECTED,
    1989             :                 .fixed = SQL_FALSE,
    1990             :         },
    1991             :         {
    1992             :                 .concise_type = SQL_C_GUID,
    1993             :                 .type = SQL_C_GUID,
    1994             :                 .precision = UNAFFECTED,
    1995             :                 .datetime_interval_precision = UNAFFECTED,
    1996             :                 .length = UNAFFECTED,
    1997             :                 .scale = UNAFFECTED,
    1998             :                 .fixed = SQL_FALSE,
    1999             :         },
    2000             :         {
    2001             :                 .concise_type = SQL_C_DEFAULT,
    2002             :                 .type = SQL_C_DEFAULT,
    2003             :                 .precision = UNAFFECTED,
    2004             :                 .datetime_interval_precision = UNAFFECTED,
    2005             :                 .length = UNAFFECTED,
    2006             :                 .scale = UNAFFECTED,
    2007             :                 .fixed = SQL_FALSE,
    2008             :         },
    2009             :         {
    2010             :                 0               /* sentinel */
    2011             :         },
    2012             : };
    2013             : 
    2014             : #ifdef ODBCDEBUG
    2015             : 
    2016             : #ifdef NATIVE_WIN32
    2017             : const wchar_t *ODBCdebug;
    2018             : #else
    2019             : const char *ODBCdebug;
    2020             : #endif
    2021             : static char unknown[32];
    2022             : 
    2023             : char *
    2024        6458 : translateCType(SQLSMALLINT ValueType)
    2025             : {
    2026        6458 :         switch (ValueType) {
    2027             :         case SQL_C_CHAR:
    2028             :                 return "SQL_C_CHAR";
    2029         438 :         case SQL_C_WCHAR:
    2030         438 :                 return "SQL_C_WCHAR";
    2031           0 :         case SQL_C_BINARY:
    2032           0 :                 return "SQL_C_BINARY";
    2033         143 :         case SQL_C_BIT:
    2034         143 :                 return "SQL_C_BIT";
    2035           0 :         case SQL_C_STINYINT:
    2036           0 :                 return "SQL_C_STINYINT";
    2037           0 :         case SQL_C_UTINYINT:
    2038           0 :                 return "SQL_C_UTINYINT";
    2039           0 :         case SQL_C_TINYINT:
    2040           0 :                 return "SQL_C_TINYINT";
    2041           5 :         case SQL_C_SSHORT:
    2042           5 :                 return "SQL_C_SSHORT";
    2043           0 :         case SQL_C_USHORT:
    2044           0 :                 return "SQL_C_USHORT";
    2045           0 :         case SQL_C_SHORT:
    2046           0 :                 return "SQL_C_SHORT";
    2047           0 :         case SQL_C_SLONG:
    2048           0 :                 return "SQL_C_SLONG";
    2049           0 :         case SQL_C_ULONG:
    2050           0 :                 return "SQL_C_ULONG";
    2051         865 :         case SQL_C_LONG:
    2052         865 :                 return "SQL_C_LONG";
    2053           0 :         case SQL_C_SBIGINT:
    2054           0 :                 return "SQL_C_SBIGINT";
    2055           0 :         case SQL_C_UBIGINT:
    2056           0 :                 return "SQL_C_UBIGINT";
    2057           0 :         case SQL_C_NUMERIC:
    2058           0 :                 return "SQL_C_NUMERIC";
    2059           0 :         case SQL_C_FLOAT:
    2060           0 :                 return "SQL_C_FLOAT";
    2061           3 :         case SQL_C_DOUBLE:
    2062           3 :                 return "SQL_C_DOUBLE";
    2063           3 :         case SQL_C_TYPE_DATE:
    2064           3 :                 return "SQL_C_TYPE_DATE";
    2065           3 :         case SQL_C_TYPE_TIME:
    2066           3 :                 return "SQL_C_TYPE_TIME";
    2067           0 :         case SQL_C_TYPE_TIMESTAMP:
    2068           0 :                 return "SQL_C_TYPE_TIMESTAMP";
    2069           0 :         case SQL_C_INTERVAL_YEAR:
    2070           0 :                 return "SQL_C_INTERVAL_YEAR";
    2071           0 :         case SQL_C_INTERVAL_MONTH:
    2072           0 :                 return "SQL_C_INTERVAL_MONTH";
    2073           0 :         case SQL_C_INTERVAL_YEAR_TO_MONTH:
    2074           0 :                 return "SQL_C_INTERVAL_YEAR_TO_MONTH";
    2075           0 :         case SQL_C_INTERVAL_DAY:
    2076           0 :                 return "SQL_C_INTERVAL_DAY";
    2077           0 :         case SQL_C_INTERVAL_HOUR:
    2078           0 :                 return "SQL_C_INTERVAL_HOUR";
    2079           0 :         case SQL_C_INTERVAL_MINUTE:
    2080           0 :                 return "SQL_C_INTERVAL_MINUTE";
    2081           0 :         case SQL_C_INTERVAL_SECOND:
    2082           0 :                 return "SQL_C_INTERVAL_SECOND";
    2083           0 :         case SQL_C_INTERVAL_DAY_TO_HOUR:
    2084           0 :                 return "SQL_C_INTERVAL_DAY_TO_HOUR";
    2085           0 :         case SQL_C_INTERVAL_DAY_TO_MINUTE:
    2086           0 :                 return "SQL_C_INTERVAL_DAY_TO_MINUTE";
    2087           0 :         case SQL_C_INTERVAL_DAY_TO_SECOND:
    2088           0 :                 return "SQL_C_INTERVAL_DAY_TO_SECOND";
    2089           0 :         case SQL_C_INTERVAL_HOUR_TO_MINUTE:
    2090           0 :                 return "SQL_C_INTERVAL_HOUR_TO_MINUTE";
    2091           0 :         case SQL_C_INTERVAL_HOUR_TO_SECOND:
    2092           0 :                 return "SQL_C_INTERVAL_HOUR_TO_SECOND";
    2093           0 :         case SQL_C_INTERVAL_MINUTE_TO_SECOND:
    2094           0 :                 return "SQL_C_INTERVAL_MINUTE_TO_SECOND";
    2095           0 :         case SQL_C_GUID:
    2096           0 :                 return "SQL_C_GUID";
    2097           0 :         case SQL_C_DEFAULT:
    2098           0 :                 return "SQL_C_DEFAULT";
    2099           0 :         case SQL_ARD_TYPE:
    2100           0 :                 return "SQL_ARD_TYPE";
    2101           0 :         case SQL_DATETIME:
    2102           0 :                 return "SQL_DATETIME";
    2103           0 :         case SQL_INTERVAL:
    2104           0 :                 return "SQL_INTERVAL";
    2105           0 :         default:
    2106           0 :                 snprintf(unknown, sizeof(unknown), "unknown (%d)",
    2107             :                          (int) ValueType);
    2108           0 :                 return unknown;
    2109             :         }
    2110             : }
    2111             : 
    2112             : char *
    2113           9 : translateSQLType(SQLSMALLINT ParameterType)
    2114             : {
    2115           9 :         switch (ParameterType) {
    2116             :         case SQL_CHAR:
    2117             :                 return "SQL_CHAR";
    2118           0 :         case SQL_VARCHAR:
    2119           0 :                 return "SQL_VARCHAR";
    2120           0 :         case SQL_LONGVARCHAR:
    2121           0 :                 return "SQL_LONGVARCHAR";
    2122           0 :         case SQL_BINARY:
    2123           0 :                 return "SQL_BINARY";
    2124           0 :         case SQL_VARBINARY:
    2125           0 :                 return "SQL_VARBINARY";
    2126           0 :         case SQL_LONGVARBINARY:
    2127           0 :                 return "SQL_LONGVARBINARY";
    2128           1 :         case SQL_TYPE_DATE:
    2129           1 :                 return "SQL_TYPE_DATE";
    2130           0 :         case SQL_INTERVAL_MONTH:
    2131           0 :                 return "SQL_INTERVAL_MONTH";
    2132           0 :         case SQL_INTERVAL_YEAR:
    2133           0 :                 return "SQL_INTERVAL_YEAR";
    2134           0 :         case SQL_INTERVAL_YEAR_TO_MONTH:
    2135           0 :                 return "SQL_INTERVAL_YEAR_TO_MONTH";
    2136           0 :         case SQL_INTERVAL_DAY:
    2137           0 :                 return "SQL_INTERVAL_DAY";
    2138           0 :         case SQL_INTERVAL_HOUR:
    2139           0 :                 return "SQL_INTERVAL_HOUR";
    2140           0 :         case SQL_INTERVAL_MINUTE:
    2141           0 :                 return "SQL_INTERVAL_MINUTE";
    2142           0 :         case SQL_INTERVAL_DAY_TO_HOUR:
    2143           0 :                 return "SQL_INTERVAL_DAY_TO_HOUR";
    2144           0 :         case SQL_INTERVAL_DAY_TO_MINUTE:
    2145           0 :                 return "SQL_INTERVAL_DAY_TO_MINUTE";
    2146           0 :         case SQL_INTERVAL_HOUR_TO_MINUTE:
    2147           0 :                 return "SQL_INTERVAL_HOUR_TO_MINUTE";
    2148           1 :         case SQL_TYPE_TIME:
    2149           1 :                 return "SQL_TYPE_TIME";
    2150           0 :         case SQL_TYPE_TIMESTAMP:
    2151           0 :                 return "SQL_TYPE_TIMESTAMP";
    2152           0 :         case SQL_INTERVAL_SECOND:
    2153           0 :                 return "SQL_INTERVAL_SECOND";
    2154           0 :         case SQL_INTERVAL_DAY_TO_SECOND:
    2155           0 :                 return "SQL_INTERVAL_DAY_TO_SECOND";
    2156           0 :         case SQL_INTERVAL_HOUR_TO_SECOND:
    2157           0 :                 return "SQL_INTERVAL_HOUR_TO_SECOND";
    2158           0 :         case SQL_INTERVAL_MINUTE_TO_SECOND:
    2159           0 :                 return "SQL_INTERVAL_MINUTE_TO_SECOND";
    2160           0 :         case SQL_DECIMAL:
    2161           0 :                 return "SQL_DECIMAL";
    2162           0 :         case SQL_NUMERIC:
    2163           0 :                 return "SQL_NUMERIC";
    2164           0 :         case SQL_FLOAT:
    2165           0 :                 return "SQL_FLOAT";
    2166           0 :         case SQL_REAL:
    2167           0 :                 return "SQL_REAL";
    2168           1 :         case SQL_DOUBLE:
    2169           1 :                 return "SQL_DOUBLE";
    2170           0 :         case SQL_WCHAR:
    2171           0 :                 return "SQL_WCHAR";
    2172           3 :         case SQL_WVARCHAR:
    2173           3 :                 return "SQL_WVARCHAR";
    2174           0 :         case SQL_WLONGVARCHAR:
    2175           0 :                 return "SQL_WLONGVARCHAR";
    2176           0 :         case SQL_BIT:
    2177           0 :                 return "SQL_BIT";
    2178           0 :         case SQL_TINYINT:
    2179           0 :                 return "SQL_TINYINT";
    2180           0 :         case SQL_SMALLINT:
    2181           0 :                 return "SQL_SMALLINT";
    2182           3 :         case SQL_INTEGER:
    2183           3 :                 return "SQL_INTEGER";
    2184           0 :         case SQL_BIGINT:
    2185           0 :                 return "SQL_BIGINT";
    2186           0 :         case SQL_HUGEINT:
    2187           0 :                 return "SQL_HUGEINT";
    2188           0 :         case SQL_GUID:
    2189           0 :                 return "SQL_GUID";
    2190           0 :         case SQL_DATETIME:
    2191           0 :                 return "SQL_DATETIME";
    2192           0 :         case SQL_INTERVAL:
    2193           0 :                 return "SQL_INTERVAL";
    2194           0 :         default:
    2195           0 :                 snprintf(unknown, sizeof(unknown), "unknown (%d)",
    2196             :                          (int) ParameterType);
    2197           0 :                 return unknown;
    2198             :         }
    2199             : }
    2200             : 
    2201             : char *
    2202          60 : translateFieldIdentifier(SQLSMALLINT FieldIdentifier)
    2203             : {
    2204          60 :         switch (FieldIdentifier) {
    2205             :         case SQL_COLUMN_LENGTH:
    2206             :                 return "SQL_COLUMN_LENGTH";
    2207           0 :         case SQL_COLUMN_PRECISION:
    2208           0 :                 return "SQL_COLUMN_PRECISION";
    2209           0 :         case SQL_COLUMN_SCALE:
    2210           0 :                 return "SQL_COLUMN_SCALE";
    2211           0 :         case SQL_DESC_ALLOC_TYPE:
    2212           0 :                 return "SQL_DESC_ALLOC_TYPE";
    2213           0 :         case SQL_DESC_ARRAY_SIZE:
    2214           0 :                 return "SQL_DESC_ARRAY_SIZE";
    2215           0 :         case SQL_DESC_ARRAY_STATUS_PTR:
    2216           0 :                 return "SQL_DESC_ARRAY_STATUS_PTR";
    2217           0 :         case SQL_DESC_AUTO_UNIQUE_VALUE:
    2218           0 :                 return "SQL_DESC_AUTO_UNIQUE_VALUE";
    2219           0 :         case SQL_DESC_BASE_COLUMN_NAME:
    2220           0 :                 return "SQL_DESC_BASE_COLUMN_NAME";
    2221           0 :         case SQL_DESC_BASE_TABLE_NAME:
    2222           0 :                 return "SQL_DESC_BASE_TABLE_NAME";
    2223           0 :         case SQL_DESC_BIND_OFFSET_PTR:
    2224           0 :                 return "SQL_DESC_BIND_OFFSET_PTR";
    2225           0 :         case SQL_DESC_BIND_TYPE:
    2226           0 :                 return "SQL_DESC_BIND_TYPE";
    2227           0 :         case SQL_DESC_CASE_SENSITIVE:
    2228           0 :                 return "SQL_DESC_CASE_SENSITIVE";
    2229           0 :         case SQL_DESC_CATALOG_NAME:
    2230           0 :                 return "SQL_DESC_CATALOG_NAME";
    2231           9 :         case SQL_DESC_CONCISE_TYPE:
    2232           9 :                 return "SQL_DESC_CONCISE_TYPE";
    2233           0 :         case SQL_DESC_COUNT:
    2234           0 :                 return "SQL_DESC_COUNT";
    2235           0 :         case SQL_DESC_DATA_PTR:
    2236           0 :                 return "SQL_DESC_DATA_PTR";
    2237           0 :         case SQL_DESC_DATETIME_INTERVAL_CODE:
    2238           0 :                 return "SQL_DESC_DATETIME_INTERVAL_CODE";
    2239           0 :         case SQL_DESC_DATETIME_INTERVAL_PRECISION:
    2240           0 :                 return "SQL_DESC_DATETIME_INTERVAL_PRECISION";
    2241           2 :         case SQL_DESC_DISPLAY_SIZE:
    2242           2 :                 return "SQL_DESC_DISPLAY_SIZE";
    2243           7 :         case SQL_DESC_FIXED_PREC_SCALE:
    2244           7 :                 return "SQL_DESC_FIXED_PREC_SCALE";
    2245           0 :         case SQL_DESC_INDICATOR_PTR:
    2246           0 :                 return "SQL_DESC_INDICATOR_PTR";
    2247           0 :         case SQL_DESC_LABEL:
    2248           0 :                 return "SQL_DESC_LABEL";
    2249           9 :         case SQL_DESC_LENGTH:
    2250           9 :                 return "SQL_DESC_LENGTH";
    2251           0 :         case SQL_DESC_LITERAL_PREFIX:
    2252           0 :                 return "SQL_DESC_LITERAL_PREFIX";
    2253           0 :         case SQL_DESC_LITERAL_SUFFIX:
    2254           0 :                 return "SQL_DESC_LITERAL_SUFFIX";
    2255           0 :         case SQL_DESC_LOCAL_TYPE_NAME:
    2256           0 :                 return "SQL_DESC_LOCAL_TYPE_NAME";
    2257           7 :         case SQL_DESC_NAME:
    2258           7 :                 return "SQL_DESC_NAME";
    2259           0 :         case SQL_DESC_NULLABLE:
    2260           0 :                 return "SQL_DESC_NULLABLE";
    2261           0 :         case SQL_DESC_NUM_PREC_RADIX:
    2262           0 :                 return "SQL_DESC_NUM_PREC_RADIX";
    2263           0 :         case SQL_DESC_OCTET_LENGTH:
    2264           0 :                 return "SQL_DESC_OCTET_LENGTH";
    2265           0 :         case SQL_DESC_OCTET_LENGTH_PTR:
    2266           0 :                 return "SQL_DESC_OCTET_LENGTH_PTR";
    2267           0 :         case SQL_DESC_PARAMETER_TYPE:
    2268           0 :                 return "SQL_DESC_PARAMETER_TYPE";
    2269           0 :         case SQL_DESC_PRECISION:
    2270           0 :                 return "SQL_DESC_PRECISION";
    2271           0 :         case SQL_DESC_ROWS_PROCESSED_PTR:
    2272           0 :                 return "SQL_DESC_ROWS_PROCESSED_PTR";
    2273           0 :         case SQL_DESC_ROWVER:
    2274           0 :                 return "SQL_DESC_ROWVER";
    2275           7 :         case SQL_DESC_SCALE:
    2276           7 :                 return "SQL_DESC_SCALE";
    2277           0 :         case SQL_DESC_SCHEMA_NAME:
    2278           0 :                 return "SQL_DESC_SCHEMA_NAME";
    2279           0 :         case SQL_DESC_SEARCHABLE:
    2280           0 :                 return "SQL_DESC_SEARCHABLE";
    2281           0 :         case SQL_DESC_TABLE_NAME:
    2282           0 :                 return "SQL_DESC_TABLE_NAME";
    2283           0 :         case SQL_DESC_TYPE:
    2284           0 :                 return "SQL_DESC_TYPE";
    2285           7 :         case SQL_DESC_TYPE_NAME:
    2286           7 :                 return "SQL_DESC_TYPE_NAME";
    2287           0 :         case SQL_DESC_UNNAMED:
    2288           0 :                 return "SQL_DESC_UNNAMED";
    2289          12 :         case SQL_DESC_UNSIGNED:
    2290          12 :                 return "SQL_DESC_UNSIGNED";
    2291           0 :         case SQL_DESC_UPDATABLE:
    2292           0 :                 return "SQL_DESC_UPDATABLE";
    2293           0 :         default:
    2294           0 :                 snprintf(unknown, sizeof(unknown), "unknown (%d)",
    2295             :                          (int) FieldIdentifier);
    2296           0 :                 return unknown;
    2297             :         }
    2298             : }
    2299             : 
    2300             : char *
    2301        1001 : translateFetchOrientation(SQLUSMALLINT FetchOrientation)
    2302             : {
    2303        1001 :         switch (FetchOrientation) {
    2304             :         case SQL_FETCH_NEXT:
    2305             :                 return "SQL_FETCH_NEXT";
    2306           0 :         case SQL_FETCH_FIRST:
    2307           0 :                 return "SQL_FETCH_FIRST";
    2308           0 :         case SQL_FETCH_LAST:
    2309           0 :                 return "SQL_FETCH_LAST";
    2310           0 :         case SQL_FETCH_PRIOR:
    2311           0 :                 return "SQL_FETCH_PRIOR";
    2312           0 :         case SQL_FETCH_RELATIVE:
    2313           0 :                 return "SQL_FETCH_RELATIVE";
    2314           0 :         case SQL_FETCH_ABSOLUTE:
    2315           0 :                 return "SQL_FETCH_ABSOLUTE";
    2316           0 :         case SQL_FETCH_BOOKMARK:
    2317           0 :                 return "SQL_FETCH_BOOKMARK";
    2318           0 :         default:
    2319           0 :                 snprintf(unknown, sizeof(unknown), "unknown (%u)", (unsigned int) FetchOrientation);
    2320           0 :                 return unknown;
    2321             :         }
    2322             : }
    2323             : 
    2324             : char *
    2325           8 : translateConnectAttribute(SQLINTEGER Attribute)
    2326             : {
    2327           8 :         switch (Attribute) {
    2328             :         case SQL_ATTR_ACCESS_MODE:
    2329             :                 return "SQL_ATTR_ACCESS_MODE";
    2330             : #ifdef SQL_ATTR_ANSI_APP
    2331           5 :         case SQL_ATTR_ANSI_APP:
    2332           5 :                 return "SQL_ATTR_ANSI_APP";
    2333             : #endif
    2334             : #ifdef SQL_ATTR_ASYNC_DBC_EVENT
    2335             :         case SQL_ATTR_ASYNC_DBC_EVENT:
    2336             :                 return "SQL_ATTR_ASYNC_DBC_EVENT";
    2337             : #endif
    2338             : #ifdef SQL_ATTR_ASYNC_DBC_FUNCTIONS_ENABLE
    2339             :         case SQL_ATTR_ASYNC_DBC_FUNCTIONS_ENABLE:
    2340             :                 return "SQL_ATTR_ASYNC_DBC_FUNCTIONS_ENABLE";
    2341             : #endif
    2342             : #ifdef SQL_ATTR_ASYNC_DBC_PCALLBACK
    2343             :         case SQL_ATTR_ASYNC_DBC_PCALLBACK:
    2344             :                 return "SQL_ATTR_ASYNC_DBC_PCALLBACK";
    2345             : #endif
    2346             : #ifdef SQL_ATTR_ASYNC_DBC_PCONTEXT
    2347             :         case SQL_ATTR_ASYNC_DBC_PCONTEXT:
    2348             :                 return "SQL_ATTR_ASYNC_DBC_PCONTEXT";
    2349             : #endif
    2350           0 :         case SQL_ATTR_ASYNC_ENABLE:
    2351           0 :                 return "SQL_ATTR_ASYNC_ENABLE";
    2352           3 :         case SQL_ATTR_AUTOCOMMIT:
    2353           3 :                 return "SQL_ATTR_AUTOCOMMIT";
    2354           0 :         case SQL_ATTR_AUTO_IPD:
    2355           0 :                 return "SQL_ATTR_AUTO_IPD";
    2356           0 :         case SQL_ATTR_CONNECTION_DEAD:
    2357           0 :                 return "SQL_ATTR_CONNECTION_DEAD";
    2358           0 :         case SQL_ATTR_CONNECTION_TIMEOUT:
    2359           0 :                 return "SQL_ATTR_CONNECTION_TIMEOUT";
    2360           0 :         case SQL_ATTR_CURRENT_CATALOG:
    2361           0 :                 return "SQL_ATTR_CURRENT_CATALOG";
    2362             : #ifdef SQL_ATTR_DBC_INFO_TOKEN
    2363             :         case SQL_ATTR_DBC_INFO_TOKEN:
    2364             :                 return "SQL_ATTR_DBC_INFO_TOKEN";
    2365             : #endif
    2366           0 :         case SQL_ATTR_DISCONNECT_BEHAVIOR:
    2367           0 :                 return "SQL_ATTR_DISCONNECT_BEHAVIOR";
    2368           0 :         case SQL_ATTR_ENLIST_IN_DTC:
    2369           0 :                 return "SQL_ATTR_ENLIST_IN_DTC";
    2370           0 :         case SQL_ATTR_ENLIST_IN_XA:
    2371           0 :                 return "SQL_ATTR_ENLIST_IN_XA";
    2372           0 :         case SQL_ATTR_LOGIN_TIMEOUT:
    2373           0 :                 return "SQL_ATTR_LOGIN_TIMEOUT";
    2374           0 :         case SQL_ATTR_METADATA_ID:
    2375           0 :                 return "SQL_ATTR_METADATA_ID";
    2376           0 :         case SQL_ATTR_ODBC_CURSORS:
    2377           0 :                 return "SQL_ATTR_ODBC_CURSORS";
    2378           0 :         case SQL_ATTR_PACKET_SIZE:
    2379           0 :                 return "SQL_ATTR_PACKET_SIZE";
    2380           0 :         case SQL_ATTR_QUIET_MODE:
    2381           0 :                 return "SQL_ATTR_QUIET_MODE";
    2382           0 :         case SQL_ATTR_TRACE:
    2383           0 :                 return "SQL_ATTR_TRACE";
    2384           0 :         case SQL_ATTR_TRACEFILE:
    2385           0 :                 return "SQL_ATTR_TRACEFILE";
    2386           0 :         case SQL_ATTR_TRANSLATE_LIB:
    2387           0 :                 return "SQL_ATTR_TRANSLATE_LIB";
    2388           0 :         case SQL_ATTR_TRANSLATE_OPTION:
    2389           0 :                 return "SQL_ATTR_TRANSLATE_OPTION";
    2390           0 :         case SQL_ATTR_TXN_ISOLATION:
    2391           0 :                 return "SQL_ATTR_TXN_ISOLATION";
    2392           0 :         default:
    2393           0 :                 snprintf(unknown, sizeof(unknown), "unknown (%d)",
    2394             :                          (int) Attribute);
    2395           0 :                 return unknown;
    2396             :         }
    2397             : }
    2398             : 
    2399             : char *
    2400           0 : translateConnectOption(SQLUSMALLINT Option)
    2401             : {
    2402           0 :         switch (Option) {
    2403             :         case SQL_ACCESS_MODE:
    2404             :                 return "SQL_ACCESS_MODE";
    2405           0 :         case SQL_AUTOCOMMIT:
    2406           0 :                 return "SQL_AUTOCOMMIT";
    2407           0 :         case SQL_LOGIN_TIMEOUT:
    2408           0 :                 return "SQL_LOGIN_TIMEOUT";
    2409           0 :         case SQL_ODBC_CURSORS:
    2410           0 :                 return "SQL_ODBC_CURSORS";
    2411           0 :         case SQL_OPT_TRACE:
    2412           0 :                 return "SQL_OPT_TRACE";
    2413           0 :         case SQL_PACKET_SIZE:
    2414           0 :                 return "SQL_PACKET_SIZE";
    2415           0 :         case SQL_TRANSLATE_OPTION:
    2416           0 :                 return "SQL_TRANSLATE_OPTION";
    2417           0 :         case SQL_TXN_ISOLATION:
    2418           0 :                 return "SQL_TXN_ISOLATION";
    2419           0 :         case SQL_QUIET_MODE:
    2420           0 :                 return "SQL_QUIET_MODE";
    2421           0 :         case SQL_CURRENT_QUALIFIER:
    2422           0 :                 return "SQL_CURRENT_QUALIFIER";
    2423           0 :         case SQL_OPT_TRACEFILE:
    2424           0 :                 return "SQL_OPT_TRACEFILE";
    2425           0 :         case SQL_TRANSLATE_DLL:
    2426           0 :                 return "SQL_TRANSLATE_DLL";
    2427           0 :         default:
    2428           0 :                 return translateConnectAttribute((SQLSMALLINT) Option);
    2429             :         }
    2430             : }
    2431             : 
    2432             : char *
    2433          82 : translateEnvAttribute(SQLINTEGER Attribute)
    2434             : {
    2435          82 :         switch (Attribute) {
    2436             :         case SQL_ATTR_ODBC_VERSION:
    2437             :                 return "SQL_ATTR_ODBC_VERSION";
    2438           0 :         case SQL_ATTR_OUTPUT_NTS:
    2439           0 :                 return "SQL_ATTR_OUTPUT_NTS";
    2440           0 :         case SQL_ATTR_CONNECTION_POOLING:
    2441           0 :                 return "SQL_ATTR_CONNECTION_POOLING";
    2442           0 :         case SQL_ATTR_CP_MATCH:
    2443           0 :                 return "SQL_ATTR_CP_MATCH";
    2444           0 :         default:
    2445           0 :                 snprintf(unknown, sizeof(unknown), "unknown (%d)",
    2446             :                          (int) Attribute);
    2447           0 :                 return unknown;
    2448             :         }
    2449             : }
    2450             : 
    2451             : char *
    2452         112 : translateStmtAttribute(SQLINTEGER Attribute)
    2453             : {
    2454         112 :         switch (Attribute) {
    2455             :         case SQL_ATTR_APP_PARAM_DESC:
    2456             :                 return "SQL_ATTR_APP_PARAM_DESC";
    2457          19 :         case SQL_ATTR_APP_ROW_DESC:
    2458          19 :                 return "SQL_ATTR_APP_ROW_DESC";
    2459           0 :         case SQL_ATTR_ASYNC_ENABLE:
    2460           0 :                 return "SQL_ATTR_ASYNC_ENABLE";
    2461           0 :         case SQL_ATTR_CONCURRENCY:
    2462           0 :                 return "SQL_ATTR_CONCURRENCY";
    2463           0 :         case SQL_ATTR_CURSOR_SCROLLABLE:
    2464           0 :                 return "SQL_ATTR_CURSOR_SCROLLABLE";
    2465           0 :         case SQL_ATTR_CURSOR_SENSITIVITY:
    2466           0 :                 return "SQL_ATTR_CURSOR_SENSITIVITY";
    2467           0 :         case SQL_ATTR_CURSOR_TYPE:
    2468           0 :                 return "SQL_ATTR_CURSOR_TYPE";
    2469          19 :         case SQL_ATTR_IMP_PARAM_DESC:
    2470          19 :                 return "SQL_ATTR_IMP_PARAM_DESC";
    2471          19 :         case SQL_ATTR_IMP_ROW_DESC:
    2472          19 :                 return "SQL_ATTR_IMP_ROW_DESC";
    2473          12 :         case SQL_ATTR_MAX_LENGTH:
    2474          12 :                 return "SQL_ATTR_MAX_LENGTH";
    2475          12 :         case SQL_ATTR_MAX_ROWS:
    2476          12 :                 return "SQL_ATTR_MAX_ROWS";
    2477           0 :         case SQL_ATTR_NOSCAN:
    2478           0 :                 return "SQL_ATTR_NOSCAN";
    2479           0 :         case SQL_ATTR_PARAM_BIND_OFFSET_PTR:
    2480           0 :                 return "SQL_ATTR_PARAM_BIND_OFFSET_PTR";
    2481           0 :         case SQL_ATTR_PARAM_BIND_TYPE:
    2482           0 :                 return "SQL_ATTR_PARAM_BIND_TYPE";
    2483           0 :         case SQL_ATTR_PARAM_OPERATION_PTR:
    2484           0 :                 return "SQL_ATTR_PARAM_OPERATION_PTR";
    2485           0 :         case SQL_ATTR_PARAM_STATUS_PTR:
    2486           0 :                 return "SQL_ATTR_PARAM_STATUS_PTR";
    2487           0 :         case SQL_ATTR_PARAMS_PROCESSED_PTR:
    2488           0 :                 return "SQL_ATTR_PARAMS_PROCESSED_PTR";
    2489           0 :         case SQL_ATTR_PARAMSET_SIZE:
    2490           0 :                 return "SQL_ATTR_PARAMSET_SIZE";
    2491           0 :         case SQL_ATTR_RETRIEVE_DATA:
    2492           0 :                 return "SQL_ATTR_RETRIEVE_DATA";
    2493           0 :         case SQL_ATTR_ROW_ARRAY_SIZE:
    2494           0 :                 return "SQL_ATTR_ROW_ARRAY_SIZE";
    2495           0 :         case SQL_ROWSET_SIZE:
    2496           0 :                 return "SQL_ROWSET_SIZE";
    2497           0 :         case SQL_ATTR_ROW_BIND_OFFSET_PTR:
    2498           0 :                 return "SQL_ATTR_ROW_BIND_OFFSET_PTR";
    2499           0 :         case SQL_ATTR_ROW_BIND_TYPE:
    2500           0 :                 return "SQL_ATTR_ROW_BIND_TYPE";
    2501           0 :         case SQL_ATTR_ROW_NUMBER:
    2502           0 :                 return "SQL_ATTR_ROW_NUMBER";
    2503           0 :         case SQL_ATTR_ROW_OPERATION_PTR:
    2504           0 :                 return "SQL_ATTR_ROW_OPERATION_PTR";
    2505           0 :         case SQL_ATTR_ROW_STATUS_PTR:
    2506           0 :                 return "SQL_ATTR_ROW_STATUS_PTR";
    2507           0 :         case SQL_ATTR_ROWS_FETCHED_PTR:
    2508           0 :                 return "SQL_ATTR_ROWS_FETCHED_PTR";
    2509           0 :         case SQL_ATTR_METADATA_ID:
    2510           0 :                 return "SQL_ATTR_METADATA_ID";
    2511           0 :         case SQL_ATTR_ENABLE_AUTO_IPD:
    2512           0 :                 return "SQL_ATTR_ENABLE_AUTO_IPD";
    2513           0 :         case SQL_ATTR_FETCH_BOOKMARK_PTR:
    2514           0 :                 return "SQL_ATTR_FETCH_BOOKMARK_PTR";
    2515           0 :         case SQL_ATTR_KEYSET_SIZE:
    2516           0 :                 return "SQL_ATTR_KEYSET_SIZE";
    2517          12 :         case SQL_ATTR_QUERY_TIMEOUT:
    2518          12 :                 return "SQL_ATTR_QUERY_TIMEOUT";
    2519           0 :         case SQL_ATTR_SIMULATE_CURSOR:
    2520           0 :                 return "SQL_ATTR_SIMULATE_CURSOR";
    2521           0 :         case SQL_ATTR_USE_BOOKMARKS:
    2522           0 :                 return "SQL_ATTR_USE_BOOKMARKS";
    2523           0 :         default:
    2524           0 :                 snprintf(unknown, sizeof(unknown), "unknown (%d)",
    2525             :                          (int) Attribute);
    2526           0 :                 return unknown;
    2527             :         }
    2528             : }
    2529             : 
    2530             : char *
    2531           0 : translateStmtOption(SQLUSMALLINT Option)
    2532             : {
    2533           0 :         switch (Option) {
    2534             :         case SQL_QUERY_TIMEOUT:
    2535             :                 return "SQL_QUERY_TIMEOUT";
    2536           0 :         case SQL_MAX_ROWS:
    2537           0 :                 return "SQL_MAX_ROWS";
    2538           0 :         case SQL_NOSCAN:
    2539           0 :                 return "SQL_NOSCAN";
    2540           0 :         case SQL_MAX_LENGTH:
    2541           0 :                 return "SQL_MAX_LENGTH";
    2542           0 :         case SQL_ASYNC_ENABLE:
    2543           0 :                 return "SQL_ASYNC_ENABLE";
    2544           0 :         case SQL_BIND_TYPE:
    2545           0 :                 return "SQL_BIND_TYPE";
    2546           0 :         case SQL_CURSOR_TYPE:
    2547           0 :                 return "SQL_CURSOR_TYPE";
    2548           0 :         case SQL_CONCURRENCY:
    2549           0 :                 return "SQL_CONCURRENCY";
    2550           0 :         case SQL_KEYSET_SIZE:
    2551           0 :                 return "SQL_KEYSET_SIZE";
    2552           0 :         case SQL_ROWSET_SIZE:
    2553           0 :                 return "SQL_ROWSET_SIZE";
    2554           0 :         case SQL_SIMULATE_CURSOR:
    2555           0 :                 return "SQL_SIMULATE_CURSOR";
    2556           0 :         case SQL_RETRIEVE_DATA:
    2557           0 :                 return "SQL_RETRIEVE_DATA";
    2558           0 :         case SQL_USE_BOOKMARKS:
    2559           0 :                 return "SQL_USE_BOOKMARKS";
    2560           0 :         case SQL_ROW_NUMBER:
    2561           0 :                 return "SQL_ROW_NUMBER";
    2562           0 :         default:
    2563           0 :                 snprintf(unknown, sizeof(unknown), "unknown (%u)", (unsigned int) Option);
    2564           0 :                 return unknown;
    2565             :         }
    2566             : }
    2567             : 
    2568             : char *
    2569           2 : translateCompletionType(SQLSMALLINT CompletionType)
    2570             : {
    2571           2 :         switch (CompletionType) {
    2572             :         case SQL_COMMIT:
    2573             :                 return "SQL_COMMIT";
    2574           1 :         case SQL_ROLLBACK:
    2575           1 :                 return "SQL_ROLLBACK";
    2576           0 :         default:
    2577           0 :                 snprintf(unknown, sizeof(unknown), "unknown (%d)",
    2578             :                          (int) CompletionType);
    2579           0 :                 return unknown;
    2580             :         }
    2581             : }
    2582             : 
    2583             : void
    2584           0 : setODBCdebug(const char *filename, bool overrideEnvVar)
    2585             : {
    2586           0 :         if (!overrideEnvVar) {
    2587             : #ifdef NATIVE_WIN32
    2588             :                 void *value = _wgetenv(L"ODBCDEBUG");
    2589             : #else
    2590           0 :                 void *value = getenv("ODBCDEBUG");
    2591             : #endif
    2592           0 :                 if (value != NULL)
    2593             :                         return;    // do not override
    2594             :         }
    2595             : 
    2596           0 :         free((void*)ODBCdebug);
    2597             : 
    2598             : #ifdef NATIVE_WIN32
    2599             :         size_t attrlen = strlen(filename);
    2600             :         SQLWCHAR *wattr = malloc((attrlen + 1) * sizeof(SQLWCHAR));
    2601             :         if (ODBCutf82wchar(filename,
    2602             :                                 (SQLINTEGER) attrlen,
    2603             :                                 wattr,
    2604             :                                 (SQLLEN) ((attrlen + 1) * sizeof(SQLWCHAR)),
    2605             :                                 NULL,
    2606             :                                 NULL)) {
    2607             :                 free(wattr);
    2608             :                 wattr = NULL;
    2609             :         }
    2610             :         ODBCdebug = wattr;
    2611             : #else
    2612           0 :         ODBCdebug = strdup(filename);
    2613             : #endif
    2614             : }
    2615             : 
    2616             : 
    2617             : #endif

Generated by: LCOV version 1.14