LTP GCOV extension - code coverage report
Current view: directory - odbc - sql2tds.c
Test: FreeTDS coverage
Date: 2008-11-21 Instrumented lines: 157
Code covered: 86.6 % Executed lines: 136

       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 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                 : #if HAVE_CONFIG_H
      22                 : #include <config.h>
      23                 : #endif /* HAVE_CONFIG_H */
      24                 : 
      25                 : #include <assert.h>
      26                 : 
      27                 : #if HAVE_STDLIB_H
      28                 : #include <stdlib.h>
      29                 : #endif /* HAVE_STDLIB_H */
      30                 : 
      31                 : #if HAVE_STRING_H
      32                 : #include <string.h>
      33                 : #endif /* HAVE_STRING_H */
      34                 : 
      35                 : #if TIME_WITH_SYS_TIME
      36                 : # if HAVE_SYS_TIME_H
      37                 : #  include <sys/time.h>
      38                 : # endif
      39                 : # include <time.h>
      40                 : #else
      41                 : # if HAVE_SYS_TIME_H
      42                 : #  include <sys/time.h>
      43                 : # else
      44                 : #  include <time.h>
      45                 : # endif
      46                 : #endif
      47                 : 
      48                 : #include "tdsodbc.h"
      49                 : #include "tdsconvert.h"
      50                 : 
      51                 : #ifdef DMALLOC
      52                 : #include <dmalloc.h>
      53                 : #endif
      54                 : 
      55                 : TDS_RCSID(var, "$Id: sql2tds.c,v 1.51.2.3 2007/12/21 11:19:05 freddy77 Exp $");
      56                 : 
      57                 : static TDS_INT
      58                 : convert_datetime2server(int bindtype, const void *src, TDS_DATETIME * dt)
      59               6 : {
      60                 :         struct tds_time src_tm;
      61                 :         unsigned int dt_time;
      62                 :         TDS_INT dt_days;
      63                 :         int i;
      64               6 :         int got_date = 1;
      65                 :         time_t curr_time;
      66                 : 
      67               6 :         const DATE_STRUCT *src_date = (const DATE_STRUCT *) src;
      68               6 :         const TIME_STRUCT *src_time = (const TIME_STRUCT *) src;
      69               6 :         const TIMESTAMP_STRUCT *src_timestamp = (const TIMESTAMP_STRUCT *) src;
      70                 : 
      71               6 :         switch (bindtype) {
      72                 :         case SQL_C_DATE:
      73                 :         case SQL_C_TYPE_DATE:
      74               2 :                 src_tm.tm_year = src_date->year - 1900;
      75               2 :                 src_tm.tm_mon = src_date->month - 1;
      76               2 :                 src_tm.tm_mday = src_date->day;
      77               2 :                 src_tm.tm_hour = 0;
      78               2 :                 src_tm.tm_min = 0;
      79               2 :                 src_tm.tm_sec = 0;
      80               2 :                 src_tm.tm_ms = 0;
      81               2 :                 break;
      82                 :         case SQL_C_TIME:
      83                 :         case SQL_C_TYPE_TIME:
      84               2 :                 got_date = 0;
      85                 : #if HAVE_GETTIMEOFDAY
      86                 :                 {
      87                 :                         struct timeval tv;
      88               2 :                         gettimeofday(&tv, NULL);
      89               2 :                         curr_time = tv.tv_sec;
      90                 :                 }
      91                 : #else
      92                 :                 curr_time = time(NULL);
      93                 : #endif
      94               2 :                 dt_days = (curr_time / 86400u) + (70u * 365u + 17u);
      95               2 :                 src_tm.tm_hour = src_time->hour;
      96               2 :                 src_tm.tm_min = src_time->minute;
      97               2 :                 src_tm.tm_sec = src_time->second;
      98               2 :                 src_tm.tm_ms = 0;
      99               2 :                 break;
     100                 :         case SQL_C_TIMESTAMP:
     101                 :         case SQL_C_TYPE_TIMESTAMP:
     102               2 :                 src_tm.tm_year = src_timestamp->year - 1900;
     103               2 :                 src_tm.tm_mon = src_timestamp->month - 1;
     104               2 :                 src_tm.tm_mday = src_timestamp->day;
     105               2 :                 src_tm.tm_hour = src_timestamp->hour;
     106               2 :                 src_tm.tm_min = src_timestamp->minute;
     107               2 :                 src_tm.tm_sec = src_timestamp->second;
     108               2 :                 src_tm.tm_ms = src_timestamp->fraction / 1000000lu;
     109               2 :                 break;
     110                 :         default:
     111               0 :                 return TDS_FAIL;
     112                 :         }
     113                 : 
     114                 :         /* TODO code copied from convert.c, function */
     115               6 :         if (got_date) {
     116               4 :                 i = (src_tm.tm_mon - 13) / 12;
     117               4 :                 dt_days = 1461 * (src_tm.tm_year + 300 + i) / 4 +
     118                 :                         (367 * (src_tm.tm_mon - 1 - 12 * i)) / 12 - (3 * ((src_tm.tm_year + 400 + i) / 100)) / 4 +
     119                 :                         src_tm.tm_mday - 109544;
     120                 :         }
     121                 : 
     122               6 :         dt->dtdays = dt_days;
     123               6 :         dt_time = (src_tm.tm_hour * 60 + src_tm.tm_min) * 60 + src_tm.tm_sec;
     124               6 :         dt->dttime = dt_time * 300 + (src_tm.tm_ms * 300 / 1000);
     125               6 :         return sizeof(TDS_DATETIME);
     126                 : }
     127                 : 
     128                 : /**
     129                 :  * Convert parameters to libtds format
     130                 :  * @return SQL_SUCCESS, SQL_ERROR or SQL_NEED_DATA
     131                 :  */
     132                 : SQLRETURN
     133                 : sql2tds(TDS_STMT * stmt, const struct _drecord *drec_ipd, const struct _drecord *drec_apd, TDSPARAMINFO * info, int nparam,
     134                 :         int compute_row, const TDS_DESC* axd, unsigned int n_row)
     135             432 : {
     136             432 :         TDS_DBC * dbc = stmt->dbc;
     137                 :         int dest_type, src_type, sql_src_type, res;
     138                 :         CONV_RESULT ores;
     139                 :         TDSBLOB *blob;
     140                 :         char *src;
     141                 :         unsigned char *dest;
     142             432 :         TDSCOLUMN *curcol = info->columns[nparam];
     143                 :         int len;
     144                 :         TDS_DATETIME dt;
     145                 :         TDS_NUMERIC num;
     146                 :         SQL_NUMERIC_STRUCT *sql_num;
     147                 :         SQLINTEGER sql_len;
     148             432 :         int need_data = 0, i;
     149                 : 
     150                 :         /* TODO handle bindings of char like "{d '2002-11-12'}" */
     151             432 :         tdsdump_log(TDS_DBG_INFO2, "type=%d\n", drec_ipd->sql_desc_concise_type);
     152                 : 
     153                 :         /* what type to convert ? */
     154             432 :         dest_type = odbc_sql_to_server_type(dbc->tds_socket, drec_ipd->sql_desc_concise_type);
     155             432 :         if (dest_type == TDS_FAIL)
     156               0 :                 return SQL_ERROR;
     157             432 :         tdsdump_log(TDS_DBG_INFO2, "trace\n");
     158                 : 
     159                 :         /* TODO what happen for unicode types ?? */
     160             432 :         tds_set_param_type(dbc->tds_socket, curcol, dest_type);
     161             432 :         if (is_numeric_type(curcol->column_type)) {
     162               8 :                 curcol->column_prec = drec_ipd->sql_desc_precision;
     163               8 :                 curcol->column_scale = drec_ipd->sql_desc_scale;
     164               8 :                 ores.n.precision = drec_ipd->sql_desc_precision;
     165               8 :                 ores.n.scale = drec_ipd->sql_desc_scale;
     166                 :         }
     167                 : 
     168             432 :         if (drec_ipd->sql_desc_parameter_type != SQL_PARAM_INPUT)
     169              32 :                 curcol->column_output = 1;
     170                 : 
     171                 :         /* compute destination length */
     172             432 :         if (curcol->column_varint_size != 0) {
     173                 :                 /* curcol->column_size = drec_apd->sql_desc_octet_length; */
     174                 :                 /*
     175                 :                  * TODO destination length should come from sql_desc_length, 
     176                 :                  * however there is the encoding problem to take into account
     177                 :                  * we should fill destination length after conversion keeping 
     178                 :                  * attention to fill correctly blob/fixed type/variable type
     179                 :                  */
     180                 :                 /* TODO location of this test is correct here ?? */
     181             348 :                 if (dest_type != SYBUNIQUE && dest_type != SYBBITN && !is_fixed_type(dest_type)) {
     182             210 :                         curcol->column_cur_size = 0;
     183             210 :                         curcol->column_size = drec_ipd->sql_desc_length;
     184             210 :                         if (curcol->column_size < 0)
     185               2 :                                 curcol->column_size = 0x7FFFFFFFl;
     186                 :                 }
     187              84 :         } else if (dest_type != SYBBIT) {
     188                 :                 /* TODO only a trick... */
     189              82 :                 tds_set_param_type(dbc->tds_socket, curcol, tds_get_null_type(dest_type));
     190                 :         }
     191                 : 
     192                 :         /* get C type */
     193             432 :         sql_src_type = drec_apd->sql_desc_concise_type;
     194             432 :         if (sql_src_type == SQL_C_DEFAULT)
     195               0 :                 sql_src_type = odbc_sql_to_c_type_default(drec_ipd->sql_desc_concise_type);
     196                 : 
     197                 :         /* test source type */
     198                 :         /* TODO test intervals */
     199             432 :         src_type = odbc_c_to_server_type(sql_src_type);
     200             432 :         if (src_type == TDS_FAIL)
     201               0 :                 return SQL_ERROR;
     202                 : 
     203                 :         /* we have no data to convert, just return */
     204             432 :         if (!compute_row)
     205              15 :                 return TDS_SUCCEED;
     206                 : 
     207             417 :         src = drec_apd->sql_desc_data_ptr;
     208             417 :         if (src && n_row) {
     209                 :                 SQLLEN len;
     210                 : 
     211             108 :                 if (axd->header.sql_desc_bind_type != SQL_BIND_BY_COLUMN) {
     212               0 :                         len = axd->header.sql_desc_bind_type;
     213               0 :                         if (axd->header.sql_desc_bind_offset_ptr)
     214               0 :                                 src += *axd->header.sql_desc_bind_offset_ptr;
     215                 :                 } else {
     216             108 :                         len = odbc_get_octet_len(sql_src_type, drec_apd);
     217             108 :                         if (len < 0)
     218                 :                                 /* TODO sure ? what happen to upper layer ?? */
     219               0 :                                 return SQL_ERROR;
     220                 :                 }
     221             108 :                 src += len * n_row;
     222                 :         }
     223                 : 
     224                 :         /* if only output assume input is NULL */
     225             417 :         if (drec_ipd->sql_desc_parameter_type == SQL_PARAM_OUTPUT) {
     226              32 :                 sql_len = SQL_NULL_DATA;
     227                 :         } else {
     228             385 :                 sql_len = odbc_get_param_len(drec_apd, drec_ipd, axd, n_row);
     229                 : 
     230                 :                 /* special case, MS ODBC handle conversion from "\0" to any to NULL, DBD::ODBC require it */
     231             385 :                 if (src_type == SYBVARCHAR && sql_len == 1 && drec_ipd->sql_desc_parameter_type == SQL_PARAM_INPUT_OUTPUT
     232                 :                     && src && *src == 0) {
     233               0 :                         sql_len = SQL_NULL_DATA;
     234                 :                 }
     235                 :         }
     236                 : 
     237                 :         /* compute source length */
     238             417 :         switch (sql_len) {
     239                 :         case SQL_NULL_DATA:
     240              32 :                 len = 0;
     241              32 :                 break;
     242                 :         case SQL_NTS:
     243             229 :                 len = strlen(src);
     244             229 :                 break;
     245                 :         case SQL_DEFAULT_PARAM:
     246                 :         case SQL_DATA_AT_EXEC:
     247                 :                 /* TODO */
     248               0 :                 return SQL_ERROR;
     249                 :                 break;
     250                 :         default:
     251             156 :                 len = sql_len;
     252             156 :                 if (sql_len < 0) {
     253                 :                         /* test for SQL_C_CHAR/SQL_C_BINARY */
     254               6 :                         switch (sql_src_type) {
     255                 :                         case SQL_C_CHAR:
     256                 :                         case SQL_C_BINARY:
     257                 :                                 break;
     258                 :                         default:
     259               0 :                                 return SQL_ERROR;
     260                 :                         }
     261               6 :                         len = SQL_LEN_DATA_AT_EXEC(sql_len);
     262               6 :                         need_data = 1;
     263                 : 
     264                 :                         /* dynamic length allowed only for BLOB fields */
     265               6 :                         switch (drec_ipd->sql_desc_concise_type) {
     266                 :                         case SQL_LONGVARCHAR:
     267                 :                         case SQL_LONGVARBINARY:
     268               6 :                                 break;
     269                 :                         default:
     270               0 :                                 return SQL_ERROR;
     271                 :                         }
     272                 :                 }
     273                 :         }
     274                 : 
     275                 :         /* allocate given space */
     276             417 :         if (!tds_alloc_param_row(info, curcol))
     277               0 :                 return SQL_ERROR;
     278                 : 
     279             417 :         if (need_data) {
     280               6 :                 curcol->column_cur_size = 0;
     281               6 :                 return SQL_NEED_DATA;
     282                 :         }
     283                 : 
     284                 :         /* set null */
     285             411 :         assert(drec_ipd->sql_desc_parameter_type != SQL_PARAM_OUTPUT || sql_len == SQL_NULL_DATA);
     286             411 :         if (sql_len == SQL_NULL_DATA) {
     287              32 :                 curcol->column_cur_size = -1;
     288              32 :                 return TDS_SUCCEED;
     289                 :         }
     290                 : 
     291                 :         /* convert special parameters (not libTDS compatible) */
     292             379 :         switch (src_type) {
     293                 :         case SYBDATETIME:
     294               6 :                 convert_datetime2server(drec_apd->sql_desc_concise_type, src, &dt);
     295               6 :                 src = (char *) &dt;
     296               6 :                 break;
     297                 :         case SYBDECIMAL:
     298                 :         case SYBNUMERIC:
     299               2 :                 sql_num = (SQL_NUMERIC_STRUCT *) src;
     300               2 :                 num.precision = sql_num->precision;
     301               2 :                 num.scale = sql_num->scale;
     302               2 :                 num.array[0] = sql_num->sign ^ 1;
     303                 :                 /* test precision so client do not crash our library */
     304               2 :                 if (num.precision <= 0 || num.precision > 38 || num.scale > num.precision)
     305                 :                         /* TODO add proper error */
     306               0 :                         return SQL_ERROR;
     307               2 :                 i = tds_numeric_bytes_per_prec[num.precision];
     308               2 :                 memcpy(num.array + 1, sql_num->val, i - 1);
     309               2 :                 tds_swap_bytes(num.array + 1, i - 1);
     310               2 :                 if (i < sizeof(num.array))
     311               2 :                         memset(num.array + i, 0, sizeof(num.array) - i);
     312               2 :                 src = (char *) &num;
     313                 :                 break;
     314                 :                 /* TODO intervals */
     315                 :         }
     316                 : 
     317             379 :         res = tds_convert(dbc->env->tds_ctx, src_type, src, len, dest_type, &ores);
     318             379 :         if (res < 0)
     319               0 :                 return SQL_ERROR;
     320             379 :         tdsdump_log(TDS_DBG_INFO2, "trace\n");
     321                 : 
     322                 :         /* truncate ?? */
     323                 :         /* TODO what happen for blobs ?? */
     324             379 :         if (res > curcol->column_size)
     325               2 :                 res = curcol->column_size;
     326             379 :         curcol->column_cur_size = res;
     327                 : 
     328                 :         /* free allocated memory */
     329             379 :         dest = &info->current_row[curcol->column_offset];
     330             379 :         switch ((TDS_SERVER_TYPE) dest_type) {
     331                 :         case SYBCHAR:
     332                 :         case SYBVARCHAR:
     333                 :         case XSYBCHAR:
     334                 :         case XSYBVARCHAR:
     335             170 :                 memcpy(&info->current_row[curcol->column_offset], ores.c, res);
     336             170 :                 free(ores.c);
     337             170 :                 break;
     338                 :         case SYBTEXT:
     339               5 :                 blob = (TDSBLOB *) dest;
     340               5 :                 if (blob->textvalue)
     341               0 :                         free(blob->textvalue);
     342               5 :                 blob->textvalue = ores.c;
     343               5 :                 break;
     344                 :         case SYBBINARY:
     345                 :         case SYBVARBINARY:
     346                 :         case XSYBBINARY:
     347                 :         case XSYBVARBINARY:
     348               0 :                 memcpy(&info->current_row[curcol->column_offset], ores.ib, res);
     349               0 :                 free(ores.ib);
     350               0 :                 break;
     351                 :         case SYBLONGBINARY:
     352                 :         case SYBIMAGE:
     353               2 :                 blob = (TDSBLOB *) dest;
     354               2 :                 if (blob->textvalue)
     355               0 :                         free(blob->textvalue);
     356               2 :                 blob->textvalue = ores.ib;
     357               2 :                 break;
     358                 :         case SYBNUMERIC:
     359                 :         case SYBDECIMAL:
     360                 :                 /*
     361                 :                  * for these types we ignore column_size so fix it in case
     362                 :                  * we overwrote it
     363                 :                  */
     364               2 :                 res = sizeof(TDS_NUMERIC);
     365                 :         case SYBINTN:
     366                 :         case SYBINT1:
     367                 :         case SYBINT2:
     368                 :         case SYBINT4:
     369                 :         case SYBINT8:
     370                 :         case SYBFLT8:
     371                 :         case SYBDATETIME:
     372                 :         case SYBBIT:
     373                 :         case SYBMONEY4:
     374                 :         case SYBMONEY:
     375                 :         case SYBDATETIME4:
     376                 :         case SYBREAL:
     377                 :         case SYBBITN:
     378                 :         case SYBFLTN:
     379                 :         case SYBMONEYN:
     380                 :         case SYBDATETIMN:
     381                 :         case SYBSINT1:
     382                 :         case SYBUINT2:
     383                 :         case SYBUINT4:
     384                 :         case SYBUINT8:
     385                 :         case SYBUNIQUE:
     386             202 :                 memcpy(&info->current_row[curcol->column_offset], &ores, res);
     387             202 :                 break;
     388                 :         case XSYBNVARCHAR:
     389                 :         case XSYBNCHAR:
     390                 :         case SYBNVARCHAR:
     391                 :         case SYBNTEXT:
     392                 :         case SYBVOID:
     393                 :         case SYBVARIANT:
     394                 :                 /* TODO ODBC 3.5 */
     395               0 :                 assert(0);
     396                 :                 break;
     397                 :         }
     398                 : 
     399             379 :         return SQL_SUCCESS;
     400                 : }

Generated by: LTP GCOV extension version 1.6