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-01-18 11:50:39 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        7968 : free_convert(int type, CONV_RESULT *cr)
      38             : {
      39        7968 :         switch (type) {
      40        3344 :         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        3344 :                 free(cr->c);
      44             :                 break;
      45             :         }
      46        7968 : }
      47             : 
      48             : int
      49           8 : 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           8 :         int i, j, iterations = 0, result;
      62             : 
      63           8 :         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           8 :         if (argc > 1) {
      92           0 :                 iterations = atoi(argv[1]);
      93           0 :                 printf("Computing %d iterations\n", iterations);
      94             :         }
      95             : 
      96           8 :         setbuf(stdout, NULL);
      97           8 :         setbuf(stderr, NULL);
      98             : 
      99           8 :         ctx = tds_alloc_context(NULL);
     100           8 :         assert(ctx);
     101           8 :         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           8 :         free(ctx->locale->date_fmt);
     106           8 :         ctx->locale->date_fmt = strdup("%Y-%m-%d");
     107           8 :         free(ctx->locale->time_fmt);
     108           8 :         ctx->locale->time_fmt = strdup("%H:%M:%S");
     109             : 
     110             : 
     111             :         /*
     112             :          * Test every possible conversion pair
     113             :          */
     114      524296 :         for (i = 0; i < 0x10000; i++) {
     115      524288 :                 srctype  = i >> 8;
     116      524288 :                 desttype = i & 0xff;
     117      524288 :                 srctype = (srctype + SYBCHAR) & 0xff;
     118             : 
     119      524288 :                 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      515984 :                         memset(&src, 0, sizeof(src));
     125      515984 :                         srclen = 4;
     126      515984 :                         result = tds_convert(ctx, srctype, (const TDS_CHAR *) &src, srclen, desttype, &cr);
     127      515984 :                         if (result >= 0)
     128           0 :                                 free_convert(desttype, &cr);
     129      515984 :                         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      515984 :                         continue;       /* don't attempt nonconvertible types */
     136             :                 }
     137             : 
     138        8304 :                 if (srctype == desttype)
     139         320 :                         continue;       /* don't attempt same types */
     140             : 
     141             :                 /* valid types should have a name ! */
     142        7984 :                 assert(tds_prtype(srctype)[0] != 0);
     143        7984 :                 assert(tds_prtype(desttype)[0] != 0);
     144             : 
     145        7984 :                 cr.n.precision = 8;
     146        7984 :                 cr.n.scale = 2;
     147             : 
     148        7984 :                 switch (srctype) {
     149        2624 :                 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        2624 :                         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          80 :                         case SYBMSDATE:
     169             :                         case SYBDATE:
     170          80 :                                 src = "2012-11-27";
     171          80 :                                 break;
     172          40 :                         case SYBTIME:
     173          40 :                                 src = "15:27:12";
     174          40 :                                 break;
     175          80 :                         case SYBMSTIME:
     176             :                         case SYB5BIGTIME:
     177          80 :                                 src = "15:27:12.327862";
     178          80 :                                 break;
     179         120 :                         case SYBMSDATETIME2:
     180             :                         case SYBMSDATETIMEOFFSET:
     181             :                         case SYB5BIGDATETIME:
     182         120 :                                 src = "2015-09-12 21:48:12.638161";
     183         120 :                                 break;
     184         160 :                         case SYBBINARY:
     185             :                         case SYBIMAGE:
     186         160 :                                 src = "0xbeef";
     187         160 :                                 break;
     188         704 :                         case SYBINT1:
     189             :                         case SYBINT2:
     190             :                         case SYBINT4:
     191             :                         case SYBINT8:
     192             :                         case SYBUINT1:
     193             :                         case SYBUINT2:
     194             :                         case SYBUINT4:
     195             :                         case SYBUINT8:
     196         704 :                                 src = "255";
     197         704 :                                 break;
     198         432 :                         case SYBFLT8:
     199             :                         case SYBREAL:
     200             :                         case SYBNUMERIC:
     201             :                         case SYBDECIMAL:
     202             :                         case SYBMONEY:
     203             :                         case SYBMONEY4:
     204         432 :                                 src = "1999.25";
     205             :                                 cr.n.precision = 8;
     206             :                                 cr.n.scale = 2;
     207         432 :                                 break;
     208          40 :                         case SYBUNIQUE:
     209          40 :                                 src = "A8C60F70-5BD4-3E02-B769-7CCCCA585DCC";
     210          40 :                                 break;
     211         648 :                         case SYBBIT:
     212             :                         default:
     213         648 :                                 src = "1";
     214         648 :                                 break;
     215             :                         }
     216             :                         assert(src);
     217        2624 :                         srclen = strlen(src);
     218        2624 :                         break;
     219             :                 case SYBINT1:
     220             :                 case SYBSINT1:
     221             :                 case SYBUINT1:
     222             :                         src = (char *) &tds_tinyint;
     223             :                         srclen = sizeof(tds_tinyint);
     224             :                         break;
     225         216 :                 case SYBINT2:
     226         216 :                         src = (char *) &tds_smallint;
     227         216 :                         srclen = sizeof(tds_smallint);
     228         216 :                         break;
     229         216 :                 case SYBINT4:
     230         216 :                         src = (char *) &tds_int;
     231         216 :                         srclen = sizeof(tds_int);
     232         216 :                         break;
     233         216 :                 case SYBINT8:
     234         216 :                         src = (char *) &tds_int8;
     235         216 :                         srclen = sizeof(tds_int8);
     236         216 :                         break;
     237         216 :                 case SYBUINT2:
     238         216 :                         src = (char *) &tds_usmallint;
     239         216 :                         srclen = sizeof(tds_usmallint);
     240         216 :                         break;
     241         216 :                 case SYBUINT4:
     242         216 :                         src = (char *) &tds_uint;
     243         216 :                         srclen = sizeof(tds_uint);
     244         216 :                         break;
     245         216 :                 case SYBUINT8:
     246         216 :                         src = (char *) &tds_uint8;
     247         216 :                         srclen = sizeof(tds_uint8);
     248         216 :                         break;
     249         216 :                 case SYBFLT8:
     250         216 :                         tds_float = 3.14159;
     251         216 :                         src = (char *) &tds_float;
     252         216 :                         srclen = sizeof(tds_float);
     253         216 :                         break;
     254         216 :                 case SYBREAL:
     255         216 :                         tds_real = (TDS_REAL) 3.14159;
     256         216 :                         src = (char *) &tds_real;
     257         216 :                         srclen = sizeof(tds_real);
     258         216 :                         break;
     259         432 :                 case SYBNUMERIC:
     260             :                 case SYBDECIMAL:
     261         432 :                         src = (char *) &numeric;
     262         432 :                         srclen = sizeof(numeric);
     263         432 :                         break;
     264         216 :                 case SYBMONEY:
     265         216 :                         src = (char *) &money;
     266         216 :                         srclen = sizeof(money);
     267         216 :                         break;
     268         216 :                 case SYBMONEY4:
     269         216 :                         src = (char *) &money4;
     270         216 :                         srclen = sizeof(money4);
     271         216 :                         break;
     272         432 :                 case SYBBIT:
     273             :                 case SYBBITN:
     274         432 :                         src = (char *) &bit_input;
     275         432 :                         srclen = sizeof(bit_input);
     276         432 :                         break;
     277         160 :                 case SYBDATETIME:
     278         160 :                         src = (char *) &datetime;
     279         160 :                         srclen = sizeof(datetime);
     280         160 :                         break;
     281         160 :                 case SYBDATETIME4:
     282         160 :                         src = (char *) &datetime4;
     283         160 :                         srclen = sizeof(datetime4);
     284         160 :                         break;
     285         160 :                 case SYBDATE:
     286         160 :                         src = (char *) &date;
     287         160 :                         srclen = sizeof(date);
     288         160 :                         break;
     289         160 :                 case SYBTIME:
     290         160 :                         src = (char *) &time;
     291         160 :                         srclen = sizeof(time);
     292         160 :                         break;
     293         160 :                 case SYB5BIGTIME:
     294         160 :                         src = (char *) &bigtime;
     295         160 :                         srclen = sizeof(bigtime);
     296         160 :                         break;
     297         160 :                 case SYB5BIGDATETIME:
     298         160 :                         src = (char *) &bigdatetime;
     299         160 :                         srclen = sizeof(bigdatetime);
     300         160 :                         break;
     301          88 :                 case SYBUNIQUE:
     302          88 :                         src = (char *) &tds_unique;
     303          88 :                         srclen = sizeof(tds_unique);
     304          88 :                         break;
     305         640 :                 case SYBMSTIME:
     306             :                 case SYBMSDATE:
     307             :                 case SYBMSDATETIME2:
     308             :                 case SYBMSDATETIMEOFFSET:
     309         640 :                         src = (char *) &dta;
     310         640 :                         srclen = sizeof(dta);
     311         640 :                         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        7984 :                 result = tds_convert(ctx, srctype, src, srclen, desttype, &cr);
     329        7984 :                 if (result >= 0)
     330        7968 :                         free_convert(desttype, &cr);
     331             : 
     332        7984 :                 if (result < 0) {
     333          16 :                         if (result == TDS_CONVERT_NOAVAIL)      /* tds_willconvert returned true, but it lied. */
     334           0 :                                 fprintf(stderr, "Conversion not yet implemented:\n\t");
     335             : 
     336          16 :                         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          16 :                         if (result == TDS_CONVERT_NOAVAIL)
     342           0 :                                 exit(1);
     343             :                 }
     344             : 
     345        7984 :                 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        7984 :                 switch (desttype) {
     355         336 :                 case SYBNUMERIC:
     356             :                 case SYBDECIMAL:
     357         336 :                         numeric = cr.n;
     358         336 :                         break;
     359         216 :                 case SYBMONEY:
     360         216 :                         money = cr.m;
     361         216 :                         break;
     362         216 :                 case SYBMONEY4:
     363         216 :                         money4 = cr.m4;
     364         216 :                         break;
     365         112 :                 case SYBDATETIME:
     366         112 :                         datetime = cr.dt;
     367         112 :                         break;
     368         112 :                 case SYBDATETIME4:
     369         112 :                         datetime4 = cr.dt4;
     370         112 :                         break;
     371         112 :                 case SYBDATE:
     372         112 :                         date = cr.date;
     373         112 :                         break;
     374         112 :                 case SYBTIME:
     375         112 :                         time = cr.time;
     376         112 :                         break;
     377         112 :                 case SYBMSDATETIME2:
     378         112 :                         dta = cr.dta;
     379         112 :                         break;
     380         112 :                 case SYB5BIGTIME:
     381         112 :                         bigtime = cr.bigtime;
     382         112 :                         break;
     383         112 :                 case SYB5BIGDATETIME:
     384         112 :                         bigdatetime = cr.bigdatetime;
     385         112 :                         break;
     386         432 :                 case SYBINT1:
     387             :                 case SYBUINT1:
     388         432 :                         tds_tinyint = cr.ti;
     389         432 :                         break;
     390         216 :                 case SYBINT2:
     391         216 :                         tds_smallint = cr.si;
     392         216 :                         break;
     393         216 :                 case SYBINT4:
     394         216 :                         tds_int = cr.i;
     395         216 :                         break;
     396         216 :                 case SYBINT8:
     397         216 :                         tds_int8 = cr.bi;
     398         216 :                         break;
     399         216 :                 case SYBUINT2:
     400         216 :                         tds_usmallint = cr.usi;
     401         216 :                         break;
     402         216 :                 case SYBUINT4:
     403         216 :                         tds_uint = cr.ui;
     404         216 :                         break;
     405         216 :                 case SYBUINT8:
     406         216 :                         tds_uint8 = cr.ubi;
     407         216 :                         break;
     408          40 :                 case SYBUNIQUE:
     409          40 :                         tds_unique = cr.u;
     410          40 :                         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        7984 :                 result = gettimeofday(&start, NULL);
     420        7984 :                 starttime = (double) start.tv_sec + (double) start.tv_usec * 0.000001;
     421             : 
     422        7984 :                 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        7984 :                 if (result < 0)
     428           0 :                         continue;
     429             : 
     430        7984 :                 result = gettimeofday(&end, NULL);
     431        7984 :                 endtime = (double) end.tv_sec + (double) end.tv_usec * 0.000001;
     432             : 
     433        7984 :                 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           8 :         tds_free_context(ctx);
     440             : 
     441           8 :         return g_result;
     442             : }

Generated by: LCOV version 1.13