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 : }
|