1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-01 03:47:19 +03:00

MDEV-5800 InnoDB support for indexed vcols

* remove old 5.2+ InnoDB support for virtual columns
  * enable corresponding parts of the innodb-5.7 sources
  * copy corresponding test cases from 5.7
  * copy detailed Alter_inplace_info::HA_ALTER_FLAGS flags from 5.7
     - and more detailed detection of changes in fill_alter_inplace_info()
  * more "innodb compatibility hooks" in sql_class.cc to
     - create/destroy/reset a THD (used by background purge threads)
     - find a prelocked table by name
     - open a table (from a background purge thread)

  * different from 5.7:
    - new service thread "thd_destructor_proxy" to make sure all THDs are
      destroyed at the correct point in time during the server shutdown
    - proper opening/closing of tables for vcol evaluations in
       + FK checks (use already opened prelocked tables)
       + purge threads (open the table, MDLock it, add it to tdc, close
         when not needed)
    - cache open tables in vc_templ
    - avoid unnecessary allocations, reuse table->record[0] and table->s->default_values
    - not needed in 5.7, because it overcalculates:
      + tell the server to calculate vcols for an on-going inline ADD INDEX
      + calculate vcols for correct error messages

  * update other engines (mroonga/tokudb) accordingly
This commit is contained in:
Sergei Golubchik
2016-11-07 22:35:02 +01:00
parent 7fca91f2b4
commit 1cae1af6f9
65 changed files with 7367 additions and 1106 deletions

View File

@ -0,0 +1,240 @@
--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;
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;
SET DEBUG_SYNC = 'innodb_inplace_alter_table_enter SIGNAL start_create WAIT_FOR go_ahead';
--send ALTER TABLE t ADD COLUMN x INT
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 ADD COLUMN x2 INT
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 SESSION 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);
SET SESSION debug_dbug="";
--disable_info
SHOW CREATE TABLE t;
SELECT c FROM t;
DROP TABLE t;
--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;
disconnect con1;
SET DEBUG_SYNC = 'RESET';
--source include/wait_until_count_sessions.inc