1 /*
2 * Test reading data with SQLGetData
3 */
4 #include "common.h"
5 #include <assert.h>
6
7 static void
test_err(const char * data,int c_type,const char * state)8 test_err(const char *data, int c_type, const char *state)
9 {
10 char sql[128];
11 SQLLEN ind;
12 const unsigned int buf_size = 128;
13 char *buf = (char *) malloc(buf_size);
14
15 sprintf(sql, "SELECT '%s'", data);
16 odbc_command(sql);
17 SQLFetch(odbc_stmt);
18 CHKGetData(1, c_type, buf, buf_size, &ind, "E");
19 free(buf);
20 odbc_read_error();
21 if (strcmp(odbc_sqlstate, state) != 0) {
22 fprintf(stderr, "Unexpected sql state returned\n");
23 odbc_disconnect();
24 exit(1);
25 }
26 odbc_reset_statement();
27 }
28
29 static int lc;
30 static int type;
31
32 static int
mycmp(const char * s1,const char * s2)33 mycmp(const char *s1, const char *s2)
34 {
35 SQLWCHAR buf[128], *wp;
36 unsigned l;
37
38 if (type == SQL_C_CHAR)
39 return strcmp(s1, s2);
40
41 l = strlen(s2);
42 assert(l < TDS_VECTOR_SIZE(buf));
43 wp = buf;
44 do {
45 *wp++ = *s2;
46 } while (*s2++);
47
48 return memcmp(s1, buf, l * lc + lc);
49 }
50
51 static void
test_split(const char * n_flag)52 test_split(const char *n_flag)
53 {
54 #define CheckLen(x) do { \
55 if (len != (x)) { \
56 fprintf(stderr, "Wrong len %ld at line %d expected %d\n", (long int) len, __LINE__, (x)); \
57 exit(1); \
58 } \
59 } while(0)
60
61 char *sql;
62 char *buf = NULL;
63 const char *collate = "";
64 SQLLEN len;
65
66 /* TODO test with VARCHAR too */
67 if (odbc_db_is_microsoft())
68 collate = " COLLATE Latin1_General_CI_AS";
69 sql = odbc_buf_asprintf(&odbc_buf, "SELECT CONVERT(%sTEXT,'Prova'%s + REPLICATE('x',500))%s", n_flag, collate, collate);
70 odbc_command(sql);
71
72 CHKFetch("S");
73
74 /* these 2 tests test an old severe BUG in FreeTDS */
75 buf = (char *) ODBC_GET(1);
76 CHKGetData(1, type, buf, 0, &len, "I");
77 if (len != SQL_NO_TOTAL)
78 CheckLen(505*lc);
79 CHKGetData(1, type, buf, 0, &len, "I");
80 if (len != SQL_NO_TOTAL)
81 CheckLen(505*lc);
82 buf = (char *) ODBC_GET(3*lc);
83 CHKGetData(1, type, buf, 3 * lc, &len, "I");
84 if (len != SQL_NO_TOTAL)
85 CheckLen(505*lc);
86 if (mycmp(buf, "Pr") != 0) {
87 printf("Wrong data result 1\n");
88 exit(1);
89 }
90
91 buf = (char *) ODBC_GET(16*lc);
92 CHKGetData(1, type, buf, 16 * lc, &len, "I");
93 if (len != SQL_NO_TOTAL)
94 CheckLen(503*lc);
95 if (mycmp(buf, "ovaxxxxxxxxxxxx") != 0) {
96 printf("Wrong data result 2 res = '%s'\n", buf);
97 exit(1);
98 }
99
100 buf = (char *) ODBC_GET(256*lc);
101 CHKGetData(1, type, buf, 256 * lc, &len, "I");
102 if (len != SQL_NO_TOTAL)
103 CheckLen(488*lc);
104 CHKGetData(1, type, buf, 256 * lc, &len, "S");
105 CheckLen(233*lc);
106 CHKGetData(1, type, buf, 256 * lc, &len, "No");
107
108 odbc_reset_statement();
109
110 /* test with varchar, not blob but variable */
111 sql = odbc_buf_asprintf(&odbc_buf, "SELECT CONVERT(%sVARCHAR(100), 'Other test')", n_flag);
112 odbc_command(sql);
113
114 CHKFetch("S");
115
116 buf = (char *) ODBC_GET(7*lc);
117 CHKGetData(1, type, buf, 7 * lc, NULL, "I");
118 if (mycmp(buf, "Other ") != 0) {
119 printf("Wrong data result 1\n");
120 exit(1);
121 }
122
123 buf = (char *) ODBC_GET(5*lc);
124 CHKGetData(1, type, buf, 20, NULL, "S");
125 if (mycmp(buf, "test") != 0) {
126 printf("Wrong data result 2 res = '%s'\n", buf);
127 exit(1);
128 }
129 ODBC_FREE();
130
131 odbc_reset_statement();
132 }
133
134 int
main(int argc,char * argv[])135 main(int argc, char *argv[])
136 {
137 char buf[32];
138 SQLINTEGER int_buf;
139 SQLLEN len;
140 SQLRETURN rc;
141 TIMESTAMP_STRUCT tss;
142
143 odbc_connect();
144
145 lc = 1;
146 type = SQL_C_CHAR;
147 test_split("");
148
149 lc = sizeof(SQLWCHAR);
150 type = SQL_C_WCHAR;
151 test_split("");
152
153 if (odbc_db_is_microsoft() && odbc_db_version_int() >= 0x07000000u) {
154 lc = 1;
155 type = SQL_C_CHAR;
156 test_split("N");
157
158 lc = sizeof(SQLWCHAR);
159 type = SQL_C_WCHAR;
160 test_split("N");
161 }
162
163 /* test with fixed length */
164 odbc_command("SELECT CONVERT(INT, 12345)");
165
166 CHKFetch("S");
167
168 int_buf = 0xdeadbeef;
169 CHKGetData(1, SQL_C_SLONG, &int_buf, 0, NULL, "S");
170 if (int_buf != 12345) {
171 printf("Wrong data result\n");
172 exit(1);
173 }
174
175 CHKGetData(1, SQL_C_SLONG, &int_buf, 0, NULL, "No");
176 if (int_buf != 12345) {
177 printf("Wrong data result 2 res = %d\n", (int) int_buf);
178 exit(1);
179 }
180
181 odbc_reset_statement();
182
183 /* test with numeric */
184 odbc_command("SELECT CONVERT(NUMERIC(18,5), 1850000000000)");
185
186 CHKFetch("S");
187
188 memset(buf, 'x', sizeof(buf));
189 CHKGetData(1, SQL_C_CHAR, buf, 14, NULL, "S");
190 buf[sizeof(buf)-1] = 0;
191 if (strcmp(buf, "1850000000000") != 0) {
192 printf("Wrong data result: %s\n", buf);
193 exit(1);
194 }
195
196 /* should give NO DATA */
197 CHKGetData(1, SQL_C_CHAR, buf, 14, NULL, "No");
198 buf[sizeof(buf)-1] = 0;
199 if (strcmp(buf, "1850000000000") != 0) {
200 printf("Wrong data result 3 res = %s\n", buf);
201 exit(1);
202 }
203
204 odbc_reset_statement();
205
206
207 /* test int to truncated string */
208 odbc_command("SELECT CONVERT(INTEGER, 12345)");
209 CHKFetch("S");
210
211 /* error 22003 */
212 memset(buf, 'x', sizeof(buf));
213 CHKGetData(1, SQL_C_CHAR, buf, 4, NULL, "E");
214 #ifdef ENABLE_DEVELOPING
215 buf[4] = 0;
216 if (strcmp(buf, "xxxx") != 0) {
217 fprintf(stderr, "Wrong buffer result buf = %s\n", buf);
218 exit(1);
219 }
220 #endif
221 odbc_read_error();
222 if (strcmp(odbc_sqlstate, "22003") != 0) {
223 fprintf(stderr, "Unexpected sql state %s returned\n", odbc_sqlstate);
224 odbc_disconnect();
225 exit(1);
226 }
227 CHKGetData(1, SQL_C_CHAR, buf, 2, NULL, "No");
228 odbc_reset_statement();
229
230 /* test unique identifier to truncated string */
231 rc = odbc_command2("SELECT CONVERT(UNIQUEIDENTIFIER, 'AA7DF450-F119-11CD-8465-00AA00425D90')", "SENo");
232 if (rc != SQL_ERROR) {
233 CHKFetch("S");
234
235 /* error 22003 */
236 CHKGetData(1, SQL_C_CHAR, buf, 17, NULL, "E");
237 odbc_read_error();
238 if (strcmp(odbc_sqlstate, "22003") != 0) {
239 fprintf(stderr, "Unexpected sql state %s returned\n", odbc_sqlstate);
240 odbc_disconnect();
241 exit(1);
242 }
243 CHKGetData(1, SQL_C_CHAR, buf, 2, NULL, "No");
244 }
245 odbc_reset_statement();
246
247
248 odbc_disconnect();
249
250 odbc_use_version3 = 1;
251 odbc_connect();
252
253 /* test error from SQLGetData */
254 /* wrong constant, SQL_VARCHAR is invalid as C type */
255 test_err("prova 123", SQL_VARCHAR, "HY003");
256 /* use ARD but no ARD data column */
257 test_err("prova 123", SQL_ARD_TYPE, "07009");
258 /* wrong conversion, int */
259 test_err("prova 123", SQL_C_LONG, "22018");
260 /* wrong conversion, date */
261 test_err("prova 123", SQL_C_TIMESTAMP, "22018");
262 /* overflow */
263 test_err("1234567890123456789", SQL_C_LONG, "22003");
264
265 /* test datetime precision */
266 odbc_command("SELECT CONVERT(DATETIME, '2018-08-15 12:34:56.007')");
267
268 CHKFetch("S");
269
270 memset(&tss, 'x', sizeof(tss));
271 CHKGetData(1, SQL_C_TYPE_TIMESTAMP, &tss, sizeof(tss), NULL, "S");
272 if (tss.fraction != 7000000) {
273 printf("Wrong data result: %lu\n", (unsigned long) tss.fraction);
274 exit(1);
275 }
276
277 odbc_reset_statement();
278
279 /* test for empty string from mssql */
280 if (odbc_db_is_microsoft()) {
281 lc = 1;
282 type = SQL_C_CHAR;
283
284 for (;;) {
285 void *buf = ODBC_GET(lc);
286
287 odbc_command("SELECT CONVERT(TEXT,'' COLLATE Latin1_General_CI_AS)");
288
289 CHKFetch("S");
290
291 len = 1234;
292 CHKGetData(1, type, buf, lc, &len, "S");
293
294 if (len != 0) {
295 fprintf(stderr, "Wrong len returned, returned %ld\n", (long) len);
296 return 1;
297 }
298
299 CHKGetData(1, type, buf, lc, NULL, "No");
300 odbc_reset_statement();
301 ODBC_FREE();
302
303 buf = ODBC_GET(4096*lc);
304
305 odbc_command("SELECT CONVERT(TEXT,'' COLLATE Latin1_General_CI_AS)");
306
307 CHKFetch("S");
308
309 len = 1234;
310 CHKGetData(1, type, buf, lc*4096, &len, "S");
311
312 if (len != 0) {
313 fprintf(stderr, "Wrong len returned, returned %ld\n", (long) len);
314 return 1;
315 }
316
317 CHKGetData(1, type, buf, lc*4096, NULL, "No");
318 odbc_reset_statement();
319 ODBC_FREE();
320
321 if (type != SQL_C_CHAR)
322 break;
323 lc = sizeof(SQLWCHAR);
324 type = SQL_C_WCHAR;
325 }
326
327 odbc_command("SELECT CONVERT(TEXT,'' COLLATE Latin1_General_CI_AS)");
328
329 CHKFetch("S");
330
331 len = 1234;
332 CHKGetData(1, SQL_C_BINARY, buf, 1, &len, "S");
333
334 if (len != 0) {
335 fprintf(stderr, "Wrong len returned, returned %ld\n", (long) len);
336 return 1;
337 }
338
339 CHKGetData(1, SQL_C_BINARY, buf, 1, NULL, "No");
340 }
341
342 odbc_disconnect();
343
344 printf("Done.\n");
345 return 0;
346 }
347