LCOV - code coverage report
Current view: top level - src/tds/unittests - allcolumns.c (source / functions) Hit Total Coverage
Test: FreeTDS coverage Lines: 166 171 97.1 %
Date: 2026-03-24 22:22:09 Functions: 4 4 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  Brian Bruns
       3             :  * Copyright (C) 2017  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             : #define TDS_DONT_DEFINE_DEFAULT_FUNCTIONS
      22             : #include "common.h"
      23             : #include <assert.h>
      24             : #include <freetds/tds/convert.h>
      25             : #include <freetds/tds/checks.h>
      26             : #include <freetds/tds/all_types.h>
      27             : 
      28             : static bool
      29        4230 : is_convert_pointer_type(int type)
      30             : {
      31        4230 :         switch (type) {
      32             :         case SYBCHAR: case SYBVARCHAR: case SYBTEXT: case XSYBCHAR: case XSYBVARCHAR:
      33             :         case SYBBINARY: case SYBVARBINARY: case SYBIMAGE: case XSYBBINARY: case XSYBVARBINARY:
      34             :         case SYBLONGBINARY:
      35             :                 return true;
      36             :         }
      37        3660 :         return false;
      38             : }
      39             : 
      40             : 
      41             : static void
      42        2160 : free_convert(int type, CONV_RESULT *cr)
      43             : {
      44        2160 :         if (is_convert_pointer_type(type))
      45         330 :                 free(cr->c);
      46        2160 : }
      47             : 
      48             : static void create_type(TDSSOCKET *tds, int desttype, int server_type, tds_any_type_t *func);
      49             : 
      50             : enum { TDSVER_MS = 0x704, TDSVER_SYB = 0x500 };
      51             : 
      52          30 : void tds_all_types(TDSSOCKET *tds, tds_any_type_t *func)
      53             : {
      54             :         int desttype;
      55             : 
      56          30 :         tds->conn->tds_version = TDSVER_MS;
      57             : 
      58             :         /*
      59             :          * Test every type
      60             :          */
      61        7710 :         for (desttype = 0; desttype < 0x100; desttype++) {
      62             :                 int types_buffer[10];
      63        7680 :                 int *types = types_buffer, *types_end;
      64             :                 int server_type;
      65             :                 int varint, other_varint;
      66             : 
      67        7680 :                 if (!is_tds_type_valid(desttype))
      68       12240 :                         continue;
      69             : 
      70        1740 :                 tds->conn->tds_version = TDSVER_MS;
      71             : 
      72             :                 /* if is only Sybase change version to Sybase */
      73        1740 :                 varint = tds_get_varint_size(tds->conn, desttype);
      74        1740 :                 tds->conn->tds_version ^= TDSVER_MS ^ TDSVER_SYB;
      75        1740 :                 other_varint = tds_get_varint_size(tds->conn, desttype);
      76        1740 :                 tds->conn->tds_version ^= TDSVER_MS ^ TDSVER_SYB;
      77        1740 :                 if (varint == 1 && varint != other_varint)
      78         360 :                         tds->conn->tds_version = TDSVER_SYB;
      79             : 
      80        1740 :                 server_type = desttype;
      81        1740 :                 switch (desttype) {
      82             :                 /* unsupported */
      83          60 :                 case SYBVOID:
      84             :                 case SYBINTERVAL:
      85          60 :                         continue;
      86             :                 /* nullable, use another type */
      87             :                 /* TODO, try all sizes */
      88          30 :                 case SYBINTN:
      89          30 :                         *types++ = SYBINT1;
      90          30 :                         *types++ = SYBINT2;
      91          30 :                         *types++ = SYBINT4;
      92          30 :                         *types++ = SYBINT8;
      93          30 :                         break;
      94          30 :                 case SYBUINTN:
      95          30 :                         *types++ = SYBUINT1;
      96          30 :                         *types++ = SYBUINT2;
      97          30 :                         *types++ = SYBUINT4;
      98          30 :                         *types++ = SYBUINT8;
      99          30 :                         tds->conn->tds_version = TDSVER_SYB;
     100          30 :                         break;
     101          30 :                 case SYBFLTN:
     102          30 :                         *types++ = SYBREAL;
     103          30 :                         *types++ = SYBFLT8;
     104          30 :                         break;
     105          30 :                 case SYBMONEYN:
     106          30 :                         *types++ = SYBMONEY4;
     107          30 :                         *types++ = SYBMONEY;
     108          30 :                         break;
     109          30 :                 case SYBDATETIMN:
     110          30 :                         *types++ = SYBDATETIME4;
     111          30 :                         *types++ = SYBDATETIME;
     112          30 :                         break;
     113          30 :                 case SYBDATEN:
     114          30 :                         *types++ = SYBDATE;
     115          30 :                         tds->conn->tds_version = TDSVER_SYB;
     116          30 :                         break;
     117          30 :                 case SYBTIMEN:
     118          30 :                         *types++ = SYBTIME;
     119          30 :                         tds->conn->tds_version = TDSVER_SYB;
     120          30 :                         break;
     121          30 :                 case SYB5INT8:
     122          30 :                         *types++ = SYBINT8;
     123          30 :                         break;
     124             :                 /* TODO tds_set_column_type */
     125             : 
     126         300 :                 case SYBXML: /* ?? */
     127             :                 case SYBNTEXT: /* ?? */
     128             :                 case XSYBNVARCHAR:
     129             :                 case XSYBNCHAR:
     130             :                 case SYBNVARCHAR:
     131             :                 case SYBMSUDT:
     132             :                 case SYBMSXML:
     133             :                 case SYBUNITEXT:
     134             :                 case SYBVARIANT: /* TODO */
     135             :                 case SYBSINT1: /* TODO */
     136             :                 case SYBMSTABLE: /* TODO */
     137         300 :                         continue;
     138             :                 }
     139             : 
     140        1380 :                 if (types == types_buffer)
     141        1140 :                         *types++ = desttype;
     142             : 
     143        1380 :                 types_end = types;
     144        3030 :                 for (types = types_buffer; types != types_end; ++types) {
     145        1650 :                         create_type(tds, *types, server_type, func);
     146        1650 :                         if (*types != server_type)
     147         510 :                                 create_type(tds, *types, *types, func);
     148             :                 }
     149             :         }
     150          30 : }
     151             : 
     152        2160 : static void create_type(TDSSOCKET *tds, int desttype, int server_type, tds_any_type_t *func)
     153             : {
     154        2160 :         const TDSCONTEXT *ctx = tds_get_ctx(tds);
     155             :         int result;
     156        2160 :         TDS_CHAR *src = NULL;
     157             :         TDS_UINT srclen;
     158             : 
     159             :         CONV_RESULT cr;
     160        2160 :         const int srctype = SYBCHAR;
     161             : 
     162             :         TDSRESULTINFO *results;
     163             :         TDSCOLUMN *curcol;
     164             : 
     165        2160 :         cr.n.precision = 8;
     166        2160 :         cr.n.scale = 2;
     167             : 
     168        2160 :         switch (desttype) {
     169             :         case SYBCHAR:
     170             :         case SYBVARCHAR:
     171             :         case SYBTEXT:
     172             :         case XSYBVARCHAR:
     173             :         case XSYBCHAR:
     174             :                 src = "test of a character field";
     175             :                 break;
     176         180 :         case SYBDATETIME:
     177             :         case SYBDATETIME4:
     178         180 :                 src = "Apr 12, 1985 17:49:41";
     179         180 :                 break;
     180         120 :         case SYBMSDATE:
     181             :         case SYBDATE:
     182         120 :                 src = "2012-11-27";
     183         120 :                 break;
     184          90 :         case SYBTIME:
     185          90 :                 src = "15:27:12";
     186          90 :                 break;
     187          60 :         case SYBMSTIME:
     188             :         case SYB5BIGTIME:
     189          60 :                 src = "15:27:12.327862";
     190          60 :                 break;
     191          90 :         case SYBMSDATETIME2:
     192             :         case SYBMSDATETIMEOFFSET:
     193             :         case SYB5BIGDATETIME:
     194          90 :                 src = "2015-09-12 21:48:12.638161";
     195          90 :                 break;
     196          60 :         case SYBBINARY:
     197             :         case SYBIMAGE:
     198          60 :                 src = "0xbeef";
     199          60 :                 break;
     200         540 :         case SYBINT1:
     201             :         case SYBINT2:
     202             :         case SYBINT4:
     203             :         case SYBUINT1:
     204             :         case SYBUINT2:
     205             :         case SYBUINT4:
     206         540 :                 src = "255";
     207         540 :                 break;
     208         240 :         case SYBINT8:
     209             :         case SYBUINT8:
     210         240 :                 src = "374632567765";
     211         240 :                 break;
     212         360 :         case SYBFLT8:
     213             :         case SYBREAL:
     214             :         case SYBMONEY:
     215             :         case SYBMONEY4:
     216         360 :                 src = "1237.45";
     217             :                 cr.n.precision = 8;
     218             :                 cr.n.scale = 2;
     219         360 :                 break;
     220          60 :         case SYBNUMERIC:
     221             :         case SYBDECIMAL:
     222          60 :                 src = "947919.25";
     223             :                 cr.n.precision = 8;
     224             :                 cr.n.scale = 2;
     225          60 :                 break;
     226          30 :         case SYBUNIQUE:
     227          30 :                 src = "A8C60F70-5BD4-3E02-B769-7CCCCA585DCC";
     228          30 :                 break;
     229         180 :         case SYBBIT:
     230             :         default:
     231         180 :                 src = "1";
     232         180 :                 break;
     233             :         }
     234             :         assert(src);
     235        2160 :         srclen = (TDS_UINT) strlen(src);
     236             : 
     237             :         /*
     238             :          * Now at last do the conversion
     239             :          */
     240             : 
     241        2160 :         result = tds_convert(ctx, srctype, src, srclen, desttype, &cr);
     242             : 
     243        2160 :         if (result < 0) {
     244           0 :                 if (result == TDS_CONVERT_NOAVAIL)      /* tds_willconvert returned true, but it lied. */
     245           0 :                         fprintf(stderr, "Conversion not yet implemented:\n\t");
     246             : 
     247           0 :                 fprintf(stderr, "failed (%d) to convert %d (%s, %d bytes) : %d (%s).\n",
     248             :                         result,
     249             :                         srctype, tds_prtype(srctype), srclen,
     250             :                         desttype, tds_prtype(desttype));
     251             : 
     252           0 :                 if (result == TDS_CONVERT_NOAVAIL)
     253           0 :                         exit(1);
     254             :         }
     255             : 
     256        2160 :         printf("converted %d (%s, %d bytes) -> %d (%s, %d bytes).\n",
     257             :                srctype, tds_prtype(srctype), srclen,
     258             :                desttype, tds_prtype(desttype), result);
     259             : 
     260        2160 :         results = tds_alloc_param_result(NULL);
     261        2160 :         assert(results);
     262        2160 :         curcol = results->columns[0];
     263        2160 :         assert(curcol);
     264             : 
     265        2160 :         tds_set_column_type(tds->conn, curcol, server_type);
     266        2160 :         curcol->on_server.column_size = curcol->column_size = curcol->column_cur_size = result;
     267        2160 :         if (is_numeric_type(desttype)) {
     268          60 :                 curcol->column_prec = cr.n.precision;
     269          60 :                 curcol->column_scale = cr.n.scale;
     270             :         }
     271        2160 :         switch (desttype) {
     272          60 :         case SYB5BIGDATETIME:
     273             :         case SYB5BIGTIME:
     274          60 :                 curcol->column_prec = curcol->column_scale = 6;
     275          60 :                 break;
     276             :         }
     277        2160 :         CHECK_COLUMN_EXTRA(curcol);
     278             : 
     279        2160 :         tds_alloc_param_data(curcol);
     280        2160 :         if (is_blob_col(curcol)) {
     281          90 :                 ((TDSBLOB *) curcol->column_data)->textvalue = cr.c;
     282          90 :                 cr.c = NULL;
     283        2070 :         } else if (is_convert_pointer_type(desttype)) {
     284         240 :                 memcpy(curcol->column_data, cr.c, (size_t) result);
     285             :         } else {
     286        1830 :                 memcpy(curcol->column_data, &cr.i, (size_t) result);
     287             :         }
     288             : 
     289        2160 :         func(tds, curcol);
     290             : 
     291             :         /* try to convert to SQL_VARIANT */
     292        2160 :         if (is_variant_inner_type(desttype)) {
     293             :                 TDSVARIANT *v;
     294             :                 TDSCOLUMN *basecol;
     295             : 
     296        1470 :                 tds->conn->tds_version = TDSVER_MS;
     297             : 
     298        1470 :                 results = tds_alloc_param_result(results);
     299        1470 :                 assert(results);
     300             : 
     301        1470 :                 basecol = results->columns[0];
     302        1470 :                 curcol = results->columns[1];
     303        1470 :                 tds_set_column_type(tds->conn, curcol, SYBVARIANT);
     304        1470 :                 CHECK_COLUMN_EXTRA(curcol);
     305             : 
     306        1470 :                 tds_alloc_param_data(curcol);
     307        1470 :                 v = (TDSVARIANT *) curcol->column_data;
     308        1470 :                 v->size = basecol->column_size;
     309        1470 :                 v->type = basecol->column_type;
     310        1470 :                 memcpy(v->collation, basecol->column_collation, sizeof(v->collation));
     311             : 
     312        1470 :                 assert(basecol->column_cur_size > 0);
     313        1470 :                 v->data = tds_new(TDS_CHAR, (size_t) basecol->column_cur_size);
     314        1470 :                 assert(v->data);
     315        1470 :                 v->data_len = basecol->column_cur_size;
     316        1470 :                 curcol->column_cur_size = v->data_len;
     317        1470 :                 curcol->column_size = curcol->on_server.column_size = 8009;
     318        1470 :                 assert(!is_blob_col(basecol));
     319             :                 assert(v->data_len >= 0);
     320        1470 :                 memcpy(v->data, basecol->column_data, (size_t) v->data_len);
     321        1470 :                 CHECK_COLUMN_EXTRA(curcol);
     322             : 
     323        1470 :                 func(tds, curcol);
     324             :         }
     325             : 
     326        2160 :         tds_free_results(results);
     327             : 
     328        2160 :         if (result >= 0)
     329        2160 :                 free_convert(desttype, &cr);
     330        2160 : }

Generated by: LCOV version 1.13