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