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

Generated by: LCOV version 1.13