LCOV - code coverage report
Current view: top level - src/tds/unittests - convert.c (source / functions) Hit Total Coverage
Test: FreeTDS coverage Lines: 221 238 92.9 %
Date: 2025-04-22 17:15:43 Functions: 2 2 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             :  *
       4             :  * This library is free software; you can redistribute it and/or
       5             :  * modify it under the terms of the GNU Library General Public
       6             :  * License as published by the Free Software Foundation; either
       7             :  * version 2 of the License, or (at your option) any later version.
       8             :  *
       9             :  * This library is distributed in the hope that it will be useful,
      10             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      12             :  * Library General Public License for more details.
      13             :  *
      14             :  * You should have received a copy of the GNU Library General Public
      15             :  * License along with this library; if not, write to the
      16             :  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
      17             :  * Boston, MA 02111-1307, USA.
      18             :  */
      19             : 
      20             : /* 
      21             :  * Purpose: test conversions.  If they work, test their performance.  
      22             :  * To test performance, call this program with an iteration count (10 is probably fine).
      23             :  * The following shows performance converting to varchar:
      24             :  * $ make convert && ./convert 1 |grep iterations |grep 'varchar\.' |sort -n 
      25             :  */
      26             : #include "common.h"
      27             : #include <assert.h>
      28             : #include <freetds/convert.h>
      29             : #include <freetds/replacements.h>
      30             : 
      31             : #include <freetds/time.h>
      32             : 
      33             : static int g_result = 0;
      34             : static TDSCONTEXT *ctx;
      35             : 
      36             : static void
      37        9960 : free_convert(int type, CONV_RESULT *cr)
      38             : {
      39        9960 :         switch (type) {
      40        4180 :         case SYBCHAR: case SYBVARCHAR: case SYBTEXT: case XSYBCHAR: case XSYBVARCHAR:
      41             :         case SYBBINARY: case SYBVARBINARY: case SYBIMAGE: case XSYBBINARY: case XSYBVARBINARY:
      42             :         case SYBLONGBINARY:
      43        4180 :                 free(cr->c);
      44             :                 break;
      45             :         }
      46        9960 : }
      47             : 
      48          10 : TEST_MAIN()
      49             : {
      50             :         int srctype;
      51             :         int desttype;
      52             : 
      53             :         /* some default inputs */
      54             :         static const int bit_input = 1;
      55             : 
      56             :         /* timing variables to compute performance */
      57             :         struct timeval start, end;
      58             :         double starttime, endtime;
      59             : 
      60          10 :         int i, j, iterations = 0, result;
      61             : 
      62          10 :         TDS_CHAR *src = NULL;
      63             :         TDS_UINT srclen;
      64             :         CONV_RESULT cr;
      65             : 
      66             :         TDS_NUMERIC numeric;
      67             :         TDS_MONEY money;
      68             :         TDS_MONEY4 money4;
      69             :         TDS_DATETIME datetime;
      70             :         TDS_DATETIME4 datetime4;
      71             :         TDS_DATETIMEALL dta;
      72             :         TDS_DATE date;
      73             :         TDS_TIME time;
      74             :         TDS_BIGDATETIME bigdatetime;
      75             :         TDS_BIGTIME bigtime;
      76             : 
      77             :         TDS_TINYINT tds_tinyint;
      78             :         TDS_SMALLINT tds_smallint;
      79             :         TDS_INT tds_int;
      80             :         TDS_INT8 tds_int8;
      81             :         TDS_USMALLINT tds_usmallint;
      82             :         TDS_UINT tds_uint;
      83             :         TDS_UINT8 tds_uint8;
      84             : 
      85             :         TDS_REAL tds_real;
      86             :         TDS_FLOAT tds_float;
      87             : 
      88             :         TDS_UNIQUE tds_unique;
      89             : 
      90          10 :         if (argc > 1) {
      91           0 :                 iterations = atoi(argv[1]);
      92           0 :                 printf("Computing %d iterations\n", iterations);
      93             :         }
      94             : 
      95          10 :         setbuf(stdout, NULL);
      96          10 :         setbuf(stderr, NULL);
      97             : 
      98          10 :         ctx = tds_alloc_context(NULL);
      99          10 :         assert(ctx);
     100          10 :         if (!ctx->locale->datetime_fmt) {
     101             :                 /* set default in case there's no locale file */
     102           0 :                 ctx->locale->datetime_fmt = strdup(STD_DATETIME_FMT);
     103             :         }
     104          10 :         free(ctx->locale->date_fmt);
     105          10 :         ctx->locale->date_fmt = strdup("%Y-%m-%d");
     106          10 :         free(ctx->locale->time_fmt);
     107          10 :         ctx->locale->time_fmt = strdup("%H:%M:%S");
     108             : 
     109             : 
     110             :         /*
     111             :          * Test every possible conversion pair
     112             :          */
     113      655370 :         for (i = 0; i < 0x10000; i++) {
     114      655360 :                 srctype  = i >> 8;
     115      655360 :                 desttype = i & 0xff;
     116      655360 :                 srctype = (srctype + SYBCHAR) & 0xff;
     117             : 
     118      655360 :                 if (!tds_willconvert(srctype, desttype)) {
     119             :                         /* pass a CONV_RESULT as input for make sure size and alignment is enough
     120             :                          * for all types */
     121             :                         CONV_RESULT src;
     122             : 
     123      644980 :                         memset(&src, 0, sizeof(src));
     124      644980 :                         srclen = 4;
     125      644980 :                         result = tds_convert(ctx, srctype, (const TDS_CHAR *) &src, srclen, desttype, &cr);
     126      644980 :                         if (result >= 0)
     127           0 :                                 free_convert(desttype, &cr);
     128      644980 :                         if (result != TDS_CONVERT_NOAVAIL) {
     129           0 :                                 printf("NOT EXPECTED: converted %d (%s, %d bytes) : %d (%s, %d bytes).\n",
     130             :                                        srctype, tds_prtype(srctype), srclen,
     131             :                                        desttype, tds_prtype(desttype), result);
     132           0 :                                 exit(1);
     133             :                         }
     134      644980 :                         continue;       /* don't attempt nonconvertible types */
     135             :                 }
     136             : 
     137       10380 :                 if (srctype == desttype)
     138         400 :                         continue;       /* don't attempt same types */
     139             : 
     140             :                 /* valid types should have a name ! */
     141        9980 :                 assert(tds_prtype(srctype)[0] != 0);
     142        9980 :                 assert(tds_prtype(desttype)[0] != 0);
     143             : 
     144        9980 :                 cr.n.precision = 8;
     145        9980 :                 cr.n.scale = 2;
     146             : 
     147        9980 :                 switch (srctype) {
     148        3280 :                 case SYBCHAR:
     149             :                 case SYBVARCHAR:
     150             :                 case SYBTEXT:
     151             :                 case SYBBINARY:
     152             :                 case SYBVARBINARY:
     153             :                 case SYBIMAGE:
     154             :                 case SYBLONGBINARY:
     155             :                 case XSYBBINARY:
     156             :                 case XSYBVARBINARY:
     157             :                 case XSYBCHAR:
     158             :                 case XSYBVARCHAR:
     159        3280 :                         switch (desttype) {
     160             :                         case SYBCHAR:
     161             :                         case SYBVARCHAR:
     162             :                         case SYBTEXT:
     163             :                         case SYBDATETIME:
     164             :                         case SYBDATETIME4:
     165             :                                 src = "Jan  1, 1999";
     166             :                                 break;
     167         100 :                         case SYBMSDATE:
     168             :                         case SYBDATE:
     169         100 :                                 src = "2012-11-27";
     170         100 :                                 break;
     171          50 :                         case SYBTIME:
     172          50 :                                 src = "15:27:12";
     173          50 :                                 break;
     174         100 :                         case SYBMSTIME:
     175             :                         case SYB5BIGTIME:
     176         100 :                                 src = "15:27:12.327862";
     177         100 :                                 break;
     178         150 :                         case SYBMSDATETIME2:
     179             :                         case SYBMSDATETIMEOFFSET:
     180             :                         case SYB5BIGDATETIME:
     181         150 :                                 src = "2015-09-12 21:48:12.638161";
     182         150 :                                 break;
     183         200 :                         case SYBBINARY:
     184             :                         case SYBIMAGE:
     185         200 :                                 src = "0xbeef";
     186         200 :                                 break;
     187         880 :                         case SYBINT1:
     188             :                         case SYBINT2:
     189             :                         case SYBINT4:
     190             :                         case SYBINT8:
     191             :                         case SYBUINT1:
     192             :                         case SYBUINT2:
     193             :                         case SYBUINT4:
     194             :                         case SYBUINT8:
     195         880 :                                 src = "255";
     196         880 :                                 break;
     197         540 :                         case SYBFLT8:
     198             :                         case SYBREAL:
     199             :                         case SYBNUMERIC:
     200             :                         case SYBDECIMAL:
     201             :                         case SYBMONEY:
     202             :                         case SYBMONEY4:
     203         540 :                                 src = "1999.25";
     204             :                                 cr.n.precision = 8;
     205             :                                 cr.n.scale = 2;
     206         540 :                                 break;
     207          50 :                         case SYBUNIQUE:
     208          50 :                                 src = "A8C60F70-5BD4-3E02-B769-7CCCCA585DCC";
     209          50 :                                 break;
     210         810 :                         case SYBBIT:
     211             :                         default:
     212         810 :                                 src = "1";
     213         810 :                                 break;
     214             :                         }
     215             :                         assert(src);
     216        3280 :                         srclen = (TDS_UINT) strlen(src);
     217        3280 :                         break;
     218             :                 case SYBINT1:
     219             :                 case SYBSINT1:
     220             :                 case SYBUINT1:
     221             :                         src = (char *) &tds_tinyint;
     222             :                         srclen = sizeof(tds_tinyint);
     223             :                         break;
     224         270 :                 case SYBINT2:
     225         270 :                         src = (char *) &tds_smallint;
     226         270 :                         srclen = sizeof(tds_smallint);
     227         270 :                         break;
     228         270 :                 case SYBINT4:
     229         270 :                         src = (char *) &tds_int;
     230         270 :                         srclen = sizeof(tds_int);
     231         270 :                         break;
     232         270 :                 case SYBINT8:
     233         270 :                         src = (char *) &tds_int8;
     234         270 :                         srclen = sizeof(tds_int8);
     235         270 :                         break;
     236         270 :                 case SYBUINT2:
     237         270 :                         src = (char *) &tds_usmallint;
     238         270 :                         srclen = sizeof(tds_usmallint);
     239         270 :                         break;
     240         270 :                 case SYBUINT4:
     241         270 :                         src = (char *) &tds_uint;
     242         270 :                         srclen = sizeof(tds_uint);
     243         270 :                         break;
     244         270 :                 case SYBUINT8:
     245         270 :                         src = (char *) &tds_uint8;
     246         270 :                         srclen = sizeof(tds_uint8);
     247         270 :                         break;
     248         270 :                 case SYBFLT8:
     249         270 :                         tds_float = 3.14159;
     250         270 :                         src = (char *) &tds_float;
     251         270 :                         srclen = sizeof(tds_float);
     252         270 :                         break;
     253         270 :                 case SYBREAL:
     254         270 :                         tds_real = (TDS_REAL) 3.14159;
     255         270 :                         src = (char *) &tds_real;
     256         270 :                         srclen = sizeof(tds_real);
     257         270 :                         break;
     258         540 :                 case SYBNUMERIC:
     259             :                 case SYBDECIMAL:
     260         540 :                         src = (char *) &numeric;
     261         540 :                         srclen = sizeof(numeric);
     262         540 :                         break;
     263         270 :                 case SYBMONEY:
     264         270 :                         src = (char *) &money;
     265         270 :                         srclen = sizeof(money);
     266         270 :                         break;
     267         270 :                 case SYBMONEY4:
     268         270 :                         src = (char *) &money4;
     269         270 :                         srclen = sizeof(money4);
     270         270 :                         break;
     271         540 :                 case SYBBIT:
     272             :                 case SYBBITN:
     273         540 :                         src = (char *) &bit_input;
     274         540 :                         srclen = sizeof(bit_input);
     275         540 :                         break;
     276         200 :                 case SYBDATETIME:
     277         200 :                         src = (char *) &datetime;
     278         200 :                         srclen = sizeof(datetime);
     279         200 :                         break;
     280         200 :                 case SYBDATETIME4:
     281         200 :                         src = (char *) &datetime4;
     282         200 :                         srclen = sizeof(datetime4);
     283         200 :                         break;
     284         200 :                 case SYBDATE:
     285         200 :                         src = (char *) &date;
     286         200 :                         srclen = sizeof(date);
     287         200 :                         break;
     288         200 :                 case SYBTIME:
     289         200 :                         src = (char *) &time;
     290         200 :                         srclen = sizeof(time);
     291         200 :                         break;
     292         200 :                 case SYB5BIGTIME:
     293         200 :                         src = (char *) &bigtime;
     294         200 :                         srclen = sizeof(bigtime);
     295         200 :                         break;
     296         200 :                 case SYB5BIGDATETIME:
     297         200 :                         src = (char *) &bigdatetime;
     298         200 :                         srclen = sizeof(bigdatetime);
     299         200 :                         break;
     300         110 :                 case SYBUNIQUE:
     301         110 :                         src = (char *) &tds_unique;
     302         110 :                         srclen = sizeof(tds_unique);
     303         110 :                         break;
     304         800 :                 case SYBMSTIME:
     305             :                 case SYBMSDATE:
     306             :                 case SYBMSDATETIME2:
     307             :                 case SYBMSDATETIMEOFFSET:
     308         800 :                         src = (char *) &dta;
     309         800 :                         srclen = sizeof(dta);
     310         800 :                         break;
     311             :                 /*****  not defined yet
     312             :                         case SYBBOUNDARY:
     313             :                         case SYBSENSITIVITY:
     314             :                                 fprintf (stderr, "type %d not supported\n", srctype );
     315             :                                 continue;
     316             :                                 break;
     317             :                 *****/
     318           0 :                 default:
     319           0 :                         fprintf(stderr, "no such type %d (%s)\n", srctype, tds_prtype(srctype));
     320           0 :                         return -1;
     321             :                 }
     322             : 
     323             :                 /* 
     324             :                  * Now at last do the conversion
     325             :                  */
     326             : 
     327        9980 :                 result = tds_convert(ctx, srctype, src, srclen, desttype, &cr);
     328        9980 :                 if (result >= 0)
     329        9960 :                         free_convert(desttype, &cr);
     330             : 
     331        9980 :                 if (result < 0) {
     332          20 :                         if (result == TDS_CONVERT_NOAVAIL)      /* tds_willconvert returned true, but it lied. */
     333           0 :                                 fprintf(stderr, "Conversion not yet implemented:\n\t");
     334             : 
     335          20 :                         fprintf(stderr, "failed (%d) to convert %d (%s, %d bytes) : %d (%s).\n",
     336             :                                 result,
     337             :                                 srctype, tds_prtype(srctype), srclen,
     338             :                                 desttype, tds_prtype(desttype));
     339             : 
     340          20 :                         if (result == TDS_CONVERT_NOAVAIL)
     341           0 :                                 exit(1);
     342             :                 }
     343             : 
     344        9980 :                 printf("converted %d (%s, %d bytes) -> %d (%s, %d bytes).\n",
     345             :                        srctype, tds_prtype(srctype), srclen,
     346             :                        desttype, tds_prtype(desttype), result);
     347             : 
     348             :                 /* 
     349             :                  * In the first iteration, start with varchar -> others.  
     350             :                  * By saving the output, we initialize subsequent inputs.
     351             :                  */
     352             : 
     353        9980 :                 switch (desttype) {
     354         420 :                 case SYBNUMERIC:
     355             :                 case SYBDECIMAL:
     356         420 :                         numeric = cr.n;
     357         420 :                         break;
     358         270 :                 case SYBMONEY:
     359         270 :                         money = cr.m;
     360         270 :                         break;
     361         270 :                 case SYBMONEY4:
     362         270 :                         money4 = cr.m4;
     363         270 :                         break;
     364         140 :                 case SYBDATETIME:
     365         140 :                         datetime = cr.dt;
     366         140 :                         break;
     367         140 :                 case SYBDATETIME4:
     368         140 :                         datetime4 = cr.dt4;
     369         140 :                         break;
     370         140 :                 case SYBDATE:
     371         140 :                         date = cr.date;
     372         140 :                         break;
     373         140 :                 case SYBTIME:
     374         140 :                         time = cr.time;
     375         140 :                         break;
     376         140 :                 case SYBMSDATETIME2:
     377         140 :                         dta = cr.dta;
     378         140 :                         break;
     379         140 :                 case SYB5BIGTIME:
     380         140 :                         bigtime = cr.bigtime;
     381         140 :                         break;
     382         140 :                 case SYB5BIGDATETIME:
     383         140 :                         bigdatetime = cr.bigdatetime;
     384         140 :                         break;
     385         540 :                 case SYBINT1:
     386             :                 case SYBUINT1:
     387         540 :                         tds_tinyint = cr.ti;
     388         540 :                         break;
     389         270 :                 case SYBINT2:
     390         270 :                         tds_smallint = cr.si;
     391         270 :                         break;
     392         270 :                 case SYBINT4:
     393         270 :                         tds_int = cr.i;
     394         270 :                         break;
     395         270 :                 case SYBINT8:
     396         270 :                         tds_int8 = cr.bi;
     397         270 :                         break;
     398         270 :                 case SYBUINT2:
     399         270 :                         tds_usmallint = cr.usi;
     400         270 :                         break;
     401         270 :                 case SYBUINT4:
     402         270 :                         tds_uint = cr.ui;
     403         270 :                         break;
     404         270 :                 case SYBUINT8:
     405         270 :                         tds_uint8 = cr.ubi;
     406         270 :                         break;
     407          50 :                 case SYBUNIQUE:
     408          50 :                         tds_unique = cr.u;
     409          50 :                         break;
     410             :                 default:
     411             :                         break;
     412             :                 }
     413             : 
     414             :                 /*
     415             :                  * If an iteration count was passed on the command line (not by "make check")
     416             :                  * run the conversion N times and print the conversions per second.
     417             :                  */
     418        9980 :                 result = gettimeofday(&start, NULL);
     419        9980 :                 starttime = (double) start.tv_sec + (double) start.tv_usec * 0.000001;
     420             : 
     421        9980 :                 for (j = 0; result >= 0 && j < iterations; j++) {
     422           0 :                         result = tds_convert(ctx, srctype, src, srclen, desttype, &cr);
     423           0 :                         if (result >= 0)
     424           0 :                                 free_convert(desttype, &cr);
     425             :                 }
     426        9980 :                 if (result < 0)
     427           0 :                         continue;
     428             : 
     429        9980 :                 result = gettimeofday(&end, NULL);
     430        9980 :                 endtime = (double) end.tv_sec + (double) end.tv_usec * 0.000001;
     431             : 
     432        9980 :                 if (endtime != starttime && iterations) {
     433           0 :                         printf("%9.0f iterations/second converting %13s => %s.\n",
     434           0 :                                 j / (endtime - starttime), tds_prtype(srctype), tds_prtype(desttype));
     435             :                 }
     436             : 
     437             :         }
     438          10 :         tds_free_context(ctx);
     439             : 
     440          10 :         return g_result;
     441             : }

Generated by: LCOV version 1.13