Line data Source code
1 : #define MSDBLIB 1
2 : #include "common.h"
3 :
4 : static void
5 0 : dump_addr(FILE *out, const char *msg, const void *p, size_t len)
6 : {
7 : size_t n;
8 0 : if (msg)
9 0 : fprintf(out, "%s", msg);
10 0 : for (n = 0; n < len; ++n)
11 0 : fprintf(out, " %02X", ((unsigned char*) p)[n]);
12 0 : fprintf(out, "\n");
13 0 : }
14 :
15 : static void
16 1784 : chk(RETCODE ret, const char *msg)
17 : {
18 1784 : printf("%s: res %d\n", msg, ret);
19 1784 : if (ret == SUCCEED)
20 1784 : return;
21 0 : fprintf(stderr, "error: %s\n", msg);
22 0 : exit(1);
23 : }
24 :
25 : static void
26 384 : zero_end(DBNUMERIC *num)
27 : {
28 : /* 27213 == math.floor(math.log(10,256)*65536) */
29 384 : unsigned len = 4u+num->precision*27213u/65536u;
30 384 : if (num->precision < 1 || num->precision > 77)
31 : return;
32 384 : assert(len >= 4 && len <= sizeof(*num));
33 384 : memset(((char*) num) + len, 0, sizeof(*num) - len);
34 : }
35 :
36 : static int msdblib;
37 :
38 : static void
39 192 : test(int bind_type, const char *bind_name, int override_prec, int override_scale, int out_prec, int out_scale, int line)
40 : {
41 : LOGINREC *login;
42 : DBPROCESS *dbproc;
43 192 : DBNUMERIC *num = NULL, *num2 = NULL;
44 : RETCODE ret;
45 : DBTYPEINFO ti;
46 : int i;
47 :
48 192 : printf("*** Starting test msdblib %d bind %s prec %d scale %d out prec %d out scale %d line %d\n",
49 : msdblib, bind_name, override_prec, override_scale, out_prec, out_scale, line);
50 192 : chk(sql_rewind(), "sql_rewind");
51 192 : login = dblogin();
52 :
53 192 : DBSETLUSER(login, USER);
54 192 : DBSETLPWD(login, PASSWORD);
55 192 : DBSETLAPP(login, "numeric");
56 192 : dbsetmaxprocs(25);
57 192 : DBSETLHOST(login, SERVER);
58 :
59 192 : dbproc = tdsdbopen(login, SERVER, msdblib);
60 192 : dbloginfree(login);
61 192 : login = NULL;
62 192 : if (strlen(DATABASE))
63 192 : dbuse(dbproc, DATABASE);
64 :
65 192 : sql_cmd(dbproc);
66 192 : dbsqlexec(dbproc);
67 192 : while (dbresults(dbproc) != NO_MORE_RESULTS) {
68 : /* nop */
69 : }
70 :
71 192 : sql_cmd(dbproc);
72 192 : dbsqlexec(dbproc);
73 192 : while (dbresults(dbproc) != NO_MORE_RESULTS) {
74 : /* nop */
75 : }
76 :
77 192 : if (DBTDS_5_0 < DBTDS(dbproc)) {
78 144 : ret = dbcmd(dbproc,
79 : "SET ARITHABORT ON;"
80 : "SET CONCAT_NULL_YIELDS_NULL ON;"
81 : "SET ANSI_NULLS ON;"
82 : "SET ANSI_NULL_DFLT_ON ON;"
83 : "SET ANSI_PADDING ON;"
84 : "SET ANSI_WARNINGS ON;"
85 : "SET ANSI_NULL_DFLT_ON ON;"
86 : "SET CURSOR_CLOSE_ON_COMMIT ON;"
87 : "SET QUOTED_IDENTIFIER ON");
88 144 : chk(ret, "dbcmd");
89 144 : ret = dbsqlexec(dbproc);
90 144 : chk(ret, "dbsqlexec");
91 :
92 144 : ret = dbcancel(dbproc);
93 144 : chk(ret, "dbcancel");
94 : }
95 :
96 192 : ret = dbrpcinit(dbproc, "testDecimal", 0);
97 192 : chk(ret, "dbrpcinit");
98 :
99 192 : num = (DBDECIMAL *) calloc(1, sizeof(DBDECIMAL));
100 192 : ti.scale = 5;
101 192 : ti.precision = 16;
102 192 : ret = dbconvert_ps(dbproc, SYBVARCHAR, (const BYTE *) "123.45", -1, SYBDECIMAL, (BYTE *) num, sizeof(*num), &ti);
103 192 : chk(ret > 0, "dbconvert_ps");
104 :
105 192 : ret = dbrpcparam(dbproc, "@idecimal", 0, SYBDECIMAL, -1, sizeof(DBDECIMAL), (BYTE *) num);
106 192 : chk(ret, "dbrpcparam");
107 192 : ret = dbrpcsend(dbproc);
108 192 : chk(ret, "dbrpcsend");
109 192 : ret = dbsqlok(dbproc);
110 192 : chk(ret, "dbsqlok");
111 :
112 : /* TODO check MS/Sybase format */
113 192 : num2 = (DBDECIMAL *) calloc(1, sizeof(DBDECIMAL));
114 192 : ti.precision = override_prec;
115 192 : ti.scale = override_scale;
116 192 : ret = dbconvert_ps(dbproc, SYBVARCHAR, (const BYTE *) "246.9", -1, SYBDECIMAL, (BYTE *) num2, sizeof(*num2), &ti);
117 192 : chk(ret > 0, "dbconvert_ps");
118 :
119 384 : for (i=0; (ret = dbresults(dbproc)) != NO_MORE_RESULTS; ++i) {
120 : RETCODE row_code;
121 :
122 192 : switch (ret) {
123 192 : case SUCCEED:
124 192 : if (DBROWS(dbproc) == FAIL)
125 0 : continue;
126 192 : assert(DBROWS(dbproc) == SUCCEED);
127 192 : printf("dbrows() returned SUCCEED, processing rows\n");
128 :
129 192 : memset(num, 0, sizeof(*num));
130 192 : num->precision = out_prec ? out_prec : num2->precision;
131 192 : num->scale = out_scale ? out_scale : num2->scale;
132 192 : dbbind(dbproc, 1, bind_type, 0, (BYTE *) num);
133 :
134 192 : while ((row_code = dbnextrow(dbproc)) != NO_MORE_ROWS) {
135 192 : if (row_code == REG_ROW) {
136 192 : zero_end(num);
137 192 : zero_end(num2);
138 192 : if (memcmp(num, num2, sizeof(*num)) != 0) {
139 0 : fprintf(stderr, "Failed. Output results does not match\n");
140 0 : dump_addr(stderr, "got: ", num, sizeof(*num));
141 0 : dump_addr(stderr, "expected: ", num2, sizeof(*num2));
142 0 : exit(1);
143 : }
144 : } else {
145 : /* not supporting computed rows in this unit test */
146 0 : fprintf(stderr, "Failed. Expected a row\n");
147 0 : exit(1);
148 : }
149 : }
150 : break;
151 0 : case FAIL:
152 0 : fprintf(stderr, "dbresults returned FAIL\n");
153 0 : exit(1);
154 0 : default:
155 0 : fprintf(stderr, "unexpected return code %d from dbresults\n", ret);
156 0 : exit(1);
157 : }
158 : } /* while dbresults */
159 :
160 192 : sql_cmd(dbproc);
161 :
162 192 : free(num2);
163 192 : free(num);
164 :
165 192 : dbclose(dbproc);
166 192 : }
167 :
168 : #define test(a,b,c,d,e) test(a, #a, b, c, d, e, __LINE__)
169 :
170 : int
171 8 : main(int argc, char **argv)
172 : {
173 8 : read_login_info(argc, argv);
174 :
175 8 : dbsetversion(DBVERSION_100);
176 8 : dbinit();
177 :
178 : /* tests with MS behaviour */
179 8 : msdblib = 1;
180 8 : test(DECIMALBIND, 20, 10, 0, 0);
181 8 : test(NUMERICBIND, 20, 10, 0, 0);
182 8 : test(SRCDECIMALBIND, 20, 10, 0, 0);
183 8 : test(SRCNUMERICBIND, 20, 10, 0, 0);
184 : /* in these 2 case MS override what server returns */
185 8 : test(DECIMALBIND, 10, 4, 10, 4);
186 8 : test(NUMERICBIND, 10, 4, 10, 4);
187 8 : test(SRCDECIMALBIND, 20, 10, 10, 4);
188 8 : test(SRCNUMERICBIND, 20, 10, 10, 4);
189 :
190 : /* tests with Sybase behaviour */
191 8 : msdblib = 0;
192 8 : test(DECIMALBIND, 20, 10, 0, 0);
193 8 : test(NUMERICBIND, 20, 10, 0, 0);
194 8 : test(SRCDECIMALBIND, 20, 10, 0, 0);
195 8 : test(SRCNUMERICBIND, 20, 10, 0, 0);
196 : /* no matter what Sybase return always according to source */
197 8 : test(DECIMALBIND, 20, 10, 10, 4);
198 8 : test(NUMERICBIND, 20, 10, 10, 4);
199 8 : test(SRCDECIMALBIND, 20, 10, 10, 4);
200 8 : test(SRCNUMERICBIND, 20, 10, 10, 4);
201 :
202 8 : chk(sql_reopen("numeric_2"), "sql_reopen");
203 :
204 8 : msdblib = 1;
205 : /* on MS use always output */
206 8 : test(DECIMALBIND, 20, 0, 20, 0);
207 8 : test(NUMERICBIND, 19, 0, 19, 0);
208 8 : test(SRCDECIMALBIND, 18, 0, 18, 0);
209 8 : test(SRCNUMERICBIND, 17, 0, 17, 0);
210 :
211 8 : msdblib = 0;
212 8 : test(DECIMALBIND, 18, 0, 20, 0);
213 8 : test(NUMERICBIND, 18, 0, 19, 0);
214 : /* this is MS only and behave like MS */
215 8 : test(SRCDECIMALBIND, 18, 0, 18, 0);
216 8 : test(SRCNUMERICBIND, 17, 0, 17, 0);
217 :
218 8 : dbexit();
219 :
220 8 : printf("Succeed\n");
221 : return 0;
222 : }
223 :
|