Line data Source code
1 : /* FreeTDS - Library of routines accessing Sybase and Microsoft databases
2 : * Copyright (C) 1998-1999 Brian Bruns
3 : * Copyright (C) 2015 Frediano Ziglio
4 : *
5 : * This library is free software; you can redistribute it and/or
6 : * modify it under the terms of the GNU Library General Public
7 : * License as published by the Free Software Foundation; either
8 : * version 2 of the License, or (at your option) any later version.
9 : *
10 : * This library is distributed in the hope that it will be useful,
11 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 : * Library General Public License for more details.
14 : *
15 : * You should have received a copy of the GNU Library General Public
16 : * License along with this library; if not, write to the
17 : * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 : * Boston, MA 02111-1307, USA.
19 : */
20 :
21 : /**
22 : * This test exercise manually conversions from types.
23 : * Does not require any connection.
24 : */
25 :
26 : #include "common.h"
27 : #include <freetds/convert.h>
28 :
29 : static TDSCONTEXT ctx;
30 :
31 : static void
32 1400 : test0(const char *src, int len, int midtype, int dsttype, const char *result, int line)
33 : {
34 : int i, res;
35 : char buf[256];
36 : CONV_RESULT cr, cr_mid, cr_out;
37 1400 : int srctype = SYBVARCHAR;
38 : char *copy;
39 :
40 1400 : copy = tds_new(char, len);
41 1400 : memcpy(copy, src, len);
42 1400 : src = copy;
43 :
44 1400 : if (midtype) {
45 180 : if (midtype == SYBNUMERIC || midtype == SYBDECIMAL) {
46 0 : cr_mid.n.precision = 20;
47 0 : cr_mid.n.scale = 8;
48 : }
49 180 : res = tds_convert(&ctx, SYBVARCHAR, src, len, midtype, &cr_mid);
50 180 : if (res < 0) {
51 0 : fprintf(stderr, "Unexpected failure converting %*.*s\n", len, len, src);
52 0 : exit(1);
53 : }
54 : src = (const char *) &cr_mid;
55 : len = res;
56 : srctype = midtype;
57 : }
58 1400 : if (dsttype == SYBNUMERIC || dsttype == SYBDECIMAL) {
59 10 : cr.n.precision = 20;
60 10 : cr.n.scale = 8;
61 : }
62 1400 : res = tds_convert(&ctx, srctype, src, len, dsttype, &cr);
63 1400 : if (res < 0)
64 530 : strcpy(buf, "error");
65 : else {
66 870 : buf[0] = 0;
67 870 : switch (dsttype) {
68 60 : case SYBINT1:
69 : case SYBUINT1:
70 60 : sprintf(buf, "%d", cr.ti);
71 60 : break;
72 30 : case SYBINT2:
73 30 : sprintf(buf, "%d", cr.si);
74 30 : break;
75 20 : case SYBUINT2:
76 20 : sprintf(buf, "%u", cr.usi);
77 20 : break;
78 90 : case SYBINT4:
79 90 : sprintf(buf, "%d", cr.i);
80 90 : break;
81 50 : case SYBUINT4:
82 50 : sprintf(buf, "%u", cr.ui);
83 50 : break;
84 80 : case SYBINT8:
85 80 : sprintf(buf, "0x%08x%08x", (unsigned int) ((cr.bi >> 32) & 0xfffffffflu), (unsigned int) (cr.bi & 0xfffffffflu));
86 80 : break;
87 150 : case SYB5BIGTIME:
88 : case SYB5BIGDATETIME:
89 : case SYBUINT8:
90 150 : sprintf(buf, "0x%08x%08x", (unsigned int) ((cr.ubi >> 32) & 0xfffffffflu), (unsigned int) (cr.ubi & 0xfffffffflu));
91 150 : break;
92 30 : case SYBUNIQUE:
93 300 : sprintf(buf, "%08X-%04X-%04X-%02X%02X%02X%02X"
94 : "%02X%02X%02X%02X",
95 : cr.u.Data1,
96 60 : cr.u.Data2, cr.u.Data3,
97 60 : cr.u.Data4[0], cr.u.Data4[1],
98 180 : cr.u.Data4[2], cr.u.Data4[3], cr.u.Data4[4], cr.u.Data4[5], cr.u.Data4[6], cr.u.Data4[7]);
99 30 : break;
100 130 : case SYBBINARY:
101 130 : sprintf(buf, "len=%d", res);
102 560 : for (i = 0; i < res; ++i)
103 430 : sprintf(strchr(buf, 0), " %02X", (TDS_UCHAR) cr.ib[i]);
104 130 : free(cr.ib);
105 130 : break;
106 50 : case SYBCHAR:
107 50 : sprintf(buf, "len=%d %s", res, cr.c);
108 50 : free(cr.c);
109 50 : break;
110 90 : case SYBDATETIME:
111 90 : sprintf(buf, "%ld %ld", (long int) cr.dt.dtdays, (long int) cr.dt.dttime);
112 90 : break;
113 40 : case SYBDATE:
114 40 : sprintf(buf, "%ld", (long int) cr.date);
115 40 : break;
116 40 : case SYBTIME:
117 40 : sprintf(buf, "%ld", (long int) cr.time);
118 40 : break;
119 10 : case SYBNUMERIC:
120 : case SYBDECIMAL:
121 10 : cr_out.cc.c = buf;
122 10 : cr_out.cc.len = sizeof(buf) - 1;
123 10 : res = tds_convert(&ctx, dsttype, &cr.n, sizeof(cr.n), TDS_CONVERT_CHAR, &cr_out);
124 10 : if (res < 0) {
125 0 : fprintf(stderr, "Unexpected failure converting %*.*s\n", len, len, src);
126 0 : exit(1);
127 : }
128 10 : buf[res] = 0;
129 : }
130 : }
131 1400 : printf("%s\n", buf);
132 1400 : if (strcmp(buf, result) != 0) {
133 0 : fprintf(stderr, "Expected '%s' got '%s' at line %d\n", result, buf, line);
134 0 : exit(1);
135 : }
136 1400 : free(copy);
137 1400 : }
138 :
139 : #define test(s,d,r) test0(s,(int)strlen(s),0,d,r,__LINE__)
140 : #define test2(s,m,d,r) test0(s,(int)strlen(s),m,d,r,__LINE__)
141 :
142 : static int
143 : int_types[] = {
144 : SYBINT1, SYBUINT1, SYBINT2, SYBUINT2,
145 : SYBINT4, SYBUINT4, SYBINT8, SYBUINT8,
146 : SYBMONEY4, SYBMONEY,
147 : SYBNUMERIC,
148 : -1
149 : };
150 :
151 : static const char *
152 : int_values[] = {
153 : "0",
154 : "127", "255",
155 : "128", "256",
156 : "32767", "65535",
157 : "32768", "65536",
158 : "214748",
159 : "214749",
160 : "2147483647", "4294967295",
161 : "2147483648", "4294967296",
162 : "922337203685477",
163 : "922337203685478",
164 : "9223372036854775807", "18446744073709551615",
165 : "9223372036854775808", "18446744073709551616",
166 : "-128",
167 : "-129",
168 : "-32768",
169 : "-32769",
170 : "-214748",
171 : "-214749",
172 : "-2147483648",
173 : "-2147483649",
174 : "-922337203685477",
175 : "-922337203685478",
176 : "-9223372036854775808",
177 : "-9223372036854775809",
178 : NULL
179 : };
180 :
181 : int
182 10 : main(void)
183 : {
184 : int *type1, *type2;
185 : const char **value;
186 10 : int big_endian = 1;
187 : if (((char *) &big_endian)[0] == 1)
188 10 : big_endian = 0;
189 :
190 10 : memset(&ctx, 0, sizeof(ctx));
191 :
192 10 : if ((ctx.locale = tds_get_locale()) == NULL)
193 : return 1;
194 :
195 : /* date */
196 10 : free(ctx.locale->datetime_fmt);
197 10 : ctx.locale->datetime_fmt = strdup("%Y-%m-%d %H:%M:%S.%z");
198 10 : free(ctx.locale->date_fmt);
199 10 : ctx.locale->date_fmt = strdup("%Y-%m-%d");
200 10 : free(ctx.locale->time_fmt);
201 10 : ctx.locale->time_fmt = strdup("%H:%M:%S.%z");
202 :
203 : /* test some conversion */
204 10 : printf("some checks...\n");
205 10 : test("1234", SYBINT4, "1234");
206 10 : test("1234", SYBUINT4, "1234");
207 10 : test("123", SYBINT1, "123");
208 10 : test("123", SYBUINT1, "123");
209 10 : test(" - 1234 ", SYBINT2, "-1234");
210 10 : test(" - 1234 a", SYBINT2, "error");
211 10 : test("", SYBINT4, "0");
212 10 : test(" ", SYBINT4, "0");
213 10 : test(" 123", SYBINT4, "123");
214 10 : test(" 123 ", SYBINT4, "123");
215 10 : test(" + 123 ", SYBINT4, "123");
216 10 : test(" + 123 ", SYBUINT4, "123");
217 10 : test(" - 0 ", SYBINT4, "0");
218 10 : test(" - 0 ", SYBUINT4, "0");
219 10 : test("+", SYBINT4, "error");
220 10 : test(" +", SYBINT4, "error");
221 10 : test("+ ", SYBINT4, "error");
222 10 : test(" + ", SYBINT4, "error");
223 10 : test("-", SYBINT4, "error");
224 10 : test(" -", SYBINT4, "error");
225 10 : test("- ", SYBINT4, "error");
226 10 : test(" - ", SYBINT4, "error");
227 :
228 10 : test(" - 1234 ", SYBINT8, "0xfffffffffffffb2e");
229 10 : test("1234x", SYBINT8, "error");
230 10 : test(" - 1234 a", SYBINT8, "error");
231 10 : test("", SYBINT8, "0x0000000000000000");
232 10 : test(" ", SYBINT8, "0x0000000000000000");
233 10 : test(" 123", SYBINT8, "0x000000000000007b");
234 10 : test(" 123 ", SYBINT8, "0x000000000000007b");
235 10 : test(" + 123 ", SYBINT8, "0x000000000000007b");
236 10 : test(" 123", SYBUINT8, "0x000000000000007b");
237 10 : test(" 123 ", SYBUINT8, "0x000000000000007b");
238 10 : test(" + 123 ", SYBUINT8, "0x000000000000007b");
239 10 : test("+", SYBINT8, "error");
240 10 : test(" +", SYBINT8, "error");
241 10 : test("+ ", SYBINT8, "error");
242 10 : test(" + ", SYBINT8, "error");
243 10 : test("-", SYBINT8, "error");
244 10 : test(" -", SYBINT8, "error");
245 10 : test("- ", SYBINT8, "error");
246 10 : test(" - ", SYBINT8, "error");
247 :
248 : /* test for overflow */
249 : /* for SYBUINT8 a test with all different digit near limit is required */
250 10 : printf("overflow checks...\n");
251 10 : test("9223372036854775807", SYBINT8, "0x7fffffffffffffff");
252 10 : test("9223372036854775807", SYBUINT8, "0x7fffffffffffffff");
253 10 : test("9223372036854775808", SYBINT8, "error");
254 10 : test("-9223372036854775808", SYBINT8, "0x8000000000000000");
255 10 : test("9223372036854775808", SYBUINT8, "0x8000000000000000");
256 10 : test("18446744073709551610", SYBUINT8, "0xfffffffffffffffa");
257 10 : test("18446744073709551611", SYBUINT8, "0xfffffffffffffffb");
258 10 : test("18446744073709551612", SYBUINT8, "0xfffffffffffffffc");
259 10 : test("18446744073709551613", SYBUINT8, "0xfffffffffffffffd");
260 10 : test("18446744073709551614", SYBUINT8, "0xfffffffffffffffe");
261 10 : test("18446744073709551615", SYBUINT8, "0xffffffffffffffff");
262 10 : test("18446744073709551616", SYBUINT8, "error");
263 10 : test("18446744073709551617", SYBUINT8, "error");
264 10 : test("18446744073709551618", SYBUINT8, "error");
265 10 : test("18446744073709551619", SYBUINT8, "error");
266 10 : test("18446744073709551620", SYBUINT8, "error");
267 10 : test("20496382304121724025", SYBUINT8, "error");
268 10 : test("20496382308118429681", SYBUINT8, "error");
269 10 : test("-1", SYBUINT8, "error");
270 10 : test("-9223372036854775809", SYBINT8, "error");
271 10 : test("2147483647", SYBINT4, "2147483647");
272 10 : test("2147483648", SYBINT4, "error");
273 10 : test("2147483647", SYBUINT4, "2147483647");
274 10 : test("4294967295", SYBUINT4, "4294967295");
275 10 : test("4294967296", SYBUINT4, "error");
276 10 : test("-2147483648", SYBINT4, "-2147483648");
277 10 : test("-2147483648", SYBUINT4, "error");
278 10 : test("-2147483649", SYBINT4, "error");
279 10 : test("32767", SYBINT2, "32767");
280 10 : test("32767", SYBUINT2, "32767");
281 10 : test("65535", SYBUINT2, "65535");
282 10 : test("65536", SYBUINT2, "error");
283 10 : test("32768", SYBINT2, "error");
284 10 : test("-32768", SYBINT2, "-32768");
285 10 : test("-32769", SYBINT2, "error");
286 10 : test("255", SYBINT1, "255");
287 10 : test("256", SYBINT1, "error");
288 10 : test("255", SYBUINT1, "255");
289 10 : test("256", SYBUINT1, "error");
290 10 : test("0", SYBINT1, "0");
291 10 : test("-1", SYBINT1, "error");
292 10 : test("0", SYBUINT1, "0");
293 10 : test("-1", SYBUINT1, "error");
294 :
295 : /*
296 : * test overflow on very big numbers
297 : * I use increment of 10^9 to be sure lower 32bit be correct
298 : * in a case
299 : */
300 10 : printf("overflow on big number checks...\n");
301 10 : test("62147483647", SYBINT4, "error");
302 10 : test("63147483647", SYBINT4, "error");
303 10 : test("64147483647", SYBINT4, "error");
304 10 : test("65147483647", SYBINT4, "error");
305 10 : test("53248632876323876761", SYBINT8, "error");
306 10 : test("56248632876323876761", SYBINT8, "error");
307 10 : test("59248632876323876761", SYBINT8, "error");
308 10 : test("12248632876323876761", SYBINT8, "error");
309 :
310 : /* money */
311 10 : test2("1234.11111111111111111111111111111111111111111111111111111111111111111111111111111111111111",
312 : SYBMONEY, SYBCHAR, "len=9 1234.1111");
313 :
314 : /* some test for unique */
315 10 : printf("unique type...\n");
316 10 : test("12345678-1234-1234-9876543298765432", SYBUNIQUE, "12345678-1234-1234-9876543298765432");
317 10 : test("{12345678-1234-1E34-9876ab3298765432}", SYBUNIQUE, "12345678-1234-1E34-9876AB3298765432");
318 10 : test(" 12345678-1234-1234-9876543298765432", SYBUNIQUE, "error");
319 10 : test(" {12345678-1234-1234-9876543298765432}", SYBUNIQUE, "error");
320 10 : test("12345678-1234-G234-9876543298765432", SYBUNIQUE, "error");
321 10 : test("12345678-1234-a234-9876543298765432", SYBUNIQUE, "12345678-1234-A234-9876543298765432");
322 10 : test("123a5678-1234-a234-98765-43298765432", SYBUNIQUE, "error");
323 10 : test("123-5678-1234-a234-9876543298765432", SYBUNIQUE, "error");
324 :
325 10 : printf("binary test...\n");
326 10 : test("0x1234", SYBBINARY, "len=2 12 34");
327 10 : test("0xaBFd ", SYBBINARY, "len=2 AB FD");
328 10 : test("AbfD ", SYBBINARY, "len=2 AB FD");
329 10 : test("0x000", SYBBINARY, "len=2 00 00");
330 10 : test("0x0", SYBBINARY, "len=1 00");
331 10 : test("0x100", SYBBINARY, "len=2 01 00");
332 10 : test("0x1", SYBBINARY, "len=1 01");
333 :
334 10 : test("Jan 01 2006", SYBDATETIME, "38716 0");
335 10 : test("January 01 2006", SYBDATETIME, "38716 0");
336 10 : test("March 05 2005", SYBDATETIME, "38414 0");
337 10 : test("may 13 2001", SYBDATETIME, "37022 0");
338 :
339 10 : test("02 Jan 2006", SYBDATETIME, "38717 0");
340 10 : test("2 Jan 2006", SYBDATETIME, "38717 0");
341 10 : test("02Jan2006", SYBDATETIME, "38717 0");
342 10 : test("20060102", SYBDATETIME, "38717 0");
343 10 : test("060102", SYBDATETIME, "38717 0");
344 :
345 10 : test("2006-01-02", SYBDATE, "38717");
346 10 : test("12:34:56.337", SYBTIME, "13588901");
347 :
348 10 : test2("2006-01-02", SYBDATE, SYBDATE, "38717");
349 10 : test2("12:34:56.337", SYBTIME, SYBTIME, "13588901");
350 :
351 10 : test2("2006-01-02 12:34:56.337", SYBDATETIME, SYBDATE, "38717");
352 10 : test2("2006-01-02 12:34:56.337", SYBDATETIME, SYBTIME, "13588901");
353 :
354 10 : test("2006-01-02 12:34:56.337321", SYB5BIGTIME, "0x0000000a8bdf41a9");
355 10 : test("2006-01-23 12:34:56.337321", SYB5BIGDATETIME, "0x00e0e7c784d661a9");
356 10 : test("2006-01-02 12:34:56.337321", SYB5BIGDATETIME, "0x00e0e621122b81a9");
357 :
358 10 : test2("2006-01-02 12:34:56.337765", SYB5BIGDATETIME, SYBCHAR, "len=26 2006-01-02 12:34:56.337765");
359 10 : test("2006-01-02 12:34:56.337765", SYB5BIGDATETIME, "0x00e0e621122b8365");
360 :
361 10 : test2("2006-01-02 12:34:56.337", SYBMSDATETIME2, SYBDATE, "38717");
362 10 : test2("2006-01-02 12:34:56.337", SYBMSDATETIME2, SYBTIME, "13588901");
363 :
364 10 : test2("2006-01-02 12:34:56.337", SYBMSDATETIME2, SYBCHAR, "len=27 2006-01-02 12:34:56.3370000");
365 : #if 0
366 : /* FIXME should fail conversion ?? */
367 : test2("2006-01-02", SYBDATE, SYBTIME, "0");
368 : test2("12:34:56.337", SYBTIME, SYBDATE, "0");
369 : #endif
370 :
371 10 : test2("2006-01-02", SYBDATE, SYBCHAR, "len=10 2006-01-02");
372 10 : test2("12:34:56.337", SYBTIME, SYBCHAR, "len=12 12:34:56.337");
373 :
374 10 : test2("123", SYBINT1, SYBBINARY, "len=1 7B");
375 10 : test2("0.000001", SYBFLT8, SYBNUMERIC, "0.00000100");
376 : if (big_endian) {
377 : test2("12345", SYBINT2, SYBBINARY, "len=2 30 39");
378 : test2("123456789", SYBINT4, SYBBINARY, "len=4 07 5B CD 15");
379 : test2("123456789", SYBUINT8, SYBBINARY, "len=8 00 00 00 00 07 5B CD 15");
380 : test2("123456789", SYBINT8, SYBBINARY, "len=8 00 00 00 00 07 5B CD 15");
381 : test2("-123456789", SYBINT8, SYBBINARY, "len=8 FF FF FF FF F8 A4 32 EB");
382 : } else {
383 10 : test2("12345", SYBINT2, SYBBINARY, "len=2 39 30");
384 10 : test2("123456789", SYBINT4, SYBBINARY, "len=4 15 CD 5B 07");
385 10 : test2("123456789", SYBUINT8, SYBBINARY, "len=8 15 CD 5B 07 00 00 00 00");
386 10 : test2("123456789", SYBINT8, SYBBINARY, "len=8 15 CD 5B 07 00 00 00 00");
387 10 : test2("-123456789", SYBINT8, SYBBINARY, "len=8 EB 32 A4 F8 FF FF FF FF");
388 : }
389 :
390 : /* now try many int conversion operations */
391 340 : for (value = int_values; *value; ++value)
392 3630 : for (type1 = int_types; *type1 >= 0; ++type1)
393 39930 : for (type2 = int_types; *type2 >= 0; ++type2) {
394 : char buf[64], expected[64];
395 : CONV_RESULT cr_src, cr_dst;
396 : TDS_INT len_src, len_dst;
397 :
398 : /* try conversion from char (already tested above) */
399 39930 : cr_src.n.precision = 20; cr_src.n.scale = 0;
400 39930 : len_src = tds_convert(&ctx, SYBVARCHAR, *value, strlen(*value), *type1, &cr_src);
401 39930 : cr_dst.n.precision = 20; cr_dst.n.scale = 0;
402 39930 : len_dst = tds_convert(&ctx, SYBVARCHAR, *value, strlen(*value), *type2, &cr_dst);
403 39930 : if (len_src <= 0 || len_dst <= 0)
404 27230 : continue;
405 12700 : cr_dst.n.precision = 20; cr_dst.n.scale = 0;
406 12700 : if (tds_convert(&ctx, *type1, &cr_src.i, len_src, *type2, &cr_dst) <= 0) {
407 0 : fprintf(stderr, "conversion from %s to %s of %s should succeed\n",
408 : tds_prtype(*type1), tds_prtype(*type2), *value);
409 0 : return 1;
410 : }
411 12700 : memcpy(&cr_src, &cr_dst, sizeof(cr_dst));
412 12700 : cr_dst.cc.c = buf;
413 12700 : cr_dst.cc.len = sizeof(buf)-4;
414 12700 : len_dst = tds_convert(&ctx, *type2, &cr_src.i, len_dst, TDS_CONVERT_CHAR, &cr_dst);
415 12700 : if (len_dst <= 0) {
416 0 : fprintf(stderr, "conversion from %s to string should succeed\n",
417 : tds_prtype(*type1));
418 0 : return 1;
419 : }
420 12700 : buf[len_dst] = 0;
421 12700 : if (*type2 == SYBMONEY4 || *type2 == SYBMONEY)
422 2840 : sprintf(expected, "%s.0000", *value);
423 : else
424 9860 : strcpy(expected, *value);
425 12700 : if (strcmp(buf, expected) != 0) {
426 0 : fprintf(stderr, "conversion from %s to %s of %s got wrong value '%s'\n",
427 : tds_prtype(*type1), tds_prtype(*type2), *value, buf);
428 0 : return 1;
429 : }
430 : }
431 :
432 10 : tds_free_locale(ctx.locale);
433 :
434 10 : return 0;
435 : }
|