--source include/have_innodb.inc --source include/have_debug_sync.inc --source include/have_debug.inc --source include/count_sessions.inc set default_storage_engine=innodb; # Ensure that the history list length will actually be decremented by purge. SET @save_stats_persistent = @@GLOBAL.innodb_stats_persistent; SET GLOBAL innodb_stats_persistent = 0; CREATE TABLE `t` ( `a` VARCHAR(100), `b` VARCHAR(100), `c` VARCHAR(200) GENERATED ALWAYS AS (CONCAT(a,b)) VIRTUAL, `h` VARCHAR(10) DEFAULT NULL, `i` int ) ENGINE=InnoDB; INSERT INTO t VALUES (REPEAT('g', 100), REPEAT('x', 10), DEFAULT, "kk", 1); INSERT INTO t VALUES (REPEAT('a', 100), REPEAT('b', 100), DEFAULT, "mm", 2); CREATE INDEX idx ON t(c(100)); SET session debug_dbug="+d,ib_alter_add_virtual_fail"; --error ER_WRONG_KEY_COLUMN ALTER TABLE t ADD COLUMN x VARCHAR(200) GENERATED ALWAYS AS (a) VIRTUAL, ALGORITHM = INPLACE; --error ER_WRONG_KEY_COLUMN ALTER TABLE t DROP COLUMN c, ALGORITHM = INPLACE; SET session debug_dbug=""; DROP TABLE t; #online test CREATE TABLE t (a INT, b INT, c INT GENERATED ALWAYS AS(a+b), h VARCHAR(10)); INSERT INTO t VALUES (11, 3, DEFAULT, 'mm'); INSERT INTO t VALUES (18, 1, DEFAULT, 'mm'); INSERT INTO t VALUES (28, 1, DEFAULT, 'mm'); INSERT INTO t VALUES (null, null, DEFAULT, "mx"); SET DEBUG_SYNC = 'innodb_inplace_alter_table_enter SIGNAL start_create WAIT_FOR go_ahead'; --send CREATE INDEX idx ON t(c) connect (con1,localhost,root,,); SET DEBUG_SYNC = 'now WAIT_FOR start_create'; update t set a=0 where a = 11; start transaction; update t set a=1 where a = 0; ROLLBACK; SET DEBUG_SYNC = 'now SIGNAL go_ahead'; connection default; reap; SELECT c FROM t; SHOW CREATE TABLE t; SELECT * FROM t; --error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON ALTER TABLE t FORCE, LOCK=NONE; if (0) {# MDEV-14341 TODO: re-enable this SET DEBUG_SYNC = 'innodb_inplace_alter_table_enter SIGNAL start_create WAIT_FOR go_ahead'; --send ALTER TABLE t FORCE connection con1; SET DEBUG_SYNC = 'now WAIT_FOR start_create'; start transaction; update t set a=1 where a = 0; rollback; start transaction; delete from t; insert into t values(1,null,default,null); rollback; start transaction; update t set b=b+1; rollback; SET DEBUG_SYNC = 'now SIGNAL go_ahead'; connection default; reap; check table t; SELECT c FROM t; SET DEBUG_SYNC = 'innodb_inplace_alter_table_enter SIGNAL start_create WAIT_FOR go_ahead'; --send ALTER TABLE t FORCE connection con1; SET DEBUG_SYNC = 'now WAIT_FOR start_create'; start transaction; DELETE FROM t WHERE a = 0; ROLLBACK; DELETE FROM t WHERE a = 0; SET DEBUG_SYNC = 'now SIGNAL go_ahead'; connection default; reap; SELECT c FROM t; } disconnect con1; DROP TABLE t; SET DEBUG_SYNC = 'RESET'; # Test add virtual column and add index at the same time # introduce some error CREATE TABLE t (a INT, b INT, c INT GENERATED ALWAYS AS(a+b), h VARCHAR(10)); INSERT INTO t VALUES (11, 3, DEFAULT, 'mm'); INSERT INTO t VALUES (18, 1, DEFAULT, 'mm'); INSERT INTO t VALUES (28, 1, DEFAULT, 'mm'); INSERT INTO t VALUES (null, null, DEFAULT, 'mm'); CREATE INDEX idx_1 on t(c); SET @saved_dbug = @@SESSION.debug_dbug; SET debug_dbug = '+d,create_index_fail'; --enable_info --error ER_DUP_ENTRY ALTER TABLE t ADD COLUMN x INT GENERATED ALWAYS AS(a+b), ADD INDEX idx (x), ADD INDEX idcx (c,x); UPDATE t SET a=a+1; --error ER_DUP_ENTRY ALTER TABLE t ADD INDEX idc(c); SET debug_dbug = @saved_dbug; --disable_info UPDATE t SET b=b-1; SHOW CREATE TABLE t; SELECT c FROM t; DROP TABLE t; if (0) {# MDEV-14341 TODO: re-enable LOCK=NONE and these tests --echo # --echo # Bug#22018532 ASSERTION WHEN ONLINE REAPPLY REBUILD LOG ON --echo # MULTIPLE INDEXED VIRTUAL COLUMNS --echo # create table t ( a int as (1) virtual, b int, c int as (1) virtual, unique(b), unique(c), key(a) ) engine=innodb; insert ignore into t values(); SET DEBUG_SYNC = 'innodb_inplace_alter_table_enter SIGNAL start_create WAIT_FOR go_ahead'; --send optimize table t connect (con1,localhost,root,,); SET DEBUG_SYNC = 'now WAIT_FOR start_create'; insert ignore into t values(); SET DEBUG_SYNC = 'now SIGNAL go_ahead'; connection default; --echo /* connection default */ optimize table t; reap; SELECT c FROM t; SHOW CREATE TABLE t; SELECT * FROM t; DROP TABLE t; # Do another test without duplicate error CREATE TABLE t (a INT, b INT, c INT GENERATED ALWAYS AS(a+b), h VARCHAR(10)); INSERT INTO t VALUES (11, 3, DEFAULT, 'mm'); INSERT INTO t VALUES (18, 1, DEFAULT, 'mm'); INSERT INTO t VALUES (28, 1, DEFAULT, 'mm'); INSERT INTO t VALUES (null, null, DEFAULT, 'mm'); CREATE INDEX idx ON t(c); SET DEBUG_SYNC = 'innodb_inplace_alter_table_enter SIGNAL start_rebuild WAIT_FOR go_ahead'; --send optimize table t connection con1; SET DEBUG_SYNC = 'now WAIT_FOR start_rebuild'; INSERT INTO t VALUES (48, 2, DEFAULT, 'xx'); INSERT INTO t VALUES (68, 3, DEFAULT, 'sx'); SET DEBUG_SYNC = 'now SIGNAL go_ahead'; connection default; --echo /* connection default */ optimize table t; reap; SELECT c FROM t; disconnect con1; DROP TABLE t; --echo # --echo # Bug#22951879 - ASSERTS RELATED TO ONLINE DDL AND GCOL --echo # # Create a table with 2 virtual column, one (vbidxcol) is indexed and # the other one (vbcol) is not create table ibstd_14 (a int not null, d int not null, b varchar(198) not null, c char(181), vadcol int as (a+length(d)) stored, vbcol char(2) as (substr(b,2,2)) virtual, vbidxcol char(3) as (substr(b,1,3)) virtual , index(d), index(a), index(vbidxcol), index(a,vbidxcol), index(vbidxcol,d), unique key (b(10), a, d), index(c(99), b(31)), index(b(5), c(10), a) , index(a,d)) engine=InnoDB stats_persistent=1 row_format=dynamic; # Do an alter table rebuild table and also create a new index on this # non-indexed virtual column SET DEBUG_SYNC = 'innodb_inplace_alter_table_enter SIGNAL start_create WAIT_FOR go_ahead'; --send alter table ibstd_14 row_format=compressed key_block_size=4,add key kn3 (d,c,vbcol,b) # Do a concurrent insert, and make sure this newly indexed virtual column # is also logged connect (con1,localhost,root); SET DEBUG_SYNC = 'now WAIT_FOR start_create'; insert into ibstd_14 (a,d,b,c, vbidxcol, vbcol) values ('118','6',repeat('oacolaarlruoacuroauurloraarucoooarcooauoolacalllaulrruarrrucruuooclacuoouccarrcoocloccorrrrarourcooalloocooccouruolaorlcaocualolc','1'),repeat('lolrrlalcocroraaulauclaaucolcorcuooaolruaooooluooooouaoorlarucorullalcrrloccououaooaorluorraclrcooouuolocoaolcocaaculruoocucoocoooauuolarcoraraocaoolulolarru','1'),default,default); insert into ibstd_14 (a,d,b,c, vbidxcol, vbcol) values ('118','6', 'aaaa', 'lll', default, default); # Also do an concurrent update, make sure this is performed update ibstd_14 set b='11111' where b='aaaa'; SET DEBUG_SYNC = 'now SIGNAL go_ahead'; connection default; reap; select * from ibstd_14; # This will use the newly added "kn3" index, to check materialized vbcol # after log reapply select d,c,vbcol,b from ibstd_14; # check the value is inserted into the index select vbcol from ibstd_14; drop table ibstd_14; --echo # --echo # Bug#22018745 CORRUPTION IN ONLINE TABLE REBUILD --echo # (ROW_FORMAT=REDUNDANT, INDEXED VIRTUAL COLUMN) --echo # CREATE TABLE t ( b char(5) PRIMARY KEY, v char(3) GENERATED ALWAYS AS (substr(b,1,3)) VIRTUAL, KEY(v) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=REDUNDANT; connection con1; SET DEBUG_SYNC='row_log_table_apply1_before SIGNAL prepared WAIT_FOR apply'; --send OPTIMIZE TABLE t connection default; SET DEBUG_SYNC='now WAIT_FOR prepared'; INSERT INTO t SET b='fubar'; BEGIN; DELETE FROM t; ROLLBACK; SET DEBUG_SYNC='now SIGNAL apply'; connection con1; reap; connection default; CHECK TABLE t; SELECT * FROM t; DROP TABLE t; disconnect con1; } SET DEBUG_SYNC = 'RESET'; --echo # --echo # Bug#28825718 - ASSERTION FAILURE: TRX0REC.CC:NNN:N_IDX > 0 WHILE DOING REPLACE/INSERT --echo # CREATE TABLE t1(a INT PRIMARY KEY, b INT, c INT GENERATED ALWAYS AS(b+1) VIRTUAL) ENGINE=InnoDB; INSERT INTO t1(a, b) VALUES(1, 1); connect (con1,localhost,root,,); SET DEBUG_SYNC = 'row_log_apply_after SIGNAL s1 WAIT_FOR s2'; SET lock_wait_timeout = 1; --send ALTER TABLE t1 ADD UNIQUE INDEX(c, b) connection default; SET DEBUG_SYNC = 'now WAIT_FOR s1'; SET DEBUG_SYNC = 'row_log_insert_handle SIGNAL s2 WAIT_FOR s3'; --send INSERT INTO t1(a, b) VALUES(2, 2) connection con1; --error ER_LOCK_WAIT_TIMEOUT reap; SET DEBUG_SYNC = 'now SIGNAL s3'; disconnect con1; connection default; reap; SET DEBUG_SYNC = 'RESET'; ALTER TABLE t1 ADD KEY(b); INSERT INTO t1(a, b) VALUES(3, 3); SELECT * FROM t1; CHECK TABLE t1; DROP TABLE t1; --echo # --echo # MDEV-28806 Assertion `flag == 1' failure in --echo # row_build_index_entry_low upon concurrent ALTER and UPDATE --echo # CREATE TABLE t1(a CHAR(8), b INT, c INT AS (b), KEY(a)) ENGINE=InnoDB; INSERT INTO t1(b) VALUES (1),(2); --connect (con1,localhost,root,,test) SET DEBUG_SYNC="alter_table_inplace_before_lock_upgrade SIGNAL dml_start WAIT_FOR dml_commit"; send ALTER TABLE t1 ADD KEY ind (c); --connection default SET DEBUG_SYNC="now WAIT_FOR dml_start"; UPDATE t1 SET a ='foo'; SET DEBUG_SYNC="now SIGNAL dml_commit"; # Cleanup --connection con1 --reap CHECK TABLE t1; DROP TABLE t1; --disconnect con1 connection default; SET DEBUG_SYNC=RESET; SET GLOBAL innodb_stats_persistent = @save_stats_persistent; --source include/wait_until_count_sessions.inc