Line data Source code
1 : /*
2 : * Test bulk copy cancellation (blk_done with CS_BLK_CANCEL).
3 : * Check data not committed are discarded and that connection
4 : * can be used after cancellation.
5 : */
6 :
7 : #include "common.h"
8 :
9 : #include <bkpublic.h>
10 :
11 : static const char table_name[] = "blk_cancel_test";
12 :
13 : static CS_CONNECTION *conn;
14 : static CS_COMMAND *cmd;
15 : static CS_BLKDESC *blkdesc;
16 :
17 : static CS_INT row_id, row_id_len = sizeof(row_id);
18 : static char row_data[201];
19 : static CS_INT row_data_len;
20 :
21 : /* start a bulk copy into the table binding the columns */
22 : static void
23 70 : start_in(void)
24 : {
25 : CS_DATAFMT fmt;
26 :
27 70 : check_call(blk_init, (blkdesc, CS_BLK_IN, (char *) table_name, CS_NULLTERM));
28 :
29 70 : memset(&fmt, 0, sizeof(fmt));
30 70 : fmt.count = 1;
31 70 : fmt.datatype = CS_INT_TYPE;
32 70 : fmt.maxlength = sizeof(row_id);
33 70 : check_call(blk_bind, (blkdesc, 1, &fmt, &row_id, &row_id_len, NULL));
34 :
35 70 : memset(&fmt, 0, sizeof(fmt));
36 70 : fmt.count = 1;
37 : fmt.datatype = CS_CHAR_TYPE;
38 70 : fmt.maxlength = sizeof(row_data) - 1;
39 70 : check_call(blk_bind, (blkdesc, 2, &fmt, row_data, &row_data_len, NULL));
40 70 : }
41 :
42 : /* send some rows, enough rows cause packets to be sent to the server */
43 : static void
44 70 : send_rows(int first, int num)
45 : {
46 : int i;
47 :
48 60370 : for (i = 0; i < num; i++) {
49 60300 : row_id = first + i;
50 60300 : row_data_len = 50 + row_id % 150;
51 60300 : memset(row_data, 'a' + row_id % 26, row_data_len);
52 60300 : check_call(blk_rowxfer, (blkdesc));
53 : }
54 70 : }
55 :
56 : static void
57 110 : done(CS_INT type, CS_INT expected)
58 : {
59 110 : CS_INT rows = -1;
60 :
61 110 : check_call(blk_done, (blkdesc, type, &rows));
62 110 : if (rows != expected) {
63 0 : fprintf(stderr, "blk_done(%d) returned %d rows, expected %d\n", (int) type, (int) rows, (int) expected);
64 0 : exit(1);
65 : }
66 110 : }
67 :
68 : /* check table content, this also check the connection is still usable */
69 : static void
70 80 : check_table(CS_INT expected_count, CS_INT expected_sum)
71 : {
72 : char sql[128];
73 : CS_DATAFMT fmt;
74 80 : CS_INT values[2], result_type, count, num_rows = 0;
75 : CS_RETCODE ret;
76 : int i;
77 :
78 80 : sprintf(sql, "select count(*), coalesce(sum(id), 0) from %s", table_name);
79 80 : check_call(ct_command, (cmd, CS_LANG_CMD, sql, CS_NULLTERM, CS_UNUSED));
80 80 : check_call(ct_send, (cmd));
81 80 : while ((ret = ct_results(cmd, &result_type)) == CS_SUCCEED) {
82 160 : switch (result_type) {
83 : case CS_ROW_RESULT:
84 160 : for (i = 0; i < 2; i++) {
85 160 : memset(&fmt, 0, sizeof(fmt));
86 160 : fmt.datatype = CS_INT_TYPE;
87 160 : fmt.maxlength = sizeof(CS_INT);
88 160 : fmt.count = 1;
89 160 : check_call(ct_bind, (cmd, i + 1, &fmt, &values[i], NULL, NULL));
90 : }
91 160 : while ((ret = ct_fetch(cmd, CS_UNUSED, CS_UNUSED, CS_UNUSED, &count)) == CS_SUCCEED)
92 80 : ++num_rows;
93 80 : assert(ret == CS_END_DATA);
94 : break;
95 : case CS_CMD_SUCCEED:
96 : case CS_CMD_DONE:
97 : break;
98 0 : default:
99 0 : fprintf(stderr, "unexpected result type %d\n", (int) result_type);
100 0 : exit(1);
101 : }
102 : }
103 80 : assert(ret == CS_END_RESULTS);
104 80 : assert(num_rows == 1);
105 :
106 80 : printf("table has %d rows, sum %d\n", (int) values[0], (int) values[1]);
107 80 : if (values[0] != expected_count || values[1] != expected_sum) {
108 0 : fprintf(stderr, "wrong table content, expected %d rows, sum %d\n", (int) expected_count, (int) expected_sum);
109 0 : exit(1);
110 : }
111 80 : }
112 :
113 : static void
114 20 : clear_table(void)
115 : {
116 : char sql[128];
117 :
118 20 : sprintf(sql, "delete from %s", table_name);
119 20 : check_call(run_command, (cmd, sql));
120 20 : }
121 :
122 : /* sum of ids from first to first + num - 1 */
123 : static CS_INT
124 : sum_ids(int first, int num)
125 : {
126 : return (CS_INT) (((long) first * 2 + num - 1) * num / 2);
127 : }
128 :
129 10 : TEST_MAIN()
130 : {
131 : CS_CONTEXT *ctx;
132 10 : bool verbose = false;
133 : char sql[256];
134 : CS_DATAFMT fmt;
135 : CS_INT id, id_len, rows;
136 : int i;
137 :
138 10 : printf("%s: Testing bulk copy cancellation\n", __FILE__);
139 10 : check_call(try_ctlogin, (&ctx, &conn, &cmd, verbose));
140 :
141 10 : sprintf(sql, "if exists (select 1 from sysobjects where type = 'U' and name = '%s') drop table %s", table_name, table_name);
142 10 : check_call(run_command, (cmd, sql));
143 :
144 10 : sprintf(sql, "create table %s (id int not null, data varchar(200) not null)", table_name);
145 10 : check_call(run_command, (cmd, sql));
146 :
147 10 : check_call(blk_alloc, (conn, BLK_VERSION_100, &blkdesc));
148 :
149 10 : printf("cancel with data not sent yet to server\n");
150 10 : start_in();
151 10 : send_rows(1, 5);
152 10 : done(CS_BLK_CANCEL, 0);
153 10 : check_table(0, 0);
154 :
155 10 : printf("cancel after some packets were sent to server\n");
156 10 : start_in();
157 10 : send_rows(1, 2000);
158 10 : done(CS_BLK_CANCEL, 0);
159 10 : check_table(0, 0);
160 :
161 10 : printf("cancel after a committed batch\n");
162 10 : start_in();
163 10 : send_rows(1, 10);
164 10 : done(CS_BLK_BATCH, 10);
165 10 : send_rows(11, 2000);
166 10 : done(CS_BLK_CANCEL, 0);
167 10 : check_table(10, sum_ids(1, 10));
168 10 : clear_table();
169 :
170 10 : printf("cancel just after a batch\n");
171 10 : start_in();
172 10 : send_rows(1, 10);
173 10 : done(CS_BLK_BATCH, 10);
174 10 : done(CS_BLK_CANCEL, 0);
175 10 : check_table(10, sum_ids(1, 10));
176 10 : clear_table();
177 :
178 10 : printf("cancel before transferring any row\n");
179 10 : start_in();
180 10 : done(CS_BLK_CANCEL, 0);
181 10 : check_table(0, 0);
182 :
183 10 : printf("cancel twice, second does nothing\n");
184 10 : start_in();
185 10 : send_rows(1, 5);
186 10 : done(CS_BLK_CANCEL, 0);
187 10 : done(CS_BLK_CANCEL, 0);
188 10 : check_table(0, 0);
189 :
190 10 : printf("normal copy after cancellation\n");
191 10 : start_in();
192 10 : send_rows(1, 2000);
193 10 : done(CS_BLK_ALL, 2000);
194 10 : check_table(2000, sum_ids(1, 2000));
195 :
196 10 : printf("cancel copy out\n");
197 10 : check_call(blk_init, (blkdesc, CS_BLK_OUT, (char *) table_name, CS_NULLTERM));
198 10 : memset(&fmt, 0, sizeof(fmt));
199 10 : fmt.count = 1;
200 10 : fmt.datatype = CS_INT_TYPE;
201 10 : fmt.maxlength = sizeof(id);
202 10 : check_call(blk_bind, (blkdesc, 1, &fmt, &id, &id_len, NULL));
203 60 : for (i = 0; i < 5; i++) {
204 50 : check_call(blk_rowxfer_mult, (blkdesc, &rows));
205 50 : assert(rows == 1);
206 : }
207 10 : done(CS_BLK_CANCEL, 0);
208 10 : check_table(2000, sum_ids(1, 2000));
209 :
210 10 : blk_drop(blkdesc);
211 :
212 10 : sprintf(sql, "drop table %s", table_name);
213 10 : check_call(run_command, (cmd, sql));
214 :
215 10 : printf("done\n");
216 :
217 10 : check_call(try_ctlogout, (ctx, conn, cmd, verbose));
218 :
219 10 : return 0;
220 : }
|