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 7552 : free_convert(int type, CONV_RESULT *cr)
38 : {
39 7552 : switch (type) {
40 3256 : 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 3256 : free(cr->c);
44 : break;
45 : }
46 7552 : }
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 516424 : memset(&src, 0, sizeof(src));
125 516424 : srclen = 4;
126 516424 : result = tds_convert(ctx, srctype, (const TDS_CHAR *) &src, srclen, desttype, &cr);
127 516424 : if (result >= 0)
128 0 : free_convert(desttype, &cr);
129 516424 : 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 516424 : continue; /* don't attempt nonconvertible types */
136 : }
137 :
138 7864 : if (srctype == desttype)
139 312 : continue; /* don't attempt same types */
140 :
141 : /* valid types should have a name ! */
142 7552 : assert(tds_prtype(srctype)[0] != 0);
143 7552 : assert(tds_prtype(desttype)[0] != 0);
144 :
145 7552 : cr.n.precision = 8;
146 7552 : cr.n.scale = 2;
147 :
148 7552 : switch (srctype) {
149 2536 : 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 2536 : 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 560 : case SYBBIT:
212 : default:
213 560 : src = "1";
214 560 : break;
215 : }
216 : assert(src);
217 2536 : srclen = strlen(src);
218 2536 : break;
219 : case SYBINT1:
220 : case SYBUINT1:
221 : src = (char *) &tds_tinyint;
222 : srclen = sizeof(tds_tinyint);
223 : break;
224 208 : case SYBINT2:
225 208 : src = (char *) &tds_smallint;
226 208 : srclen = sizeof(tds_smallint);
227 208 : break;
228 208 : case SYBINT4:
229 208 : src = (char *) &tds_int;
230 208 : srclen = sizeof(tds_int);
231 208 : break;
232 208 : case SYBINT8:
233 208 : src = (char *) &tds_int8;
234 208 : srclen = sizeof(tds_int8);
235 208 : break;
236 208 : case SYBUINT2:
237 208 : src = (char *) &tds_usmallint;
238 208 : srclen = sizeof(tds_usmallint);
239 208 : break;
240 208 : case SYBUINT4:
241 208 : src = (char *) &tds_uint;
242 208 : srclen = sizeof(tds_uint);
243 208 : break;
244 208 : case SYBUINT8:
245 208 : src = (char *) &tds_uint8;
246 208 : srclen = sizeof(tds_uint8);
247 208 : break;
248 208 : case SYBFLT8:
249 208 : tds_float = 3.14159;
250 208 : src = (char *) &tds_float;
251 208 : srclen = sizeof(tds_float);
252 208 : break;
253 208 : case SYBREAL:
254 208 : tds_real = (TDS_REAL) 3.14159;
255 208 : src = (char *) &tds_real;
256 208 : srclen = sizeof(tds_real);
257 208 : break;
258 416 : case SYBNUMERIC:
259 : case SYBDECIMAL:
260 416 : src = (char *) &numeric;
261 416 : srclen = sizeof(numeric);
262 416 : break;
263 208 : case SYBMONEY:
264 208 : src = (char *) &money;
265 208 : srclen = sizeof(money);
266 208 : break;
267 208 : case SYBMONEY4:
268 208 : src = (char *) &money4;
269 208 : srclen = sizeof(money4);
270 208 : break;
271 416 : case SYBBIT:
272 : case SYBBITN:
273 416 : src = (char *) &bit_input;
274 416 : srclen = sizeof(bit_input);
275 416 : break;
276 160 : case SYBDATETIME:
277 160 : src = (char *) &datetime;
278 160 : srclen = sizeof(datetime);
279 160 : break;
280 160 : case SYBDATETIME4:
281 160 : src = (char *) &datetime4;
282 160 : srclen = sizeof(datetime4);
283 160 : break;
284 160 : case SYBDATE:
285 160 : src = (char *) &date;
286 160 : srclen = sizeof(date);
287 160 : break;
288 160 : case SYBTIME:
289 160 : src = (char *) &time;
290 160 : srclen = sizeof(time);
291 160 : break;
292 160 : case SYB5BIGTIME:
293 160 : src = (char *) &bigtime;
294 160 : srclen = sizeof(bigtime);
295 160 : break;
296 160 : case SYB5BIGDATETIME:
297 160 : src = (char *) &bigdatetime;
298 160 : srclen = sizeof(bigdatetime);
299 160 : break;
300 88 : case SYBUNIQUE:
301 88 : src = (char *) &tds_unique;
302 88 : srclen = sizeof(tds_unique);
303 88 : break;
304 640 : case SYBMSTIME:
305 : case SYBMSDATE:
306 : case SYBMSDATETIME2:
307 : case SYBMSDATETIMEOFFSET:
308 640 : src = (char *) &dta;
309 640 : srclen = sizeof(dta);
310 640 : 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 7552 : result = tds_convert(ctx, srctype, src, srclen, desttype, &cr);
328 7552 : if (result >= 0)
329 7552 : free_convert(desttype, &cr);
330 :
331 7552 : if (result < 0) {
332 0 : if (result == TDS_CONVERT_NOAVAIL) /* tds_willconvert returned true, but it lied. */
333 0 : fprintf(stderr, "Conversion not yet implemented:\n\t");
334 :
335 0 : 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 0 : if (result == TDS_CONVERT_NOAVAIL)
341 0 : exit(1);
342 : }
343 :
344 7552 : 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 7552 : switch (desttype) {
354 320 : case SYBNUMERIC:
355 : case SYBDECIMAL:
356 320 : numeric = cr.n;
357 320 : break;
358 208 : case SYBMONEY:
359 208 : money = cr.m;
360 208 : break;
361 208 : case SYBMONEY4:
362 208 : money4 = cr.m4;
363 208 : break;
364 112 : case SYBDATETIME:
365 112 : datetime = cr.dt;
366 112 : break;
367 112 : case SYBDATETIME4:
368 112 : datetime4 = cr.dt4;
369 112 : break;
370 112 : case SYBDATE:
371 112 : date = cr.date;
372 112 : break;
373 112 : case SYBTIME:
374 112 : time = cr.time;
375 112 : break;
376 112 : case SYBMSDATETIME2:
377 112 : dta = cr.dta;
378 112 : break;
379 112 : case SYB5BIGTIME:
380 112 : bigtime = cr.bigtime;
381 112 : break;
382 112 : case SYB5BIGDATETIME:
383 112 : bigdatetime = cr.bigdatetime;
384 112 : break;
385 416 : case SYBINT1:
386 : case SYBUINT1:
387 416 : tds_tinyint = cr.ti;
388 416 : break;
389 208 : case SYBINT2:
390 208 : tds_smallint = cr.si;
391 208 : break;
392 208 : case SYBINT4:
393 208 : tds_int = cr.i;
394 208 : break;
395 208 : case SYBINT8:
396 208 : tds_int8 = cr.bi;
397 208 : break;
398 208 : case SYBUINT2:
399 208 : tds_usmallint = cr.usi;
400 208 : break;
401 208 : case SYBUINT4:
402 208 : tds_uint = cr.ui;
403 208 : break;
404 208 : case SYBUINT8:
405 208 : tds_uint8 = cr.ubi;
406 208 : break;
407 40 : case SYBUNIQUE:
408 40 : tds_unique = cr.u;
409 40 : 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 7552 : result = gettimeofday(&start, NULL);
419 7552 : starttime = (double) start.tv_sec + (double) start.tv_usec * 0.000001;
420 :
421 7552 : 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 7552 : if (result < 0)
427 0 : continue;
428 :
429 7552 : result = gettimeofday(&end, NULL);
430 7552 : endtime = (double) end.tv_sec + (double) end.tv_usec * 0.000001;
431 :
432 7552 : 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 8 : tds_free_context(ctx);
439 :
440 8 : return g_result;
441 : }
|