File: create_select_atomic.test

package info (click to toggle)
mysql-8.0 8.0.43-3
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 1,273,924 kB
  • sloc: cpp: 4,684,605; ansic: 412,450; pascal: 108,398; java: 83,641; perl: 30,221; cs: 27,067; sql: 26,594; sh: 24,181; python: 21,816; yacc: 17,169; php: 11,522; xml: 7,388; javascript: 7,076; makefile: 2,194; lex: 1,075; awk: 670; asm: 520; objc: 183; ruby: 97; lisp: 86
file content (329 lines) | stat: -rw-r--r-- 11,010 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
#########################################
# ==== Purpose ====
#
# Test crash and recovery of CREATE TABLE ... AS SELECT (DDL_CTAS)
# and also test CREATE TABLE ... START TRANSACTION and related cases.
#
# ==== Requirements ====
#
# R1 Crash before committing DDL_CTAS should cause metadata of table
#    being created to be rollbacked.
#
# R2 CREATE TABLE ... TRANSACTION; command should not allow any SQL
#    commands other than BINLOG INSERT, COMMIT and ROLLBACK.
#
# R3 Reject use of CREATE TABLE ... TRANSACTION using a prepared statement.
#
# ==== Implementation ====
#
# TC1: Crash DDL_CTAS after table is created but before INSERT.
# 1) Create table t0 with few rows.
# 2) Set debug point to induce crash before inserting rows during DDL_CTAS.
#    crash_before_create_select_insert
# 3) Execute DDL_CTAS and cause crash.
# 4) Wait for server to stop and then restart the server.
# 5) Verify that we have just t0 and no t1 created.
# 6) Reset the debug point.
#
# TC2: Crash DDL_CTAS after table is created and INSERT is completed.
# Repeat steps from TC1 with debug point crash_after_create_select_insert.
#
# TC3: Crash DDL_CTAS during commit before flushing binlog.
# Repeat steps from TC1 with debug point crash_commit_before_log.
#
# TC4: Crash DDL_CTAS during commit after flushing binlog.
# Repeat steps from TC1 with debug point crash_after_flush_binlog.
#
# TC5: Concurrent access to table being created should be blocked.
# 1) Execute CREATE TABLE ... START TRANSACTION; and block during commit;
# 2) Execute SELECT * FROM t1; in another connection;
# 3) Verify that SELECT command is waiting for MDL lock.
# 4) Continue execution of 1).
# 5) Verify that we see results from SELECT.
#
# TC6: Test ROLLBACK after CREATE TABLE ... START TRANSACTION.
# 1) Execute CREATE TABLE ... START TRANSACTION;
# 2) Execute ROLLBACK;
# 3) Verify that table t1 does not exist.
#
# TC7: Test COMMIT after CREATE TABLE ... START TRANSACTION.
# 1) Execute CREATE TABLE ... START TRANSACTION;
# 2) Execute COMMIT;
# 3) Verify that table t1 does exist.
#
# TC8: Test previous two cases from within a SP.
# 1) Create a procedure with following steps.
#    - Steps 1/2 in TC5.
#    - Steps 1/2 in TC6.
# 2) Execute the procedure.
# 3) Verify that table t1 does exist.
#
# TC9: Reject prepared statement and CREATE TABLE .. START TRANSACTION.
# 1) Test that we get ER_UNSUPPORTED_PS if CREATE TABLE ... START
#    TRANSACTION is executed using PREPARE command.
#
# TC10: Reject CREATE TABLE .. START TRANSACTION with non-atomic engine.
# 1) Test that we get ER_NOT_ALLOWED_WITH_START_TRANSACTION if CREATE
#    TABLE ... START TRANSACTION is executed using SE does not support
#    atomic DDL.
#
# TC11: Reject DML, DDL and other commands except for COMMIT, ROLLBACK after
#      CREATE TABLE ... START TRANSACTION.
# 1) Execute CREATE TABLE ... START TRANSACTION;
# 2) Execute INSERT and see we get
#    ER_STATEMENT_NOT_ALLOWED_AFTER_START_TRANSACTION
# 3) Execute UPDATE and see we get
#    ER_STATEMENT_NOT_ALLOWED_AFTER_START_TRANSACTION
# 4) Execute SET and see we get
#    ER_STATEMENT_NOT_ALLOWED_AFTER_START_TRANSACTION
#
# TC12: Reject ALTER TABLE with START TRANSACTION.
#
# TC13: Reject CREATE TEMPORARY TABLE with START TRANSACTION.
#
# TC14: Reject CREATE TABLE ... AS SELECT with START TRANSACTION.
#
# ==== References ====
#
# WL#13355 Make CREATE TABLE...SELECT atomic and crash-safe
#

