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

Generated by: LCOV version 1.13