Line data Source code
1 : /* FreeTDS - Library of routines accessing Sybase and Microsoft databases
2 : * Copyright (C) 2005 Frediano Ziglio
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 : #include "common.h"
21 : #include <freetds/convert.h>
22 : #include <assert.h>
23 :
24 : /* test numeric scale */
25 :
26 : static int g_result = 0;
27 : static TDSCONTEXT ctx;
28 :
29 : static void
30 488 : test0(const char *src, int prec, int scale, int prec2, unsigned char scale2)
31 : {
32 : int i;
33 : char buf[256];
34 : char result[256];
35 : char *p;
36 : CONV_RESULT cr;
37 : TDS_NUMERIC num;
38 :
39 : /* get initial number */
40 488 : memset(&cr.n, 0, sizeof(cr.n));
41 488 : cr.n.precision = prec;
42 488 : cr.n.scale = scale;
43 488 : if (tds_convert(&ctx, SYBVARCHAR, src, (TDS_UINT)strlen(src), SYBNUMERIC, &cr) < 0) {
44 0 : fprintf(stderr, "Error getting numeric %s(%d,%d)\n", src, prec, scale);
45 0 : exit(1);
46 : }
47 488 : num = cr.n;
48 :
49 : /* change scale with string */
50 488 : tds_numeric_to_string(&num, buf);
51 1192 : while ((p = strchr(buf, '.')) != NULL)
52 216 : memmove(p, p+1, strlen(p));
53 :
54 2368 : for (i = 0; i < (scale2 - scale); ++i)
55 2368 : strcat(buf, "0");
56 360 : for (i = 0; i < (scale - scale2); ++i) {
57 360 : assert(strlen(buf) > 1);
58 360 : buf[strlen(buf)-1] = 0;
59 : }
60 488 : if (scale2) {
61 448 : size_t len = strlen(buf);
62 448 : assert(len > scale2);
63 448 : memmove(buf + len - scale2 + 1, buf + len - scale2, scale2 + 1);
64 448 : buf[len-scale2] = '.';
65 : }
66 488 : cr.n.precision = prec2;
67 488 : cr.n.scale = scale2;
68 488 : if (tds_convert(&ctx, SYBVARCHAR, src, (TDS_UINT)strlen(src), SYBNUMERIC, &cr) < 0)
69 208 : strcpy(buf, "error");
70 :
71 : /* change scale with function */
72 488 : if (tds_numeric_change_prec_scale(&num, prec2, scale2) < 0)
73 208 : strcpy(result, "error");
74 : else
75 280 : tds_numeric_to_string(&num, result);
76 :
77 488 : if (strcmp(buf, result) != 0) {
78 0 : fprintf(stderr, "Failed! %s (%d,%d) -> (%d,%d)\n\tshould be %s\n\tis %s\n",
79 : src, prec, scale, prec2, scale2, buf, result);
80 0 : g_result = 1;
81 0 : exit(1);
82 : } else {
83 488 : printf("%s -> %s ok!\n", src, buf);
84 : }
85 488 : }
86 :
87 : static void
88 : test(const char *src, int prec, int scale, int scale2)
89 : {
90 432 : test0(src, prec, scale, prec, scale2);
91 : }
92 :
93 : int
94 8 : main(int argc, char **argv)
95 : {
96 : int i;
97 8 : memset(&ctx, 0, sizeof(ctx));
98 :
99 : /* increase scale */
100 88 : for (i = 0; i < 10; ++i) {
101 160 : test("1234", 18+i, 0, 2+i);
102 160 : test("1234.1234", 18+i, 5, 3+i);
103 160 : test("1234.1234", 22+i, 5+i, 12+i);
104 : }
105 :
106 : /* overflow */
107 8 : test("1234", 4, 0, 2);
108 96 : for (i = 1; i < 12; ++i)
109 176 : test("1234", 3+i, 0, i);
110 80 : for (i = 2; i < 12; ++i)
111 160 : test("1234", 2+i, 0, i);
112 :
113 : /* decrease scale */
114 8 : test("1234", 10, 4, 0);
115 8 : test("1234.765", 30, 20, 2);
116 :
117 8 : test0("765432.2", 30, 2, 20, 2);
118 8 : test0("765432.2", 30, 2, 40, 2);
119 8 : test0("765432.2", 30, 2, 6, 2);
120 :
121 : /* test big overflows */
122 8 : test0("10000000000000000000000000", 30, 0, 10, 0);
123 8 : test0("1000000000000000000", 30, 0, 10, 0);
124 :
125 8 : test0("10000000000000000", 30, 10, 19, 0);
126 8 : test0("10000000000000000", 30, 10, 12, 0);
127 :
128 : #if 0
129 : {
130 : int p1, s1, p2, s2;
131 : for (p1 = 1; p1 <= 77; ++p1) {
132 : printf("(%d,%d) -> (%d,%d)\n", p1, s1, p2, s2);
133 : for (s1 = 0; s1 < p1; ++s1)
134 : for (p2 = 1; p2 <= 77; ++p2)
135 : for (s2 = 0; s2 < p2; ++s2)
136 : test0("9", p1, s1, p2, s2);
137 : }
138 : }
139 : #endif
140 :
141 8 : if (!g_result)
142 8 : printf("All passed!\n");
143 :
144 8 : return g_result;
145 : }
|