Line data Source code
1 : #include "common.h"
2 : #include <assert.h>
3 :
4 : /* Test using array binding */
5 :
6 : static SQLTCHAR *test_query = NULL;
7 : static int multiply = 90;
8 : static int failure = 0;
9 :
10 : #define XMALLOC_N(t, n) (t*) ODBC_GET(n*sizeof(t))
11 :
12 : static void
13 62 : query_test(int prepare, SQLRETURN expected, const char *expected_status)
14 : {
15 : #define DESC_LEN 51
16 : #define ARRAY_SIZE 10
17 :
18 62 : SQLUINTEGER *ids = XMALLOC_N(SQLUINTEGER,ARRAY_SIZE);
19 : typedef SQLCHAR desc_t[DESC_LEN];
20 62 : desc_t *descs = XMALLOC_N(desc_t, ARRAY_SIZE);
21 62 : SQLLEN *id_lens = XMALLOC_N(SQLLEN,ARRAY_SIZE), *desc_lens = XMALLOC_N(SQLLEN,ARRAY_SIZE);
22 62 : SQLUSMALLINT i, *statuses = XMALLOC_N(SQLUSMALLINT,ARRAY_SIZE);
23 62 : unsigned *num_errors = XMALLOC_N(unsigned, ARRAY_SIZE);
24 : SQLULEN processed;
25 : RETCODE ret;
26 : char status[20];
27 62 : SQLTCHAR *err = (SQLTCHAR *) ODBC_GET(sizeof(odbc_err)*sizeof(SQLTCHAR));
28 62 : SQLTCHAR *state = (SQLTCHAR *) ODBC_GET(sizeof(odbc_sqlstate)*sizeof(SQLTCHAR));
29 :
30 62 : assert(odbc_stmt != SQL_NULL_HSTMT);
31 62 : odbc_reset_statement();
32 :
33 62 : odbc_command("create table #tmp1 (id tinyint, value char(20))");
34 :
35 62 : SQLSetStmtAttr(odbc_stmt, SQL_ATTR_PARAM_BIND_TYPE, SQL_PARAM_BIND_BY_COLUMN, 0);
36 62 : SQLSetStmtAttr(odbc_stmt, SQL_ATTR_PARAMSET_SIZE, (void *) ARRAY_SIZE, 0);
37 62 : SQLSetStmtAttr(odbc_stmt, SQL_ATTR_PARAM_STATUS_PTR, statuses, 0);
38 62 : SQLSetStmtAttr(odbc_stmt, SQL_ATTR_PARAMS_PROCESSED_PTR, &processed, 0);
39 62 : SQLBindParameter(odbc_stmt, 1, SQL_PARAM_INPUT, SQL_C_ULONG, SQL_INTEGER, 5, 0, ids, 0, id_lens);
40 62 : SQLBindParameter(odbc_stmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, DESC_LEN - 1, 0, descs, DESC_LEN, desc_lens);
41 :
42 62 : processed = ARRAY_SIZE + 1;
43 682 : for (i = 0; i < ARRAY_SIZE; i++) {
44 620 : statuses[i] = SQL_PARAM_DIAG_UNAVAILABLE;
45 620 : ids[i] = (i + 1) * multiply;
46 620 : sprintf((char *) descs[i], "data %d \xf4", i * 7);
47 620 : id_lens[i] = 0;
48 620 : desc_lens[i] = SQL_NTS;
49 620 : num_errors[i] = 0;
50 : }
51 62 : multiply = 90;
52 :
53 62 : if (!prepare) {
54 32 : ret = SQLExecDirect(odbc_stmt, test_query, SQL_NTS);
55 : } else {
56 30 : SQLPrepare(odbc_stmt, test_query, SQL_NTS);
57 30 : ret = SQLExecute(odbc_stmt);
58 : }
59 :
60 62 : if (processed > ARRAY_SIZE) {
61 : char buf[256];
62 :
63 0 : sprintf(buf, "Invalid processed number: %d", (int) processed);
64 0 : ODBC_REPORT_ERROR(buf);
65 : }
66 :
67 732 : for (i = 1; CHKGetDiagRec(SQL_HANDLE_STMT, odbc_stmt, i, state, NULL, err, sizeof(odbc_err), NULL, "SINo") != SQL_NO_DATA; ++i) {
68 : SQLINTEGER row;
69 :
70 732 : strcpy(odbc_err, C(err));
71 732 : strcpy(odbc_sqlstate, C(state));
72 732 : CHKGetDiagField(SQL_HANDLE_STMT, odbc_stmt, i, SQL_DIAG_ROW_NUMBER, &row, sizeof(row), NULL, "S");
73 :
74 732 : if (row == SQL_ROW_NUMBER_UNKNOWN) continue;
75 732 : if (row < 1 || row > ARRAY_SIZE) {
76 0 : fprintf(stderr, "invalid row %d returned reading error number %d\n", (int) row, i);
77 0 : exit(1);
78 : }
79 732 : ++num_errors[row-1];
80 732 : printf("for row %2d returned '%s' %s\n", (int) row, odbc_sqlstate, odbc_err);
81 : }
82 :
83 620 : for (i = 0; i < processed; ++i) {
84 620 : int has_diag = 0;
85 :
86 620 : switch (statuses[i]) {
87 : case SQL_PARAM_SUCCESS_WITH_INFO:
88 0 : has_diag = 1;
89 : case SQL_PARAM_SUCCESS:
90 254 : status[i] = 'V';
91 : break;
92 :
93 366 : case SQL_PARAM_ERROR:
94 366 : has_diag = 1;
95 366 : status[i] = '!';
96 : break;
97 :
98 0 : case SQL_PARAM_UNUSED:
99 0 : status[i] = ' ';
100 : break;
101 :
102 0 : case SQL_PARAM_DIAG_UNAVAILABLE:
103 0 : status[i] = '?';
104 : break;
105 0 : default:
106 0 : fprintf(stderr, "Invalid status returned %d\n", statuses[i]);
107 0 : exit(1);
108 : }
109 :
110 : if (has_diag) {
111 366 : if (!num_errors[i]) {
112 0 : fprintf(stderr, "Diagnostics not returned for status %d\n", i);
113 0 : failure = 1;
114 : }
115 : } else {
116 254 : if (num_errors[i]) {
117 0 : fprintf(stderr, "Diagnostics returned for status %d\n", i);
118 0 : failure = 1;
119 : }
120 : }
121 : }
122 62 : status[i] = 0;
123 :
124 62 : if (ret != expected || strcmp(expected_status, status) != 0) {
125 0 : fprintf(stderr, "Invalid result: got %d \"%s\" expected %d \"%s\" processed %d\n",
126 : ret, status, expected, expected_status, (int) processed);
127 0 : if (ret != SQL_SUCCESS)
128 0 : odbc_read_error();
129 0 : failure = 1;
130 : }
131 :
132 62 : odbc_reset_statement();
133 :
134 62 : odbc_command_with_result(odbc_stmt, "drop table #tmp1");
135 62 : }
136 :
137 : int
138 8 : main(void)
139 : {
140 8 : odbc_use_version3 = 1;
141 8 : odbc_conn_additional_params = "ClientCharset=ISO-8859-1;";
142 8 : odbc_connect();
143 :
144 8 : if (odbc_db_is_microsoft()) {
145 : /* all successes */
146 6 : test_query = T("INSERT INTO #tmp1 (id, value) VALUES (?, ?)");
147 6 : multiply = 1;
148 6 : query_test(0, SQL_SUCCESS, "VVVVVVVVVV");
149 6 : multiply = 1;
150 6 : query_test(1, SQL_SUCCESS, "VVVVVVVVVV");
151 :
152 : /* all errors */
153 6 : test_query = T("INSERT INTO #tmp1 (id, value) VALUES (?, ?)");
154 6 : multiply = 257;
155 6 : query_test(0, SQL_ERROR, "!!!!!!!!!!");
156 6 : multiply = 257;
157 6 : query_test(1, SQL_SUCCESS_WITH_INFO, "!!!!!!!!!!");
158 :
159 6 : test_query = T("INSERT INTO #tmp1 (id, value) VALUES (?, ?)");
160 6 : query_test(0, SQL_ERROR, "VV!!!!!!!!");
161 6 : query_test(1, SQL_SUCCESS_WITH_INFO, "VV!!!!!!!!");
162 :
163 6 : test_query = T("INSERT INTO #tmp1 (id, value) VALUES (900-?, ?)");
164 6 : query_test(0, SQL_SUCCESS_WITH_INFO, "!!!!!!!VVV");
165 6 : query_test(1, SQL_SUCCESS_WITH_INFO, "!!!!!!!VVV");
166 :
167 6 : test_query = T("INSERT INTO #tmp1 (id) VALUES (?) UPDATE #tmp1 SET value = ?");
168 6 : query_test(0, SQL_SUCCESS_WITH_INFO, "VVVV!V!V!V");
169 6 : query_test(1, SQL_SUCCESS_WITH_INFO, "VV!!!!!!!!");
170 :
171 : #ifdef ENABLE_DEVELOPING
172 : /* with result, see how SQLMoreResult work */
173 : test_query = T("INSERT INTO #tmp1 (id) VALUES (?) SELECT * FROM #tmp1 UPDATE #tmp1 SET value = ?");
174 : /* IMHO our driver is better here -- freddy77 */
175 : query_test(0, SQL_SUCCESS, odbc_driver_is_freetds() ? "VVVVV!V!V!" : "VVVVVV!VVV");
176 : query_test(1, SQL_SUCCESS, "VVVVVVVVVV");
177 : #endif
178 : } else {
179 : /* Sybase test for conversions before executing */
180 2 : test_query = T("INSERT INTO #tmp1 (id, value) VALUES (?/8, ?)");
181 2 : query_test(0, SQL_SUCCESS, "VVVVVVVVVV");
182 : }
183 :
184 : /* TODO record binding, array fetch, sqlputdata */
185 :
186 8 : odbc_disconnect();
187 :
188 8 : printf(failure ? "Failed :(\n" : "Success!\n");
189 8 : return failure;
190 : }
191 :
|