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 624 : 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 624 : memset(&cr.n, 0, sizeof(cr.n));
41 624 : cr.n.precision = prec;
42 624 : cr.n.scale = scale;
43 624 : 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 624 : num = cr.n;
48 :
49 : /* change scale with string */
50 624 : tds_numeric_to_string(&num, buf);
51 1600 : while ((p = strchr(buf, '.')) != NULL)
52 352 : memmove(p, p+1, strlen(p));
53 :
54 2368 : for (i = 0; i < (scale2 - scale); ++i)
55 2368 : strcat(buf, "0");
56 1584 : for (i = 0; i < (scale - scale2); ++i) {
57 1584 : assert(strlen(buf) > 1);
58 1584 : buf[strlen(buf)-1] = 0;
59 : }
60 624 : if (scale2) {
61 584 : size_t len = strlen(buf);
62 584 : assert(len > scale2);
63 584 : memmove(buf + len - scale2 + 1, buf + len - scale2, scale2 + 1);
64 584 : buf[len-scale2] = '.';
65 : }
66 624 : cr.n.precision = prec2;
67 624 : cr.n.scale = scale2;
68 624 : 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 624 : if (tds_numeric_change_prec_scale(&num, prec2, scale2) < 0)
73 208 : strcpy(result, "error");
74 : else
75 416 : tds_numeric_to_string(&num, result);
76 :
77 624 : 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 624 : printf("%s -> %s ok!\n", src, buf);
84 : }
85 624 : }
86 :
87 : static void
88 : test(const char *src, int prec, int scale, int scale2)
89 : {
90 568 : test0(src, prec, scale, prec, scale2);
91 : }
92 :
93 : int
94 8 : main(void)
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 152 : for (i = 2; i < 20; ++i)
116 144 : test("1234.765", 30, 20, i);
117 :
118 8 : test0("765432.2", 30, 2, 20, 2);
119 8 : test0("765432.2", 30, 2, 40, 2);
120 8 : test0("765432.2", 30, 2, 6, 2);
121 :
122 : /* test big overflows */
123 8 : test0("10000000000000000000000000", 30, 0, 10, 0);
124 8 : test0("1000000000000000000", 30, 0, 10, 0);
125 :
126 8 : test0("10000000000000000", 30, 10, 19, 0);
127 8 : test0("10000000000000000", 30, 10, 12, 0);
128 :
129 : #if 0
130 : {
131 : int p1, s1, p2, s2;
132 : for (p1 = 1; p1 <= 77; ++p1) {
133 : printf("(%d,%d) -> (%d,%d)\n", p1, s1, p2, s2);
134 : for (s1 = 0; s1 < p1; ++s1)
135 : for (p2 = 1; p2 <= 77; ++p2)
136 : for (s2 = 0; s2 < p2; ++s2)
137 : test0("9", p1, s1, p2, s2);
138 : }
139 : }
140 : #endif
141 :
142 8 : if (!g_result)
143 8 : printf("All passed!\n");
144 :
145 8 : return g_result;
146 : }
|