Line data Source code
1 : #include "common.h"
2 : #include <freetds/macros.h>
3 :
4 : /* test conversion of Hebrew characters (which have shift sequences) */
5 :
6 : static const char * const column_names[] = {
7 : "hebrew",
8 : "cn"
9 : };
10 :
11 : typedef struct {
12 : /* number of column */
13 : int num;
14 : /* hex representation, used during insert */
15 : const char *hex;
16 : /* output */
17 : const char *out;
18 : } column_t;
19 :
20 : static const column_t columns[] = {
21 : { 0, "0xde05d905d305e205", "\xd7\x9e\xd7\x99\xd7\x93\xd7\xa2" },
22 : { 0, "0x69006e0066006f00", "info", },
23 : { 0, "0xd805e705e105d805", "\xd7\x98\xd7\xa7\xd7\xa1\xd7\x98", },
24 : { 0, "0xd005d105db05", "\xd7\x90\xd7\x91\xd7\x9b", },
25 : { 1, "0xf78b7353d153278d3a00228c228c56e02000",
26 : "\xe8\xaf\xb7\xe5\x8d\xb3\xe5\x8f\x91\xe8\xb4\xa7\x3a\xe8\xb0\xa2\xe8\xb0\xa2\xee\x81\x96\x20", },
27 : { 0, NULL, NULL },
28 : };
29 :
30 : static void
31 0 : hexdump(FILE* fp, const char* prefix, const void* p, size_t n)
32 : {
33 0 : const unsigned char* cp = p;
34 :
35 0 : fprintf(fp, "%s", prefix);
36 0 : while (n--)
37 0 : fprintf(fp, "%02X", *cp++);
38 0 : fprintf(fp, "\n");
39 0 : }
40 :
41 10 : TEST_MAIN()
42 : {
43 : char tmp[1024];
44 : char out[TDS_VECTOR_SIZE(column_names)][32];
45 : SQLLEN n_len[TDS_VECTOR_SIZE(column_names)];
46 : const column_t *p;
47 : int n;
48 :
49 10 : odbc_conn_additional_params = "ClientCharset=UTF-8;";
50 :
51 10 : odbc_connect();
52 10 : if (!odbc_driver_is_freetds()) {
53 0 : odbc_disconnect();
54 0 : printf("Driver is not FreeTDS, exiting\n");
55 0 : odbc_test_skipped();
56 0 : return 0;
57 : }
58 :
59 10 : if (!odbc_db_is_microsoft() || odbc_db_version_int() < 0x08000000u || odbc_tds_version() < 0x701) {
60 2 : odbc_disconnect();
61 : /* protocol till 7.1 does not support telling encoding so we
62 : * cannot understand how the string is encoded
63 : */
64 2 : printf("Test for MSSQL only using protocol 7.1\n");
65 2 : odbc_test_skipped();
66 0 : return 0;
67 : }
68 :
69 8 : CHKAllocStmt(&odbc_stmt, "S");
70 :
71 : /* create test table */
72 8 : odbc_command("CREATE TABLE #tmp (i INT"
73 : ", hebrew VARCHAR(20) COLLATE Hebrew_CI_AI NULL"
74 : ", cn VARCHAR(20) COLLATE Chinese_PRC_CI_AS NULL"
75 : ")");
76 :
77 : /* insert with INSERT statements */
78 48 : for (n = 0, p = columns; p[n].hex; ++n) {
79 80 : sprintf(tmp, "INSERT INTO #tmp(i, %s) VALUES(%d, CAST(%s AS NVARCHAR(20)))",
80 40 : column_names[p[n].num], n+1, p[n].hex);
81 40 : odbc_command(tmp);
82 : }
83 :
84 : /* test conversions in libTDS
85 : *
86 : * Because column type is VARCHAR with collation defined, SQL Server
87 : * returns the data as CP1255 (hebrew) or GB18030 (CN), and FreeTDS's
88 : * built-in iconv doesn't support those. So you need iconv installed
89 : * in Windows to pass this test.
90 : *
91 : * Using NVARCHAR makes this test work with FreeTDS's built-in iconv
92 : * as it causes the server to return the data in wide characters.
93 : */
94 : #if HAVE_ICONV
95 8 : odbc_command("SELECT hebrew, cn FROM #tmp ORDER BY i");
96 : #else
97 : fprintf(stderr, "Bypassing Hebrew MBCS test since iconv not installed (Forcing server to send UTF-16).\n");
98 : odbc_command("SELECT CAST(hebrew AS NVARCHAR(20)), CAST(cn AS NVARCHAR(20)) FROM #tmp ORDER BY i");
99 : #endif
100 : /* select with SQLBindCol/SQLFetch */
101 24 : for (n = 0; n < TDS_VECTOR_SIZE(column_names); ++n)
102 16 : CHKBindCol(n+1, SQL_C_CHAR, out[n], sizeof(out[0]), &n_len[n], "S");
103 40 : for (n = 0, p = columns; p[n].hex; ++n) {
104 40 : memset(out, 0, sizeof(out));
105 40 : CHKFetch("S");
106 40 : if (n_len[p[n].num] != strlen(p[n].out) || strcmp(p[n].out, out[p[n].num]) != 0) {
107 0 : size_t len = strlen(p[n].out);
108 :
109 0 : fprintf(stderr, "Wrong row %d %s\n", n+1, out[p[n].num]);
110 0 : hexdump(stderr, "Expect: ", p[n].out, len);
111 0 : hexdump(stderr, "Got : ", out[p[n].num], strlen(out[p[n].num]));
112 0 : odbc_disconnect();
113 0 : return 1;
114 : }
115 : }
116 :
117 8 : odbc_disconnect();
118 8 : printf("Done.\n");
119 8 : return 0;
120 : }
121 :
|