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