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 : #undef NDEBUG
56 : #include <config.h>
57 :
58 : #include <stdio.h>
59 :
60 : #if HAVE_STDLIB_H
61 : #include <stdlib.h>
62 : #endif /* HAVE_STDLIB_H */
63 :
64 : #if HAVE_STRING_H
65 : #include <string.h>
66 : #endif /* HAVE_STRING_H */
67 :
68 : #include <assert.h>
69 : #include <ctpublic.h>
70 : #include "common.h"
71 : #include <freetds/replacements.h>
72 :
73 : static CS_CONTEXT *ctx;
74 : static CS_CONNECTION *conn;
75 : static CS_COMMAND *cmd;
76 :
77 : static CS_RETCODE ex_clientmsg_cb(CS_CONTEXT * context, CS_CONNECTION * connection, CS_CLIENTMSG * errmsg);
78 : static CS_RETCODE ex_servermsg_cb(CS_CONTEXT * context, CS_CONNECTION * connection, CS_SERVERMSG * errmsg);
79 : static CS_INT ex_display_results(CS_COMMAND * cmd, char *results);
80 :
81 : static int test(int final_rows, int no_rows);
82 :
83 : int
84 8 : main(int argc, char *argv[])
85 : {
86 : CS_RETCODE ret;
87 :
88 8 : printf("%s: check row count returned\n", __FILE__);
89 8 : ret = try_ctlogin(&ctx, &conn, &cmd, 0);
90 8 : if (ret != CS_SUCCEED) {
91 0 : fprintf(stderr, "Login failed\n");
92 0 : return 1;
93 : }
94 :
95 8 : ct_callback(ctx, NULL, CS_SET, CS_CLIENTMSG_CB, (CS_VOID *) ex_clientmsg_cb);
96 8 : ct_callback(ctx, NULL, CS_SET, CS_SERVERMSG_CB, (CS_VOID *) ex_servermsg_cb);
97 :
98 : /* do not test error */
99 8 : run_command(cmd, "DROP PROCEDURE sample_rpc");
100 8 : run_command(cmd, "drop table #tmp1");
101 :
102 : /* test with rows from select */
103 8 : if (test(0, 0) || test(1, 0))
104 : return 1;
105 :
106 : /* test with empty select */
107 8 : if (test(0, 1) || test(1, 1))
108 : return 1;
109 :
110 8 : ret = try_ctlogout(ctx, conn, cmd, 0);
111 8 : if (ret != CS_SUCCEED) {
112 0 : fprintf(stderr, "Logout failed\n");
113 0 : return 1;
114 : }
115 :
116 : return 0;
117 : }
118 :
119 : static int
120 32 : test(int final_rows, int no_rows)
121 : {
122 : CS_RETCODE ret;
123 : CS_CHAR cmdbuf[4096];
124 : char results[1024];
125 :
126 32 : run_command(cmd, "create table #tmp1 (i int not null)");
127 :
128 32 : strlcpy(cmdbuf, "create proc sample_rpc as ", sizeof(cmdbuf));
129 :
130 32 : strlcpy(results, "CS_ROW_RESULT -1\n", sizeof(results));
131 32 : strlcat(cmdbuf, "insert into #tmp1 values(1) "
132 : "insert into #tmp1 values(2) "
133 : "insert into #tmp1 values(3) ", sizeof(cmdbuf)
134 : );
135 :
136 32 : if (no_rows) {
137 16 : strlcat(cmdbuf, "select * from #tmp1 where i > 10 ",
138 : sizeof(cmdbuf));
139 16 : strlcat(results, "CS_CMD_DONE 0\n", sizeof(results));
140 : } else {
141 16 : strlcat(cmdbuf, "select * from #tmp1 ", sizeof(cmdbuf));
142 16 : strlcat(results, "CS_CMD_DONE 3\n", sizeof(results));
143 : }
144 :
145 32 : strlcat(results, "CS_STATUS_RESULT -1\n", sizeof(results));
146 :
147 32 : if (final_rows) {
148 16 : strlcat(cmdbuf, "insert into #tmp1 values(4) "
149 : "delete from #tmp1 where i <= 2 ",
150 : sizeof(cmdbuf)
151 : );
152 16 : strlcat(results, "CS_CMD_SUCCEED 2\n"
153 : "CS_CMD_DONE 2\n", sizeof(results));
154 : } else {
155 16 : strlcat(results, "CS_CMD_SUCCEED -1\n"
156 : "CS_CMD_DONE -1\n", sizeof(results));
157 : }
158 :
159 32 : printf("testing query:\n----\n%s\n----\n", cmdbuf);
160 :
161 32 : ret = run_command(cmd, cmdbuf);
162 32 : if (ret != CS_SUCCEED) {
163 0 : fprintf(stderr, "create proc failed\n");
164 0 : return 1;
165 : }
166 :
167 32 : printf("----------\n");
168 32 : if ((ret = ct_command(cmd, CS_RPC_CMD, "sample_rpc", CS_NULLTERM, CS_NO_RECOMPILE)) != CS_SUCCEED) {
169 0 : fprintf(stderr, "ct_command(CS_RPC_CMD) failed");
170 0 : return 1;
171 : }
172 :
173 32 : if (ct_send(cmd) != CS_SUCCEED) {
174 0 : fprintf(stderr, "ct_send(RPC) failed");
175 0 : return 1;
176 : }
177 32 : ex_display_results(cmd, results);
178 :
179 : /* cleanup */
180 32 : run_command(cmd, "DROP PROCEDURE sample_rpc");
181 32 : run_command(cmd, "drop table #tmp1");
182 :
183 32 : return 0;
184 : }
185 :
186 : static CS_INT
187 32 : ex_display_results(CS_COMMAND * cmd, char *results)
188 : {
189 : CS_RETCODE ret;
190 : CS_INT res_type;
191 : CS_INT num_cols;
192 32 : CS_INT row_count = 0;
193 : CS_INT rows_read;
194 : CS_SMALLINT msg_id;
195 :
196 : /*
197 : * Process the results of the RPC.
198 : */
199 224 : while ((ret = ct_results(cmd, &res_type)) == CS_SUCCEED) {
200 : char res[32];
201 : int rows, pos;
202 :
203 160 : CS_INT rowsAffected = -1;
204 160 : ct_res_info(cmd, CS_ROW_COUNT, &rowsAffected, CS_UNUSED, NULL);
205 160 : printf("ct_results returned %s type and %d rows\n", res_type_str(res_type), (int) rowsAffected);
206 :
207 : /* check expected results are the same as got ones */
208 160 : pos = -1;
209 160 : assert(sscanf(results, "%30s %d %n", res, &rows, &pos) >= 2 && pos > 0);
210 160 : results += pos;
211 160 : if (strcmp(res_type_str(res_type), res) != 0 || rowsAffected != rows) {
212 0 : fprintf(stderr, "Expected ct_results %s rows %d\n", res, rows);
213 0 : exit(1);
214 : }
215 :
216 160 : switch (res_type) {
217 64 : case CS_ROW_RESULT:
218 : case CS_PARAM_RESULT:
219 : case CS_STATUS_RESULT:
220 :
221 : /*
222 : * All three of these result types are fetchable.
223 : * Since the result model for rpcs and rows have
224 : * been unified in the New Client-Library, we
225 : * will use the same routine to display them
226 : */
227 :
228 : /*
229 : * Find out how many columns there are in this result set.
230 : */
231 64 : ret = ct_res_info(cmd, CS_NUMDATA, &num_cols, CS_UNUSED, NULL);
232 64 : if (ret != CS_SUCCEED) {
233 0 : fprintf(stderr, "ct_res_info(CS_NUMDATA) failed");
234 0 : return 1;
235 : }
236 :
237 : /*
238 : * Make sure we have at least one column
239 : */
240 64 : if (num_cols <= 0) {
241 0 : fprintf(stderr, "ct_res_info(CS_NUMDATA) returned zero columns");
242 0 : return 1;
243 : }
244 :
245 144 : while (((ret = ct_fetch(cmd, CS_UNUSED, CS_UNUSED, CS_UNUSED,
246 64 : &rows_read)) == CS_SUCCEED) || (ret == CS_ROW_FAIL)) {
247 : /*
248 : * Increment our row count by the number of rows just fetched.
249 : */
250 80 : row_count = row_count + rows_read;
251 :
252 : /*
253 : * Check if we hit a recoverable error.
254 : */
255 80 : if (ret == CS_ROW_FAIL) {
256 0 : printf("Error on row %d.\n", row_count);
257 0 : fflush(stdout);
258 : }
259 : }
260 :
261 : /*
262 : * We're done processing rows. Let's check the final return
263 : * value of ct_fetch().
264 : */
265 64 : switch ((int) ret) {
266 64 : case CS_END_DATA:
267 : /*
268 : * Everything went fine.
269 : */
270 64 : printf("All done processing rows.\n");
271 64 : fflush(stdout);
272 : break;
273 :
274 0 : case CS_FAIL:
275 : /*
276 : * Something terrible happened.
277 : */
278 0 : fprintf(stderr, "ct_fetch returned CS_FAIL\n");
279 0 : return 1;
280 : break;
281 :
282 0 : default:
283 : /*
284 : * We got an unexpected return value.
285 : */
286 0 : fprintf(stderr, "ct_fetch returned %d\n", ret);
287 0 : return 1;
288 : break;
289 :
290 : }
291 64 : break;
292 :
293 0 : case CS_MSG_RESULT:
294 0 : ret = ct_res_info(cmd, CS_MSGTYPE, (CS_VOID *) & msg_id, CS_UNUSED, NULL);
295 0 : if (ret != CS_SUCCEED) {
296 0 : fprintf(stderr, "ct_res_info(msg_id) failed");
297 0 : return 1;
298 : }
299 0 : printf("ct_result returned CS_MSG_RESULT where msg id = %d.\n", msg_id);
300 0 : fflush(stdout);
301 0 : break;
302 :
303 : case CS_CMD_SUCCEED:
304 : case CS_CMD_DONE:
305 : case CS_CMD_FAIL:
306 : break;
307 :
308 0 : default:
309 : /*
310 : * We got something unexpected.
311 : */
312 0 : fprintf(stderr, "ct_results returned unexpected result type.");
313 0 : return CS_FAIL;
314 : }
315 : }
316 :
317 : /*
318 : * We're done processing results. Let's check the
319 : * return value of ct_results() to see if everything
320 : * went ok.
321 : */
322 32 : switch ((int) ret) {
323 : case CS_END_RESULTS:
324 : /*
325 : * Everything went fine.
326 : */
327 : break;
328 :
329 0 : case CS_FAIL:
330 : /*
331 : * Something failed happened.
332 : */
333 0 : fprintf(stderr, "ct_results failed.");
334 0 : break;
335 :
336 0 : default:
337 : /*
338 : * We got an unexpected return value.
339 : */
340 0 : fprintf(stderr, "ct_results returned unexpected result type.");
341 0 : break;
342 : }
343 :
344 : return CS_SUCCEED;
345 : }
346 :
347 : static CS_RETCODE
348 0 : ex_clientmsg_cb(CS_CONTEXT * context, CS_CONNECTION * connection, CS_CLIENTMSG * errmsg)
349 : {
350 0 : printf("\nOpen Client Message:\n");
351 0 : printf("Message number: LAYER = (%ld) ORIGIN = (%ld) ", (long) CS_LAYER(errmsg->msgnumber), (long) CS_ORIGIN(errmsg->msgnumber));
352 0 : printf("SEVERITY = (%ld) NUMBER = (%ld)\n", (long) CS_SEVERITY(errmsg->msgnumber), (long) CS_NUMBER(errmsg->msgnumber));
353 0 : printf("Message String: %s\n", errmsg->msgstring);
354 0 : if (errmsg->osstringlen > 0) {
355 0 : printf("Operating System Error: %s\n", errmsg->osstring);
356 : }
357 0 : fflush(stdout);
358 :
359 0 : return CS_SUCCEED;
360 : }
361 :
362 : static CS_RETCODE
363 14 : ex_servermsg_cb(CS_CONTEXT * context, CS_CONNECTION * connection, CS_SERVERMSG * srvmsg)
364 : {
365 14 : printf("\nServer message:\n");
366 14 : printf("Message number: %ld, Severity %ld, ", (long) srvmsg->msgnumber, (long) srvmsg->severity);
367 14 : printf("State %ld, Line %ld\n", (long) srvmsg->state, (long) srvmsg->line);
368 :
369 14 : if (srvmsg->svrnlen > 0) {
370 14 : printf("Server '%s'\n", srvmsg->svrname);
371 : }
372 :
373 14 : if (srvmsg->proclen > 0) {
374 0 : printf(" Procedure '%s'\n", srvmsg->proc);
375 : }
376 :
377 14 : printf("Message String: %s\n", srvmsg->text);
378 14 : fflush(stdout);
379 :
380 14 : return CS_SUCCEED;
381 : }
|