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

Generated by: LCOV version 1.13