LCOV - code coverage report
Current view: top level - src/odbc - odbc_util.c (source / functions) Hit Total Coverage
Test: FreeTDS coverage Lines: 371 453 81.9 %
Date: 2026-03-24 22:22:09 Functions: 20 20 100.0 %

          Line data    Source code
       1             : /* FreeTDS - Library of routines accessing Sybase and Microsoft databases
       2             :  * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005  Brian Bruns
       3             :  * Copyright (C) 2005-2010  Frediano Ziglio
       4             :  *
       5             :  * This library is free software; you can redistribute it and/or
       6             :  * modify it under the terms of the GNU Library General Public
       7             :  * License as published by the Free Software Foundation; either
       8             :  * version 2 of the License, or (at your option) any later version.
       9             :  *
      10             :  * This library is distributed in the hope that it will be useful,
      11             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      12             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13             :  * Library General Public License for more details.
      14             :  *
      15             :  * You should have received a copy of the GNU Library General Public
      16             :  * License along with this library; if not, write to the
      17             :  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
      18             :  * Boston, MA 02111-1307, USA.
      19             :  */
      20             : 
      21             : #include <config.h>
      22             : 
      23             : #if HAVE_STDLIB_H
      24             : #include <stdlib.h>
      25             : #endif /* HAVE_STDLIB_H */
      26             : 
      27             : #include <stddef.h>
      28             : 
      29             : #if HAVE_STRING_H
      30             : #include <string.h>
      31             : #endif /* HAVE_STRING_H */
      32             : 
      33             : #include <assert.h>
      34             : 
      35             : #include <freetds/odbc.h>
      36             : #include <freetds/tds/iconv.h>
      37             : #include <freetds/utils/string.h>
      38             : #include <freetds/tds/convert.h>
      39             : #include <freetds/enum_cap.h>
      40             : #include <freetds/utils/bjoern-utf8.h>
      41             : #include <odbcss.h>
      42             : 
      43             : /**
      44             :  * \ingroup odbc_api
      45             :  * \defgroup odbc_util ODBC utility
      46             :  * Functions called within \c ODBC driver.
      47             :  */
      48             : 
      49             : /**
      50             :  * \addtogroup odbc_util
      51             :  * @{ 
      52             :  */
      53             : 
      54             : #ifdef ENABLE_ODBC_WIDE
      55             : static DSTR *odbc_iso2utf(DSTR *res, const char *s, size_t len);
      56             : static DSTR *odbc_mb2utf(TDS_DBC *dbc, DSTR *res, const char *s, size_t len);
      57             : static DSTR *odbc_wide2utf(DSTR *res, const SQLWCHAR *s, size_t len);
      58             : #endif
      59             : 
      60             : SQLRETURN
      61       32318 : odbc_set_stmt_query(TDS_STMT * stmt, const ODBC_CHAR *sql, ptrdiff_t sql_len _WIDE)
      62             : {
      63       32318 :         if (sql_len == SQL_NTS)
      64             : #ifdef ENABLE_ODBC_WIDE
      65       31822 :                 sql_len = wide ? sqlwcslen(sql->wide) : strlen(sql->mb);
      66             : #else
      67             :                 sql_len = strlen((const char*) sql);
      68             : #endif
      69         496 :         else if (sql_len <= 0)
      70             :                 return SQL_ERROR;
      71             : 
      72             :         /* TODO already NULL ?? */
      73       32318 :         tds_free_param_results(stmt->params);
      74       32318 :         stmt->params = NULL;
      75       32318 :         stmt->param_num = 0;
      76       32318 :         stmt->param_count = 0;
      77       32318 :         stmt->is_prepared_query = 0;
      78       32318 :         stmt->prepared_query_is_func = 0;
      79       32318 :         stmt->prepared_query_is_rpc = 0;
      80       32318 :         stmt->prepared_pos = 0;
      81       32318 :         stmt->curr_param_row = 0;
      82       32318 :         stmt->num_param_rows = 1;
      83       32318 :         stmt->need_reprepare = 0;
      84       32318 :         stmt->params_queried = 0;
      85             : 
      86       32318 :         if (!odbc_dstr_copy(stmt->dbc, &stmt->query, sql_len, sql))
      87             :                 return SQL_ERROR;
      88             : 
      89       32318 :         return SQL_SUCCESS;
      90             : }
      91             : 
      92             : size_t
      93       42898 : odbc_get_string_size(ptrdiff_t size, const ODBC_CHAR * str _WIDE)
      94             : {
      95       42898 :         if (str) {
      96       42542 :                 if (size == SQL_NTS)
      97             : #ifdef ENABLE_ODBC_WIDE
      98        9524 :                         return wide ? sqlwcslen(str->wide) : strlen(str->mb);
      99             : #else
     100             :                         return strlen((const char*) str);
     101             : #endif
     102       33018 :                 if (size >= 0)
     103       33018 :                         return (unsigned int) size;
     104             :         }
     105             :         /* SQL_NULL_DATA or any other strange value */
     106             :         return 0;
     107             : }
     108             : 
     109             : #ifdef ENABLE_ODBC_WIDE
     110             : static DSTR*
     111        1647 : odbc_iso2utf(DSTR *res, const char *s, size_t len)
     112             : {
     113        1647 :         size_t i, o_len = len + 1;
     114             :         char *out, *p;
     115             : 
     116        1647 :         assert(s);
     117       19667 :         for (i = 0; i < len; ++i)
     118       19667 :                 if ((s[i] & 0x80) != 0)
     119           0 :                         ++o_len;
     120             : 
     121        1647 :         if (!tds_dstr_alloc(res, o_len))
     122             :                 return NULL;
     123        3294 :         out = tds_dstr_buf(res);
     124             : 
     125       21314 :         for (p = out; len > 0; --len) {
     126       19667 :                 unsigned char u = (unsigned char) *s++;
     127       19667 :                 if ((u & 0x80) != 0) {
     128           0 :                         *p++ = 0xc0 | (0x1f & (u >> 6));
     129           0 :                         *p++ = 0x80 | (0x3f & u);
     130             :                 } else {
     131       19667 :                         *p++ = u;
     132             :                 }
     133             :         }
     134        1647 :         assert(p + 1 <= out + o_len);
     135        1647 :         return tds_dstr_setlen(res, p - out);
     136             : }
     137             : 
     138             : static DSTR*
     139       22215 : odbc_wide2utf(DSTR *res, const SQLWCHAR *s, size_t len)
     140             : {
     141       22215 :         size_t i, o_len = len + 1;
     142             :         char *out, *p;
     143             : 
     144             : #if SIZEOF_SQLWCHAR > 2
     145             : # define MASK(n) ((0xffffffffu << (n)) & 0xffffffffu)
     146             : #else
     147             : # define MASK(n) ((0xffffu << (n)) & 0xffffu)
     148             : #endif
     149             : 
     150       22215 :         assert(s || len == 0);
     151      811197 :         for (i = 0; i < len; ++i) {
     152      811197 :                 if ((s[i] & MASK(7)) == 0)
     153      810672 :                         continue;
     154         525 :                 ++o_len;
     155         525 :                 if ((s[i] & MASK(11)) == 0)
     156         350 :                         continue;
     157         175 :                 ++o_len;
     158             : #if SIZEOF_SQLWCHAR > 2
     159             :                 if ((s[i] & MASK(16)) == 0)
     160             :                         continue;
     161             :                 ++o_len;
     162             :                 if ((s[i] & MASK(21)) == 0)
     163             :                         continue;
     164             :                 ++o_len;
     165             :                 if ((s[i] & MASK(26)) == 0)
     166             :                         continue;
     167             :                 ++o_len;
     168             : #endif
     169             :         }
     170             : 
     171       22215 :         if (!tds_dstr_alloc(res, o_len))
     172             :                 return NULL;
     173       44430 :         out = tds_dstr_buf(res);
     174             : 
     175             : #undef MASK
     176             : #define MASK(n) ((0xffffffffu << (n)) & 0xffffffffu)
     177      833362 :         for (p = out; len > 0; --len) {
     178      811147 :                 uint32_t u = *s++;
     179             :                 /* easy case, ASCII */
     180      811147 :                 if ((u & MASK(7)) == 0) {
     181      810672 :                         *p++ = (char) u;
     182      810672 :                         continue;
     183             :                 }
     184             : #if SIZEOF_SQLWCHAR == 2
     185         475 :                 if ((u & 0xfc00) == 0xd800 && len > 1) {
     186          50 :                         uint32_t c2 = *s;
     187          50 :                         if ((c2 & 0xfc00) == 0xdc00) {
     188          50 :                                 u = (u << 10) + c2 - ((0xd800 << 10) + 0xdc00 - 0x10000);
     189          50 :                                 ++s;
     190          50 :                                 --len;
     191             :                         }
     192             :                 }
     193             : #endif
     194         475 :                 if ((u & MASK(11)) == 0) {
     195         350 :                         *p++ = 0xc0 | (u >> 6);
     196             :                 } else {
     197         125 :                         if ((u & MASK(16)) == 0) {
     198          75 :                                 *p++ = 0xe0 | (u >> 12);
     199             :                         } else {
     200             :                                 if ((SIZEOF_SQLWCHAR == 2) || (u & MASK(21)) == 0) {
     201          50 :                                         *p++ = 0xf0 | (u >> 18);
     202             :                                 } else {
     203             :                                         if ((u & MASK(26)) == 0) {
     204             :                                                 *p++ = 0xf8 | (u >> 24);
     205             :                                         } else {
     206             :                                                 *p++ = 0xfc | (0x01 & (u >> 30));
     207             :                                                 *p++ = 0x80 | (0x3f & (u >> 24));
     208             :                                         }
     209             :                                         *p++ = 0x80 | (0x3f & (u >> 18));
     210             :                                 }
     211          50 :                                 *p++ = 0x80 | (0x3f & (u >> 12));
     212             :                         }
     213         125 :                         *p++ = 0x80 | (0x3f & (u >> 6));
     214             :                 }
     215         475 :                 *p++ = 0x80 | (0x3f & u);
     216             :         }
     217       22215 :         assert(p + 1 <= out + o_len);
     218       22215 :         return tds_dstr_setlen(res, p - out);
     219             : }
     220             : 
     221             : static DSTR*
     222       18607 : odbc_mb2utf(TDS_DBC *dbc, DSTR *res, const char *s, size_t len)
     223             : {
     224             :         char *buf;
     225             : 
     226             :         const char *ib;
     227             :         char *ob;
     228             :         size_t il, ol;
     229       18607 :         TDSICONV *char_conv = dbc->mb_conv;
     230             : 
     231       18607 :         if (!char_conv)
     232        1647 :                 return odbc_iso2utf(res, s, len);
     233             : 
     234       16960 :         if (char_conv->flags == TDS_ENCODING_MEMCPY)
     235         272 :                 return tds_dstr_copyn(res, s, len);
     236             : 
     237       16688 :         il = len;
     238             : 
     239             :         /* allocate needed buffer (+1 is to exclude 0 case) */
     240       16688 :         ol = il * char_conv->to.charset.max_bytes_per_char / char_conv->from.charset.min_bytes_per_char + 1;
     241       16688 :         assert(ol > 0);
     242       16688 :         if (!tds_dstr_alloc(res, ol))
     243             :                 return NULL;
     244       33376 :         buf = tds_dstr_buf(res);
     245             : 
     246       16688 :         ib = s;
     247       16688 :         ob = buf;
     248       16688 :         --ol; /* leave space for terminator */
     249             : 
     250             :         /* char_conv is only mostly const */
     251       16688 :         memset((TDS_ERRNO_MESSAGE_FLAGS*) &char_conv->suppress, 0, sizeof(char_conv->suppress));
     252       16688 :         if (tds_iconv(dbc->tds_socket, char_conv, to_server, &ib, &il, &ob, &ol) == (size_t)-1)
     253             :                 return NULL;
     254             : 
     255       16688 :         return tds_dstr_setlen(res, ob - buf);
     256             : }
     257             : #endif
     258             : 
     259             : #ifdef ENABLE_ODBC_WIDE
     260             : /**
     261             :  * Copy a string from client setting according to ODBC convenction
     262             :  * @param dbc       database connection. Can't be NULL
     263             :  * @param s         output string
     264             :  * @param size      size of str, Can be SQL_NTS
     265             :  * @param str       string to convert
     266             :  * @param flag      set of flags.
     267             :  *                  0x01 wide string in buffer
     268             :  *                  0x20 size is in bytes, not characters
     269             :  */
     270             : DSTR*
     271       40822 : odbc_dstr_copy_flag(TDS_DBC *dbc, DSTR *s, ptrdiff_t size, const ODBC_CHAR * str, int flag)
     272             : {
     273       40822 :         int wide = flag&1;
     274             :         size_t len;
     275             : 
     276       40822 :         len = odbc_get_string_size((flag&0x21) == 0x21 && size >= 0 ? size/SIZEOF_SQLWCHAR : size, str, wide);
     277       40822 :         if (wide)
     278       22215 :                 return odbc_wide2utf(s, str->wide, len);
     279             : 
     280       18607 :         return odbc_mb2utf(dbc, s, str->mb, len);
     281             : }
     282             : #else
     283             : DSTR*
     284             : odbc_dstr_copy(TDS_DBC *dbc TDS_UNUSED, DSTR *s, ptrdiff_t size, const ODBC_CHAR * str)
     285             : {
     286             :         return tds_dstr_copyn(s, (const char *) str, odbc_get_string_size(size, str));
     287             : }
     288             : #endif
     289             : 
     290             : /**
     291             :  * Copy a string to client setting size according to ODBC convenction
     292             :  * @param dbc       database connection. Can be NULL
     293             :  * @param buffer    client buffer
     294             :  * @param cbBuffer  client buffer size (in bytes)
     295             :  * @param pcbBuffer pointer to SQLSMALLINT to hold string size
     296             :  * @param s         string to copy
     297             :  * @param len       len of string to copy. <0 null terminated
     298             :  * @param flag      set of flags.
     299             :  *                  0x01 wide string in buffer
     300             :  *                  0x10 pcbBuffer is SQLINTEGER otherwise SQLSMALLINT
     301             :  *                  0x20 size is in bytes, not characters
     302             :  */
     303             : SQLRETURN
     304        9048 : odbc_set_string_flag(TDS_DBC *dbc TDS_UNUSED, SQLPOINTER buffer, SQLINTEGER cbBuffer,
     305             :                      void FAR * pcbBuffer, const char *s, ptrdiff_t len, int flag)
     306             : {
     307        9048 :         SQLRETURN result = SQL_SUCCESS;
     308        9048 :         int out_len = 0;
     309             : #if !defined(NDEBUG) && defined(ENABLE_ODBC_WIDE)
     310             :         ptrdiff_t initial_size;
     311             : #endif
     312             : 
     313        9048 :         if (len < 0)
     314        4246 :                 len = strlen(s);
     315             : 
     316        9048 :         if (cbBuffer < 0)
     317           0 :                 cbBuffer = 0;
     318             : 
     319             : #ifdef ENABLE_ODBC_WIDE
     320        9048 :         if ((flag & 1) != 0) {
     321             :                 /* wide characters */
     322        4589 :                 const unsigned char *p = (const unsigned char*) s;
     323        4589 :                 const unsigned char *const p_end = p + len;
     324        4589 :                 SQLWCHAR *dest = (SQLWCHAR*) buffer;
     325             : 
     326        4589 :                 if (flag&0x20)
     327        1516 :                         cbBuffer /= SIZEOF_SQLWCHAR;
     328             : #ifndef NDEBUG
     329        4589 :                 initial_size = cbBuffer;
     330             : #endif
     331       96296 :                 while (p < p_end) {
     332             :                         uint32_t u, state = UTF8_ACCEPT;
     333             : 
     334      174836 :                         while (decode_utf8(&state, &u, *p++) > UTF8_REJECT && p < p_end)
     335         300 :                                 continue;
     336       87118 :                         if (state != UTF8_ACCEPT)
     337             :                                 break;
     338             : 
     339       87118 :                         ++out_len;
     340       87118 :                         if (SIZEOF_SQLWCHAR == 2 && u >= 0x10000 && u < 0x110000u)
     341          50 :                                 ++out_len;
     342       87118 :                         if (!dest)
     343        1628 :                                 continue;
     344       85490 :                         if (SIZEOF_SQLWCHAR == 2 && u >= 0x10000) {
     345          50 :                                 if (cbBuffer > 2 && u < 0x110000u) {
     346          50 :                                         *dest++ = (SQLWCHAR) (0xd7c0 + (u >> 10));
     347          50 :                                         *dest++ = (SQLWCHAR) (0xdc00 + (u & 0x3ffu));
     348          50 :                                         cbBuffer -= 2;
     349          50 :                                         continue;
     350             :                                 }
     351           0 :                                 if (cbBuffer > 1) {
     352           0 :                                         *dest++ = (SQLWCHAR) '?';
     353           0 :                                         --cbBuffer;
     354             :                                 }
     355       85440 :                         } else if (cbBuffer > 1) {
     356       82744 :                                 *dest++ = (SQLWCHAR) u;
     357       82744 :                                 --cbBuffer;
     358       82744 :                                 continue;
     359             :                         }
     360             :                         result = SQL_SUCCESS_WITH_INFO;
     361             :                 }
     362             :                 /* terminate buffer */
     363        4589 :                 assert(dest == NULL || dest-(SQLWCHAR*) buffer == out_len
     364             :                        || (dest-(SQLWCHAR*) buffer <= out_len && cbBuffer <= 1));
     365        4589 :                 if (dest && cbBuffer) {
     366        4058 :                         *dest++ = 0;
     367        4058 :                         assert(dest-(SQLWCHAR*) buffer <= initial_size);
     368             :                 }
     369        4589 :                 assert(dest == NULL || dest-(SQLWCHAR*) buffer <= initial_size);
     370        4589 :                 if (flag&0x20)
     371        1516 :                         out_len *= SIZEOF_SQLWCHAR;
     372        4459 :         } else if (!dbc || !dbc->mb_conv) {
     373             :                 /* to ISO-8859-1 */
     374         106 :                 const unsigned char *p = (const unsigned char*) s;
     375         106 :                 const unsigned char *const p_end = p + len;
     376         106 :                 unsigned char *dest = (unsigned char*) buffer;
     377             : 
     378             : #ifndef NDEBUG
     379         106 :                 initial_size = cbBuffer;
     380             : #endif
     381        7749 :                 while (p < p_end) {
     382             :                         uint32_t u, state = UTF8_ACCEPT;
     383             : 
     384       15074 :                         while (decode_utf8(&state, &u, *p++) > UTF8_REJECT && p < p_end)
     385           0 :                                 continue;
     386        7537 :                         if (state != UTF8_ACCEPT)
     387             :                                 break;
     388             : 
     389        7537 :                         ++out_len;
     390        7537 :                         if (!dest)
     391           0 :                                 continue;
     392        7537 :                         if (cbBuffer > 1) {
     393        7537 :                                 *dest++ = u > 0x100 ? '?' : u;
     394        7537 :                                 --cbBuffer;
     395        7537 :                                 continue;
     396             :                         }
     397             :                         result = SQL_SUCCESS_WITH_INFO;
     398             :                 }
     399         106 :                 assert(dest == NULL || dest-(unsigned char*) buffer == out_len
     400             :                        || (dest-(unsigned char*) buffer <= out_len && cbBuffer <= 1));
     401             :                 /* terminate buffer */
     402         106 :                 if (dest && cbBuffer) {
     403         106 :                         *dest++ = 0;
     404         106 :                         assert(dest-(unsigned char*) buffer <= initial_size);
     405             :                 }
     406         106 :                 assert(dest == NULL || dest-(unsigned char*) buffer <= initial_size);
     407        4353 :         } else if (dbc->mb_conv->flags == TDS_ENCODING_MEMCPY) {
     408             :                 /* to UTF-8 */
     409         111 :                 out_len = len;
     410         111 :                 if (len >= cbBuffer) {
     411           0 :                         len = cbBuffer - 1;
     412           0 :                         result = SQL_SUCCESS_WITH_INFO;
     413             :                 }
     414         111 :                 if (buffer && len >= 0) {
     415             :                         /* buffer can overlap, use memmove, thanks to Valgrind */
     416         111 :                         memmove((char *) buffer, s, len);
     417         111 :                         ((char *) buffer)[len] = 0;
     418             :                 }
     419             :         } else {
     420             :                 const char *ib;
     421             :                 char *ob;
     422             :                 size_t il, ol;
     423        4242 :                 TDSICONV *char_conv = dbc->mb_conv;
     424             : 
     425        4242 :                 il = len;
     426        4242 :                 ib = s;
     427        4242 :                 ol = cbBuffer;
     428        4242 :                 ob = (char *) buffer;
     429             : 
     430             :                 /* char_conv is only mostly const */
     431        4242 :                 memset((TDS_ERRNO_MESSAGE_FLAGS*) &char_conv->suppress, 0, sizeof(char_conv->suppress));
     432        4242 :                 char_conv->suppress.e2big = 1;
     433        4242 :                 if (cbBuffer && tds_iconv(dbc->tds_socket, char_conv, to_client, &ib, &il, &ob, &ol) == (size_t)-1 && errno != E2BIG)
     434           0 :                         result = SQL_ERROR;
     435        4242 :                 out_len = cbBuffer - (int) ol;
     436        9046 :                 while (result != SQL_ERROR && il) {
     437             :                         char discard[128];
     438         562 :                         ol = sizeof(discard);
     439         562 :                         ob = discard;
     440         562 :                         char_conv->suppress.e2big = 1;
     441         562 :                         if (tds_iconv(dbc->tds_socket, char_conv, to_client, &ib, &il, &ob, &ol) == (size_t)-1 && errno != E2BIG)
     442           0 :                                 result = SQL_ERROR;
     443         562 :                         ol = sizeof(discard) - ol;
     444             :                         /* if there are still left space copy the partial conversion */
     445         562 :                         if (out_len < cbBuffer) {
     446           0 :                                 size_t max_copy = cbBuffer - out_len;
     447           0 :                                 if (max_copy > ol)
     448           0 :                                         max_copy = ol;
     449           0 :                                 memcpy(((char *) buffer) + out_len, discard, max_copy);
     450             :                         }
     451         562 :                         out_len += ol;
     452             :                 }
     453        4242 :                 if (out_len >= cbBuffer && result != SQL_ERROR)
     454         544 :                         result = SQL_SUCCESS_WITH_INFO;
     455        4242 :                 if (buffer && cbBuffer > 0)
     456        3711 :                         ((char *) buffer)[cbBuffer-1 < out_len ? cbBuffer-1:out_len] = 0;
     457             :         }
     458             : #else
     459             :         out_len = len;
     460             :         if (len >= cbBuffer) {
     461             :                 len = cbBuffer - 1;
     462             :                 result = SQL_SUCCESS_WITH_INFO;
     463             :         }
     464             :         if (buffer && len >= 0) {
     465             :                 /* buffer can overlap, use memmove, thanks to Valgrind */
     466             :                 memmove((char *) buffer, s, len);
     467             :                 ((char *) buffer)[len] = 0;
     468             :         }
     469             : #endif
     470             : 
     471             :         /* set output length */
     472        9048 :         if (pcbBuffer) {
     473        4910 :                 if (flag & 0x10)
     474         238 :                         *((SQLINTEGER *) pcbBuffer) = out_len;
     475             :                 else
     476        4672 :                         *((SQLSMALLINT *) pcbBuffer) = out_len;
     477             :         }
     478        9048 :         return result;
     479             : }
     480             : 
     481             : 
     482             : void
     483        1220 : odbc_set_return_status(struct _hstmt *stmt, unsigned int n_row)
     484             : {
     485        1220 :         TDSSOCKET *tds = stmt->tds;
     486             : 
     487             :         /* TODO handle different type results (functions) on mssql2k */
     488        1220 :         if (stmt->prepared_query_is_func && tds->has_status) {
     489             :                 struct _drecord *drec;
     490             :                 SQLLEN len;
     491         194 :                 const TDS_DESC* axd = stmt->apd;
     492             :                 TDS_INTPTR len_offset;
     493             :                 char *data_ptr;
     494             : 
     495         194 :                 if (axd->header.sql_desc_count < 1)
     496             :                         return;
     497         194 :                 drec = &axd->records[0];
     498         194 :                 data_ptr = (char *) drec->sql_desc_data_ptr;
     499         194 :                 if (!data_ptr)
     500             :                         return;
     501             : 
     502         194 :                 if (axd->header.sql_desc_bind_type != SQL_BIND_BY_COLUMN) {
     503           0 :                         len_offset = axd->header.sql_desc_bind_type * n_row;
     504           0 :                         data_ptr += len_offset;
     505             :                 } else {
     506         194 :                         len_offset = sizeof(SQLLEN) * n_row;
     507         194 :                         data_ptr += sizeof(SQLINTEGER) * n_row;
     508             :                 }
     509         194 :                 if (axd->header.sql_desc_bind_offset_ptr) {
     510           0 :                         len_offset += *axd->header.sql_desc_bind_offset_ptr;
     511           0 :                         data_ptr += *axd->header.sql_desc_bind_offset_ptr;
     512             :                 }
     513             : #define LEN(ptr) *((SQLLEN*)(((char*)(ptr)) + len_offset))
     514             : 
     515         194 :                 len = odbc_tds2sql_int4(stmt, &tds->ret_status, drec->sql_desc_concise_type,
     516         194 :                                         (TDS_CHAR *) data_ptr, drec->sql_desc_octet_length);
     517         194 :                 if (len == SQL_NULL_DATA)
     518             :                         return /* SQL_ERROR */ ;
     519         194 :                 if (drec->sql_desc_indicator_ptr)
     520         194 :                         LEN(drec->sql_desc_indicator_ptr) = 0;
     521         194 :                 if (drec->sql_desc_octet_length_ptr)
     522         194 :                         LEN(drec->sql_desc_octet_length_ptr) = len;
     523             :         }
     524             : #undef LEN
     525             : }
     526             : 
     527             : void
     528         834 : odbc_set_return_params(struct _hstmt *stmt, unsigned int n_row)
     529             : {
     530         834 :         TDSSOCKET *tds = stmt->tds;
     531         834 :         TDSPARAMINFO *info = tds->current_results;
     532             : 
     533         834 :         int i_begin = stmt->prepared_query_is_func ? 1 : 0;
     534             :         int i;
     535         834 :         int nparam = i_begin;
     536             : 
     537             :         /* I don't understand why but this happen -- freddy77 */
     538             :         /* TODO check why, put an assert ? */
     539         834 :         if (!info)
     540             :                 return;
     541             : 
     542         990 :         for (i = 0; i < info->num_cols; ++i) {
     543         990 :                 const TDS_DESC* axd = stmt->apd;
     544             :                 const struct _drecord *drec_apd, *drec_ipd;
     545         990 :                 TDSCOLUMN *colinfo = info->columns[i];
     546             :                 SQLLEN len;
     547             :                 int c_type;
     548             :                 char *data_ptr;
     549             :                 TDS_INTPTR len_offset;
     550             : 
     551             :                 /* find next output parameter */
     552             :                 for (;;) {
     553        1144 :                         drec_apd = NULL;
     554             :                         /* TODO best way to stop */
     555        1144 :                         if (nparam >= axd->header.sql_desc_count || nparam >= stmt->ipd->header.sql_desc_count)
     556             :                                 return;
     557        1144 :                         drec_apd = &axd->records[nparam];
     558        1144 :                         drec_ipd = &stmt->ipd->records[nparam];
     559        1144 :                         if (stmt->ipd->records[nparam++].sql_desc_parameter_type != SQL_PARAM_INPUT)
     560             :                                 break;
     561             :                 }
     562             : 
     563         990 :                 data_ptr = (char *) drec_apd->sql_desc_data_ptr;
     564         990 :                 if (!data_ptr)
     565             :                         return;
     566         990 :                 if (axd->header.sql_desc_bind_type != SQL_BIND_BY_COLUMN) {
     567           0 :                         len_offset = axd->header.sql_desc_bind_type * n_row;
     568           0 :                         data_ptr += len_offset;
     569             :                 } else {
     570         990 :                         len_offset = sizeof(SQLLEN) * n_row;
     571         990 :                         data_ptr += odbc_get_octet_len(drec_apd->sql_desc_concise_type, drec_apd) * n_row;
     572             :                 }
     573         990 :                 if (axd->header.sql_desc_bind_offset_ptr) {
     574           0 :                         len_offset += *axd->header.sql_desc_bind_offset_ptr;
     575           0 :                         data_ptr += *axd->header.sql_desc_bind_offset_ptr;
     576             :                 }
     577             : #define LEN(ptr) *((SQLLEN*)(((char*)(ptr)) + len_offset))
     578             : 
     579             :                 /* null parameter ? */
     580         990 :                 if (colinfo->column_cur_size < 0) {
     581             :                         /* FIXME error if NULL */
     582           0 :                         if (drec_apd->sql_desc_indicator_ptr)
     583           0 :                                 LEN(drec_apd->sql_desc_indicator_ptr) = SQL_NULL_DATA;
     584           0 :                         continue;
     585             :                 }
     586             : 
     587         990 :                 colinfo->column_text_sqlgetdatapos = 0;
     588         990 :                 colinfo->column_iconv_left = 0;
     589         990 :                 c_type = drec_apd->sql_desc_concise_type;
     590         990 :                 if (c_type == SQL_C_DEFAULT)
     591           0 :                         c_type = odbc_sql_to_c_type_default(drec_ipd->sql_desc_concise_type);
     592             :                 /* 
     593             :                  * TODO why IPD ?? perhaps SQLBindParameter it's not correct ??
     594             :                  * Or tests are wrong ??
     595             :                  */
     596         990 :                 len = odbc_tds2sql_col(stmt, colinfo, c_type, (TDS_CHAR*) data_ptr, drec_apd->sql_desc_octet_length, drec_ipd);
     597         990 :                 if (len == SQL_NULL_DATA)
     598             :                         return /* SQL_ERROR */ ;
     599         990 :                 if (drec_apd->sql_desc_indicator_ptr)
     600         990 :                         LEN(drec_apd->sql_desc_indicator_ptr) = 0;
     601         990 :                 if (drec_apd->sql_desc_octet_length_ptr)
     602         990 :                         LEN(drec_apd->sql_desc_octet_length_ptr) = len;
     603             : #undef LEN
     604             :         }
     605             : }
     606             : 
     607             : /**
     608             :  * Pass this an SQL_C_* type and get a SYB* type which most closely corresponds
     609             :  * to the SQL_C_* type.
     610             :  * This function can return XSYBNVARCHAR or SYBUINTx even if server do not support it
     611             :  */
     612             : TDS_SERVER_TYPE
     613       77040 : odbc_c_to_server_type(int c_type)
     614             : {
     615       82818 :         switch (c_type) {
     616             :                 /* FIXME this should be dependent on size of data !!! */
     617             :         case SQL_C_BINARY:
     618             :                 return SYBBINARY;
     619             : #ifdef SQL_C_WCHAR
     620             :         case SQL_C_WCHAR:
     621             :                 return XSYBNVARCHAR;
     622             : #endif
     623             :                 /* TODO what happen if varchar is more than 255 characters long */
     624             :         case SQL_C_CHAR:
     625             :                 return SYBVARCHAR;
     626             :         case SQL_C_FLOAT:
     627             :                 return SYBREAL;
     628             :         case SQL_C_DOUBLE:
     629             :                 return SYBFLT8;
     630             :         case SQL_C_BIT:
     631             :                 return SYBBIT;
     632             : #if (ODBCVER >= 0x0300)
     633             :         case SQL_C_UBIGINT:
     634             :                 return SYBUINT8;
     635             :         case SQL_C_SBIGINT:
     636             :                 return SYBINT8;
     637             : #ifdef SQL_C_GUID
     638             :         case SQL_C_GUID:
     639             :                 return SYBUNIQUE;
     640             : #endif
     641             : #endif
     642             :         case SQL_C_ULONG:
     643             :                 return SYBUINT4;
     644             :         case SQL_C_LONG:
     645             :         case SQL_C_SLONG:
     646             :                 return SYBINT4;
     647             :         case SQL_C_USHORT:
     648             :                 return SYBUINT2;
     649             :         case SQL_C_SHORT:
     650             :         case SQL_C_SSHORT:
     651             :                 return SYBINT2;
     652             :         case SQL_C_STINYINT:
     653             :                 return SYBSINT1;
     654             :         case SQL_C_TINYINT:
     655             :         case SQL_C_UTINYINT:
     656             :                 return SYBINT1;
     657             :                 /* ODBC date formats are completely different from SQL one */
     658             :         case SQL_C_DATE:
     659             :         case SQL_C_TIME:
     660             :         case SQL_C_TIMESTAMP:
     661             :         case SQL_C_TYPE_DATE:
     662             :         case SQL_C_TYPE_TIME:
     663             :         case SQL_C_TYPE_TIMESTAMP:
     664             :                 return SYBMSDATETIME2;
     665             :                 /* ODBC numeric/decimal formats are completely differect from tds one */
     666             :         case SQL_C_NUMERIC:
     667             :                 return SYBNUMERIC;
     668             :                 /* not supported */
     669             :         case SQL_C_INTERVAL_YEAR:
     670             :         case SQL_C_INTERVAL_MONTH:
     671             :         case SQL_C_INTERVAL_DAY:
     672             :         case SQL_C_INTERVAL_HOUR:
     673             :         case SQL_C_INTERVAL_MINUTE:
     674             :         case SQL_C_INTERVAL_SECOND:
     675             :         case SQL_C_INTERVAL_YEAR_TO_MONTH:
     676             :         case SQL_C_INTERVAL_DAY_TO_HOUR:
     677             :         case SQL_C_INTERVAL_DAY_TO_MINUTE:
     678             :         case SQL_C_INTERVAL_DAY_TO_SECOND:
     679             :         case SQL_C_INTERVAL_HOUR_TO_MINUTE:
     680             :         case SQL_C_INTERVAL_HOUR_TO_SECOND:
     681             :         case SQL_C_INTERVAL_MINUTE_TO_SECOND:
     682             :                 break;
     683             :         }
     684             :         return TDS_INVALID_TYPE;
     685             : }
     686             : 
     687             : int
     688          10 : odbc_sql_to_c_type_default(int sql_type)
     689             : {
     690             : 
     691          10 :         switch (sql_type) {
     692             : 
     693             :         case SQL_CHAR:
     694             :         case SQL_VARCHAR:
     695             :         case SQL_LONGVARCHAR:
     696             :         /* these types map to SQL_C_CHAR for compatibility with old applications */
     697             : #ifdef SQL_C_WCHAR
     698             :         case SQL_WCHAR:
     699             :         case SQL_WVARCHAR:
     700             :         case SQL_WLONGVARCHAR:
     701             : #endif
     702             :                 return SQL_C_CHAR;
     703             :                 /* for compatibility numeric are converted to CHAR, not to structure */
     704             :         case SQL_DECIMAL:
     705             :         case SQL_NUMERIC:
     706             :                 return SQL_C_CHAR;
     707             : #ifdef SQL_GUID
     708           0 :         case SQL_GUID:
     709             :                 /* TODO return SQL_C_CHAR for Sybase ?? */
     710           0 :                 return SQL_C_GUID;
     711             : #endif
     712           0 :         case SQL_BIT:
     713           0 :                 return SQL_C_BIT;
     714           0 :         case SQL_TINYINT:
     715           0 :                 return SQL_C_UTINYINT;
     716           0 :         case SQL_SMALLINT:
     717           0 :                 return SQL_C_SSHORT;
     718           0 :         case SQL_INTEGER:
     719           0 :                 return SQL_C_SLONG;
     720           0 :         case SQL_BIGINT:
     721           0 :                 return SQL_C_SBIGINT;
     722           0 :         case SQL_REAL:
     723           0 :                 return SQL_C_FLOAT;
     724           0 :         case SQL_FLOAT:
     725             :         case SQL_DOUBLE:
     726           0 :                 return SQL_C_DOUBLE;
     727           0 :         case SQL_DATE:
     728             :         case SQL_TYPE_DATE:
     729           0 :                 return SQL_C_TYPE_DATE;
     730           0 :         case SQL_TIME:
     731             :         case SQL_TYPE_TIME:
     732           0 :                 return SQL_C_TYPE_TIME;
     733           0 :         case SQL_TIMESTAMP:
     734             :         case SQL_TYPE_TIMESTAMP:
     735           0 :                 return SQL_C_TYPE_TIMESTAMP;
     736           0 :         case SQL_BINARY:
     737             :         case SQL_VARBINARY:
     738             :         case SQL_LONGVARBINARY:
     739           0 :                 return SQL_C_BINARY;
     740           0 :         case SQL_SS_TABLE:
     741           0 :                 return SQL_C_BINARY;
     742             :                 /* TODO interval types */
     743           0 :         default:
     744           0 :                 return 0;
     745             :         }
     746             : }
     747             : 
     748             : TDS_SERVER_TYPE
     749       24776 : odbc_sql_to_server_type(TDSCONNECTION * conn, int sql_type, int sql_unsigned)
     750             : {
     751             : 
     752       24776 :         switch (sql_type) {
     753        1362 :         case SQL_WCHAR:
     754        1362 :                 if (IS_TDS7_PLUS(conn))
     755             :                         return XSYBNCHAR;
     756             :                 /* fall thought */
     757             :         case SQL_CHAR:
     758        1450 :                 return SYBCHAR;
     759         492 :         case SQL_WVARCHAR:
     760         492 :                 if (IS_TDS7_PLUS(conn))
     761             :                         return XSYBNVARCHAR;
     762             :                 /* fall thought */
     763             :         case SQL_VARCHAR:
     764        2852 :                 return SYBVARCHAR;
     765           0 :         case SQL_SS_VARIANT:
     766           0 :                 if (IS_TDS71_PLUS(conn))
     767             :                         return SYBVARIANT;
     768           0 :                 if (IS_TDS7_PLUS(conn))
     769             :                         return XSYBNVARCHAR;
     770           0 :                 return SYBVARCHAR;
     771           0 :         case SQL_SS_XML:
     772           0 :                 if (IS_TDS72_PLUS(conn))
     773             :                         return SYBMSXML;
     774             :                 /* fall thought */
     775             :         case SQL_WLONGVARCHAR:
     776         464 :                 if (IS_TDS7_PLUS(conn))
     777             :                         return SYBNTEXT;
     778             :                 /* fall thought */
     779             :         case SQL_LONGVARCHAR:
     780         668 :                 return SYBTEXT;
     781             :         case SQL_DECIMAL:
     782             :                 return SYBDECIMAL;
     783         916 :         case SQL_NUMERIC:
     784         916 :                 return SYBNUMERIC;
     785             : #ifdef SQL_GUID
     786          44 :         case SQL_GUID:
     787          44 :                 if (IS_TDS7_PLUS(conn))
     788             :                         return SYBUNIQUE;
     789           0 :                 return TDS_INVALID_TYPE;
     790             : #endif
     791         886 :         case SQL_BIT:
     792             :                 /* NOTE: always return not nullable type */
     793         886 :                 return SYBBIT;
     794         524 :         case SQL_TINYINT:
     795         524 :                 return SYBINT1;
     796         724 :         case SQL_SMALLINT:
     797         724 :                 if (sql_unsigned && tds_capability_has_req(conn, TDS_REQ_DATA_UINT2))
     798             :                         return SYBUINT2;
     799             :                 return SYBINT2;
     800        3340 :         case SQL_INTEGER:
     801        3340 :                 if (sql_unsigned && tds_capability_has_req(conn, TDS_REQ_DATA_UINT4))
     802             :                         return SYBUINT4;
     803             :                 return SYBINT4;
     804         108 :         case SQL_BIGINT:
     805         108 :                 if (sql_unsigned && tds_capability_has_req(conn, TDS_REQ_DATA_UINT8))
     806             :                         return SYBUINT8;
     807             :                 return SYBINT8;
     808        1100 :         case SQL_REAL:
     809        1100 :                 return SYBREAL;
     810        1154 :         case SQL_FLOAT:
     811             :         case SQL_DOUBLE:
     812        1154 :                 return SYBFLT8;
     813             :                 /* ODBC version 2 */
     814        1424 :         case SQL_DATE:
     815             :         case SQL_TIME:
     816             :         case SQL_TIMESTAMP:
     817             :                 /* ODBC version 3 */
     818             :         case SQL_TYPE_DATE:
     819        1664 :                 if (IS_TDS50(conn) && tds_capability_has_req(conn, TDS_REQ_DATA_BIGDATETIME))
     820             :                         return SYB5BIGDATETIME;
     821        1664 :                 if (IS_TDS50(conn) && tds_capability_has_req(conn, TDS_REQ_DATA_DATE))
     822             :                         return SYBDATE;
     823        1424 :                 if (IS_TDS73_PLUS(conn))
     824             :                         return SYBMSDATE;
     825             :                 goto type_timestamp;
     826         374 :         case SQL_TYPE_TIME:
     827         434 :                 if (IS_TDS50(conn) && tds_capability_has_req(conn, TDS_REQ_DATA_BIGTIME))
     828             :                         return SYB5BIGTIME;
     829         434 :                 if (IS_TDS50(conn) && tds_capability_has_req(conn, TDS_REQ_DATA_TIME))
     830             :                         return SYBTIME;
     831         374 :                 if (IS_TDS73_PLUS(conn))
     832             :                         return SYBMSTIME;
     833             :                 /* fall thought */
     834          60 :         type_timestamp:
     835             :         case SQL_TYPE_TIMESTAMP:
     836        1328 :                 if (IS_TDS73_PLUS(conn))
     837             :                         return SYBMSDATETIME2;
     838        1188 :                 if (IS_TDS50(conn) && tds_capability_has_req(conn, TDS_REQ_DATA_BIGDATETIME))
     839             :                         return SYB5BIGDATETIME;
     840             :                 return SYBDATETIME;
     841           0 :         case SQL_SS_TIME2:
     842           0 :                 if (IS_TDS73_PLUS(conn))
     843             :                         return SYBMSTIME;
     844           0 :                 if (IS_TDS50(conn) && tds_capability_has_req(conn, TDS_REQ_DATA_BIGDATETIME))
     845             :                         return SYB5BIGDATETIME;
     846             :                 return SYBDATETIME;
     847           0 :         case SQL_SS_TIMESTAMPOFFSET:
     848           0 :                 if (IS_TDS73_PLUS(conn))
     849             :                         return SYBMSDATETIMEOFFSET;
     850           0 :                 if (IS_TDS50(conn) && tds_capability_has_req(conn, TDS_REQ_DATA_BIGDATETIME))
     851             :                         return SYB5BIGDATETIME;
     852             :                 return SYBDATETIME;
     853        1234 :         case SQL_BINARY:
     854        1234 :                 return SYBBINARY;
     855         214 :         case SQL_VARBINARY:
     856         214 :                 return SYBVARBINARY;
     857         180 :         case SQL_LONGVARBINARY:
     858         180 :                 return SYBIMAGE;
     859           8 :         case SQL_SS_TABLE:
     860           8 :                 return SYBMSTABLE;
     861             :                 /* TODO interval types */
     862        4400 :         default:
     863        4400 :                 return TDS_INVALID_TYPE;
     864             :         }
     865             : }
     866             : 
     867             : /** Returns the version of the RDBMS in the ODBC format */
     868             : void
     869          98 : odbc_rdbms_version(TDSSOCKET * tds, char *pversion_string)
     870             : {
     871          98 :         TDS_UINT version = tds->conn->product_version;
     872         196 :         sprintf(pversion_string, "%.02d.%.02d.%.04d", (int) ((version & 0x7F000000) >> 24),
     873         196 :                 (int) ((version & 0x00FF0000) >> 16), (int) (version & 0x0000FFFF));
     874          98 : }
     875             : 
     876             : /** Return length of parameter from parameter information */
     877             : SQLLEN
     878       13198 : odbc_get_param_len(const struct _drecord *drec_axd, const struct _drecord *drec_ixd, const TDS_DESC* axd, SQLSETPOSIROW n_row)
     879             : {
     880             :         SQLLEN len;
     881             :         int size;
     882             :         TDS_INTPTR len_offset;
     883             : 
     884       13198 :         if (axd->header.sql_desc_bind_type != SQL_BIND_BY_COLUMN)
     885          60 :                 len_offset = axd->header.sql_desc_bind_type * n_row;
     886             :         else
     887       13138 :                 len_offset = sizeof(SQLLEN) * n_row;
     888       13198 :         if (axd->header.sql_desc_bind_offset_ptr)
     889          60 :                 len_offset += *axd->header.sql_desc_bind_offset_ptr;
     890             : 
     891             : #define LEN(ptr) *((SQLLEN*)(((char*)(ptr)) + len_offset))
     892             : 
     893       13198 :         if (drec_axd->sql_desc_indicator_ptr && LEN(drec_axd->sql_desc_indicator_ptr) == SQL_NULL_DATA)
     894             :                 len = SQL_NULL_DATA;
     895       12690 :         else if (drec_axd->sql_desc_octet_length_ptr)
     896        8220 :                 len = LEN(drec_axd->sql_desc_octet_length_ptr);
     897             :         else {
     898        4470 :                 len = 0;
     899             :                 /* TODO add XML if defined */
     900             :                 /* FIXME, other types available */
     901        4470 :                 if (drec_axd->sql_desc_concise_type == SQL_C_CHAR || drec_axd->sql_desc_concise_type == SQL_C_WCHAR
     902        4030 :                     || drec_axd->sql_desc_concise_type == SQL_C_BINARY) {
     903             :                         len = SQL_NTS;
     904             :                 } else {
     905        3870 :                         int type = drec_axd->sql_desc_concise_type;
     906             :                         TDS_SERVER_TYPE server_type;
     907             : 
     908        3870 :                         if (type == SQL_C_DEFAULT)
     909           0 :                                 type = odbc_sql_to_c_type_default(drec_ixd->sql_desc_concise_type);
     910        3870 :                         server_type = odbc_c_to_server_type(type);
     911             : 
     912             :                         /* FIXME check what happen to DATE/TIME types */
     913        3870 :                         size = tds_get_size_by_type(server_type);
     914        3870 :                         if (size > 0)
     915        2630 :                                 len = size;
     916             :                 }
     917             :         }
     918       13198 :         return len;
     919             : #undef LEN
     920             : }
     921             : 
     922             : #ifdef SQL_GUID
     923             : # define TYPE_NORMAL_SQL_GUID TYPE_NORMAL(SQL_GUID)
     924             : #else
     925             : # define TYPE_NORMAL_SQL_GUID
     926             : #endif
     927             : #define SQL_TYPES \
     928             :         TYPE_NORMAL(SQL_BIT) \
     929             :         TYPE_NORMAL(SQL_SMALLINT) \
     930             :         TYPE_NORMAL(SQL_TINYINT) \
     931             :         TYPE_NORMAL(SQL_INTEGER) \
     932             :         TYPE_NORMAL(SQL_BIGINT) \
     933             : \
     934             :         TYPE_NORMAL_SQL_GUID \
     935             : \
     936             :         TYPE_NORMAL(SQL_BINARY) \
     937             :         TYPE_NORMAL(SQL_VARBINARY) \
     938             :         TYPE_NORMAL(SQL_LONGVARBINARY) \
     939             : \
     940             :         TYPE_NORMAL(SQL_CHAR) \
     941             :         TYPE_NORMAL(SQL_VARCHAR) \
     942             :         TYPE_NORMAL(SQL_LONGVARCHAR) \
     943             :         TYPE_NORMAL(SQL_WCHAR) \
     944             :         TYPE_NORMAL(SQL_WVARCHAR) \
     945             :         TYPE_NORMAL(SQL_WLONGVARCHAR) \
     946             : \
     947             :         TYPE_NORMAL(SQL_DECIMAL) \
     948             :         TYPE_NORMAL(SQL_NUMERIC) \
     949             : \
     950             :         TYPE_NORMAL(SQL_FLOAT) \
     951             :         TYPE_NORMAL(SQL_REAL) \
     952             :         TYPE_NORMAL(SQL_DOUBLE)\
     953             : \
     954             :         TYPE_NORMAL(SQL_SS_TIMESTAMPOFFSET) \
     955             :         TYPE_NORMAL(SQL_SS_TIME2) \
     956             :         TYPE_NORMAL(SQL_SS_XML) \
     957             :         TYPE_NORMAL(SQL_SS_VARIANT) \
     958             :         TYPE_NORMAL(SQL_TYPE_DATE) \
     959             :         TYPE_NORMAL(SQL_TYPE_TIME) \
     960             : \
     961             :         TYPE_NORMAL(SQL_SS_TABLE) \
     962             : \
     963             :         TYPE_VERBOSE_START(SQL_DATETIME) \
     964             :         TYPE_VERBOSE_DATE(SQL_DATETIME, SQL_CODE_TIMESTAMP, SQL_TYPE_TIMESTAMP, SQL_TIMESTAMP) \
     965             :         TYPE_VERBOSE_END(SQL_DATETIME)
     966             : 
     967             : SQLSMALLINT
     968      683465 : odbc_get_concise_sql_type(SQLSMALLINT type, SQLSMALLINT interval)
     969             : {
     970             : #define TYPE_NORMAL(t) case t: return type;
     971             : #define TYPE_VERBOSE_START(t) \
     972             :         case t: switch (interval) {
     973             : #define TYPE_VERBOSE_DATE(t, interval, concise, old) \
     974             :         case interval: return concise;
     975             : #define TYPE_VERBOSE_END(t) \
     976             :         } \
     977             :         break;
     978             : 
     979      683465 :         switch (type) {
     980       24260 :                 SQL_TYPES;
     981             :         }
     982           0 :         return 0;
     983             : #undef TYPE_NORMAL
     984             : #undef TYPE_VERBOSE_START
     985             : #undef TYPE_VERBOSE_DATE
     986             : #undef TYPE_VERBOSE_END
     987             : }
     988             : 
     989             : /**
     990             :  * Set concise type and all cascading field.
     991             :  * @param concise_type concise type to set
     992             :  * @param drec         record to set. NULL to test error without setting
     993             :  * @param check_only   it <>0 (true) check only, do not set type
     994             :  */
     995             : SQLRETURN
     996       15538 : odbc_set_concise_sql_type(SQLSMALLINT concise_type, struct _drecord * drec, int check_only)
     997             : {
     998       15538 :         SQLSMALLINT type = concise_type, interval_code = 0;
     999             : 
    1000             : #define TYPE_NORMAL(t) case t: break;
    1001             : #define TYPE_VERBOSE_START(t)
    1002             : #define TYPE_VERBOSE_DATE(t, interval, concise, old) \
    1003             :         case old: concise_type = concise; \
    1004             :         case concise: type = t; interval_code = interval; break;
    1005             : #define TYPE_VERBOSE_END(t)
    1006             : 
    1007       15538 :         switch (type) {
    1008         148 :                 SQL_TYPES;
    1009             :         default:
    1010             :                 return SQL_ERROR;
    1011             :         }
    1012       15298 :         if (!check_only) {
    1013       15298 :                 if (drec->sql_desc_concise_type == SQL_SS_TABLE)
    1014        4096 :                         tvp_free((SQLTVP *) drec->sql_desc_data_ptr);
    1015             : 
    1016       15298 :                 drec->sql_desc_concise_type = concise_type;
    1017       15298 :                 drec->sql_desc_type = type;
    1018       15298 :                 drec->sql_desc_datetime_interval_code = interval_code;
    1019       15298 :                 drec->sql_desc_data_ptr = NULL;
    1020             : 
    1021       15298 :                 switch (drec->sql_desc_type) {
    1022         240 :                 case SQL_NUMERIC:
    1023             :                 case SQL_DECIMAL:
    1024         240 :                         drec->sql_desc_precision = 38;
    1025         240 :                         drec->sql_desc_scale = 0;
    1026         240 :                         break;
    1027             :                         /* TODO finish */
    1028             :                 }
    1029             :         }
    1030             :         return SQL_SUCCESS;
    1031             : #undef TYPE_NORMAL
    1032             : #undef TYPE_VERBOSE_START
    1033             : #undef TYPE_VERBOSE_DATE
    1034             : #undef TYPE_VERBOSE_END
    1035             : }
    1036             : 
    1037             : #ifdef SQL_C_GUID
    1038             : # define TYPE_NORMAL_SQL_C_GUID TYPE_NORMAL(SQL_C_GUID)
    1039             : #else
    1040             : # define TYPE_NORMAL_SQL_C_GUID
    1041             : #endif
    1042             : #define C_TYPES \
    1043             :         TYPE_NORMAL(SQL_C_BIT) \
    1044             :         TYPE_NORMAL(SQL_C_SHORT) \
    1045             :         TYPE_NORMAL(SQL_C_TINYINT) \
    1046             :         TYPE_NORMAL(SQL_C_UTINYINT) \
    1047             :         TYPE_NORMAL(SQL_C_STINYINT) \
    1048             :         TYPE_NORMAL(SQL_C_LONG) \
    1049             :         TYPE_NORMAL(SQL_C_SBIGINT) \
    1050             :         TYPE_NORMAL(SQL_C_UBIGINT) \
    1051             :         TYPE_NORMAL(SQL_C_SSHORT) \
    1052             :         TYPE_NORMAL(SQL_C_SLONG) \
    1053             :         TYPE_NORMAL(SQL_C_USHORT) \
    1054             :         TYPE_NORMAL(SQL_C_ULONG) \
    1055             : \
    1056             :         TYPE_NORMAL_SQL_C_GUID \
    1057             :         TYPE_NORMAL(SQL_C_DEFAULT) \
    1058             : \
    1059             :         TYPE_NORMAL(SQL_C_BINARY) \
    1060             : \
    1061             :         TYPE_NORMAL(SQL_C_CHAR) \
    1062             :         TYPE_NORMAL(SQL_C_WCHAR) \
    1063             : \
    1064             :         TYPE_NORMAL(SQL_C_NUMERIC) \
    1065             : \
    1066             :         TYPE_NORMAL(SQL_C_FLOAT) \
    1067             :         TYPE_NORMAL(SQL_C_DOUBLE)\
    1068             : \
    1069             :         TYPE_VERBOSE_START(SQL_DATETIME) \
    1070             :         TYPE_VERBOSE_DATE(SQL_DATETIME, SQL_CODE_DATE, SQL_C_TYPE_DATE, SQL_C_DATE) \
    1071             :         TYPE_VERBOSE_DATE(SQL_DATETIME, SQL_CODE_TIME, SQL_C_TYPE_TIME, SQL_C_TIME) \
    1072             :         TYPE_VERBOSE_DATE(SQL_DATETIME, SQL_CODE_TIMESTAMP, SQL_C_TYPE_TIMESTAMP, SQL_C_TIMESTAMP) \
    1073             :         TYPE_VERBOSE_END(SQL_DATETIME) \
    1074             : \
    1075             :         TYPE_VERBOSE_START(SQL_INTERVAL) \
    1076             :         TYPE_VERBOSE(SQL_INTERVAL, SQL_CODE_DAY, SQL_C_INTERVAL_DAY) \
    1077             :         TYPE_VERBOSE(SQL_INTERVAL, SQL_CODE_DAY_TO_HOUR, SQL_C_INTERVAL_DAY_TO_HOUR) \
    1078             :         TYPE_VERBOSE(SQL_INTERVAL, SQL_CODE_DAY_TO_MINUTE, SQL_C_INTERVAL_DAY_TO_MINUTE) \
    1079             :         TYPE_VERBOSE(SQL_INTERVAL, SQL_CODE_DAY_TO_SECOND, SQL_C_INTERVAL_DAY_TO_SECOND) \
    1080             :         TYPE_VERBOSE(SQL_INTERVAL, SQL_CODE_HOUR, SQL_C_INTERVAL_HOUR) \
    1081             :         TYPE_VERBOSE(SQL_INTERVAL, SQL_CODE_HOUR_TO_MINUTE, SQL_C_INTERVAL_HOUR_TO_MINUTE) \
    1082             :         TYPE_VERBOSE(SQL_INTERVAL, SQL_CODE_HOUR_TO_SECOND, SQL_C_INTERVAL_HOUR_TO_SECOND) \
    1083             :         TYPE_VERBOSE(SQL_INTERVAL, SQL_CODE_MINUTE, SQL_C_INTERVAL_MINUTE) \
    1084             :         TYPE_VERBOSE(SQL_INTERVAL, SQL_CODE_MINUTE_TO_SECOND, SQL_C_INTERVAL_MINUTE_TO_SECOND) \
    1085             :         TYPE_VERBOSE(SQL_INTERVAL, SQL_CODE_MONTH, SQL_C_INTERVAL_MONTH) \
    1086             :         TYPE_VERBOSE(SQL_INTERVAL, SQL_CODE_SECOND, SQL_C_INTERVAL_SECOND) \
    1087             :         TYPE_VERBOSE(SQL_INTERVAL, SQL_CODE_YEAR, SQL_C_INTERVAL_YEAR) \
    1088             :         TYPE_VERBOSE(SQL_INTERVAL, SQL_CODE_YEAR_TO_MONTH, SQL_C_INTERVAL_YEAR_TO_MONTH) \
    1089             :         TYPE_VERBOSE_END(SQL_INTERVAL)
    1090             : 
    1091             : SQLSMALLINT
    1092      273600 : odbc_get_concise_c_type(SQLSMALLINT type, SQLSMALLINT interval)
    1093             : {
    1094             : #define TYPE_NORMAL(t) case t: return type;
    1095             : #define TYPE_VERBOSE_START(t) \
    1096             :         case t: switch (interval) {
    1097             : #define TYPE_VERBOSE(t, interval, concise) \
    1098             :         case interval: return concise;
    1099             : #define TYPE_VERBOSE_DATE(t, interval, concise, old) \
    1100             :         case interval: return concise;
    1101             : #define TYPE_VERBOSE_END(t) \
    1102             :         } \
    1103             :         break;
    1104             : 
    1105      273600 :         switch (type) {
    1106        9522 :                 C_TYPES;
    1107             :         }
    1108           0 :         return 0;
    1109             : #undef TYPE_NORMAL
    1110             : #undef TYPE_VERBOSE_START
    1111             : #undef TYPE_VERBOSE
    1112             : #undef TYPE_VERBOSE_DATE
    1113             : #undef TYPE_VERBOSE_END
    1114             : }
    1115             : 
    1116             : /**
    1117             :  * Set concise type and all cascading field.
    1118             :  * @param concise_type concise type to set
    1119             :  * @param drec         record to set. NULL to test error without setting
    1120             :  * @param check_only   it <>0 (true) check only, do not set type
    1121             :  */
    1122             : SQLRETURN
    1123       21372 : odbc_set_concise_c_type(SQLSMALLINT concise_type, struct _drecord * drec, int check_only)
    1124             : {
    1125       21372 :         SQLSMALLINT type = concise_type, interval_code = 0;
    1126             : 
    1127             : #define TYPE_NORMAL(t) case t: break;
    1128             : #define TYPE_VERBOSE_START(t)
    1129             : #define TYPE_VERBOSE(t, interval, concise) \
    1130             :         case concise: type = t; interval_code = interval; break;
    1131             : #define TYPE_VERBOSE_DATE(t, interval, concise, old) \
    1132             :         case concise: type = t; interval_code = interval; break; \
    1133             :         case old: concise_type = concise; type = t; interval_code = interval; break;
    1134             : #define TYPE_VERBOSE_END(t)
    1135             : 
    1136       21372 :         switch (type) {
    1137         166 :                 C_TYPES;
    1138             :         default:
    1139             :                 return SQL_ERROR;
    1140             :         }
    1141       21232 :         if (!check_only) {
    1142       21232 :                 drec->sql_desc_concise_type = concise_type;
    1143       21232 :                 drec->sql_desc_type = type;
    1144       21232 :                 drec->sql_desc_datetime_interval_code = interval_code;
    1145       21232 :                 drec->sql_desc_data_ptr = NULL;
    1146             : 
    1147       21232 :                 switch (drec->sql_desc_type) {
    1148         604 :                 case SQL_C_NUMERIC:
    1149         604 :                         drec->sql_desc_length = 38;
    1150         604 :                         drec->sql_desc_precision = 38;
    1151         604 :                         drec->sql_desc_scale = 0;
    1152         604 :                         break;
    1153             :                         /* TODO finish */
    1154             :                 }
    1155             :         }
    1156             :         return SQL_SUCCESS;
    1157             : #undef TYPE_NORMAL
    1158             : #undef TYPE_VERBOSE_START
    1159             : #undef TYPE_VERBOSE
    1160             : #undef TYPE_VERBOSE_DATE
    1161             : #undef TYPE_VERBOSE_END
    1162             : }
    1163             : 
    1164             : SQLLEN
    1165        4430 : odbc_get_octet_len(int c_type, const struct _drecord *drec)
    1166             : {
    1167             :         SQLLEN len;
    1168             : 
    1169             :         /* this shit is mine -- freddy77 */
    1170        4430 :         switch (c_type) {
    1171        2344 :         case SQL_C_CHAR:
    1172             :         case SQL_C_WCHAR:
    1173             :         case SQL_C_BINARY:
    1174        2344 :                 len = drec->sql_desc_octet_length;
    1175        2344 :                 break;
    1176             :         case SQL_C_DATE:
    1177             :         case SQL_C_TYPE_DATE:
    1178             :                 len = sizeof(DATE_STRUCT);
    1179             :                 break;
    1180             :         case SQL_C_TIME:
    1181             :         case SQL_C_TYPE_TIME:
    1182             :                 len = sizeof(TIME_STRUCT);
    1183             :                 break;
    1184           0 :         case SQL_C_TIMESTAMP:
    1185             :         case SQL_C_TYPE_TIMESTAMP:
    1186           0 :                 len = sizeof(TIMESTAMP_STRUCT);
    1187           0 :                 break;
    1188         178 :         case SQL_C_NUMERIC:
    1189         178 :                 len = sizeof(SQL_NUMERIC_STRUCT);
    1190         178 :                 break;
    1191        1908 :         default:
    1192        1908 :                 len = tds_get_size_by_type(odbc_c_to_server_type(c_type));
    1193        1908 :                 break;
    1194             :         }
    1195        4430 :         return len;
    1196             : }
    1197             : 
    1198             : void
    1199       15360 : odbc_convert_err_set(struct _sql_errors *errs, TDS_INT err)
    1200             : {
    1201             :         /*
    1202             :          * TODO we really need a column offset in the _sql_error structure so that caller can
    1203             :          * invoke SQLGetDiagField to learn which column is failing
    1204             :          */
    1205       15360 :         switch (err) {
    1206       12360 :         case TDS_CONVERT_NOAVAIL:
    1207       12360 :                 odbc_errs_add(errs, "HY003", NULL);
    1208       12360 :                 break;
    1209         830 :         case TDS_CONVERT_SYNTAX:
    1210         830 :                 odbc_errs_add(errs, "22018", NULL);
    1211         830 :                 break;
    1212        2170 :         case TDS_CONVERT_OVERFLOW:
    1213        2170 :                 odbc_errs_add(errs, "22003", NULL);
    1214        2170 :                 break;
    1215           0 :         case TDS_CONVERT_FAIL:
    1216           0 :                 odbc_errs_add(errs, "07006", NULL);
    1217           0 :                 break;
    1218           0 :         case TDS_CONVERT_NOMEM:
    1219           0 :                 odbc_errs_add(errs, "HY001", NULL);
    1220           0 :                 break;
    1221             :         }
    1222       15360 : }
    1223             : 
    1224             : /** @} */

Generated by: LCOV version 1.13