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 1120 : 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 1120 : int srctype = SYBVARCHAR;
38 : char *copy;
39 :
40 1120 : copy = tds_new(char, len);
41 1120 : memcpy(copy, src, len);
42 1120 : src = copy;
43 :
44 1120 : if (midtype) {
45 144 : if (midtype == SYBNUMERIC || midtype == SYBDECIMAL) {
46 0 : cr_mid.n.precision = 20;
47 0 : cr_mid.n.scale = 8;
48 : }
49 144 : res = tds_convert(&ctx, SYBVARCHAR, src, len, midtype, &cr_mid);
50 144 : 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 1120 : if (dsttype == SYBNUMERIC || dsttype == SYBDECIMAL) {
59 8 : cr.n.precision = 20;
60 8 : cr.n.scale = 8;
61 : }
62 1120 : res = tds_convert(&ctx, srctype, src, len, dsttype, &cr);
63 1120 : if (res < 0)
64 424 : strcpy(buf, "error");
65 : else {
66 696 : buf[0] = 0;
67 696 : switch (dsttype) {
68 48 : case SYBINT1:
69 : case SYBUINT1:
70 48 : sprintf(buf, "%d", cr.ti);
71 48 : break;
72 24 : case SYBINT2:
73 24 : sprintf(buf, "%d", cr.si);
74 24 : break;
75 16 : case SYBUINT2:
76 16 : sprintf(buf, "%u", cr.usi);
77 16 : break;
78 72 : case SYBINT4:
79 72 : sprintf(buf, "%d", cr.i);
80 72 : break;
81 40 : case SYBUINT4:
82 40 : sprintf(buf, "%u", cr.ui);
83 40 : break;
84 64 : case SYBINT8:
85 64 : sprintf(buf, "0x%08x%08x", (unsigned int) ((cr.bi >> 32) & 0xfffffffflu), (unsigned int) (cr.bi & 0xfffffffflu));
86 64 : break;
87 120 : case SYB5BIGTIME:
88 : case SYB5BIGDATETIME:
89 : case SYBUINT8:
90 120 : sprintf(buf, "0x%08x%08x", (unsigned int) ((cr.ubi >> 32) & 0xfffffffflu), (unsigned int) (cr.ubi & 0xfffffffflu));
91 120 : break;
92 24 : case SYBUNIQUE:
93 240 : sprintf(buf, "%08X-%04X-%04X-%02X%02X%02X%02X"
94 : "%02X%02X%02X%02X",
95 : cr.u.Data1,
96 48 : cr.u.Data2, cr.u.Data3,
97 48 : cr.u.Data4[0], cr.u.Data4[1],
98 144 : 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 24 : break;
100 104 : case SYBBINARY:
101 104 : sprintf(buf, "len=%d", res);
102 448 : for (i = 0; i < res; ++i)
103 344 : sprintf(strchr(buf, 0), " %02X", (TDS_UCHAR) cr.ib[i]);
104 104 : free(cr.ib);
105 104 : break;
106 40 : case SYBCHAR:
107 40 : sprintf(buf, "len=%d %s", res, cr.c);
108 40 : free(cr.c);
109 40 : break;
110 72 : case SYBDATETIME:
111 72 : sprintf(buf, "%ld %ld", (long int) cr.dt.dtdays, (long int) cr.dt.dttime);
112 72 : break;
113 32 : case SYBDATE:
114 32 : sprintf(buf, "%ld", (long int) cr.date);
115 32 : break;
116 32 : case SYBTIME:
117 32 : sprintf(buf, "%ld", (long int) cr.time);
118 32 : break;
119 8 : case SYBNUMERIC:
120 : case SYBDECIMAL:
121 8 : cr_out.cc.c = buf;
122 8 : cr_out.cc.len = sizeof(buf) - 1;
123 8 : res = tds_convert(&ctx, dsttype, &cr.n, sizeof(cr.n), TDS_CONVERT_CHAR, &cr_out);
124 8 : if (res < 0) {
125 0 : fprintf(stderr, "Unexpected failure converting %*.*s\n", len, len, src);
126 0 : exit(1);
127 : }
128 8 : buf[res] = 0;
129 : }
130 : }
131 1120 : printf("%s\n", buf);
132 1120 : 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 1120 : free(copy);
137 1120 : }
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 8 : main(void)
183 : {
184 : int *type1, *type2;
185 : const char **value;
186 8 : int big_endian = 1;
187 : if (((char *) &big_endian)[0] == 1)
188 8 : big_endian = 0;
189 :
190 8 : memset(&ctx, 0, sizeof(ctx));
191 :
192 8 : if ((ctx.locale = tds_get_locale()) == NULL)
193 : return 1;
194 :
195 : /* date */
196 8 : free(ctx.locale->datetime_fmt);
197 8 : ctx.locale->datetime_fmt = strdup("%Y-%m-%d %H:%M:%S.%z");
198 8 : free(ctx.locale->date_fmt);
199 8 : ctx.locale->date_fmt = strdup("%Y-%m-%d");
200 8 : free(ctx.locale->time_fmt);
201 8 : ctx.locale->time_fmt = strdup("%H:%M:%S.%z");
202 :
203 : /* test some conversion */
204 8 : printf("some checks...\n");
205 8 : test("1234", SYBINT4, "1234");
206 8 : test("1234", SYBUINT4, "1234");
207 8 : test("123", SYBINT1, "123");
208 8 : test("123", SYBUINT1, "123");
209 8 : test(" - 1234 ", SYBINT2, "-1234");
210 8 : test(" - 1234 a", SYBINT2, "error");
211 8 : test("", SYBINT4, "0");
212 8 : test(" ", SYBINT4, "0");
213 8 : test(" 123", SYBINT4, "123");
214 8 : test(" 123 ", SYBINT4, "123");
215 8 : test(" + 123 ", SYBINT4, "123");
216 8 : test(" + 123 ", SYBUINT4, "123");
217 8 : test(" - 0 ", SYBINT4, "0");
218 8 : test(" - 0 ", SYBUINT4, "0");
219 8 : test("+", SYBINT4, "error");
220 8 : test(" +", SYBINT4, "error");
221 8 : test("+ ", SYBINT4, "error");
222 8 : test(" + ", SYBINT4, "error");
223 8 : test("-", SYBINT4, "error");
224 8 : test(" -", SYBINT4, "error");
225 8 : test("- ", SYBINT4, "error");
226 8 : test(" - ", SYBINT4, "error");
227 :
228 8 : test(" - 1234 ", SYBINT8, "0xfffffffffffffb2e");
229 8 : test("1234x", SYBINT8, "error");
230 8 : test(" - 1234 a", SYBINT8, "error");
231 8 : test("", SYBINT8, "0x0000000000000000");
232 8 : test(" ", SYBINT8, "0x0000000000000000");
233 8 : test(" 123", SYBINT8, "0x000000000000007b");
234 8 : test(" 123 ", SYBINT8, "0x000000000000007b");
235 8 : test(" + 123 ", SYBINT8, "0x000000000000007b");
236 8 : test(" 123", SYBUINT8, "0x000000000000007b");
237 8 : test(" 123 ", SYBUINT8, "0x000000000000007b");
238 8 : test(" + 123 ", SYBUINT8, "0x000000000000007b");
239 8 : test("+", SYBINT8, "error");
240 8 : test(" +", SYBINT8, "error");
241 8 : test("+ ", SYBINT8, "error");
242 8 : test(" + ", SYBINT8, "error");
243 8 : test("-", SYBINT8, "error");
244 8 : test(" -", SYBINT8, "error");
245 8 : test("- ", SYBINT8, "error");
246 8 : test(" - ", SYBINT8, "error");
247 :
248 : /* test for overflow */
249 : /* for SYBUINT8 a test with all different digit near limit is required */
250 8 : printf("overflow checks...\n");
251 8 : test("9223372036854775807", SYBINT8, "0x7fffffffffffffff");
252 8 : test("9223372036854775807", SYBUINT8, "0x7fffffffffffffff");
253 8 : test("9223372036854775808", SYBINT8, "error");
254 8 : test("-9223372036854775808", SYBINT8, "0x8000000000000000");
255 8 : test("9223372036854775808", SYBUINT8, "0x8000000000000000");
256 8 : test("18446744073709551610", SYBUINT8, "0xfffffffffffffffa");
257 8 : test("18446744073709551611", SYBUINT8, "0xfffffffffffffffb");
258 8 : test("18446744073709551612", SYBUINT8, "0xfffffffffffffffc");
259 8 : test("18446744073709551613", SYBUINT8, "0xfffffffffffffffd");
260 8 : test("18446744073709551614", SYBUINT8, "0xfffffffffffffffe");
261 8 : test("18446744073709551615", SYBUINT8, "0xffffffffffffffff");
262 8 : test("18446744073709551616", SYBUINT8, "error");
263 8 : test("18446744073709551617", SYBUINT8, "error");
264 8 : test("18446744073709551618", SYBUINT8, "error");
265 8 : test("18446744073709551619", SYBUINT8, "error");
266 8 : test("18446744073709551620", SYBUINT8, "error");
267 8 : test("20496382304121724025", SYBUINT8, "error");
268 8 : test("20496382308118429681", SYBUINT8, "error");
269 8 : test("-1", SYBUINT8, "error");
270 8 : test("-9223372036854775809", SYBINT8, "error");
271 8 : test("2147483647", SYBINT4, "2147483647");
272 8 : test("2147483648", SYBINT4, "error");
273 8 : test("2147483647", SYBUINT4, "2147483647");
274 8 : test("4294967295", SYBUINT4, "4294967295");
275 8 : test("4294967296", SYBUINT4, "error");
276 8 : test("-2147483648", SYBINT4, "-2147483648");
277 8 : test("-2147483648", SYBUINT4, "error");
278 8 : test("-2147483649", SYBINT4, "error");
279 8 : test("32767", SYBINT2, "32767");
280 8 : test("32767", SYBUINT2, "32767");
281 8 : test("65535", SYBUINT2, "65535");
282 8 : test("65536", SYBUINT2, "error");
283 8 : test("32768", SYBINT2, "error");
284 8 : test("-32768", SYBINT2, "-32768");
285 8 : test("-32769", SYBINT2, "error");
286 8 : test("255", SYBINT1, "255");
287 8 : test("256", SYBINT1, "error");
288 8 : test("255", SYBUINT1, "255");
289 8 : test("256", SYBUINT1, "error");
290 8 : test("0", SYBINT1, "0");
291 8 : test("-1", SYBINT1, "error");
292 8 : test("0", SYBUINT1, "0");
293 8 : 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 8 : printf("overflow on big number checks...\n");
301 8 : test("62147483647", SYBINT4, "error");
302 8 : test("63147483647", SYBINT4, "error");
303 8 : test("64147483647", SYBINT4, "error");
304 8 : test("65147483647", SYBINT4, "error");
305 8 : test("53248632876323876761", SYBINT8, "error");
306 8 : test("56248632876323876761", SYBINT8, "error");
307 8 : test("59248632876323876761", SYBINT8, "error");
308 8 : test("12248632876323876761", SYBINT8, "error");
309 :
310 : /* money */
311 8 : test2("1234.11111111111111111111111111111111111111111111111111111111111111111111111111111111111111",
312 : SYBMONEY, SYBCHAR, "len=9 1234.1111");
313 :
314 : /* some test for unique */
315 8 : printf("unique type...\n");
316 8 : test("12345678-1234-1234-9876543298765432", SYBUNIQUE, "12345678-1234-1234-9876543298765432");
317 8 : test("{12345678-1234-1E34-9876ab3298765432}", SYBUNIQUE, "12345678-1234-1E34-9876AB3298765432");
318 8 : test(" 12345678-1234-1234-9876543298765432", SYBUNIQUE, "error");
319 8 : test(" {12345678-1234-1234-9876543298765432}", SYBUNIQUE, "error");
320 8 : test("12345678-1234-G234-9876543298765432", SYBUNIQUE, "error");
321 8 : test("12345678-1234-a234-9876543298765432", SYBUNIQUE, "12345678-1234-A234-9876543298765432");
322 8 : test("123a5678-1234-a234-98765-43298765432", SYBUNIQUE, "error");
323 8 : test("123-5678-1234-a234-9876543298765432", SYBUNIQUE, "error");
324 :
325 8 : printf("binary test...\n");
326 8 : test("0x1234", SYBBINARY, "len=2 12 34");
327 8 : test("0xaBFd ", SYBBINARY, "len=2 AB FD");
328 8 : test("AbfD ", SYBBINARY, "len=2 AB FD");
329 8 : test("0x000", SYBBINARY, "len=2 00 00");
330 8 : test("0x0", SYBBINARY, "len=1 00");
331 8 : test("0x100", SYBBINARY, "len=2 01 00");
332 8 : test("0x1", SYBBINARY, "len=1 01");
333 :
334 8 : test("Jan 01 2006", SYBDATETIME, "38716 0");
335 8 : test("January 01 2006", SYBDATETIME, "38716 0");
336 8 : test("March 05 2005", SYBDATETIME, "38414 0");
337 8 : test("may 13 2001", SYBDATETIME, "37022 0");
338 :
339 8 : test("02 Jan 2006", SYBDATETIME, "38717 0");
340 8 : test("2 Jan 2006", SYBDATETIME, "38717 0");
341 8 : test("02Jan2006", SYBDATETIME, "38717 0");
342 8 : test("20060102", SYBDATETIME, "38717 0");
343 8 : test("060102", SYBDATETIME, "38717 0");
344 :
345 8 : test("2006-01-02", SYBDATE, "38717");
346 8 : test("12:34:56.337", SYBTIME, "13588901");
347 :
348 8 : test2("2006-01-02", SYBDATE, SYBDATE, "38717");
349 8 : test2("12:34:56.337", SYBTIME, SYBTIME, "13588901");
350 :
351 8 : test2("2006-01-02 12:34:56.337", SYBDATETIME, SYBDATE, "38717");
352 8 : test2("2006-01-02 12:34:56.337", SYBDATETIME, SYBTIME, "13588901");
353 :
354 8 : test("2006-01-02 12:34:56.337321", SYB5BIGTIME, "0x0000000a8bdf41a9");
355 8 : test("2006-01-23 12:34:56.337321", SYB5BIGDATETIME, "0x00e0e7c784d661a9");
356 8 : test("2006-01-02 12:34:56.337321", SYB5BIGDATETIME, "0x00e0e621122b81a9");
357 :
358 8 : test2("2006-01-02 12:34:56.337765", SYB5BIGDATETIME, SYBCHAR, "len=26 2006-01-02 12:34:56.337765");
359 8 : test("2006-01-02 12:34:56.337765", SYB5BIGDATETIME, "0x00e0e621122b8365");
360 :
361 8 : test2("2006-01-02 12:34:56.337", SYBMSDATETIME2, SYBDATE, "38717");
362 8 : test2("2006-01-02 12:34:56.337", SYBMSDATETIME2, SYBTIME, "13588901");
363 :
364 8 : 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 8 : test2("2006-01-02", SYBDATE, SYBCHAR, "len=10 2006-01-02");
372 8 : test2("12:34:56.337", SYBTIME, SYBCHAR, "len=12 12:34:56.337");
373 :
374 8 : test2("123", SYBINT1, SYBBINARY, "len=1 7B");
375 8 : 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 8 : test2("12345", SYBINT2, SYBBINARY, "len=2 39 30");
384 8 : test2("123456789", SYBINT4, SYBBINARY, "len=4 15 CD 5B 07");
385 8 : test2("123456789", SYBUINT8, SYBBINARY, "len=8 15 CD 5B 07 00 00 00 00");
386 8 : test2("123456789", SYBINT8, SYBBINARY, "len=8 15 CD 5B 07 00 00 00 00");
387 8 : test2("-123456789", SYBINT8, SYBBINARY, "len=8 EB 32 A4 F8 FF FF FF FF");
388 : }
389 :
390 : /* now try many int conversion operations */
391 272 : for (value = int_values; *value; ++value)
392 2904 : for (type1 = int_types; *type1 >= 0; ++type1)
393 31944 : 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 31944 : cr_src.n.precision = 20; cr_src.n.scale = 0;
400 31944 : len_src = tds_convert(&ctx, SYBVARCHAR, *value, strlen(*value), *type1, &cr_src);
401 31944 : cr_dst.n.precision = 20; cr_dst.n.scale = 0;
402 31944 : len_dst = tds_convert(&ctx, SYBVARCHAR, *value, strlen(*value), *type2, &cr_dst);
403 31944 : if (len_src <= 0 || len_dst <= 0)
404 21784 : continue;
405 10160 : cr_dst.n.precision = 20; cr_dst.n.scale = 0;
406 10160 : 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 10160 : memcpy(&cr_src, &cr_dst, sizeof(cr_dst));
412 10160 : cr_dst.cc.c = buf;
413 10160 : cr_dst.cc.len = sizeof(buf)-4;
414 10160 : len_dst = tds_convert(&ctx, *type2, &cr_src.i, len_dst, TDS_CONVERT_CHAR, &cr_dst);
415 10160 : 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 10160 : buf[len_dst] = 0;
421 10160 : if (*type2 == SYBMONEY4 || *type2 == SYBMONEY)
422 2272 : sprintf(expected, "%s.0000", *value);
423 : else
424 7888 : strcpy(expected, *value);
425 10160 : 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 8 : tds_free_locale(ctx.locale);
433 :
434 8 : return 0;
435 : }
|