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