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