Line data Source code
1 : /*
2 : * Tests rows count
3 : *
4 : * These are the results using Sybase CT-Library. This test check that ct_results returns the same results.
5 : *
6 : *
7 : * "insert into #tmp1 values(1) "
8 : * "insert into #tmp1 values(2) "
9 : * "insert into #tmp1 values(3) "
10 : * "select * from #tmp1 "
11 : *
12 : * Open Client Message:
13 : * number 16843050 layer 1 origin 1 severity 1 number 42
14 : * msgstring: ct_res_info(ROWCOUNT): user api layer: external error: This routine cannot be called after ct_results() returns a result type of CS_ROW_RESULT.
15 : * osstring: (null)
16 : * ct_results returned CS_ROW_RESULT type and -1 rows
17 : * All done processing rows.
18 : * ct_results returned CS_CMD_DONE type and 3 rows
19 : *
20 : * Open Client Message:
21 : * number 16843051 layer 1 origin 1 severity 1 number 43
22 : * msgstring: ct_res_info(ROWCOUNT): user api layer: external error: This routine cannot be called after ct_results() returns a result type of CS_STATUS_RESULT.
23 : * osstring: (null)
24 : * ct_results returned CS_STATUS_RESULT type and -1 rows
25 : * All done processing rows.
26 : * ct_results returned CS_CMD_SUCCEED type and -1 rows
27 : * ct_results returned CS_CMD_DONE type and -1 rows
28 : *
29 : *
30 : * "insert into #tmp1 values(1) "
31 : * "insert into #tmp1 values(2) "
32 : * "insert into #tmp1 values(3) "
33 : * "select * from #tmp1 "
34 : * "insert into #tmp1 values(4) "
35 : * "delete from #tmp1 where i <= 2 "
36 : *
37 : * Open Client Message:
38 : * number 16843050 layer 1 origin 1 severity 1 number 42
39 : * msgstring: ct_res_info(ROWCOUNT): user api layer: external error: This routine cannot be called after ct_results() returns a result type of CS_ROW_RESULT.
40 : * osstring: (null)
41 : * ct_results returned CS_ROW_RESULT type and -1 rows
42 : * All done processing rows.
43 : * ct_results returned CS_CMD_DONE type and 3 rows
44 : *
45 : * Open Client Message:
46 : * number 16843051 layer 1 origin 1 severity 1 number 43
47 : * msgstring: ct_res_info(ROWCOUNT): user api layer: external error: This routine cannot be called after ct_results() returns a result type of CS_STATUS_RESULT.
48 : * osstring: (null)
49 : * ct_results returned CS_STATUS_RESULT type and -1 rows
50 : * All done processing rows.
51 : * ct_results returned CS_CMD_SUCCEED type and 2 rows
52 : * ct_results returned CS_CMD_DONE type and 2 rows
53 : */
54 :
55 : #include "common.h"
56 :
57 : #include <freetds/replacements.h>
58 :
59 : static CS_CONTEXT *ctx;
60 : static CS_CONNECTION *conn;
61 : static CS_COMMAND *cmd;
62 :
63 : static CS_INT ex_display_results(CS_COMMAND * cmd, char *results);
64 :
65 : static int test(int final_rows, int no_rows);
66 :
67 10 : TEST_MAIN()
68 : {
69 10 : printf("%s: check row count returned\n", __FILE__);
70 10 : check_call(try_ctlogin, (&ctx, &conn, &cmd, 0));
71 10 : error_to_stdout = true;
72 :
73 : /* do not test error */
74 10 : run_command(cmd, "DROP PROCEDURE sample_rpc");
75 10 : run_command(cmd, "drop table #tmp1");
76 :
77 : /* test with rows from select */
78 10 : if (test(0, 0) || test(1, 0))
79 : return 1;
80 :
81 : /* test with empty select */
82 10 : if (test(0, 1) || test(1, 1))
83 : return 1;
84 :
85 10 : check_call(try_ctlogout, (ctx, conn, cmd, 0));
86 :
87 10 : return 0;
88 : }
89 :
90 : static int
91 40 : test(int final_rows, int no_rows)
92 : {
93 : CS_CHAR cmdbuf[4096];
94 : char results[1024];
95 :
96 40 : run_command(cmd, "create table #tmp1 (i int not null)");
97 :
98 40 : strlcpy(cmdbuf, "create proc sample_rpc as ", sizeof(cmdbuf));
99 :
100 40 : strlcpy(results, "CS_ROW_RESULT -1\n", sizeof(results));
101 40 : strlcat(cmdbuf, "insert into #tmp1 values(1) "
102 : "insert into #tmp1 values(2) "
103 : "insert into #tmp1 values(3) ", sizeof(cmdbuf)
104 : );
105 :
106 40 : if (no_rows) {
107 20 : strlcat(cmdbuf, "select * from #tmp1 where i > 10 ",
108 : sizeof(cmdbuf));
109 20 : strlcat(results, "CS_CMD_DONE 0\n", sizeof(results));
110 : } else {
111 20 : strlcat(cmdbuf, "select * from #tmp1 ", sizeof(cmdbuf));
112 20 : strlcat(results, "CS_CMD_DONE 3\n", sizeof(results));
113 : }
114 :
115 40 : strlcat(results, "CS_STATUS_RESULT -1\n", sizeof(results));
116 :
117 40 : if (final_rows) {
118 20 : strlcat(cmdbuf, "insert into #tmp1 values(4) "
119 : "delete from #tmp1 where i <= 2 ",
120 : sizeof(cmdbuf)
121 : );
122 20 : strlcat(results, "CS_CMD_SUCCEED 2\n"
123 : "CS_CMD_DONE 2\n", sizeof(results));
124 : } else {
125 20 : strlcat(results, "CS_CMD_SUCCEED -1\n"
126 : "CS_CMD_DONE -1\n", sizeof(results));
127 : }
128 :
129 40 : printf("testing query:\n----\n%s\n----\n", cmdbuf);
130 :
131 40 : check_call(run_command, (cmd, cmdbuf));
132 :
133 40 : printf("----------\n");
134 40 : check_call(ct_command, (cmd, CS_RPC_CMD, "sample_rpc", CS_NULLTERM, CS_NO_RECOMPILE));
135 :
136 40 : check_call(ct_send, (cmd));
137 40 : ex_display_results(cmd, results);
138 :
139 : /* cleanup */
140 40 : run_command(cmd, "DROP PROCEDURE sample_rpc");
141 40 : run_command(cmd, "drop table #tmp1");
142 :
143 40 : return 0;
144 : }
145 :
146 : static CS_INT
147 40 : ex_display_results(CS_COMMAND * cmd, char *results)
148 : {
149 : CS_RETCODE ret;
150 : CS_INT res_type;
151 : CS_INT num_cols;
152 40 : CS_INT row_count = 0;
153 : CS_INT rows_read;
154 : CS_SMALLINT msg_id;
155 :
156 : /*
157 : * Process the results of the RPC.
158 : */
159 280 : while ((ret = ct_results(cmd, &res_type)) == CS_SUCCEED) {
160 : char res[32];
161 : int rows, pos;
162 :
163 200 : CS_INT rowsAffected = -1;
164 200 : ct_res_info(cmd, CS_ROW_COUNT, &rowsAffected, CS_UNUSED, NULL);
165 200 : printf("ct_results returned %s type and %d rows\n", res_type_str(res_type), (int) rowsAffected);
166 :
167 : /* check expected results are the same as got ones */
168 200 : pos = -1;
169 200 : assert(sscanf(results, "%30s %d %n", res, &rows, &pos) >= 2 && pos > 0);
170 200 : results += pos;
171 200 : if (strcmp(res_type_str(res_type), res) != 0 || rowsAffected != rows) {
172 0 : fprintf(stderr, "Expected ct_results %s rows %d\n", res, rows);
173 0 : exit(1);
174 : }
175 :
176 200 : switch (res_type) {
177 80 : case CS_ROW_RESULT:
178 : case CS_PARAM_RESULT:
179 : case CS_STATUS_RESULT:
180 :
181 : /*
182 : * All three of these result types are fetchable.
183 : * Since the result model for rpcs and rows have
184 : * been unified in the New Client-Library, we
185 : * will use the same routine to display them
186 : */
187 :
188 : /*
189 : * Find out how many columns there are in this result set.
190 : */
191 80 : check_call(ct_res_info, (cmd, CS_NUMDATA, &num_cols, CS_UNUSED, NULL));
192 :
193 : /*
194 : * Make sure we have at least one column
195 : */
196 80 : if (num_cols <= 0) {
197 0 : fprintf(stderr, "ct_res_info(CS_NUMDATA) returned zero columns");
198 0 : return 1;
199 : }
200 :
201 180 : while (((ret = ct_fetch(cmd, CS_UNUSED, CS_UNUSED, CS_UNUSED,
202 80 : &rows_read)) == CS_SUCCEED) || (ret == CS_ROW_FAIL)) {
203 : /*
204 : * Increment our row count by the number of rows just fetched.
205 : */
206 100 : row_count = row_count + rows_read;
207 :
208 : /*
209 : * Check if we hit a recoverable error.
210 : */
211 100 : if (ret == CS_ROW_FAIL) {
212 0 : printf("Error on row %d.\n", row_count);
213 0 : fflush(stdout);
214 : }
215 : }
216 :
217 : /*
218 : * We're done processing rows. Let's check the final return
219 : * value of ct_fetch().
220 : */
221 80 : switch ((int) ret) {
222 80 : case CS_END_DATA:
223 : /*
224 : * Everything went fine.
225 : */
226 80 : printf("All done processing rows.\n");
227 80 : fflush(stdout);
228 : break;
229 :
230 0 : case CS_FAIL:
231 : /*
232 : * Something terrible happened.
233 : */
234 0 : fprintf(stderr, "ct_fetch returned CS_FAIL\n");
235 0 : return 1;
236 : break;
237 :
238 0 : default:
239 : /*
240 : * We got an unexpected return value.
241 : */
242 0 : fprintf(stderr, "ct_fetch returned %d\n", ret);
243 0 : return 1;
244 : break;
245 :
246 : }
247 80 : break;
248 :
249 0 : case CS_MSG_RESULT:
250 0 : check_call(ct_res_info, (cmd, CS_MSGTYPE, (CS_VOID *) & msg_id, CS_UNUSED, NULL));
251 0 : printf("ct_result returned CS_MSG_RESULT where msg id = %d.\n", msg_id);
252 0 : fflush(stdout);
253 0 : break;
254 :
255 : case CS_CMD_SUCCEED:
256 : case CS_CMD_DONE:
257 : case CS_CMD_FAIL:
258 : break;
259 :
260 0 : default:
261 : /*
262 : * We got something unexpected.
263 : */
264 0 : fprintf(stderr, "ct_results returned unexpected result type.");
265 0 : return CS_FAIL;
266 : }
267 : }
268 :
269 : /*
270 : * We're done processing results. Let's check the
271 : * return value of ct_results() to see if everything
272 : * went ok.
273 : */
274 40 : switch ((int) ret) {
275 : case CS_END_RESULTS:
276 : /*
277 : * Everything went fine.
278 : */
279 : break;
280 :
281 0 : case CS_FAIL:
282 : /*
283 : * Something failed happened.
284 : */
285 0 : fprintf(stderr, "ct_results failed.");
286 0 : break;
287 :
288 0 : default:
289 : /*
290 : * We got an unexpected return value.
291 : */
292 0 : fprintf(stderr, "ct_results returned unexpected result type.");
293 0 : break;
294 : }
295 :
296 : return CS_SUCCEED;
297 : }
|