LTP GCOV extension - code coverage report
Current view: directory - odbc - convert_tds2sql.c
Test: FreeTDS coverage
Date: 2008-11-21 Instrumented lines: 104
Code covered: 89.4 % Executed lines: 93

       1                 : /* FreeTDS - Library of routines accessing Sybase and Microsoft databases
       2                 :  * Copyright (C) 1998-1999  Brian Bruns
       3                 :  * Copyright (C) 2003-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                 : #include "tdsodbc.h"
      36                 : #include "tdsconvert.h"
      37                 : 
      38                 : #ifdef DMALLOC
      39                 : #include <dmalloc.h>
      40                 : #endif
      41                 : 
      42                 : TDS_RCSID(var, "$Id: convert_tds2sql.c,v 1.46 2005/08/23 17:25:51 freddy77 Exp $");
      43                 : 
      44                 : TDS_INT
      45                 : convert_tds2sql(TDSCONTEXT * context, int srctype, TDS_CHAR * src, TDS_UINT srclen, int desttype, TDS_CHAR * dest, SQLULEN destlen,
      46                 :                 const struct _drecord *drec_ixd)
      47            1281 : {
      48                 :         TDS_INT nDestSybType;
      49            1281 :         TDS_INT nRetVal = TDS_FAIL;
      50                 : 
      51                 :         CONV_RESULT ores;
      52                 : 
      53                 :         TDSDATEREC dr;
      54                 :         DATE_STRUCT *dsp;
      55                 :         TIME_STRUCT *tsp;
      56                 :         TIMESTAMP_STRUCT *tssp;
      57                 :         SQL_NUMERIC_STRUCT *num;
      58                 : 
      59            1281 :         int ret = TDS_FAIL;
      60                 :         int i, cplen;
      61                 : 
      62            1281 :         tdsdump_log(TDS_DBG_FUNC, "convert_tds2sql: src is %d dest = %d\n", srctype, desttype);
      63                 : 
      64            1281 :         assert(desttype != SQL_C_DEFAULT);
      65                 : 
      66            1281 :         nDestSybType = odbc_c_to_server_type(desttype);
      67            1281 :         if (nDestSybType == TDS_FAIL)
      68               0 :                 return TDS_CONVERT_NOAVAIL;
      69                 : 
      70                 :         /* special case for binary type */
      71            1281 :         if (desttype == SQL_C_BINARY) {
      72              48 :                 tdsdump_log(TDS_DBG_FUNC, "convert_tds2sql: outputting binary data destlen = %lu \n", (unsigned long) destlen);
      73                 : 
      74              48 :                 if (is_numeric_type(srctype)) {
      75               4 :                         desttype = SQL_C_NUMERIC;
      76               4 :                         nDestSybType = SYBNUMERIC;
      77                 :                         /* prevent buffer overflow */
      78               4 :                         if (destlen < sizeof(SQL_NUMERIC_STRUCT))
      79               0 :                                 return TDS_CONVERT_FAIL;
      80               4 :                         ores.n.precision = ((TDS_NUMERIC *) src)->precision;
      81               4 :                         ores.n.scale = ((TDS_NUMERIC *) src)->scale;
      82                 :                 } else {
      83              44 :                         ret = srclen;
      84              44 :                         if (destlen > 0) {
      85              44 :                                 cplen = (destlen > srclen) ? srclen : destlen;
      86              44 :                                 assert(cplen >= 0);
      87                 :                                 /* do not NULL terminate binary buffer */
      88              44 :                                 memcpy(dest, src, cplen);
      89                 :                         } else {
      90                 :                                 /* if destlen == 0 we return only length */
      91               0 :                                 if (destlen != 0)
      92               0 :                                         ret = TDS_FAIL;
      93                 :                         }
      94              44 :                         return ret;
      95                 :                 }
      96            1233 :         } else if (is_numeric_type(nDestSybType)) {
      97                 :                 /* TODO use descriptor information (APD) ?? However APD can contain SQL_C_DEFAULT... */
      98              10 :                 if (drec_ixd)
      99              10 :                         ores.n.precision = drec_ixd->sql_desc_precision;
     100                 :                 else
     101               0 :                         ores.n.precision = 38;
     102              10 :                 ores.n.scale = 0;
     103                 :         }
     104                 : 
     105                 : 
     106            1237 :         nRetVal = tds_convert(context, srctype, src, srclen, nDestSybType, &ores);
     107            1237 :         if (nRetVal < 0)
     108               0 :                 return nRetVal;
     109                 : 
     110            1237 :         switch (desttype) {
     111                 : 
     112                 :         case SQL_C_CHAR:
     113             730 :                 tdsdump_log(TDS_DBG_FUNC, "convert_tds2sql: outputting character data destlen = %lu \n", (unsigned long) destlen);
     114                 : 
     115             730 :                 ret = nRetVal;
     116                 :                 /* TODO handle not terminated configuration */
     117             730 :                 if (destlen > 0) {
     118             726 :                         cplen = (destlen - 1) > nRetVal ? nRetVal : (destlen - 1);
     119             726 :                         assert(cplen >= 0);
     120                 :                         /*
     121                 :                          * odbc always terminate but do not overwrite 
     122                 :                          * destination buffer more than needed
     123                 :                          */
     124             726 :                         memcpy(dest, ores.c, cplen);
     125             726 :                         dest[cplen] = 0;
     126                 :                 } else {
     127                 :                         /* if destlen == 0 we return only length */
     128               4 :                         if (destlen != 0)
     129               0 :                                 ret = TDS_FAIL;
     130                 :                 }
     131                 : 
     132             730 :                 free(ores.c);
     133             730 :                 break;
     134                 : 
     135                 :         case SQL_C_TYPE_DATE:
     136                 :         case SQL_C_DATE:
     137                 : 
     138                 :                 /* we've already converted the returned value to a SYBDATETIME */
     139                 :                 /* now decompose date into constituent parts...                */
     140                 : 
     141               2 :                 tds_datecrack(SYBDATETIME, &(ores.dt), &dr);
     142                 : 
     143               2 :                 dsp = (DATE_STRUCT *) dest;
     144                 : 
     145               2 :                 dsp->year = dr.year;
     146               2 :                 dsp->month = dr.month + 1;
     147               2 :                 dsp->day = dr.day;
     148                 : 
     149               2 :                 ret = sizeof(DATE_STRUCT);
     150               2 :                 break;
     151                 : 
     152                 :         case SQL_C_TYPE_TIME:
     153                 :         case SQL_C_TIME:
     154                 : 
     155                 :                 /* we've already converted the returned value to a SYBDATETIME */
     156                 :                 /* now decompose date into constituent parts...                */
     157                 : 
     158               2 :                 tds_datecrack(SYBDATETIME, &(ores.dt), &dr);
     159                 : 
     160               2 :                 tsp = (TIME_STRUCT *) dest;
     161                 : 
     162               2 :                 tsp->hour = dr.hour;
     163               2 :                 tsp->minute = dr.minute;
     164               2 :                 tsp->second = dr.second;
     165                 : 
     166               2 :                 ret = sizeof(TIME_STRUCT);
     167               2 :                 break;
     168                 : 
     169                 :         case SQL_C_TYPE_TIMESTAMP:
     170                 :         case SQL_C_TIMESTAMP:
     171                 : 
     172                 :                 /* we've already converted the returned value to a SYBDATETIME */
     173                 :                 /* now decompose date into constituent parts...                */
     174                 : 
     175               4 :                 tds_datecrack(SYBDATETIME, &(ores.dt), &dr);
     176                 : 
     177               4 :                 tssp = (TIMESTAMP_STRUCT *) dest;
     178                 : 
     179               4 :                 tssp->year = dr.year;
     180               4 :                 tssp->month = dr.month + 1;
     181               4 :                 tssp->day = dr.day;
     182               4 :                 tssp->hour = dr.hour;
     183               4 :                 tssp->minute = dr.minute;
     184               4 :                 tssp->second = dr.second;
     185               4 :                 tssp->fraction = dr.millisecond * 1000000u;
     186                 : 
     187               4 :                 ret = sizeof(TIMESTAMP_STRUCT);
     188               4 :                 break;
     189                 : 
     190                 : #ifdef SQL_C_SBIGINT
     191                 :         case SQL_C_SBIGINT:
     192                 :         case SQL_C_UBIGINT:
     193               0 :                 *((TDS_INT8 *) dest) = ores.bi;
     194               0 :                 ret = sizeof(TDS_INT8);
     195               0 :                 break;
     196                 : #endif
     197                 : 
     198                 :         case SQL_C_LONG:
     199                 :         case SQL_C_SLONG:
     200                 :         case SQL_C_ULONG:
     201             224 :                 *((TDS_INT *) dest) = ores.i;
     202             224 :                 ret = sizeof(TDS_INT);
     203             224 :                 break;
     204                 : 
     205                 :         case SQL_C_SHORT:
     206                 :         case SQL_C_SSHORT:
     207                 :         case SQL_C_USHORT:
     208             234 :                 *((TDS_SMALLINT *) dest) = ores.si;
     209             234 :                 ret = sizeof(TDS_SMALLINT);
     210             234 :                 break;
     211                 : 
     212                 :         case SQL_C_TINYINT:
     213                 :         case SQL_C_STINYINT:
     214                 :         case SQL_C_UTINYINT:
     215                 :         case SQL_C_BIT:
     216               6 :                 *((TDS_TINYINT *) dest) = ores.ti;
     217               6 :                 ret = sizeof(TDS_TINYINT);
     218               6 :                 break;
     219                 : 
     220                 :         case SQL_C_DOUBLE:
     221               8 :                 *((TDS_FLOAT *) dest) = ores.f;
     222               8 :                 ret = sizeof(TDS_FLOAT);
     223               8 :                 break;
     224                 : 
     225                 :         case SQL_C_FLOAT:
     226               8 :                 *((TDS_REAL *) dest) = ores.r;
     227               8 :                 ret = sizeof(TDS_REAL);
     228               8 :                 break;
     229                 : 
     230                 :         case SQL_C_NUMERIC:
     231                 :                 /* ODBC numeric is quite different from TDS one ... */
     232              14 :                 num = (SQL_NUMERIC_STRUCT *) dest;
     233              14 :                 num->precision = ores.n.precision;
     234              14 :                 num->scale = ores.n.scale;
     235              14 :                 num->sign = ores.n.array[0] ^ 1;
     236                 :                 /* FIXME can i be greater than SQL_MAX_NUMERIC_LEN ?? */
     237              14 :                 i = tds_numeric_bytes_per_prec[ores.n.precision] - 1;
     238              14 :                 memcpy(num->val, ores.n.array + 1, i);
     239              14 :                 tds_swap_bytes(num->val, i);
     240              14 :                 if (i < SQL_MAX_NUMERIC_LEN)
     241               8 :                         memset(num->val + i, 0, SQL_MAX_NUMERIC_LEN - i);
     242              14 :                 ret = sizeof(SQL_NUMERIC_STRUCT);
     243              14 :                 break;
     244                 : 
     245                 : #ifdef SQL_C_GUID
     246                 :         case SQL_C_GUID:
     247               5 :                 memcpy(dest, &(ores.u), sizeof(TDS_UNIQUE));
     248               5 :                 ret = sizeof(TDS_UNIQUE);
     249               5 :                 break;
     250                 : #endif
     251                 : 
     252                 :         case SQL_C_BINARY:
     253                 :                 /* type already handled */
     254               0 :                 assert(desttype != SQL_C_BINARY);
     255                 : 
     256                 :         default:
     257                 :                 break;
     258                 : 
     259                 :         }
     260                 : 
     261            1237 :         return ret;
     262                 : }

Generated by: LTP GCOV extension version 1.6