Line data Source code
1 : #include "common.h"
2 :
3 : /* test binding with UTF-8 encoding */
4 :
5 : #ifndef _WIN32
6 : /* test table name, it contains two japanese characters */
7 : static const char table_name[] = "mytab\xe7\x8e\x8b\xe9\xb4\xbb";
8 :
9 : static const char * const strings[] = {
10 : /* ascii */
11 : "aaa", "aaa",
12 : /* latin 1*/
13 : "abc\xc3\xa9\xc3\xa1\xc3\xb4", "abc\xc3\xa9\xc3\xae\xc3\xb4",
14 : /* Japanese... */
15 : "abc\xe7\x8e\x8b\xe9\xb4\xbb", "abc\xe7\x8e\x8b\xe9\xb4\xbb\xe5\x82\x91\xe7\x8e\x8b\xe9\xb4\xbb\xe5\x82\x91",
16 : NULL, NULL
17 : };
18 :
19 : /* same strings in hex */
20 : static const char * const strings_hex[] = {
21 : /* ascii */
22 : "0x610061006100", "0x610061006100",
23 : /* latin 1*/
24 : "0x610062006300e900e100f400", "0x610062006300e900ee00f400",
25 : /* Japanese... */
26 : "0x6100620063008b733b9d", "0x6100620063008b733b9d91508b733b9d9150",
27 : NULL, NULL
28 : };
29 :
30 : static char tmp[1024*3];
31 :
32 : static void
33 12 : TestBinding(int minimun)
34 : {
35 : const char * const*p;
36 : SQLINTEGER n;
37 : SQLLEN n_len;
38 :
39 12 : sprintf(tmp, "DELETE FROM %s", table_name);
40 12 : odbc_command(tmp);
41 :
42 : /* insert with SQLPrepare/SQLBindParameter/SQLExecute */
43 12 : sprintf(tmp, "INSERT INTO %s VALUES(?,?,?)", table_name);
44 12 : CHKPrepare(T(tmp), SQL_NTS, "S");
45 12 : CHKBindParameter(1, SQL_PARAM_INPUT, SQL_C_LONG,
46 : SQL_INTEGER, 0, 0, &n, 0, &n_len, "S");
47 12 : n_len = sizeof(n);
48 :
49 48 : for (n = 1, p = strings; p[0] && p[1]; p += 2, ++n) {
50 : SQLLEN s1_len, s2_len;
51 : unsigned int len;
52 :
53 36 : len = minimun ? (strlen(strings_hex[p-strings]) - 2) /4 : 40;
54 36 : CHKBindParameter(2, SQL_PARAM_INPUT, SQL_C_CHAR,
55 : SQL_WCHAR, len, 0, (void *) p[0], 0, &s1_len, "S");
56 36 : len = minimun ? (strlen(strings_hex[p+1-strings]) - 2) /4 : 40;
57 : /* FIXME this with SQL_VARCHAR produce wrong protocol data */
58 36 : CHKBindParameter(3, SQL_PARAM_INPUT, SQL_C_CHAR,
59 : SQL_WVARCHAR, len, 0, (void *) p[1], 0, &s2_len, "S");
60 36 : s1_len = strlen(p[0]);
61 36 : s2_len = strlen(p[1]);
62 36 : printf("insert #%d\n", (int) n);
63 36 : CHKExecute("S");
64 : }
65 :
66 : /* check rows */
67 48 : for (n = 1, p = strings_hex; p[0] && p[1]; p += 2, ++n) {
68 36 : sprintf(tmp, "IF NOT EXISTS(SELECT * FROM %s WHERE k = %d AND c = %s AND vc = %s) SELECT 1", table_name, (int) n, p[0], p[1]);
69 36 : odbc_check_no_row(tmp);
70 : }
71 :
72 12 : odbc_reset_statement();
73 12 : }
74 :
75 : int
76 8 : main(int argc, char *argv[])
77 : {
78 : const char * const*p;
79 : SQLINTEGER n;
80 :
81 8 : odbc_use_version3 = 1;
82 8 : odbc_conn_additional_params = "ClientCharset=UTF-8;";
83 :
84 8 : odbc_connect();
85 8 : if (!odbc_driver_is_freetds()) {
86 0 : odbc_disconnect();
87 0 : printf("Driver is not FreeTDS, exiting\n");
88 0 : odbc_test_skipped();
89 0 : return 0;
90 : }
91 :
92 8 : if (!odbc_db_is_microsoft() || odbc_db_version_int() < 0x08000000u) {
93 2 : odbc_disconnect();
94 2 : printf("Test for MSSQL only\n");
95 2 : odbc_test_skipped();
96 0 : return 0;
97 : }
98 :
99 6 : CHKAllocStmt(&odbc_stmt, "S");
100 :
101 : /* create test table */
102 6 : sprintf(tmp, "IF OBJECT_ID(N'%s') IS NOT NULL DROP TABLE %s", table_name, table_name);
103 6 : odbc_command(tmp);
104 6 : sprintf(tmp, "CREATE TABLE %s (k int, c NCHAR(10), vc NVARCHAR(10))", table_name);
105 6 : odbc_command(tmp);
106 :
107 : /* insert with INSERT statements */
108 24 : for (n = 1, p = strings; p[0] && p[1]; p += 2, ++n) {
109 18 : sprintf(tmp, "INSERT INTO %s VALUES (%d,N'%s',N'%s')", table_name, (int) n, p[0], p[1]);
110 18 : odbc_command(tmp);
111 : }
112 :
113 : /* check rows */
114 18 : for (n = 1, p = strings_hex; p[0] && p[1]; p += 2, ++n) {
115 18 : sprintf(tmp, "IF NOT EXISTS(SELECT * FROM %s WHERE k = %d AND c = %s AND vc = %s) SELECT 1", table_name, (int) n, p[0], p[1]);
116 18 : odbc_check_no_row(tmp);
117 : }
118 :
119 6 : TestBinding(0);
120 :
121 6 : TestBinding(1);
122 :
123 : /* cleanup */
124 6 : sprintf(tmp, "IF OBJECT_ID(N'%s') IS NOT NULL DROP TABLE %s", table_name, table_name);
125 6 : odbc_command(tmp);
126 :
127 6 : odbc_disconnect();
128 6 : printf("Done.\n");
129 6 : return 0;
130 : }
131 :
132 : #else
133 :
134 : int
135 : main(void)
136 : {
137 : /* on Windows SQLExecDirect is always converted to SQLExecDirectW by the DM */
138 : printf("Not possible for this platform.\n");
139 : odbc_test_skipped();
140 : return 0;
141 : }
142 : #endif
|