LCOV - code coverage report
Current view: top level - src/odbc - sql2tds.c (source / functions) Hit Total Coverage
Test: FreeTDS coverage Lines: 235 282 83.3 %
Date: 2024-03-23 08:24:27 Functions: 5 5 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-2015  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             : #include <assert.h>
      24             : 
      25             : #if HAVE_STDLIB_H
      26             : #include <stdlib.h>
      27             : #endif /* HAVE_STDLIB_H */
      28             : 
      29             : #if HAVE_STRING_H
      30             : #include <string.h>
      31             : #endif /* HAVE_STRING_H */
      32             : 
      33             : #include <freetds/time.h>
      34             : #include <freetds/odbc.h>
      35             : #include <freetds/convert.h>
      36             : #include <freetds/iconv.h>
      37             : #include <freetds/utils/string.h>
      38             : #include <freetds/utils.h>
      39             : 
      40             : TDS_INT
      41         404 : convert_datetime2server(int bindtype, const void *src, TDS_DATETIMEALL * dta)
      42             : {
      43             :         struct tm src_tm;
      44             :         int tm_dms;
      45             :         unsigned int dt_time;
      46             :         int i;
      47             :         time_t curr_time;
      48             : 
      49         404 :         const DATE_STRUCT *src_date = (const DATE_STRUCT *) src;
      50         404 :         const TIME_STRUCT *src_time = (const TIME_STRUCT *) src;
      51         404 :         const TIMESTAMP_STRUCT *src_timestamp = (const TIMESTAMP_STRUCT *) src;
      52             : 
      53         404 :         memset(dta, 0, sizeof(*dta));
      54             : 
      55         404 :         switch (bindtype) {
      56          54 :         case SQL_C_DATE:
      57             :         case SQL_C_TYPE_DATE:
      58          54 :                 src_tm.tm_year = src_date->year - 1900;
      59          54 :                 src_tm.tm_mon = src_date->month - 1;
      60          54 :                 src_tm.tm_mday = src_date->day;
      61          54 :                 src_tm.tm_hour = 0;
      62          54 :                 src_tm.tm_min = 0;
      63          54 :                 src_tm.tm_sec = 0;
      64          54 :                 tm_dms = 0;
      65             :                 dta->has_date = 1;
      66          54 :                 break;
      67          54 :         case SQL_C_TIME:
      68             :         case SQL_C_TYPE_TIME:
      69             : #if HAVE_GETTIMEOFDAY
      70             :                 {
      71             :                         struct timeval tv;
      72          54 :                         gettimeofday(&tv, NULL);
      73          54 :                         curr_time = tv.tv_sec;
      74             :                 }
      75             : #else
      76             :                 curr_time = time(NULL);
      77             : #endif
      78          54 :                 tds_localtime_r(&curr_time, &src_tm);
      79          54 :                 src_tm.tm_hour = src_time->hour;
      80          54 :                 src_tm.tm_min = src_time->minute;
      81          54 :                 src_tm.tm_sec = src_time->second;
      82          54 :                 tm_dms = 0;
      83             :                 dta->has_time = 1;
      84          54 :                 break;
      85         296 :         case SQL_C_TIMESTAMP:
      86             :         case SQL_C_TYPE_TIMESTAMP:
      87         296 :                 src_tm.tm_year = src_timestamp->year - 1900;
      88         296 :                 src_tm.tm_mon = src_timestamp->month - 1;
      89         296 :                 src_tm.tm_mday = src_timestamp->day;
      90         296 :                 src_tm.tm_hour = src_timestamp->hour;
      91         296 :                 src_tm.tm_min = src_timestamp->minute;
      92         296 :                 src_tm.tm_sec = src_timestamp->second;
      93         296 :                 tm_dms = src_timestamp->fraction / 100lu;
      94             :                 dta->has_date = 1;
      95             :                 dta->has_time = 1;
      96         296 :                 break;
      97             :         default:
      98             :                 return TDS_CONVERT_FAIL;
      99             :         }
     100             : 
     101             :         /* TODO code copied from convert.c, function */
     102         404 :         i = (src_tm.tm_mon - 13) / 12;
     103         404 :         dta->has_date = 1;
     104        1212 :         dta->date = 1461 * (src_tm.tm_year + 300 + i) / 4 +
     105        1212 :                 (367 * (src_tm.tm_mon - 1 - 12 * i)) / 12 - (3 * ((src_tm.tm_year + 400 + i) / 100)) / 4 +
     106         808 :                 src_tm.tm_mday - 109544;
     107             : 
     108         404 :         dta->has_time = 1;
     109         404 :         dt_time = (src_tm.tm_hour * 60 + src_tm.tm_min) * 60 + src_tm.tm_sec;
     110         404 :         dta->time = dt_time * UINT64_C(10000000) + tm_dms;
     111         404 :         return sizeof(TDS_DATETIMEALL);
     112             : }
     113             : 
     114             : static char*
     115          36 : odbc_wstr2str(TDS_STMT * stmt, const char *src, int* len)
     116             : {
     117          36 :         int srclen = (*len) / sizeof(SQLWCHAR);
     118          36 :         char *out = tds_new(char, srclen + 1), *p;
     119          36 :         const SQLWCHAR *wp = (const SQLWCHAR *) src;
     120             : 
     121          36 :         if (!out) {
     122           0 :                 odbc_errs_add(&stmt->errs, "HY001", NULL);
     123           0 :                 return NULL;
     124             :         }
     125             : 
     126             :         /* convert */
     127             :         p = out;
     128         324 :         for (; srclen && *wp < 256; --srclen)
     129         324 :                 *p++ = (char) *wp++;
     130             : 
     131             :         /* still characters, wrong format */
     132          36 :         if (srclen) {
     133           0 :                 free(out);
     134             :                 /* TODO correct error ?? */
     135           0 :                 odbc_errs_add(&stmt->errs, "07006", NULL);
     136           0 :                 return NULL;
     137             :         }
     138             : 
     139          36 :         *len = p - out;
     140          36 :         return out;
     141             : }
     142             : 
     143             : static void
     144         424 : _odbc_blob_free(TDSCOLUMN *col)
     145             : {
     146         424 :         if (!col->column_data)
     147             :                 return;
     148             : 
     149         424 :         TDS_ZERO_FREE(col->column_data);
     150             : }
     151             : 
     152             : static SQLRETURN
     153           4 : odbc_convert_table(TDS_STMT *stmt, SQLTVP *src, TDS_TVP *dest, SQLLEN num_rows)
     154             : {
     155             :         SQLLEN i;
     156             :         int j;
     157             :         TDS_TVP_ROW *row;
     158             :         TDS_TVP_ROW **prow;
     159             :         TDSPARAMINFO *params, *new_params;
     160           4 :         TDS_DESC *apd = src->apd, *ipd = src->ipd;
     161             :         SQLRETURN ret;
     162             :         char *type_name, *pch;
     163             : 
     164             :         /* probably data at execution attempt, currently not supported for TVP */
     165           4 :         if (num_rows < 0) {
     166           0 :                 odbc_errs_add(&stmt->errs, "HYC00", "Data at execution are not supported for TVP columns");
     167           0 :                 return SQL_ERROR;
     168             :         }
     169             : 
     170           4 :         tds_deinit_tvp(dest);
     171             : 
     172           8 :         type_name = strdup(tds_dstr_cstr(&src->type_name));
     173           4 :         if (!type_name)
     174             :                 goto Memory_Error;
     175             : 
     176             :         /* Tokenize and extract the schema & TVP typename from the TVP's full name */
     177           4 :         pch = strchr(type_name, '.');
     178           4 :         if (pch == NULL) {
     179           4 :                 dest->schema = tds_strndup("", 0);
     180           4 :                 dest->name = type_name;
     181             :         } else {
     182           0 :                 *pch = 0;
     183           0 :                 dest->schema = type_name;
     184           0 :                 dest->name = strdup(++pch);
     185             :         }
     186           8 :         if (!dest->schema || !dest->name)
     187             :                 goto Memory_Error;
     188             : 
     189             :         /* Ensure that the TVP typename does not contain any more '.' */
     190             :         /* Otherwise, report it as an invalid data type error */
     191           4 :         pch = strchr(dest->name, '.');
     192           4 :         if (pch != NULL) {
     193           0 :                 odbc_errs_add(&stmt->errs, "HY004", NULL);
     194           0 :                 return SQL_ERROR;
     195             :         }
     196             : 
     197             :         params = NULL;
     198           8 :         for (j = 0; j < ipd->header.sql_desc_count; j++) {
     199           8 :                 if (!(new_params = tds_alloc_param_result(params))) {
     200           0 :                         tds_free_param_results(params);
     201           0 :                         goto Memory_Error;
     202             :                 }
     203           8 :                 params = new_params;
     204             : 
     205           8 :                 ret = odbc_sql2tds(stmt, &ipd->records[j], &apd->records[j], new_params->columns[j], false, apd, 0);
     206           8 :                 if (!SQL_SUCCEEDED(ret)) {
     207           0 :                         tds_free_param_results(params);
     208           0 :                         return ret;
     209             :                 }
     210             :         }
     211           4 :         dest->metadata = params;
     212             : 
     213          22 :         for (i = 0, prow = &dest->row; i < num_rows; prow = &(*prow)->next, i++) {
     214          18 :                 if ((row = tds_new0(TDS_TVP_ROW, 1)) == NULL)
     215             :                         goto Memory_Error;
     216             : 
     217          18 :                 *prow = row;
     218             : 
     219          18 :                 params = NULL;
     220          54 :                 for (j = 0; j < ipd->header.sql_desc_count; j++) {
     221          36 :                         if (!(new_params = tds_alloc_param_result(params))) {
     222           0 :                                 tds_free_param_results(params);
     223           0 :                                 goto Memory_Error;
     224             :                         }
     225          36 :                         params = new_params;
     226             : 
     227          36 :                         ret = odbc_sql2tds(stmt, &ipd->records[j], &apd->records[j], new_params->columns[j], true, apd, i);
     228          36 :                         if (!SQL_SUCCEEDED(ret)) {
     229           0 :                                 tds_free_param_results(params);
     230           0 :                                 return ret;
     231             :                         }
     232             :                 }
     233          18 :                 row->params = params;
     234             :         }
     235             : 
     236             :         return SQL_SUCCESS;
     237             : 
     238           0 : Memory_Error:
     239           0 :         odbc_errs_add(&stmt->errs, "HY001", NULL);
     240           0 :         return SQL_ERROR;
     241             : }
     242             : 
     243             : /**
     244             :  * Convert parameters to libtds format
     245             :  * @param stmt        ODBC statement
     246             :  * @param drec_ixd    IRD or IPD record of destination
     247             :  * @param drec_ard    ARD or APD record of source
     248             :  * @param curcol      destination column
     249             :  * @param compute_row true if data needs to be written to column
     250             :  * @param axd         ARD or APD of source
     251             :  * @param n_row       number of the row to write
     252             :  * @return SQL_SUCCESS, SQL_ERROR or SQL_NEED_DATA
     253             :  */
     254             : SQLRETURN
     255       19080 : odbc_sql2tds(TDS_STMT * stmt, const struct _drecord *drec_ixd, const struct _drecord *drec_axd, TDSCOLUMN *curcol,
     256             :         bool compute_row, const TDS_DESC* axd, unsigned int n_row)
     257             : {
     258       19080 :         TDS_DBC * dbc = stmt->dbc;
     259       19080 :         TDSCONNECTION * conn = dbc->tds_socket->conn;
     260             :         TDS_SERVER_TYPE dest_type, src_type;
     261             :         int sql_src_type, res;
     262             :         CONV_RESULT ores;
     263             :         TDSBLOB *blob;
     264             :         char *src, *converted_src;
     265             :         unsigned char *dest;
     266             :         int len;
     267             :         TDS_DATETIMEALL dta;
     268             :         TDS_NUMERIC num;
     269             :         SQL_NUMERIC_STRUCT *sql_num;
     270             :         SQLINTEGER sql_len;
     271       19080 :         bool need_data = false;
     272             :         int i;
     273             : 
     274             :         /* TODO handle bindings of char like "{d '2002-11-12'}" */
     275       19080 :         tdsdump_log(TDS_DBG_INFO2, "type=%d\n", drec_ixd->sql_desc_concise_type);
     276             : 
     277             :         /* what type to convert ? */
     278       19080 :         dest_type = odbc_sql_to_server_type(conn, drec_ixd->sql_desc_concise_type, drec_ixd->sql_desc_unsigned);
     279       19080 :         if (dest_type == TDS_INVALID_TYPE) {
     280        3712 :                 odbc_errs_add(&stmt->errs, "07006", NULL);     /* Restricted data type attribute violation */
     281        3712 :                 return SQL_ERROR;
     282             :         }
     283       15368 :         tdsdump_log(TDS_DBG_INFO2, "trace\n");
     284             : 
     285             :         /* get C type */
     286       15368 :         sql_src_type = drec_axd->sql_desc_concise_type;
     287       15368 :         if (sql_src_type == SQL_C_DEFAULT)
     288           0 :                 sql_src_type = odbc_sql_to_c_type_default(drec_ixd->sql_desc_concise_type);
     289             : 
     290       15368 :         tds_set_param_type(conn, curcol, dest_type);
     291             : 
     292             :         /* TODO what happen for unicode types ?? */
     293       15368 :         if (is_char_type(dest_type)) {
     294        5200 :                 TDSICONV *conv = conn->char_convs[is_unicode_type(dest_type) ? client2ucs2 : client2server_chardata];
     295             : 
     296             :                 /* use binary format for binary to char */
     297        5200 :                 if (sql_src_type == SQL_C_BINARY) {
     298         258 :                         curcol->char_conv = NULL;
     299        4942 :                 } else if (sql_src_type == SQL_C_WCHAR) {
     300         396 :                         curcol->char_conv = tds_iconv_get_info(conn, odbc_get_wide_canonic(conn), conv->to.charset.canonic);
     301         396 :                         memcpy(curcol->column_collation, conn->collation, sizeof(conn->collation));
     302             :                 } else {
     303             : #ifdef ENABLE_ODBC_WIDE
     304        4546 :                         curcol->char_conv = tds_iconv_get_info(conn, dbc->original_charset_num, conv->to.charset.canonic);
     305             : #else
     306             :                         curcol->char_conv = NULL;
     307             : #endif
     308             :                 }
     309             :         }
     310       15368 :         if (is_numeric_type(curcol->column_type)) {
     311         764 :                 curcol->column_prec = drec_ixd->sql_desc_precision;
     312         764 :                 curcol->column_scale = drec_ixd->sql_desc_scale;
     313             :         }
     314             : 
     315       15368 :         if (drec_ixd->sql_desc_parameter_type != SQL_PARAM_INPUT)
     316        9184 :                 curcol->column_output = 1;
     317             : 
     318             :         /* compute destination length */
     319       15368 :         if (curcol->column_varint_size != 0) {
     320             :                 /* curcol->column_size = drec_axd->sql_desc_octet_length; */
     321             :                 /*
     322             :                  * TODO destination length should come from sql_desc_length, 
     323             :                  * however there is the encoding problem to take into account
     324             :                  * we should fill destination length after conversion keeping 
     325             :                  * attention to fill correctly blob/fixed type/variable type
     326             :                  */
     327             :                 /* TODO location of this test is correct here ?? */
     328       15240 :                 if (dest_type != SYBUNIQUE && !is_fixed_type(dest_type)) {
     329        7870 :                         curcol->column_cur_size = 0;
     330        7870 :                         curcol->column_size = drec_ixd->sql_desc_length;
     331             :                         /* Ensure that the column_cur_size and column_size are consistent, */
     332             :                         /* since drec_ixd->sql_desc_length contains the number of rows for a TVP */
     333        7870 :                         if (dest_type == SYBMSTABLE)
     334           4 :                                 curcol->column_size = sizeof(TDS_TVP);
     335        7870 :                         if (curcol->column_size < 0) {
     336           8 :                                 curcol->on_server.column_size = curcol->column_size = 0x7FFFFFFFl;
     337             :                         } else {
     338        7862 :                                 if (is_unicode_type(dest_type))
     339        1616 :                                         curcol->on_server.column_size = curcol->column_size * 2;
     340             :                                 else
     341        6246 :                                         curcol->on_server.column_size = curcol->column_size;
     342             :                         }
     343             :                 }
     344         128 :         } else if (dest_type != SYBBIT) {
     345             :                 /* TODO only a trick... */
     346          12 :                 tds_set_param_type(conn, curcol, tds_get_null_type(dest_type));
     347             :         }
     348             : 
     349             :         /* test source type */
     350             :         /* TODO test intervals */
     351       15368 :         src_type = odbc_c_to_server_type(sql_src_type);
     352       15368 :         if (!src_type) {
     353        4976 :                 odbc_errs_add(&stmt->errs, "07006", NULL);     /* Restricted data type attribute violation */
     354        4976 :                 return SQL_ERROR;
     355             :         }
     356             : 
     357             :         /* we have no data to convert, just return */
     358       10392 :         if (!compute_row)
     359             :                 return SQL_SUCCESS;
     360             : 
     361       10384 :         src = (char *) drec_axd->sql_desc_data_ptr;
     362       10384 :         if (src && n_row) {
     363             :                 SQLLEN len;
     364        1276 :                 if (axd->header.sql_desc_bind_type != SQL_BIND_BY_COLUMN) {
     365           0 :                         len = axd->header.sql_desc_bind_type;
     366           0 :                         if (axd->header.sql_desc_bind_offset_ptr)
     367           0 :                                 src += *axd->header.sql_desc_bind_offset_ptr;
     368             :                 } else {
     369        1276 :                         len = odbc_get_octet_len(sql_src_type, drec_axd);
     370        1276 :                         if (len < 0)
     371             :                                 /* TODO sure ? what happen to upper layer ?? */
     372             :                                 /* TODO fill error */
     373             :                                 return SQL_ERROR;
     374             :                 }
     375        1276 :                 src += len * n_row;
     376             :         }
     377             : 
     378             :         /* if only output assume input is NULL */
     379       10384 :         if (drec_ixd->sql_desc_parameter_type == SQL_PARAM_OUTPUT) {
     380             :                 sql_len = SQL_NULL_DATA;
     381             :         } else {
     382        9654 :                 sql_len = odbc_get_param_len(drec_axd, drec_ixd, axd, n_row);
     383             : 
     384             :                 /* special case, MS ODBC handle conversion from "\0" to any to NULL, DBD::ODBC require it */
     385        9654 :                 if (src_type == SYBVARCHAR && sql_len == 1 && drec_ixd->sql_desc_parameter_type == SQL_PARAM_INPUT_OUTPUT
     386           0 :                     && src && *src == 0) {
     387             :                         sql_len = SQL_NULL_DATA;
     388             :                 }
     389             :         }
     390             : 
     391             :         /* compute source length */
     392        9654 :         switch (sql_len) {
     393        1116 :         case SQL_NULL_DATA:
     394        1116 :                 len = 0;
     395             :                 break;
     396        2178 :         case SQL_NTS:
     397             :                 /* check that SQLBindParameter::ParameterValuePtr is not zero for input parameters */
     398        2178 :                 if (!src) {
     399         392 :                         odbc_errs_add(&stmt->errs, "HY090", NULL);
     400         392 :                         return SQL_ERROR;
     401             :                 }
     402        1786 :                 if (sql_src_type == SQL_C_WCHAR)
     403          72 :                         len = sqlwcslen((const SQLWCHAR *) src) * sizeof(SQLWCHAR);
     404             :                 else
     405        1714 :                         len = strlen(src);
     406             :                 break;
     407           0 :         case SQL_DEFAULT_PARAM:
     408           0 :                 odbc_errs_add(&stmt->errs, "07S01", NULL);     /* Invalid use of default parameter */
     409           0 :                 return SQL_ERROR;
     410             :                 break;
     411        7090 :         case SQL_DATA_AT_EXEC:
     412             :         default:
     413        7090 :                 len = sql_len;
     414        7090 :                 if (sql_len < 0) {
     415             :                         /* test for SQL_C_CHAR/SQL_C_BINARY */
     416             :                         switch (sql_src_type) {
     417             :                         case SQL_C_CHAR:
     418             :                         case SQL_C_WCHAR:
     419             :                         case SQL_C_BINARY:
     420             :                                 break;
     421           0 :                         default:
     422           0 :                                 odbc_errs_add(&stmt->errs, "HY090", NULL);
     423           0 :                                 return SQL_ERROR;
     424             :                         }
     425         260 :                         len = SQL_LEN_DATA_AT_EXEC(sql_len);
     426         260 :                         need_data = true;
     427             : 
     428             :                         /* dynamic length allowed only for BLOB fields */
     429         260 :                         switch (drec_ixd->sql_desc_concise_type) {
     430             :                         case SQL_LONGVARCHAR:
     431             :                         case SQL_WLONGVARCHAR:
     432             :                         case SQL_LONGVARBINARY:
     433             :                                 break;
     434           0 :                         default:
     435           0 :                                 odbc_errs_add(&stmt->errs, "HY090", NULL);
     436           0 :                                 return SQL_ERROR;
     437             :                         }
     438        6830 :                 }
     439             :         }
     440             : 
     441             :         /* set NULL. For NULLs we don't need to allocate row buffer so avoid it */
     442             :         if (!need_data) {
     443        9732 :                 assert(drec_ixd->sql_desc_parameter_type != SQL_PARAM_OUTPUT || sql_len == SQL_NULL_DATA);
     444        9732 :                 if (sql_len == SQL_NULL_DATA) {
     445        1116 :                         curcol->column_cur_size = -1;
     446        1116 :                         return SQL_SUCCESS;
     447             :                 }
     448             :         }
     449             : 
     450        8876 :         if (is_char_type(dest_type) && !need_data
     451        3368 :             && (sql_src_type == SQL_C_CHAR || sql_src_type == SQL_C_WCHAR || sql_src_type == SQL_C_BINARY)) {
     452        2458 :                 if (curcol->column_data && curcol->column_data_free)
     453           0 :                         curcol->column_data_free(curcol);
     454        2458 :                 curcol->column_data_free = NULL;
     455        2458 :                 if (is_blob_col(curcol)) {
     456             :                         /* trick to set blob without freeing it, _odbc_blob_free does not free TDSBLOB->textvalue */
     457         424 :                         TDSBLOB *blob = tds_new0(TDSBLOB, 1);
     458         424 :                         if (!blob) {
     459           0 :                                 odbc_errs_add(&stmt->errs, "HY001", NULL);
     460           0 :                                 return SQL_ERROR;
     461             :                         }
     462         424 :                         blob->textvalue = src;
     463         424 :                         curcol->column_data = (TDS_UCHAR*) blob;
     464         424 :                         curcol->column_data_free = _odbc_blob_free;
     465             :                 } else {
     466        2034 :                         curcol->column_data = (TDS_UCHAR*) src;
     467             :                 }
     468        2458 :                 curcol->column_size = len;
     469        2458 :                 curcol->column_cur_size = len;
     470        2458 :                 return SQL_SUCCESS;
     471             :         }
     472             : 
     473             :         /* allocate given space */
     474        6418 :         if (!tds_alloc_param_data(curcol)) {
     475           0 :                 odbc_errs_add(&stmt->errs, "HY001", NULL);
     476           0 :                 return SQL_ERROR;
     477             :         }
     478             : 
     479             :         /* fill data with SQLPutData */
     480        6418 :         if (need_data) {
     481         260 :                 curcol->column_cur_size = 0;
     482         260 :                 return SQL_NEED_DATA;
     483             :         }
     484             : 
     485        6158 :         if (!src) {
     486        3064 :                 odbc_errs_add(&stmt->errs, "HY090", NULL);
     487        3064 :                 return SQL_ERROR;
     488             :         }
     489             : 
     490             :         /* convert special parameters (not libTDS compatible) */
     491        3094 :         switch (src_type) {
     492         402 :         case SYBMSDATETIME2:
     493         402 :                 convert_datetime2server(sql_src_type, src, &dta);
     494         402 :                 src = (char *) &dta;
     495         402 :                 break;
     496         136 :         case SYBDECIMAL:
     497             :         case SYBNUMERIC:
     498         136 :                 sql_num = (SQL_NUMERIC_STRUCT *) src;
     499         136 :                 num.precision = sql_num->precision;
     500         136 :                 num.scale = sql_num->scale;
     501         136 :                 num.array[0] = sql_num->sign ^ 1;
     502             :                 /* test precision so client do not crash our library */
     503         136 :                 if (num.precision <= 0 || num.precision > 38 || num.scale > num.precision)
     504             :                         /* TODO add proper error */
     505             :                         return SQL_ERROR;
     506         136 :                 i = tds_numeric_bytes_per_prec[num.precision];
     507         136 :                 memcpy(num.array + 1, sql_num->val, i - 1);
     508         136 :                 tds_swap_bytes(num.array + 1, i - 1);
     509         136 :                 if (i < sizeof(num.array))
     510         136 :                         memset(num.array + i, 0, sizeof(num.array) - i);
     511             :                 src = (char *) &num;
     512             :                 break;
     513             :                 /* TODO intervals */
     514             :         default:
     515             :                 /* prevents some compiler warnings about missing cases */
     516             :                 break;
     517             :         }
     518             : 
     519        3094 :         converted_src = NULL;
     520        3094 :         if (sql_src_type == SQL_C_WCHAR) {
     521          36 :                 converted_src = src = odbc_wstr2str(stmt, src, &len);
     522          36 :                 if (!src)
     523             :                         /* TODO add proper error */
     524             :                         return SQL_ERROR;
     525             :                 src_type = SYBVARCHAR;
     526             :         }
     527             : 
     528        3094 :         dest = curcol->column_data;
     529        3094 :         switch ((TDS_SERVER_TYPE) dest_type) {
     530         126 :         case SYBCHAR:
     531             :         case SYBVARCHAR:
     532             :         case XSYBCHAR:
     533             :         case XSYBVARCHAR:
     534             :         case XSYBNVARCHAR:
     535             :         case XSYBNCHAR:
     536             :         case SYBNVARCHAR:
     537         126 :                 ores.cc.c = (TDS_CHAR*) dest;
     538         126 :                 ores.cc.len = curcol->column_size;
     539         126 :                 res = tds_convert(dbc->env->tds_ctx, src_type, src, len, TDS_CONVERT_CHAR, &ores);
     540         126 :                 if (res > curcol->column_size)
     541           0 :                         res = curcol->column_size;
     542             :                 break;
     543         174 :         case SYBBINARY:
     544             :         case SYBVARBINARY:
     545             :         case XSYBBINARY:
     546             :         case XSYBVARBINARY:
     547         174 :                 ores.cb.ib = (TDS_CHAR*) dest;
     548         174 :                 ores.cb.len = curcol->column_size;
     549         174 :                 res = tds_convert(dbc->env->tds_ctx, src_type, src, len, TDS_CONVERT_BINARY, &ores);
     550         174 :                 if (res > curcol->column_size)
     551           0 :                         res = curcol->column_size;
     552             :                 break;
     553          36 :         case SYBNTEXT:
     554          36 :                 dest_type = SYBTEXT;
     555         194 :         case SYBTEXT:
     556             :         case SYBLONGBINARY:
     557             :         case SYBIMAGE:
     558         194 :                 res = tds_convert(dbc->env->tds_ctx, src_type, src, len, dest_type, &ores);
     559         194 :                 if (res >= 0) {
     560         194 :                         blob = (TDSBLOB *) dest;
     561         194 :                         free(blob->textvalue);
     562         194 :                         blob->textvalue = ores.ib;
     563             :                 }
     564             :                 break;
     565          52 :         case SYBNUMERIC:
     566             :         case SYBDECIMAL:
     567          52 :                 ((TDS_NUMERIC *) dest)->precision = drec_ixd->sql_desc_precision;
     568          52 :                 ((TDS_NUMERIC *) dest)->scale = drec_ixd->sql_desc_scale;
     569        2596 :         case SYBINTN:
     570             :         case SYBINT1:
     571             :         case SYBINT2:
     572             :         case SYBINT4:
     573             :         case SYBINT8:
     574             :         case SYBFLT8:
     575             :         case SYBDATETIME:
     576             :         case SYBBIT:
     577             :         case SYBMONEY4:
     578             :         case SYBMONEY:
     579             :         case SYBDATETIME4:
     580             :         case SYBREAL:
     581             :         case SYBBITN:
     582             :         case SYBFLTN:
     583             :         case SYBMONEYN:
     584             :         case SYBDATETIMN:
     585             :         case SYBSINT1:
     586             :         case SYBUINT2:
     587             :         case SYBUINT4:
     588             :         case SYBUINT8:
     589             :         case SYBUNIQUE:
     590             :         case SYBMSTIME:
     591             :         case SYBMSDATE:
     592             :         case SYBMSDATETIME2:
     593             :         case SYBMSDATETIMEOFFSET:
     594             :         case SYB5BIGTIME:
     595             :         case SYB5BIGDATETIME:
     596        2596 :                 res = tds_convert(dbc->env->tds_ctx, src_type, src, len, dest_type, (CONV_RESULT*) dest);
     597        2596 :                 break;
     598           4 :         case SYBMSTABLE:
     599           4 :                 free(converted_src);
     600           4 :                 src = drec_ixd->sql_desc_data_ptr;
     601           4 :                 curcol->column_cur_size = sizeof(TDS_TVP);
     602           4 :                 return odbc_convert_table(stmt, (SQLTVP *) src, (TDS_TVP *) dest,
     603           4 :                                           drec_axd->sql_desc_octet_length_ptr == NULL ? 1 : *drec_axd->sql_desc_octet_length_ptr);
     604             :         default:
     605             :         case SYBVOID:
     606             :         case SYBVARIANT:
     607             :                 /* TODO ODBC 3.5 */
     608           0 :                 assert(0);
     609             :                 res = -1;
     610             :                 break;
     611             :         }
     612             : 
     613        3090 :         free(converted_src);
     614        3090 :         if (res < 0) {
     615           0 :                 odbc_convert_err_set(&stmt->errs, res);
     616           0 :                 return SQL_ERROR;
     617             :         }
     618             : 
     619        3090 :         curcol->column_cur_size = res;
     620             : 
     621        3090 :         return SQL_SUCCESS;
     622             : }

Generated by: LCOV version 1.13