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