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