Line data Source code
1 : #include "common.h"
2 :
3 : /* Test for {?=call store(?)} syntax and run */
4 :
5 : static void test_with_conversions(void);
6 : static void test_with_dbname(void);
7 :
8 10 : TEST_MAIN()
9 : {
10 : SQLINTEGER input, output;
11 : SQLLEN ind, ind2, ind3, ind4;
12 : SQLINTEGER out1;
13 : char out2[30];
14 :
15 10 : odbc_connect();
16 :
17 10 : odbc_command("IF OBJECT_ID('simpleresult') IS NOT NULL DROP PROC simpleresult");
18 :
19 10 : odbc_command("create proc simpleresult @i int as begin return @i end");
20 :
21 10 : CHKBindParameter(2, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &input, 0, &ind2, "S");
22 10 : CHKBindParameter(1, SQL_PARAM_OUTPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &output, 0, &ind, "S");
23 :
24 10 : CHKPrepare(T("{ \n?\t\r= call simpleresult(?)}"), SQL_NTS, "S");
25 :
26 10 : input = 123;
27 10 : ind2 = sizeof(input);
28 10 : output = 0xdeadbeef;
29 10 : CHKExecute("S");
30 :
31 10 : if (output != 123) {
32 0 : printf("Invalid result\n");
33 0 : exit(1);
34 : }
35 :
36 : /* should return "Invalid cursor state" */
37 10 : if (SQLFetch(odbc_stmt) != SQL_ERROR) {
38 0 : printf("Data not expected\n");
39 0 : exit(1);
40 : }
41 10 : ODBC_CHECK_COLS(0);
42 :
43 : /* just to reset some possible buffers */
44 10 : odbc_command("DECLARE @i INT");
45 :
46 : /* same test but with SQLExecDirect and same bindings */
47 10 : input = 567;
48 10 : ind2 = sizeof(input);
49 10 : output = 0xdeadbeef;
50 10 : CHKExecDirect(T("{?=call simpleresult(?)}"), SQL_NTS, "S");
51 :
52 10 : if (output != 567) {
53 0 : fprintf(stderr, "Invalid result\n");
54 0 : exit(1);
55 : }
56 :
57 : /* should return "Invalid cursor state" */
58 10 : CHKFetch("E");
59 :
60 10 : odbc_command("drop proc simpleresult");
61 :
62 10 : odbc_command("IF OBJECT_ID('simpleresult2') IS NOT NULL DROP PROC simpleresult2");
63 :
64 : /* force cursor close */
65 10 : SQLCloseCursor(odbc_stmt);
66 :
67 : /* test output parameter */
68 10 : odbc_command("create proc simpleresult2 @i int, @x int output, @y varchar(20) output as begin select @x = 6789 select @y = 'test foo' return @i end");
69 :
70 10 : CHKBindParameter(1, SQL_PARAM_OUTPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &output, 0, &ind, "S");
71 10 : CHKBindParameter(2, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &input, 0, &ind2, "S");
72 10 : CHKBindParameter(3, SQL_PARAM_OUTPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &out1, 0, &ind3, "S");
73 10 : CHKBindParameter(4, SQL_PARAM_OUTPUT, SQL_C_CHAR, SQL_VARCHAR, 20, 0, out2, sizeof(out2), &ind4, "S");
74 :
75 10 : CHKPrepare(T("{ \n?\t\r= call simpleresult2(?,?,?)}"), SQL_NTS, "S");
76 :
77 10 : input = 987;
78 10 : ind2 = sizeof(input);
79 10 : out1 = 888;
80 10 : output = 0xdeadbeef;
81 10 : ind3 = SQL_DATA_AT_EXEC;
82 10 : ind4 = SQL_DEFAULT_PARAM;
83 10 : strcpy(out2, "bad!");
84 10 : CHKExecute("S");
85 :
86 10 : if (output != 987 || ind3 <= 0 || ind4 <= 0 || out1 != 6789 || strcmp(out2, "test foo") != 0) {
87 0 : printf("ouput = %d ind3 = %d ind4 = %d out1 = %d out2 = %s\n", (int) output, (int) ind3, (int) ind4, (int) out1,
88 : out2);
89 0 : printf("Invalid result\n");
90 0 : exit(1);
91 : }
92 :
93 : /* should return "Invalid cursor state" */
94 10 : CHKFetch("E");
95 :
96 10 : ODBC_CHECK_COLS(0);
97 :
98 10 : odbc_command("drop proc simpleresult2");
99 :
100 : /*
101 : * test from shiv kumar
102 : * Cfr ML 2006-11-21 "specifying a 0 for the StrLen_or_IndPtr in the
103 : * SQLBindParameter call is not working on AIX"
104 : */
105 10 : odbc_command("IF OBJECT_ID('rpc_read') IS NOT NULL DROP PROC rpc_read");
106 :
107 10 : odbc_reset_statement();
108 :
109 10 : odbc_command("create proc rpc_read @i int, @x timestamp as begin select 1 return 1234 end");
110 10 : SQLCloseCursor(odbc_stmt);
111 :
112 10 : CHKPrepare(T("{ ? = CALL rpc_read ( ?, ? ) }"), SQL_NTS, "S");
113 :
114 10 : ind = 0;
115 10 : CHKBindParameter(1, SQL_PARAM_OUTPUT, SQL_C_LONG, SQL_INTEGER, 0, 0, &output, 0, &ind, "S");
116 :
117 10 : ind2 = 0;
118 10 : CHKBindParameter(2, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER, 0, 0, &input, 0, &ind2, "S");
119 :
120 10 : ind3 = 8;
121 10 : CHKBindParameter(3, SQL_PARAM_INPUT, SQL_C_BINARY, SQL_VARBINARY, 8, 0, out2, 8, &ind3, "S");
122 :
123 10 : CHKExecute("S");
124 :
125 10 : CHKFetch("S");
126 :
127 10 : CHKFetch("No");
128 :
129 10 : odbc_reset_statement();
130 10 : odbc_command("drop proc rpc_read");
131 :
132 : /*
133 : * Test from Joao Amaral
134 : * This test SQLExecute where a store procedure returns no result
135 : * This seems similar to a previous one but use set instead of select
136 : * (with is supported only by mssql and do not return all stuff as
137 : * select does)
138 : */
139 10 : if (odbc_db_is_microsoft()) {
140 :
141 8 : odbc_reset_statement();
142 :
143 8 : odbc_command("IF OBJECT_ID('sp_test') IS NOT NULL DROP PROC sp_test");
144 8 : odbc_command("create proc sp_test @res int output as set @res = 456");
145 :
146 8 : odbc_reset_statement();
147 :
148 8 : CHKPrepare(T("{ call sp_test(?)}"), SQL_NTS, "S");
149 8 : CHKBindParameter(1, SQL_PARAM_OUTPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &output, 0, &ind, "S");
150 :
151 8 : output = 0xdeadbeef;
152 8 : CHKExecute("S");
153 :
154 8 : if (output != 456) {
155 0 : fprintf(stderr, "Invalid result %d(%x)\n", (int) output, (int) output);
156 0 : return 1;
157 : }
158 8 : odbc_command("drop proc sp_test");
159 : }
160 10 : odbc_disconnect();
161 :
162 10 : if (odbc_db_is_microsoft()) {
163 8 : odbc_use_version3 = 1;
164 8 : odbc_connect();
165 :
166 8 : test_with_conversions();
167 8 : test_with_dbname();
168 8 : odbc_disconnect();
169 : }
170 :
171 10 : printf("Done.\n");
172 10 : return 0;
173 : }
174 :
175 : static void
176 8 : test_with_conversions(void)
177 : {
178 : SQLLEN ind, ind2, ind3;
179 : char out2[30];
180 :
181 : /*
182 : * test from Bower, Wayne
183 : * Cfr ML 2012-03-02 "[freetds] [unixODBC][Driver Manager]Function sequence error (SQL-HY010)"
184 : */
185 8 : odbc_command("IF OBJECT_ID('TMP_SP_Test_ODBC') IS NOT NULL DROP PROC TMP_SP_Test_ODBC");
186 8 : odbc_command("create proc TMP_SP_Test_ODBC @i int,\n@o int output\nas\nset nocount on\nselect @o = 55\nreturn 9\n");
187 8 : odbc_reset_statement();
188 :
189 8 : CHKPrepare(T("{ ? = call TMP_SP_Test_ODBC (?, ?) }"), SQL_NTS, "S");
190 :
191 8 : ind2 = 2;
192 8 : CHKBindParameter(2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, 80, 0, "10", 2, &ind2, "S");
193 8 : ind3 = SQL_NULL_DATA;
194 8 : strcpy(out2, " ");
195 8 : CHKBindParameter(3, SQL_PARAM_INPUT_OUTPUT, SQL_C_CHAR, SQL_VARCHAR, 0, 1, out2, 29, &ind3, "S");
196 8 : ind = 1;
197 8 : CHKBindParameter(1, SQL_PARAM_INPUT_OUTPUT, SQL_C_CHAR, SQL_VARCHAR, 0, 1, out2, 29, &ind, "S");
198 :
199 : /* mssql returns SUCCESS */
200 8 : CHKExecute("No");
201 :
202 8 : ODBC_CHECK_COLS(0);
203 :
204 8 : odbc_reset_statement();
205 8 : odbc_command("drop proc TMP_SP_Test_ODBC");
206 8 : }
207 :
208 : static void
209 8 : test_with_dbname(void)
210 : {
211 : SQLINTEGER len;
212 : SQLTCHAR out[512];
213 : char sql[1024];
214 : SQLINTEGER output;
215 : SQLLEN ind;
216 8 : ODBC_BUF *odbc_buf = NULL;
217 :
218 8 : len = sizeof(out);
219 8 : CHKGetConnectAttr(SQL_ATTR_CURRENT_CATALOG, (SQLPOINTER) out, sizeof(out), &len, "SI");
220 :
221 8 : odbc_command("IF OBJECT_ID('TMP_SP_Test_ODBC') IS NOT NULL DROP PROC TMP_SP_Test_ODBC");
222 8 : odbc_command("create proc TMP_SP_Test_ODBC @o int output\nas\nset @o=55\nreturn 3\n");
223 8 : odbc_reset_statement();
224 :
225 8 : sprintf(sql, "{call [%s]..TMP_SP_Test_ODBC(?)}", C(out));
226 8 : CHKBindParameter(1, SQL_PARAM_OUTPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &output, 0, &ind, "S");
227 8 : CHKPrepare(T(sql), SQL_NTS, "S");
228 :
229 8 : output = 123;
230 8 : ind = sizeof(output);
231 8 : CHKExecute("S");
232 :
233 8 : if (output != 55) {
234 0 : printf("Invalid result\n");
235 0 : exit(1);
236 : }
237 :
238 8 : odbc_reset_statement();
239 8 : odbc_command("drop proc TMP_SP_Test_ODBC");
240 8 : ODBC_FREE();
241 8 : }
|