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

Generated by: LCOV version 1.13