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