LCOV - code coverage report
Current view: top level - clients/odbc/driver - ODBCUtil.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 27 954 2.8 %
Date: 2021-10-13 02:24:04 Functions: 3 17 17.6 %

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

Generated by: LCOV version 1.14