LCOV - code coverage report
Current view: top level - clients/odbc/driver - ODBCUtil.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 92 927 9.9 %
Date: 2024-04-25 20:03:45 Functions: 6 17 35.3 %

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

Generated by: LCOV version 1.14