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