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