SET @@session.default_storage_engine = 'InnoDB'; # - UNIQUE KEY # - INDEX # - FULLTEXT INDEX # - SPATIAL INDEX (not supported) # - FOREIGN INDEX (partially supported) # - CHECK (allowed but not used) # UNIQUE create table t1 (a int, b int generated always as (a*2) stored unique); show create table t1; Table Create Table t1 CREATE TABLE `t1` ( `a` int(11) DEFAULT NULL, `b` int(11) GENERATED ALWAYS AS (`a` * 2) STORED, UNIQUE KEY `b` (`b`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 describe t1; Field Type Null Key Default Extra a int(11) YES NULL b int(11) YES UNI NULL STORED GENERATED drop table t1; create table t1 (a int, b int generated always as (a*2) stored, unique (b)); show create table t1; Table Create Table t1 CREATE TABLE `t1` ( `a` int(11) DEFAULT NULL, `b` int(11) GENERATED ALWAYS AS (`a` * 2) STORED, UNIQUE KEY `b` (`b`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 describe t1; Field Type Null Key Default Extra a int(11) YES NULL b int(11) YES UNI NULL STORED GENERATED drop table t1; create table t1 (a int, b int generated always as (a*2) stored); alter table t1 add unique key (b); drop table t1; # Testing data manipulation operations involving UNIQUE keys # on generated columns can be found in: # - gcol_ins_upd.inc # - gcol_select.inc # # INDEX create table t1 (a int, b int generated always as (a*2) stored, index (b)); show create table t1; Table Create Table t1 CREATE TABLE `t1` ( `a` int(11) DEFAULT NULL, `b` int(11) GENERATED ALWAYS AS (`a` * 2) STORED, KEY `b` (`b`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 describe t1; Field Type Null Key Default Extra a int(11) YES NULL b int(11) YES MUL NULL STORED GENERATED drop table t1; create table t1 (a int, b int generated always as (a*2) stored, index (a,b)); show create table t1; Table Create Table t1 CREATE TABLE `t1` ( `a` int(11) DEFAULT NULL, `b` int(11) GENERATED ALWAYS AS (`a` * 2) STORED, KEY `a` (`a`,`b`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 describe t1; Field Type Null Key Default Extra a int(11) YES MUL NULL b int(11) YES NULL STORED GENERATED drop table t1; create table t1 (a int, b int generated always as (a*2) stored); alter table t1 add index (b); drop table t1; create table t1 (a int, b int generated always as (a*2) stored); alter table t1 add index (a,b); create table t2 like t1; drop table t2; drop table t1; # Testing data manipulation operations involving INDEX # on generated columns can be found in: # - gcol_select.inc # # TODO: FULLTEXT INDEX # SPATIAL INDEX # FOREIGN KEY # Rejected FK options. create table t1 (a int, b int generated always as (a+1) stored, foreign key (b) references t2(a) on update set null); ERROR HY000: Cannot define foreign key with ON UPDATE SET NULL clause on a generated column create table t1 (a int, b int generated always as (a+1) stored, foreign key (b) references t2(a) on update cascade); ERROR HY000: Cannot define foreign key with ON UPDATE CASCADE clause on a generated column create table t1 (a int, b int generated always as (a+1) stored, foreign key (b) references t2(a) on delete set null); ERROR HY000: Cannot define foreign key with ON DELETE SET NULL clause on a generated column create table t1 (a int, b int generated always as (a+1) stored); alter table t1 add foreign key (b) references t2(a) on update set null; ERROR HY000: Cannot define foreign key with ON UPDATE SET NULL clause on a generated column alter table t1 add foreign key (b) references t2(a) on update cascade; ERROR HY000: Cannot define foreign key with ON UPDATE CASCADE clause on a generated column alter table t1 add foreign key (b) references t2(a) on delete set null; ERROR HY000: Cannot define foreign key with ON DELETE SET NULL clause on a generated column drop table t1; # Allowed FK options. create table t2 (a int primary key, b char(5)); create table t1 (a int, b int generated always as (a % 10) stored, foreign key (b) references t2(a) on update restrict); drop table t1; create table t1 (a int, b int generated always as (a % 10) stored, foreign key (b) references t2(a) on update no action); drop table t1; create table t1 (a int, b int generated always as (a % 10) stored, foreign key (b) references t2(a) on delete restrict); drop table t1; create table t1 (a int, b int generated always as (a % 10) stored, foreign key (b) references t2(a) on delete cascade); drop table t1; create table t1 (a int, b int generated always as (a % 10) stored, foreign key (b) references t2(a) on delete no action); drop table t1,t2; # Testing data manipulation operations involving FOREIGN KEY # on generated columns can be found in: # - gcol_ins_upd.inc # - gcol_select.inc # # TODO: CHECK # # Test how optimizer picks indexes defined on a GC # CREATE TABLE t1 (f1 int, gc int AS (f1 + 1) STORED, UNIQUE(gc)); INSERT INTO t1(f1) VALUES (1),(2),(0),(9),(3),(4),(8),(7),(5),(6); ANALYZE TABLE t1; Table Op Msg_type Msg_text test.t1 analyze status OK # Should use index SELECT * FROM t1 WHERE f1 + 1 > 7; f1 gc 7 8 8 9 9 10 EXPLAIN SELECT * FROM t1 WHERE f1 + 1 > 7; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 10 Using where SELECT * FROM t1 WHERE f1 + 1 = 7; f1 gc 6 7 EXPLAIN SELECT * FROM t1 WHERE f1 + 1 = 7; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 10 Using where SELECT * FROM t1 WHERE f1 + 1 IN (7,5); f1 gc 4 5 6 7 EXPLAIN SELECT * FROM t1 WHERE f1 + 1 IN(7,5); id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 10 Using where SELECT * FROM t1 WHERE f1 + 1 BETWEEN 5 AND 7; f1 gc 4 5 5 6 6 7 EXPLAIN SELECT * FROM t1 WHERE f1 + 1 BETWEEN 5 AND 7; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 10 Using where # Check that expression isn't transformed for a disabled key SELECT * FROM t1 IGNORE KEY (gc) WHERE f1 + 1 BETWEEN 5 AND 7; f1 gc 4 5 5 6 6 7 EXPLAIN SELECT * FROM t1 IGNORE KEY (gc) WHERE f1 + 1 BETWEEN 5 AND 7; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 10 Using where # Check that ORDER BY could be optimized SELECT * FROM t1 ORDER BY f1 + 1; f1 gc 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10 EXPLAIN SELECT * FROM t1 ORDER BY f1 + 1; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 10 Using filesort EXPLAIN SELECT * FROM t1 IGNORE KEY (gc) ORDER BY f1 + 1; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 10 Using filesort # Check that GROUP BY could be optimized SELECT f1 + 1, MAX(GC) FROM t1 GROUP BY f1 + 1; f1 + 1 MAX(GC) 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10 10 EXPLAIN SELECT f1 + 1, MAX(GC) FROM t1 GROUP BY f1 + 1; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 10 Using temporary; Using filesort EXPLAIN SELECT f1 + 1, MAX(GC) FROM t1 IGNORE KEY (gc) GROUP BY f1 + 1; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 10 Using temporary; Using filesort # Shouldn't use index SELECT * FROM t1 WHERE f1 + 1 > 7.0; f1 gc 7 8 8 9 9 10 EXPLAIN SELECT * FROM t1 WHERE f1 + 1 > 7.0; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 10 Using where DROP TABLE t1; # Pick index with proper type CREATE TABLE t1 (f1 int, gc_int int AS (f1 + 1) STORED, gc_date DATE AS (f1 + 1) STORED, KEY gc_int_idx(gc_int), KEY gc_date_idx(gc_date)); INSERT INTO t1(f1) VALUES (030303),(040404), (050505),(060606), (010101),(020202), (030303),(040404), (050505),(060606), (010101),(020202), (090909),(101010), (010101),(020202), (070707),(080808); ANALYZE TABLE t1; Table Op Msg_type Msg_text test.t1 analyze status OK SELECT * FROM t1 WHERE f1 + 1 > 070707; f1 gc_int gc_date 101010 101011 2010-10-11 70707 70708 2007-07-08 80808 80809 2008-08-09 90909 90910 2009-09-10 # INT column & index should be picked EXPLAIN SELECT * FROM t1 WHERE f1 + 1 > 070707; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 18 Using where SELECT * FROM t1 WHERE f1 + 1 > CAST(070707 AS DATE); f1 gc_int gc_date 101010 101011 2010-10-11 70707 70708 2007-07-08 80808 80809 2008-08-09 90909 90910 2009-09-10 # DATE column & index should be picked EXPLAIN SELECT * FROM t1 WHERE f1 + 1 > CAST(070707 AS DATE); id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 18 Using where DROP TABLE t1; # # BUG#21229846: WL8170: SIGNAL 11 IN JOIN::MAKE_SUM_FUNC_LIST # CREATE TABLE t1 ( pk int primary key auto_increment, col_int_key INTEGER , col_int_gc_key INT GENERATED ALWAYS AS (col_int_key + 1) STORED, KEY col_int_gc_key(col_int_gc_key) ); INSERT INTO t1 ( col_int_key) VALUES (7); ANALYZE TABLE t1; Table Op Msg_type Msg_text test.t1 analyze status OK SELECT table1.col_int_key + 1 AS field1, table2.col_int_key AS field2 FROM (t1 AS table1 JOIN t1 AS table2 ON (table2.pk = table1.pk)) ORDER BY field1, field2; field1 field2 8 7 EXPLAIN SELECT table1.col_int_key + 1 AS field1, table2.col_int_key AS field2 FROM (t1 AS table1 JOIN t1 AS table2 ON (table2.pk = table1.pk)) ORDER BY field1, field2; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE table1 ALL PRIMARY NULL NULL NULL 1 Using temporary; Using filesort 1 SIMPLE table2 eq_ref PRIMARY PRIMARY 4 test.table1.pk 1 SELECT table1.col_int_key + 1 AS field1, table2.col_int_key AS field2 FROM (t1 AS table1 JOIN t1 AS table2 ON (table2.pk = table1.pk)) GROUP BY field1, field2; field1 field2 8 7 EXPLAIN SELECT table1.col_int_key + 1 AS field1, table2.col_int_key AS field2 FROM (t1 AS table1 JOIN t1 AS table2 ON (table2.pk = table1.pk)) GROUP BY field1, field2; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE table1 ALL PRIMARY NULL NULL NULL 1 Using temporary; Using filesort 1 SIMPLE table2 eq_ref PRIMARY PRIMARY 4 test.table1.pk 1 DROP TABLE t1; # # Bug#21770798 OPTIMIZER DOES NOT USE INDEX FOR GENERATED EXPRESSIONS # WITH LOGICAL OPERATORS # CREATE TABLE t (a INT, b INT, gc_and INT GENERATED ALWAYS AS (a AND b) STORED, gc_or INT GENERATED ALWAYS AS (a OR b) STORED, gc_xor INT GENERATED ALWAYS AS (a XOR b) STORED, gc_not INT GENERATED ALWAYS AS (NOT a) STORED, gc_case INT GENERATED ALWAYS AS (CASE WHEN (a AND b) THEN a ELSE b END) STORED, INDEX(gc_and), INDEX(gc_or), INDEX(gc_xor), INDEX(gc_not), INDEX(gc_case)); INSERT INTO t (a, b) VALUES (0, 0), (0, 1), (1, 0), (1, 1); ANALYZE TABLE t; Table Op Msg_type Msg_text test.t analyze status OK EXPLAIN SELECT a, b FROM t WHERE (a AND b) = 1; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t ALL NULL NULL NULL NULL 4 Using where SELECT a, b FROM t WHERE (a AND b) = 1; a b 1 1 EXPLAIN SELECT a, b FROM t WHERE 1 = (a AND b); id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t ALL NULL NULL NULL NULL 4 Using where SELECT a, b FROM t WHERE 1 = (a AND b); a b 1 1 EXPLAIN SELECT a, b FROM t WHERE (a AND b) IN (1, 2, 3); id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t ALL NULL NULL NULL NULL 4 Using where SELECT a, b FROM t WHERE (a AND b) IN (1, 2, 3); a b 1 1 EXPLAIN SELECT a, b FROM t WHERE (a OR b) = 1; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t ALL NULL NULL NULL NULL 4 Using where SELECT a, b FROM t WHERE (a OR b) = 1; a b 0 1 1 0 1 1 EXPLAIN SELECT a, b FROM t WHERE (a OR b) BETWEEN 1 AND 10; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t ALL NULL NULL NULL NULL 4 Using where SELECT a, b FROM t WHERE (a OR b) BETWEEN 1 AND 10; a b 0 1 1 0 1 1 EXPLAIN SELECT a, b FROM t WHERE (a XOR b) = 1; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t ALL NULL NULL NULL NULL 4 Using where SELECT a, b FROM t WHERE (a XOR b) = 1; a b 0 1 1 0 EXPLAIN SELECT a FROM t WHERE (NOT a) = 1; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t ALL NULL NULL NULL NULL 4 Using where SELECT a FROM t WHERE (NOT a) = 1; a 0 0 EXPLAIN SELECT a FROM t WHERE (CASE WHEN (a AND b) THEN a ELSE b END) = 1; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t ALL NULL NULL NULL NULL 4 Using where SELECT a FROM t WHERE (CASE WHEN (a AND b) THEN a ELSE b END) = 1; a 0 1 EXPLAIN SELECT a, b FROM t WHERE 1 = (b AND a); id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t ALL NULL NULL NULL NULL 4 Using where SELECT a, b FROM t WHERE 1 = (b AND a); a b 1 1 EXPLAIN SELECT a, b FROM t WHERE 1 = (b OR a); id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t ALL NULL NULL NULL NULL 4 Using where SELECT a, b FROM t WHERE 1 = (b OR a); a b 0 1 1 0 1 1 DROP TABLE t; # # Bug#22810883: ASSERTION FAILED: # !(USED_TABS & (~READ_TABLES & ~FILTER_FOR_TABLE)) # CREATE TABLE t1 (a1 INTEGER GENERATED ALWAYS AS (1 AND 0) STORED, a2 INTEGER, KEY (a1)); INSERT INTO t1 VALUES (); CREATE TABLE t2 (b INTEGER); INSERT INTO t2 VALUES (1); ANALYZE TABLE t1, t2; Table Op Msg_type Msg_text test.t1 analyze status OK test.t2 analyze status OK # Used to choose the index on a1 and get wrong results. EXPLAIN SELECT * FROM t1 WHERE (a2 AND a2) = 0; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 1 Using where SELECT * FROM t1 WHERE (a2 AND a2) = 0; a1 a2 # Used to get assertion or wrong results. EXPLAIN SELECT * FROM t1 STRAIGHT_JOIN t2 ON b WHERE (b AND b) = 1; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 1 1 SIMPLE t2 ALL NULL NULL NULL NULL 1 Using where; Using join buffer (flat, BNL join) SELECT * FROM t1 STRAIGHT_JOIN t2 ON b WHERE (b AND b) = 1; a1 a2 b 0 NULL 1 DROP TABLE t1, t2; # DROP VIEW IF EXISTS v1,v2; DROP TABLE IF EXISTS t1,t2,t3; DROP PROCEDURE IF EXISTS p1; DROP FUNCTION IF EXISTS f1; DROP TRIGGER IF EXISTS trg1; DROP TRIGGER IF EXISTS trg2; set sql_warnings = 0;