Line data Source code
1 : #include "common.h"
2 : #include <assert.h>
3 : #include <time.h>
4 :
5 : /* Test various type from odbc and to odbc */
6 :
7 : /*
8 : * This test is useful to test odbc_sql2tds function using TestInput
9 : * odbc_sql2tds have some particular cases:
10 : * (1) char -> char handled differently with encoding problems
11 : * (2) date -> * different format TODO
12 : * (3) numeric -> * different format
13 : * (4) * -> numeric take precision and scale from ipd TODO
14 : * (5) * -> char test wide
15 : * (6) * -> blob test wchar and ntext
16 : * (7) * -> binary test also with wchar
17 : * (8) binary -> * test also with wchar
18 : * Also we have to check normal char and wide char
19 : */
20 :
21 : static char precision = 18;
22 : static char exec_direct = 0;
23 : static char prepare_before = 0;
24 : static char use_cursors = 0;
25 : static int only_test = 0;
26 :
27 : static const char *
28 7242 : split_collate(ODBC_BUF** buf, const char **type)
29 : {
30 7242 : const char *collate = "", *p;
31 :
32 7242 : if ((p = strstr(*type, " COLLATE ")) != NULL) {
33 150 : if (odbc_db_is_microsoft())
34 144 : collate = p;
35 150 : *type = odbc_buf_asprintf(buf, "%.*s", (int) (p - *type), *type);
36 : }
37 7242 : return collate;
38 : }
39 :
40 : static int
41 654 : TestOutput(const char *type, const char *value_to_convert, SQLSMALLINT out_c_type, SQLSMALLINT out_sql_type, const char *expected)
42 : {
43 : char sbuf[1024];
44 : unsigned char out_buf[256];
45 654 : SQLLEN out_len = 0;
46 : const char *sep;
47 : const char *collate;
48 :
49 654 : odbc_reset_statement();
50 :
51 : /* build store procedure to test */
52 654 : odbc_command("IF OBJECT_ID('spTestProc') IS NOT NULL DROP PROC spTestProc");
53 654 : sep = "'";
54 654 : if (strncmp(value_to_convert, "0x", 2) == 0 || strncmp(value_to_convert, "NCHAR(", 6) == 0)
55 96 : sep = "";
56 654 : collate = split_collate(&odbc_buf, &type);
57 654 : sprintf(sbuf, "CREATE PROC spTestProc @i %s OUTPUT AS SELECT @i = CONVERT(%s, %s%s%s)%s",
58 : type, type, sep, value_to_convert, sep, collate);
59 654 : odbc_command(sbuf);
60 654 : memset(out_buf, 0, sizeof(out_buf));
61 :
62 654 : if (use_cursors) {
63 300 : odbc_reset_statement();
64 300 : CHKSetStmtAttr(SQL_ATTR_CURSOR_SCROLLABLE, (SQLPOINTER) SQL_SCROLLABLE, 0, "S");
65 300 : CHKSetStmtAttr(SQL_ATTR_CURSOR_TYPE, (SQLPOINTER) SQL_CURSOR_DYNAMIC, 0, "S");
66 : }
67 :
68 : /* bind parameter */
69 654 : if (exec_direct) {
70 218 : CHKBindParameter(1, SQL_PARAM_OUTPUT, out_c_type, out_sql_type, precision, 0, out_buf,
71 : sizeof(out_buf), &out_len, "S");
72 :
73 : /* call store procedure */
74 218 : CHKExecDirect(T("{call spTestProc(?)}"), SQL_NTS, "S");
75 : } else {
76 436 : if (prepare_before)
77 218 : CHKPrepare(T("{call spTestProc(?)}"), SQL_NTS, "S");
78 :
79 436 : CHKBindParameter(1, SQL_PARAM_OUTPUT, out_c_type, out_sql_type, precision, 0, out_buf,
80 : sizeof(out_buf), &out_len, "S");
81 :
82 436 : if (!prepare_before)
83 218 : CHKPrepare(T("{call spTestProc(?)}"), SQL_NTS, "S");
84 :
85 436 : CHKExecute("S");
86 : }
87 :
88 : /*
89 : * MS OBDC requires it cause first recordset is a recordset with a
90 : * warning caused by the way it execute RPC (via EXEC statement)
91 : */
92 654 : if (use_cursors && !odbc_driver_is_freetds())
93 0 : SQLMoreResults(odbc_stmt);
94 :
95 : /* test results */
96 654 : odbc_c2string(sbuf, out_c_type, out_buf, out_len);
97 :
98 654 : if (strcmp(sbuf, expected) != 0) {
99 30 : if (only_test) {
100 30 : odbc_command("drop proc spTestProc");
101 30 : ODBC_FREE();
102 30 : return 1;
103 : }
104 0 : fprintf(stderr, "Wrong result\n Got: %s\n Expected: %s\n", sbuf, expected);
105 0 : exit(1);
106 : }
107 624 : only_test = 0;
108 624 : odbc_command("drop proc spTestProc");
109 624 : ODBC_FREE();
110 624 : return 0;
111 : }
112 :
113 : static char check_truncation = 0;
114 : static char use_nts = 0;
115 :
116 : /**
117 : * Test a parameter as input to prepared statement
118 : *
119 : * "value_to_convert" will be inserted as database type "type" and C type "out_c_type" into a column of
120 : * database type "param_type" and SQL type "out_sql_type". Then a select statement check that the column
121 : * in the database is the same as "value_to_convert".
122 : * "value_to_convert" can also contain a syntax like "input -> output", in this case the initial inserted
123 : * value is "input" and the final check will check for "output".
124 : */
125 : static void
126 3294 : TestInput(SQLSMALLINT out_c_type, const char *type, SQLSMALLINT out_sql_type, const char *param_type, const char *value_to_convert)
127 : {
128 : char sbuf[1024];
129 : unsigned char out_buf[256];
130 3294 : SQLLEN out_len = 0;
131 3294 : const char *expected = value_to_convert;
132 3294 : size_t value_len = strlen(value_to_convert);
133 : const char *p;
134 3294 : const char *sep = "'";
135 : const char *collate;
136 :
137 3294 : odbc_reset_statement();
138 :
139 : /* execute a select to get data as wire */
140 3294 : if ((p = strstr(value_to_convert, " -> ")) != NULL) {
141 1296 : value_len = p - value_to_convert;
142 1296 : expected = p + 4;
143 : }
144 3294 : if (value_len >= 2 && strncmp(value_to_convert, "0x", 2) == 0)
145 396 : sep = "";
146 3294 : collate = split_collate(&odbc_buf, &type);
147 3294 : sprintf(sbuf, "SELECT CONVERT(%s, %s%.*s%s%s)", type, sep, (int) value_len, value_to_convert, sep, collate);
148 3294 : odbc_command(sbuf);
149 3294 : SQLBindCol(odbc_stmt, 1, out_c_type, out_buf, sizeof(out_buf), &out_len);
150 3294 : CHKFetch("SI");
151 3294 : CHKFetch("No");
152 3294 : CHKMoreResults("No");
153 3294 : if (use_nts) {
154 96 : out_len = SQL_NTS;
155 96 : use_nts = 0;
156 : }
157 :
158 : /* create a table with a column of that type */
159 3294 : odbc_reset_statement();
160 3294 : collate = split_collate(&odbc_buf, ¶m_type);
161 3294 : sprintf(sbuf, "CREATE TABLE #tmp_insert (col %s%s)", param_type, collate);
162 3294 : odbc_command(sbuf);
163 :
164 3294 : if (use_cursors) {
165 1518 : odbc_reset_statement();
166 1518 : CHKSetStmtAttr(SQL_ATTR_CURSOR_SCROLLABLE, (SQLPOINTER) SQL_SCROLLABLE, 0, "S");
167 1518 : CHKSetStmtAttr(SQL_ATTR_CURSOR_TYPE, (SQLPOINTER) SQL_CURSOR_DYNAMIC, 0, "S");
168 : }
169 :
170 : /* insert data using prepared statements */
171 3294 : sprintf(sbuf, "INSERT INTO #tmp_insert VALUES(?)");
172 3294 : if (exec_direct) {
173 1098 : CHKBindParameter(1, SQL_PARAM_INPUT, out_c_type, out_sql_type, 20, 0, out_buf, sizeof(out_buf), &out_len, "S");
174 :
175 1098 : if (check_truncation)
176 0 : CHKExecDirect(T(sbuf), SQL_NTS, "E");
177 : else
178 1098 : CHKExecDirect(T(sbuf), SQL_NTS, "SNo");
179 : } else {
180 2196 : if (prepare_before)
181 1098 : CHKPrepare(T(sbuf), SQL_NTS, "S");
182 :
183 2196 : CHKBindParameter(1, SQL_PARAM_INPUT, out_c_type, out_sql_type, 20, 0, out_buf, sizeof(out_buf), &out_len, "S");
184 :
185 2196 : if (!prepare_before)
186 1098 : CHKPrepare(T(sbuf), SQL_NTS, "S");
187 :
188 2196 : if (check_truncation)
189 0 : CHKExecute("E");
190 : else
191 2196 : CHKExecute("SNo");
192 : }
193 :
194 : /* check if row is present */
195 3294 : if (!check_truncation) {
196 : char *p;
197 :
198 3294 : odbc_reset_statement();
199 3294 : sep = "'";
200 3294 : if (strncmp(expected, "0x", 2) == 0)
201 192 : sep = "";
202 :
203 3294 : strcpy(sbuf, "SELECT * FROM #tmp_insert WHERE ");
204 3294 : p = strchr(sbuf, 0);
205 3294 : if (strcmp(param_type, "TEXT") == 0)
206 270 : sprintf(p, "CONVERT(VARCHAR(255), col) = CONVERT(VARCHAR(255), %s%s%s)", sep, expected, sep);
207 3024 : else if (strcmp(param_type, "NTEXT") == 0)
208 384 : sprintf(p, "CONVERT(NVARCHAR(2000), col) = CONVERT(NVARCHAR(2000), %s%s%s)", sep, expected, sep);
209 2640 : else if (strcmp(param_type, "IMAGE") == 0)
210 54 : sprintf(p, "CONVERT(VARBINARY(255), col) = CONVERT(VARBINARY(255), %s%s%s)", sep, expected, sep);
211 : else
212 2586 : sprintf(p, "col = CONVERT(%s, %s%s%s)", param_type, sep, expected, sep);
213 3294 : odbc_command(sbuf);
214 :
215 3294 : CHKFetch("S");
216 3294 : CHKFetch("No");
217 3294 : CHKMoreResults("No");
218 : }
219 3294 : check_truncation = 0;
220 3294 : odbc_command("DROP TABLE #tmp_insert");
221 3294 : ODBC_FREE();
222 3294 : }
223 :
224 : /* stripped down version of TestInput for NULLs */
225 : static void
226 480 : NullInput(SQLSMALLINT out_c_type, SQLSMALLINT out_sql_type, const char *param_type)
227 : {
228 : char sbuf[1024];
229 480 : SQLLEN out_len = SQL_NULL_DATA;
230 :
231 480 : odbc_reset_statement();
232 :
233 : /* create a table with a column of that type */
234 480 : odbc_reset_statement();
235 480 : sprintf(sbuf, "CREATE TABLE #tmp_insert (col %s NULL)", param_type);
236 480 : odbc_command(sbuf);
237 :
238 480 : if (use_cursors) {
239 216 : odbc_reset_statement();
240 216 : CHKSetStmtAttr(SQL_ATTR_CURSOR_SCROLLABLE, (SQLPOINTER) SQL_SCROLLABLE, 0, "S");
241 216 : CHKSetStmtAttr(SQL_ATTR_CURSOR_TYPE, (SQLPOINTER) SQL_CURSOR_DYNAMIC, 0, "S");
242 : }
243 :
244 : /* insert data using prepared statements */
245 480 : sprintf(sbuf, "INSERT INTO #tmp_insert VALUES(?)");
246 480 : if (exec_direct) {
247 160 : CHKBindParameter(1, SQL_PARAM_INPUT, out_c_type, out_sql_type, 20, 0, NULL, 1, &out_len, "S");
248 :
249 160 : CHKExecDirect(T(sbuf), SQL_NTS, "SNo");
250 : } else {
251 320 : if (prepare_before)
252 160 : CHKPrepare(T(sbuf), SQL_NTS, "S");
253 :
254 320 : CHKBindParameter(1, SQL_PARAM_INPUT, out_c_type, out_sql_type, 20, 0, NULL, 1, &out_len, "S");
255 :
256 320 : if (!prepare_before)
257 160 : CHKPrepare(T(sbuf), SQL_NTS, "S");
258 :
259 320 : CHKExecute("SNo");
260 : }
261 :
262 : /* check if row is present */
263 480 : odbc_reset_statement();
264 480 : if (!odbc_db_is_microsoft() && strcmp(param_type, "TEXT") == 0)
265 18 : odbc_command("SELECT * FROM #tmp_insert WHERE DATALENGTH(col) = 0 OR DATALENGTH(col) IS NULL");
266 : else
267 462 : odbc_command("SELECT * FROM #tmp_insert WHERE col IS NULL");
268 :
269 480 : CHKFetch("S");
270 480 : CHKFetch("No");
271 480 : CHKMoreResults("No");
272 480 : odbc_command("DROP TABLE #tmp_insert");
273 480 : ODBC_FREE();
274 480 : }
275 :
276 :
277 : static int big_endian = 1;
278 :
279 : static const char*
280 138 : pack(const char *fmt, ...)
281 : {
282 : static char out[80];
283 138 : char *p = out;
284 :
285 : va_list v;
286 138 : va_start(v, fmt);
287 804 : for (; *fmt; ++fmt) {
288 666 : unsigned n = va_arg(v, unsigned);
289 666 : int i, l = 2;
290 :
291 666 : assert(p - out + 8 < sizeof(out));
292 666 : switch (*fmt) {
293 198 : case 'l':
294 198 : l += 2;
295 666 : case 's':
296 2394 : for (i = 0; i < l; ++i) {
297 1728 : sprintf(p, "%02X", (n >> (8*(big_endian ? l-1-i : i))) & 0xffu);
298 1728 : p += 2;
299 : }
300 : break;
301 : default:
302 0 : assert(0);
303 : }
304 : }
305 138 : *p = 0;
306 138 : va_end(v);
307 138 : return out;
308 : }
309 :
310 : static void
311 54 : AllTests(void)
312 : {
313 : struct tm *ltime;
314 : char buf[80];
315 : time_t curr_time;
316 :
317 : SQLINTEGER y, m, d;
318 : char date[128];
319 :
320 54 : printf("use_cursors %d exec_direct %d prepare_before %d\n", use_cursors, exec_direct, prepare_before);
321 :
322 : /* test some NULLs */
323 54 : NullInput(SQL_C_CHAR, SQL_VARCHAR, "VARCHAR(100)");
324 54 : NullInput(SQL_C_CHAR, SQL_LONGVARCHAR, "TEXT");
325 54 : NullInput(SQL_C_LONG, SQL_INTEGER, "INTEGER");
326 54 : NullInput(SQL_C_LONG, SQL_LONGVARCHAR, "TEXT");
327 54 : NullInput(SQL_C_TYPE_TIMESTAMP, SQL_TYPE_TIMESTAMP, "DATETIME");
328 54 : NullInput(SQL_C_FLOAT, SQL_REAL, "FLOAT");
329 54 : NullInput(SQL_C_NUMERIC, SQL_LONGVARCHAR, "TEXT");
330 54 : if (odbc_db_is_microsoft() && odbc_db_version_int() >= 0x08000000u)
331 48 : NullInput(SQL_C_BIT, SQL_BIT, "BIT");
332 54 : NullInput(SQL_C_DOUBLE, SQL_DOUBLE, "MONEY");
333 :
334 : /* FIXME why should return 38 0 as precision and scale ?? correct ?? */
335 54 : precision = 18;
336 54 : TestOutput("NUMERIC(18,2)", "123", SQL_C_NUMERIC, SQL_NUMERIC, "18 0 1 7B");
337 54 : TestOutput("DECIMAL(18,2)", "123", SQL_C_NUMERIC, SQL_DECIMAL, "18 0 1 7B");
338 54 : precision = 38;
339 54 : TestOutput("NUMERIC(18,2)", "123", SQL_C_NUMERIC, SQL_NUMERIC, "38 0 1 7B");
340 54 : TestInput(SQL_C_LONG, "INTEGER", SQL_VARCHAR, "VARCHAR(20)", "12345");
341 54 : TestInput(SQL_C_LONG, "INTEGER", SQL_LONGVARCHAR, "TEXT", "12345");
342 : /*
343 : * MS driver behavior for output parameters is different
344 : * former returns "313233" while newer "333133323333"
345 : */
346 54 : if (odbc_driver_is_freetds())
347 54 : TestOutput("VARCHAR(20)", "313233", SQL_C_BINARY, SQL_VARCHAR, "333133323333");
348 :
349 54 : only_test = 1;
350 54 : precision = 3;
351 54 : if (TestOutput("DATETIME", "2004-02-24 15:16:17", SQL_C_BINARY, SQL_TIMESTAMP, pack("ssssssl", 2004, 2, 24, 15, 16, 17, 0))) {
352 : /* FIXME our driver ignore precision for date */
353 30 : precision = 3;
354 : /* Some MS driver incorrectly prepare with smalldatetime*/
355 30 : if (!use_cursors || odbc_driver_is_freetds()) {
356 30 : TestOutput("DATETIME", "2004-02-24 15:16:17", SQL_C_BINARY, SQL_TIMESTAMP, pack("ll", 0x9497, 0xFBAA2C));
357 : }
358 30 : TestOutput("SMALLDATETIME", "2004-02-24 15:16:17", SQL_C_BINARY, SQL_TIMESTAMP, pack("ll", 0x9497, 0xFB9640));
359 : } else {
360 24 : TestOutput("SMALLDATETIME", "2004-02-24 15:16:17", SQL_C_BINARY, SQL_TIMESTAMP, pack("ssssssl", 2004, 2, 24, 15, 16, 0, 0));
361 : }
362 54 : TestInput(SQL_C_TYPE_TIMESTAMP, "DATETIME", SQL_TYPE_TIMESTAMP, "DATETIME", "2005-07-22 09:51:34");
363 :
364 : /* test timestamp millisecond round off */
365 54 : TestInput(SQL_C_TYPE_TIMESTAMP, "DATETIME", SQL_TYPE_TIMESTAMP, "DATETIME", "2005-07-22 09:51:34.001 -> 2005-07-22 09:51:34.000");
366 54 : TestInput(SQL_C_TYPE_TIMESTAMP, "DATETIME", SQL_TYPE_TIMESTAMP, "DATETIME", "2005-07-22 09:51:34.002 -> 2005-07-22 09:51:34.003");
367 54 : TestInput(SQL_C_TYPE_TIMESTAMP, "DATETIME", SQL_TYPE_TIMESTAMP, "DATETIME", "2005-07-22 09:51:34.003 -> 2005-07-22 09:51:34.003");
368 54 : TestInput(SQL_C_TYPE_TIMESTAMP, "DATETIME", SQL_TYPE_TIMESTAMP, "DATETIME", "2005-07-22 09:51:34.004 -> 2005-07-22 09:51:34.003");
369 54 : TestInput(SQL_C_TYPE_TIMESTAMP, "DATETIME", SQL_TYPE_TIMESTAMP, "DATETIME", "2005-07-22 09:51:34.005 -> 2005-07-22 09:51:34.007");
370 54 : TestInput(SQL_C_TYPE_TIMESTAMP, "DATETIME", SQL_TYPE_TIMESTAMP, "DATETIME", "2005-07-22 09:51:34.006 -> 2005-07-22 09:51:34.007");
371 :
372 : /* FIXME on ms driver first SQLFetch return SUCCESS_WITH_INFO for truncation error */
373 54 : TestInput(SQL_C_TYPE_DATE, "DATETIME", SQL_TYPE_TIMESTAMP, "DATETIME", "2005-07-22 13:02:03 -> 2005-07-22 00:00:00");
374 :
375 : /* replace date information with current date */
376 54 : time(&curr_time);
377 54 : ltime = localtime(&curr_time);
378 54 : y = ltime->tm_year + 1900;
379 54 : m = ltime->tm_mon + 1;
380 54 : d = ltime->tm_mday;
381 : /* server concept of data can be different so try ask to server */
382 54 : odbc_command("SELECT GETDATE()");
383 54 : SQLBindCol(odbc_stmt, 1, SQL_C_CHAR, date, sizeof(date), NULL);
384 54 : if (SQLFetch(odbc_stmt) == SQL_SUCCESS) {
385 : int a, b, c;
386 54 : if (sscanf(date, "%d-%d-%d", &a, &b, &c) == 3) {
387 54 : y = a;
388 54 : m = b;
389 54 : d = c;
390 : }
391 : }
392 54 : SQLFetch(odbc_stmt);
393 54 : SQLMoreResults(odbc_stmt);
394 54 : SQLFreeStmt(odbc_stmt, SQL_UNBIND);
395 54 : sprintf(buf, "2003-07-22 13:02:03 -> %04d-%02d-%02d 13:02:03", (int) y, (int) m, (int) d);
396 54 : TestInput(SQL_C_TYPE_TIME, "DATETIME", SQL_TYPE_TIMESTAMP, "DATETIME", buf);
397 :
398 54 : TestInput(SQL_C_FLOAT, "FLOAT", SQL_REAL, "FLOAT", "1234.25");
399 54 : TestInput(SQL_C_DOUBLE, "REAL", SQL_REAL, "FLOAT", "-1234.25");
400 54 : TestInput(SQL_C_FLOAT, "REAL", SQL_REAL, "FLOAT", "1234.25");
401 54 : TestInput(SQL_C_DOUBLE, "FLOAT", SQL_REAL, "FLOAT", "-1234.25");
402 54 : TestInput(SQL_C_FLOAT, "FLOAT", SQL_FLOAT, "FLOAT", "1234.25");
403 54 : TestInput(SQL_C_DOUBLE, "REAL", SQL_FLOAT, "FLOAT", "-1234.25");
404 54 : TestInput(SQL_C_FLOAT, "FLOAT", SQL_DOUBLE, "FLOAT", "1234.25");
405 54 : TestInput(SQL_C_DOUBLE, "REAL", SQL_DOUBLE, "FLOAT", "-1234.25");
406 :
407 54 : TestInput(SQL_C_UTINYINT, "TINYINT", SQL_TINYINT, "TINYINT", "231");
408 54 : TestInput(SQL_C_STINYINT, "SMALLINT", SQL_SMALLINT, "SMALLINT", "-123");
409 :
410 54 : TestInput(SQL_C_NUMERIC, "NUMERIC(20,3)", SQL_NUMERIC, "NUMERIC(20,3)", "765432.2 -> 765432");
411 54 : TestInput(SQL_C_NUMERIC, "NUMERIC(20,3)", SQL_VARCHAR, "VARCHAR(20)", "578246.234 -> 578246");
412 54 : TestInput(SQL_C_NUMERIC, "NUMERIC(20,3)", SQL_LONGVARCHAR, "TEXT", "578246.234 -> 578246");
413 :
414 54 : TestInput(SQL_C_CHAR, "VARCHAR(100)", SQL_VARBINARY, "VARBINARY(20)", "4145544F -> AETO");
415 54 : TestInput(SQL_C_CHAR, "TEXT COLLATE Latin1_General_CI_AS", SQL_VARBINARY, "VARBINARY(20)", "4145544F -> AETO");
416 54 : TestInput(SQL_C_CHAR, "VARCHAR(100)", SQL_LONGVARBINARY, "IMAGE", "4145544F -> AETO");
417 54 : TestInput(SQL_C_BINARY, "VARBINARY(100)", SQL_VARCHAR, "VARCHAR(20)", "0x4145544F -> AETO");
418 54 : TestInput(SQL_C_BINARY, "IMAGE", SQL_VARCHAR, "VARCHAR(20)", "0x4145544F -> AETO");
419 :
420 54 : TestInput(SQL_C_BIT, "BIT", SQL_BIT, "BIT", "0");
421 54 : TestInput(SQL_C_BIT, "BIT", SQL_BIT, "BIT", "1");
422 :
423 54 : TestInput(SQL_C_DOUBLE, "MONEY", SQL_DOUBLE, "MONEY", "123.34");
424 :
425 54 : TestInput(SQL_C_CHAR, "VARCHAR(20)", SQL_VARCHAR, "VARCHAR(20)", "1EasyTest");
426 54 : TestInput(SQL_C_CHAR, "VARCHAR(20)", SQL_LONGVARCHAR, "TEXT", "1EasyTest");
427 54 : TestInput(SQL_C_WCHAR, "VARCHAR(10)", SQL_VARCHAR, "VARCHAR(10)", "Test 12345");
428 54 : TestInput(SQL_C_WCHAR, "VARCHAR(10)", SQL_LONGVARCHAR, "TEXT", "Test 12345");
429 : /* TODO use collate in syntax if available */
430 54 : TestInput(SQL_C_CHAR, "VARCHAR(20)", SQL_VARCHAR, "VARCHAR(20)", "me\xf4");
431 54 : TestInput(SQL_C_CHAR, "VARCHAR(20)", SQL_LONGVARCHAR, "TEXT", "me\xf4");
432 :
433 54 : precision = 6;
434 : /* output from char with conversions */
435 54 : TestOutput("VARCHAR(20)", "foo test", SQL_C_CHAR, SQL_VARCHAR, "6 foo te");
436 : /* TODO use collate in syntax if available */
437 : /* while usually on Microsoft database this encoding is valid on Sybase the database
438 : * could use UTF-8 encoding where \xf8\xf9 is an invalid encoded string */
439 54 : if (odbc_db_is_microsoft() && odbc_tds_version() > 0x700)
440 48 : TestOutput("VARCHAR(20) COLLATE Latin1_General_CI_AS", "NCHAR(0xf8) + NCHAR(0xf9)", SQL_C_CHAR, SQL_VARCHAR, "2 \xf8\xf9");
441 :
442 : /* MSSQL 2000 using ptotocol 7.1+ */
443 54 : if ((odbc_db_is_microsoft() && odbc_db_version_int() >= 0x08000000u && odbc_tds_version() > 0x700)
444 6 : || (!odbc_db_is_microsoft() && strncmp(odbc_db_version(), "15.00.", 6) >= 0)) {
445 54 : TestOutput("BIGINT", "-987654321065432", SQL_C_BINARY, SQL_BIGINT, big_endian ? "FFFC7DBBCF083228" : "283208CFBB7DFCFF");
446 54 : TestInput(SQL_C_SBIGINT, "BIGINT", SQL_BIGINT, "BIGINT", "-12345678901234");
447 : }
448 : /* MSSQL 2000 */
449 54 : if (odbc_db_is_microsoft() && odbc_db_version_int() >= 0x08000000u) {
450 48 : TestInput(SQL_C_CHAR, "NVARCHAR(100)", SQL_WCHAR, "NVARCHAR(100)", "test");
451 48 : TestInput(SQL_C_CHAR, "NVARCHAR(100)", SQL_WLONGVARCHAR, "NTEXT", "test");
452 : /* test for invalid stream due to truncation*/
453 48 : TestInput(SQL_C_CHAR, "NVARCHAR(100)", SQL_WCHAR, "NVARCHAR(100)", "01234567890");
454 48 : TestInput(SQL_C_CHAR, "NVARCHAR(100)", SQL_WLONGVARCHAR, "NTEXT", "01234567890");
455 : #ifdef ENABLE_DEVELOPING
456 : check_truncation = 1;
457 : TestInput(SQL_C_CHAR, "NVARCHAR(100)", SQL_WCHAR, "NVARCHAR(100)", "012345678901234567890");
458 : check_truncation = 1;
459 : TestInput(SQL_C_CHAR, "NVARCHAR(100)", SQL_WLONGVARCHAR, "NTEXT", "012345678901234567890");
460 : #endif
461 48 : TestInput(SQL_C_CHAR, "NVARCHAR(100)", SQL_WCHAR, "NVARCHAR(100)", "\xa3h\xf9 -> 0xA3006800f900");
462 48 : TestInput(SQL_C_CHAR, "NVARCHAR(100)", SQL_WLONGVARCHAR, "NTEXT", "\xa3h\xf9 -> 0xA3006800f900");
463 48 : TestInput(SQL_C_CHAR, "NVARCHAR(100)", SQL_WCHAR, "NVARCHAR(100)", "0xA3006800f900 -> \xa3h\xf9");
464 48 : TestInput(SQL_C_CHAR, "NVARCHAR(100)", SQL_WLONGVARCHAR, "NTEXT", "0xA3006800f900 -> \xa3h\xf9");
465 :
466 48 : TestInput(SQL_C_LONG, "INT", SQL_WVARCHAR, "NVARCHAR(100)", "45236");
467 48 : TestInput(SQL_C_LONG, "INT", SQL_WLONGVARCHAR, "NTEXT", "45236");
468 :
469 48 : precision = 6;
470 48 : TestOutput("NVARCHAR(20)", "foo test", SQL_C_CHAR, SQL_WVARCHAR, "6 foo te");
471 48 : precision = 12;
472 48 : TestOutput("NVARCHAR(20)", "foo test", SQL_C_CHAR, SQL_WVARCHAR, "8 foo test");
473 : /* TODO use collate in syntax if available */
474 48 : TestOutput("NVARCHAR(20)", "0xf800f900", SQL_C_CHAR, SQL_WVARCHAR, "2 \xf8\xf9");
475 :
476 48 : TestInput(SQL_C_WCHAR, "NVARCHAR(10)", SQL_WVARCHAR, "NVARCHAR(10)", "1EasyTest2");
477 48 : TestInput(SQL_C_WCHAR, "NVARCHAR(10)", SQL_WLONGVARCHAR, "NTEXT", "1EasyTest2");
478 48 : use_nts = 1;
479 48 : TestInput(SQL_C_WCHAR, "NVARCHAR(10)", SQL_WVARCHAR, "NVARCHAR(10)", "1EasyTest3");
480 48 : use_nts = 1;
481 48 : TestInput(SQL_C_WCHAR, "NVARCHAR(10)", SQL_WLONGVARCHAR, "NTEXT", "1EasyTest3");
482 48 : TestInput(SQL_C_WCHAR, "NVARCHAR(3)", SQL_WVARCHAR, "NVARCHAR(3)", "0xf800a300bc06");
483 48 : TestInput(SQL_C_WCHAR, "NVARCHAR(3)", SQL_WLONGVARCHAR, "NTEXT", "0xf800a300bc06");
484 :
485 48 : TestInput(SQL_C_WCHAR, "NVARCHAR(10)", SQL_INTEGER, "INT", " -423785 -> -423785");
486 :
487 48 : TestInput(SQL_C_CHAR, "NVARCHAR(100)", SQL_VARBINARY, "VARBINARY(20)", "4145544F -> AETO");
488 48 : TestInput(SQL_C_CHAR, "NTEXT COLLATE Latin1_General_CI_AS", SQL_VARBINARY, "VARBINARY(20)", "4145544F -> AETO");
489 :
490 48 : TestInput(SQL_C_BINARY, "VARBINARY(100)", SQL_WVARCHAR, "NVARCHAR(20)", "0x4100450054004F00 -> AETO");
491 48 : TestInput(SQL_C_BINARY, "IMAGE", SQL_WVARCHAR, "NVARCHAR(20)", "0x4100450054004F00 -> AETO");
492 : }
493 : /* MSSQL 2005 */
494 54 : if (odbc_db_is_microsoft() && odbc_db_version_int() >= 0x09000000u) {
495 36 : TestInput(SQL_C_CHAR, "VARCHAR(20)", SQL_LONGVARCHAR, "VARCHAR(MAX)", "1EasyTest");
496 36 : TestInput(SQL_C_BINARY, "VARBINARY(20)", SQL_LONGVARBINARY, "VARBINARY(MAX)", "Anything will suite!");
497 36 : TestInput(SQL_C_CHAR, "MONEY", SQL_VARCHAR, "MONEY", "123.3456");
498 : }
499 : /* MSSQL 2008 */
500 54 : if (odbc_db_is_microsoft() && odbc_db_version_int() >= 0x0a000000u) {
501 24 : TestInput(SQL_C_TYPE_DATE, "DATE", SQL_TYPE_DATE, "DATE", "2005-07-22");
502 24 : TestInput(SQL_C_TYPE_TIME, "TIME", SQL_TYPE_TIME, "TIME", "13:02:03");
503 : }
504 :
505 : /* Sybase */
506 54 : if (!odbc_db_is_microsoft()) {
507 6 : TestInput(SQL_C_CHAR, "UNIVARCHAR(100)", SQL_WCHAR, "UNIVARCHAR(100)", "test");
508 6 : TestInput(SQL_C_WCHAR, "UNIVARCHAR(100)", SQL_WCHAR, "UNIVARCHAR(100)", "test");
509 6 : TestInput(SQL_C_CHAR, "UNIVARCHAR(100)", SQL_WVARCHAR, "UNIVARCHAR(100)", "test");
510 6 : TestInput(SQL_C_WCHAR, "UNIVARCHAR(100)", SQL_WVARCHAR, "UNIVARCHAR(100)", "test");
511 : }
512 54 : }
513 :
514 10 : TEST_MAIN()
515 : {
516 10 : odbc_use_version3 = 1;
517 10 : odbc_conn_additional_params = "ClientCharset=ISO-8859-1;";
518 :
519 10 : odbc_connect();
520 :
521 10 : if (((char *) &big_endian)[0] == 1)
522 10 : big_endian = 0;
523 :
524 28 : for (use_cursors = 0; use_cursors <= 1; ++use_cursors) {
525 20 : if (use_cursors) {
526 10 : if (!tds_no_dm || !odbc_driver_is_freetds())
527 0 : odbc_reset_statement();
528 : /* if connection does not support cursors returns success */
529 10 : setenv("TDS_SKIP_SUCCESS", "1", 1);
530 10 : odbc_check_cursor();
531 : }
532 :
533 18 : exec_direct = 1;
534 18 : AllTests();
535 :
536 18 : exec_direct = 0;
537 18 : prepare_before = 1;
538 18 : AllTests();
539 :
540 18 : prepare_before = 0;
541 18 : AllTests();
542 : }
543 :
544 8 : odbc_disconnect();
545 :
546 8 : printf("Done successfully!\n");
547 8 : return 0;
548 : }
549 :
|