--source include/have_debug.inc
--source include/not_valgrind.inc
--source include/have_log_bin.inc

# Skip ps protocol because CREATE TABLE ... START TRANSACTION is not
# allowed to be run with ps protocol.
--source include/no_ps_protocol.inc

CREATE TABLE t0 (f1 INT PRIMARY KEY);
INSERT INTO t0 VALUES (1),(2),(3),(4);

--echo #
--echo # CASE 1
--echo # Crash DDL after table is created but before INSERT.
--echo #

--source include/expect_crash.inc
SET global DEBUG='+d, crash_before_create_select_insert';
--exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
--error CR_SERVER_LOST
CREATE TABLE t1 AS SELECT * FROM t0;

--echo # Recover the server.
--source include/wait_until_disconnected.inc
--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
--enable_reconnect
let $WAIT_COUNT=6000;
--source include/wait_time_until_connected_again.inc

--let $assert_text= Verify that only table t0 is present in test database
let $assert_cond= [SELECT count(table_name) COUNT FROM
  INFORMATION_SCHEMA.TABLES WHERE table_schema = \'test\', COUNT, 1] = 1;
--source include/assert.inc

SET global DEBUG='-d, crash_before_create_select_insert';

--echo #
--echo # CASE 2
--echo # Crash DDL after table is created and INSERT is completed.
--echo #

--source include/expect_crash.inc
SET global DEBUG='+d, crash_after_create_select_insert';
--exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
--error CR_SERVER_LOST
CREATE TABLE t1 AS SELECT * FROM t0;

--echo # Recover the server.
--source include/wait_until_disconnected.inc
--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
--enable_reconnect
let $WAIT_COUNT=6000;
--source include/wait_time_until_connected_again.inc

--let $assert_text= Verify that only table t0 is present in test database
--let $assert_cond= "[SELECT count(table_name) COUNT FROM INFORMATION_SCHEMA.TABLES WHERE table_schema = \'test\', COUNT, 1]" = "1"
--source include/assert.inc

SET global DEBUG='-d, crash_after_create_select_insert';

--echo #
--echo # CASE 3
--echo # Crash DDL during commit before flushing binlog.
--echo #

--source include/expect_crash.inc
SET global DEBUG='+d, crash_commit_before_log';
--exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
--error CR_SERVER_LOST
CREATE TABLE t1 AS SELECT * FROM t0;

--echo # Recover the server.
--source include/wait_until_disconnected.inc
--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
--enable_reconnect
let $WAIT_COUNT=6000;
--source include/wait_time_until_connected_again.inc

--let $assert_text= Verify that only table t0 is present in test database
let $assert_cond= [SELECT count(table_name) COUNT FROM
  INFORMATION_SCHEMA.TABLES WHERE table_schema = \'test\', COUNT, 1] = 1;
--source include/assert.inc

SET global DEBUG='-d, crash_commit_before_log';

--echo #
--echo # CASE 4
--echo # Crash DDL during commit after binlog flush.
--echo #

--source include/expect_crash.inc
SET global DEBUG='+d, crash_after_flush_binlog';
--exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
--error CR_SERVER_LOST
CREATE TABLE t1 AS SELECT * FROM t0;

--echo # Recover the server.
--source include/wait_until_disconnected.inc
--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
--enable_reconnect
let $WAIT_COUNT=6000;
--source include/wait_time_until_connected_again.inc

--let $assert_text= Verify that only table t0 and t1 is present in test database
--let $assert_cond= "[SELECT count(table_name) COUNT FROM INFORMATION_SCHEMA.TABLES WHERE table_schema = \'test\', COUNT, 1]" = "2"
--source include/assert.inc

SET global DEBUG='-d, crash_after_flush_binlog';
DROP TABLE t1;

--echo #
--echo # CASE 5
--echo # Concurrent access to table being created should be blocked.
--echo #

--connection default
SET DEBUG_SYNC='ha_commit_trans_before_acquire_commit_lock SIGNAL cond1 WAIT_FOR cond2';
--send CREATE TABLE t1 AS SELECT * FROM t0;

--connect (con1, localhost, root,,)
SET DEBUG_SYNC='now WAIT_FOR cond1';
--send SELECT * FROM t1

--connect (con2, localhost, root,,)
let $wait_condition=
  select count(*) = 1 from information_schema.processlist
  where state = "Waiting for table metadata lock" and
        info = "SELECT * FROM t1";
--source include/wait_condition.inc
SET DEBUG_SYNC='now SIGNAL cond2';

--connection default
--reap
--connection con1
--reap
--connection default
--disconnect con1
--disconnect con2

SET DEBUG_SYNC=RESET;
DROP TABLE t0, t1;

--echo #
--echo # CASE 6 ROLLBACK after CREATE TABLE ... START TRANSACTION.
--echo #
CREATE TABLE t1 (f1 INT) START TRANSACTION;
ROLLBACK;
--let $assert_text= Verify that only we don't see and table in test database
--let $assert_cond= "[SELECT count(table_name) COUNT FROM INFORMATION_SCHEMA.TABLES WHERE table_schema = \'test\', COUNT, 1]" = "0"
--source include/assert.inc

--echo #
--echo # CASE 7 COMMIT after CREATE TABLE ... START TRANSACTION.
--echo #
CREATE TABLE t1 (f1 INT) START TRANSACTION;
COMMIT;
--let $assert_text= Verify that table t1 is present in test database
--let $assert_cond= "[SELECT count(table_name) COUNT FROM INFORMATION_SCHEMA.TABLES WHERE table_schema = \'test\', COUNT, 1]" = "1"
--source include/assert.inc

DROP TABLE t1;

--echo #
--echo # CASE 8 Test previous two case from within a SP.
--echo #
DELIMITER |;
CREATE PROCEDURE proc1()
BEGIN
  CREATE TABLE t1 (f1 INT) START TRANSACTION;
  ROLLBACK;
  CREATE TABLE t1 (f1 INT) START TRANSACTION;
  COMMIT;
END|
DELIMITER ;|
CALL proc1();
--let $assert_text= Verify that table t1 is present in test database
--let $assert_cond= "[SELECT count(table_name) COUNT FROM INFORMATION_SCHEMA.TABLES WHERE table_schema = \'test\', COUNT, 1]" = "1"
--source include/assert.inc
--echo # Rerun the proceduce and check for table exist error.
--error ER_TABLE_EXISTS_ERROR
CALL proc1();
DROP TABLE t1;
DROP PROCEDURE proc1;

--echo #
--echo # CASE 9 Reject prepared stmt for CREATE TABLE ... START TRANSACTION.
--echo #
--error ER_UNSUPPORTED_PS
PREPARE stmt FROM "CREATE TABLE t1 (f1 INT) START TRANSACTION";

--echo #
--echo # CASE 10
--echo # CREATE TABLE ... START TRANSACTION with SE not supporting atomic-DDL
--echo #
--error ER_NOT_ALLOWED_WITH_START_TRANSACTION
CREATE TABLE t1 (f1 INT) ENGINE=MyiSAM START TRANSACTION;

--echo #
--echo # CASE 11
--echo # Reject DML, DDL and other commands except for COMMIT, ROLLBACK after
--echo # CREATE TABLE ... START TRANSACTION.
--echo #
CREATE TABLE t1 (f1 INT) START TRANSACTION;
--error ER_STATEMENT_NOT_ALLOWED_AFTER_START_TRANSACTION
INSERT INTO t1 VALUES (1);
--error ER_STATEMENT_NOT_ALLOWED_AFTER_START_TRANSACTION
UPDATE t1 SET f1=932;
--error ER_STATEMENT_NOT_ALLOWED_AFTER_START_TRANSACTION
CREATE TABLE t2 (f2 INT);
--error ER_STATEMENT_NOT_ALLOWED_AFTER_START_TRANSACTION
SET sql_mode = default;
ROLLBACK;

--let $assert_text= Verify that no table exists in test database
--let $assert_cond= "[SELECT count(table_name) COUNT FROM INFORMATION_SCHEMA.TABLES WHERE table_schema = \'test\', COUNT, 1]" = "0"
--source include/assert.inc

--echo #
--echo # CASE 12
--echo # ALTER TABLE ... START TRANSACTION is not supported.
--echo #
CREATE TABLE t1 (f1 INT);
--error ER_NOT_ALLOWED_WITH_START_TRANSACTION
ALTER TABLE t2 ADD f2 INT, START TRANSACTION;
DROP TABLE t1;

--echo #
--echo # CASE 13
--echo # CREATE TEMPORARY TABLE ... START TRANSACTION is not supported.
--echo #
--error ER_NOT_ALLOWED_WITH_START_TRANSACTION
CREATE TEMPORARY TABLE t1 (f1 INT) START TRANSACTION;

--echo #
--echo # CASE 14
--echo # CREATE TABLE ... AS SELECT with START TRANSACTION.
--echo #
--error ER_NOT_ALLOWED_WITH_START_TRANSACTION
CREATE TABLE t1 START TRANSACTION as SELECT * FROM t0;