diff --git a/mysql-test/main/mdev_38752.result b/mysql-test/main/mdev_38752.result new file mode 100644 index 0000000000000..c5d62c7936a97 --- /dev/null +++ b/mysql-test/main/mdev_38752.result @@ -0,0 +1,89 @@ +# +# MDEV-38752: Wrong result upon GROUP BY on a table with indexed virtual column after INSERT IGNORE +# +# Case 1: Unsafe narrowing substitution (INT -> TINYINT) +CREATE TABLE t1 (a INT PRIMARY KEY, va TINYINT AS (a), KEY(va)); +INSERT IGNORE INTO t1 (a) VALUES (100),(150),(200); +Warnings: +Warning 1264 Out of range value for column 'va' at row 2 +Warning 1264 Out of range value for column 'va' at row 3 +# Should return 3 rows (fix: substitution disallowed) +# EXPLAIN should show that va index is NOT used +EXPLAIN SELECT a, va, COUNT(*) FROM t1 GROUP BY a; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index NULL PRIMARY 4 NULL # Using index +Warnings: +Note 1105 Cannot substitute virtual column expression `t1`.`a` -> va due to type mismatch +SHOW WARNINGS; +Level Code Message +Note 1105 Cannot substitute virtual column expression `t1`.`a` -> va due to type mismatch +SELECT a, va, COUNT(*) FROM t1 GROUP BY a; +a va COUNT(*) +100 100 1 +150 127 1 +200 127 1 +DROP TABLE t1; +# Case 2: Safe substitution (INT -> INT) +CREATE TABLE t2 (a INT PRIMARY KEY, va INT AS (a), KEY(va)); +INSERT INTO t2 (a) VALUES (100),(150),(200); +# Should return 3 rows (substitution allowed, uses va index) +# EXPLAIN should show that va index is used +EXPLAIN SELECT va, COUNT(*) FROM t2 GROUP BY a; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 index NULL va 5 NULL # Using index +SHOW WARNINGS; +Level Code Message +SELECT va, COUNT(*) FROM t2 GROUP BY a; +va COUNT(*) +100 1 +150 1 +200 1 +DROP TABLE t2; +# Case 3: Unsafe narrowing for VARCHAR +CREATE TABLE t3 (a VARCHAR(20) PRIMARY KEY, va VARCHAR(5) AS (a), KEY(va)); +INSERT IGNORE INTO t3 (a) VALUES ('apple'),('banana'),('apricot'); +Warnings: +Warning 1265 Data truncated for column 'va' at row 2 +Warning 1265 Data truncated for column 'va' at row 3 +# 'apple' and 'apricot' both truncate to 'apple' in va +# Should return 3 rows +# EXPLAIN should show that va index is NOT used +EXPLAIN SELECT a, va, COUNT(*) FROM t3 GROUP BY a; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t3 index NULL PRIMARY 82 NULL # Using index +Warnings: +Note 1105 Cannot substitute virtual column expression `t3`.`a` -> va due to type mismatch +SHOW WARNINGS; +Level Code Message +Note 1105 Cannot substitute virtual column expression `t3`.`a` -> va due to type mismatch +SELECT a, va, COUNT(*) FROM t3 GROUP BY a; +a va COUNT(*) +apple apple 1 +apricot apric 1 +banana banan 1 +DROP TABLE t3; +# Case 4: Unsafe narrowing for DECIMAL +CREATE TABLE t4 (a DECIMAL(10,5) PRIMARY KEY, va DECIMAL(10,2) AS (a), KEY(va)); +INSERT IGNORE INTO t4 (a) VALUES (1.12345), (1.12346), (1.12999); +Warnings: +Note 1265 Data truncated for column 'va' at row 1 +Note 1265 Data truncated for column 'va' at row 2 +Note 1265 Data truncated for column 'va' at row 3 +# All three values truncate to 1.12 in va +# Should return 3 rows +# EXPLAIN should show that va index is NOT used +EXPLAIN SELECT a, va, COUNT(*) FROM t4 GROUP BY a; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t4 index NULL PRIMARY 6 NULL # Using index +Warnings: +Note 1105 Cannot substitute virtual column expression `t4`.`a` -> va due to type mismatch +SHOW WARNINGS; +Level Code Message +Note 1105 Cannot substitute virtual column expression `t4`.`a` -> va due to type mismatch +SELECT a, va, COUNT(*) FROM t4 GROUP BY a; +a va COUNT(*) +1.12345 1.12 1 +1.12346 1.12 1 +1.12999 1.13 1 +DROP TABLE t4; +# End of mdev_38752 tests diff --git a/mysql-test/main/mdev_38752.test b/mysql-test/main/mdev_38752.test new file mode 100644 index 0000000000000..fdd40892beaad --- /dev/null +++ b/mysql-test/main/mdev_38752.test @@ -0,0 +1,53 @@ +--source include/have_innodb.inc + +--echo # +--echo # MDEV-38752: Wrong result upon GROUP BY on a table with indexed virtual column after INSERT IGNORE +--echo # + +--echo # Case 1: Unsafe narrowing substitution (INT -> TINYINT) +CREATE TABLE t1 (a INT PRIMARY KEY, va TINYINT AS (a), KEY(va)); +INSERT IGNORE INTO t1 (a) VALUES (100),(150),(200); +--echo # Should return 3 rows (fix: substitution disallowed) +--echo # EXPLAIN should show that va index is NOT used +--replace_column 9 # +EXPLAIN SELECT a, va, COUNT(*) FROM t1 GROUP BY a; +SHOW WARNINGS; +SELECT a, va, COUNT(*) FROM t1 GROUP BY a; +DROP TABLE t1; + +--echo # Case 2: Safe substitution (INT -> INT) +CREATE TABLE t2 (a INT PRIMARY KEY, va INT AS (a), KEY(va)); +INSERT INTO t2 (a) VALUES (100),(150),(200); +--echo # Should return 3 rows (substitution allowed, uses va index) +--echo # EXPLAIN should show that va index is used +--replace_column 9 # +EXPLAIN SELECT va, COUNT(*) FROM t2 GROUP BY a; +SHOW WARNINGS; +SELECT va, COUNT(*) FROM t2 GROUP BY a; +DROP TABLE t2; + +--echo # Case 3: Unsafe narrowing for VARCHAR +CREATE TABLE t3 (a VARCHAR(20) PRIMARY KEY, va VARCHAR(5) AS (a), KEY(va)); +INSERT IGNORE INTO t3 (a) VALUES ('apple'),('banana'),('apricot'); +--echo # 'apple' and 'apricot' both truncate to 'apple' in va +--echo # Should return 3 rows +--echo # EXPLAIN should show that va index is NOT used +--replace_column 9 # +EXPLAIN SELECT a, va, COUNT(*) FROM t3 GROUP BY a; +SHOW WARNINGS; +SELECT a, va, COUNT(*) FROM t3 GROUP BY a; +DROP TABLE t3; + +--echo # Case 4: Unsafe narrowing for DECIMAL +CREATE TABLE t4 (a DECIMAL(10,5) PRIMARY KEY, va DECIMAL(10,2) AS (a), KEY(va)); +INSERT IGNORE INTO t4 (a) VALUES (1.12345), (1.12346), (1.12999); +--echo # All three values truncate to 1.12 in va +--echo # Should return 3 rows +--echo # EXPLAIN should show that va index is NOT used +--replace_column 9 # +EXPLAIN SELECT a, va, COUNT(*) FROM t4 GROUP BY a; +SHOW WARNINGS; +SELECT a, va, COUNT(*) FROM t4 GROUP BY a; +DROP TABLE t4; + +--echo # End of mdev_38752 tests diff --git a/mysql-test/suite/vcol/r/order_by_group_by_subst.result b/mysql-test/suite/vcol/r/order_by_group_by_subst.result index a5e19fbb2bddd..c1c02ca3580f2 100644 --- a/mysql-test/suite/vcol/r/order_by_group_by_subst.result +++ b/mysql-test/suite/vcol/r/order_by_group_by_subst.result @@ -18,12 +18,16 @@ id select_type table type possible_keys key key_len ref rows Extra explain select c + 1 from t order by c + 1; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t index NULL c 5 NULL 10000 Using index; Using filesort +Warnings: +Note 1105 Cannot substitute virtual column expression `t`.`c` + 1 -> vc due to type mismatch explain select c + 1 from t order by vc; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t index NULL c 5 NULL 10000 Using index; Using filesort explain select vc from t order by c + 1; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t index NULL vc 5 NULL 10000 Using index +1 SIMPLE t index NULL c 5 NULL 10000 Using index; Using filesort +Warnings: +Note 1105 Cannot substitute virtual column expression `t`.`c` + 1 -> vc due to type mismatch explain select vc from t order by c; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t index NULL c 5 NULL 10000 Using index @@ -33,28 +37,40 @@ id select_type table type possible_keys key key_len ref rows Extra explain select c from t order by c + 1; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t index NULL c 5 NULL 10000 Using index; Using filesort +Warnings: +Note 1105 Cannot substitute virtual column expression `t`.`c` + 1 -> vc due to type mismatch explain select vc from t order by c + 1 limit 2; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t index NULL vc 5 NULL 2 Using index +1 SIMPLE t index NULL c 5 NULL 10000 Using index; Using filesort +Warnings: +Note 1105 Cannot substitute virtual column expression `t`.`c` + 1 -> vc due to type mismatch explain select c + 1 from t order by c + 1 limit 2; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t index NULL vc 5 NULL 2 +1 SIMPLE t index NULL c 5 NULL 10000 Using index; Using filesort +Warnings: +Note 1105 Cannot substitute virtual column expression `t`.`c` + 1 -> vc due to type mismatch explain select c + 1 from t order by vc limit 2; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t index NULL vc 5 NULL 2 explain delete from t order by c + 1 limit 2; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t index NULL vc 5 NULL 2 +1 SIMPLE t ALL NULL NULL NULL NULL 10000 Using filesort +Warnings: +Note 1105 Cannot substitute virtual column expression `t`.`c` + 1 -> vc due to type mismatch alter table t add column d int; explain update t set d = 500 order by c + 1 limit 2; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t index NULL vc 5 NULL 2 Using buffer +1 SIMPLE t ALL NULL NULL NULL NULL 10000 Using filesort +Warnings: +Note 1105 Cannot substitute virtual column expression `t`.`c` + 1 -> vc due to type mismatch explain update t set d = 500 order by c limit 2; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t index NULL c 5 NULL 2 Using buffer explain update t set c = 500 order by c + 1 limit 2; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t index NULL vc 5 NULL 2 Using buffer +1 SIMPLE t ALL NULL NULL NULL NULL 10000 Using filesort +Warnings: +Note 1105 Cannot substitute virtual column expression `t`.`c` + 1 -> vc due to type mismatch explain update t set c = 500 order by c limit 2; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t index NULL c 5 NULL 2 Using buffer @@ -66,10 +82,14 @@ add column vc int as (c + 1), add index(vc); explain select vc from t order by c + 1; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t index NULL vc 5 NULL 10000 Using index +1 SIMPLE t ALL NULL NULL NULL NULL 10000 Using filesort +Warnings: +Note 1105 Cannot substitute virtual column expression `t`.`c` + 1 -> vc due to type mismatch explain select vc from t order by c + 1 limit 10; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t index NULL vc 5 NULL 10 Using index +1 SIMPLE t ALL NULL NULL NULL NULL 10000 Using filesort +Warnings: +Note 1105 Cannot substitute virtual column expression `t`.`c` + 1 -> vc due to type mismatch drop table t; create table t (c int, key (c)); insert into t select seq from seq_1_to_10000; @@ -84,10 +104,14 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t index NULL c 5 NULL 10000 Using index; Using filesort explain select vc2 from t order by vc1 * 2; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t index NULL vc2 5 NULL 10000 Using index +1 SIMPLE t index NULL c 5 NULL 10000 Using index; Using filesort +Warnings: +Note 1105 Cannot substitute virtual column expression `t`.`vc1` * 2 -> vc2 due to type mismatch explain select vc2 from t order by vc1 * 2 limit 2; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t index NULL vc2 5 NULL 2 Using index +1 SIMPLE t index NULL c 5 NULL 10000 Using index; Using filesort +Warnings: +Note 1105 Cannot substitute virtual column expression `t`.`vc1` * 2 -> vc2 due to type mismatch drop table t; create table t (c int, vc int generated always as (1 + 1) virtual, key (c)); insert into t values (42, default), (83, default); @@ -108,7 +132,10 @@ add column vc2 int as (1 - c), add index(vc1, vc2); explain select vc1, vc2 from t order by c + 1, 1 - c; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t index NULL vc1 10 NULL 10000 Using index +1 SIMPLE t ALL NULL NULL NULL NULL 10000 Using filesort +Warnings: +Note 1105 Cannot substitute virtual column expression `t`.`c` + 1 -> vc1 due to type mismatch +Note 1105 Cannot substitute virtual column expression 1 - `t`.`c` -> vc2 due to type mismatch drop table t; create table t (c int, key (c)); insert into t select seq from seq_1_to_10000; @@ -127,12 +154,16 @@ id select_type table type possible_keys key key_len ref rows Extra explain select c + 1 from t group by c + 1; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t index NULL c 5 NULL 10000 Using index; Using temporary; Using filesort +Warnings: +Note 1105 Cannot substitute virtual column expression `t`.`c` + 1 -> vc due to type mismatch explain select c + 1 from t group by vc; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t index NULL c 5 NULL 10000 Using index; Using temporary; Using filesort explain select vc from t group by c + 1; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t index NULL vc 5 NULL 10000 Using index +1 SIMPLE t index NULL c 5 NULL 10000 Using index; Using temporary; Using filesort +Warnings: +Note 1105 Cannot substitute virtual column expression `t`.`c` + 1 -> vc due to type mismatch explain select vc from t group by c; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t index NULL c 5 NULL 10000 Using index @@ -142,12 +173,18 @@ id select_type table type possible_keys key key_len ref rows Extra explain select c from t group by c + 1; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t index NULL c 5 NULL 10000 Using index; Using temporary; Using filesort +Warnings: +Note 1105 Cannot substitute virtual column expression `t`.`c` + 1 -> vc due to type mismatch explain select vc from t group by c + 1 limit 2; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t index NULL vc 5 NULL 2 Using index +1 SIMPLE t index NULL c 5 NULL 10000 Using index; Using temporary; Using filesort +Warnings: +Note 1105 Cannot substitute virtual column expression `t`.`c` + 1 -> vc due to type mismatch explain select c + 1 from t group by c + 1 limit 2; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t index NULL vc 5 NULL 2 +1 SIMPLE t index NULL c 5 NULL 10000 Using index; Using temporary; Using filesort +Warnings: +Note 1105 Cannot substitute virtual column expression `t`.`c` + 1 -> vc due to type mismatch explain select c + 1 from t group by vc limit 2; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t index NULL vc 5 NULL 2 @@ -159,10 +196,14 @@ add column vc int as (c + 1), add index(vc); explain select vc from t group by c + 1; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t index NULL vc 5 NULL 10000 Using index +1 SIMPLE t ALL NULL NULL NULL NULL 10000 Using temporary; Using filesort +Warnings: +Note 1105 Cannot substitute virtual column expression `t`.`c` + 1 -> vc due to type mismatch explain select vc from t group by c + 1 limit 10; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t index NULL vc 5 NULL 10 Using index +1 SIMPLE t ALL NULL NULL NULL NULL 10000 Using temporary; Using filesort +Warnings: +Note 1105 Cannot substitute virtual column expression `t`.`c` + 1 -> vc due to type mismatch drop table t; create table t (c int, key (c)); insert into t select seq from seq_1_to_10000; @@ -177,10 +218,14 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t index NULL c 5 NULL 10000 Using index; Using temporary; Using filesort explain select vc2 from t group by vc1 * 2; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t index NULL vc2 5 NULL 10000 Using index +1 SIMPLE t index NULL c 5 NULL 10000 Using index; Using temporary; Using filesort +Warnings: +Note 1105 Cannot substitute virtual column expression `t`.`vc1` * 2 -> vc2 due to type mismatch explain select vc2 from t group by vc1 * 2 limit 2; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t index NULL vc2 5 NULL 2 Using index +1 SIMPLE t index NULL c 5 NULL 10000 Using index; Using temporary; Using filesort +Warnings: +Note 1105 Cannot substitute virtual column expression `t`.`vc1` * 2 -> vc2 due to type mismatch drop table t; create table t (c int); insert into t select seq from seq_1_to_10000; @@ -191,7 +236,10 @@ add column vc2 int as (1 - c), add index(vc1, vc2); explain select vc1, vc2 from t group by c + 1, 1 - c; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t index NULL vc1 10 NULL 10000 Using index +1 SIMPLE t ALL NULL NULL NULL NULL 10000 Using temporary; Using filesort +Warnings: +Note 1105 Cannot substitute virtual column expression `t`.`c` + 1 -> vc1 due to type mismatch +Note 1105 Cannot substitute virtual column expression 1 - `t`.`c` -> vc2 due to type mismatch drop table t; # # MDEV-37435 Assertion `field' failed in virtual bool Item_field::fix_fields(THD *, Item **) diff --git a/mysql-test/suite/vcol/r/order_by_group_by_subst_notembedded.result b/mysql-test/suite/vcol/r/order_by_group_by_subst_notembedded.result index 40153c1d44173..b926e8722c6a0 100644 --- a/mysql-test/suite/vcol/r/order_by_group_by_subst_notembedded.result +++ b/mysql-test/suite/vcol/r/order_by_group_by_subst_notembedded.result @@ -11,33 +11,25 @@ set optimizer_trace=1; explain select c + 1 from t order by c + 1; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t index NULL c 5 NULL 10000 Using index; Using filesort +Warnings: +Note 1105 Cannot substitute virtual column expression `t`.`c` + 1 -> vc due to type mismatch select json_detailed(json_extract(trace, '$**.virtual_column_substitution')) from information_schema.optimizer_trace; json_detailed(json_extract(trace, '$**.virtual_column_substitution')) -[ - { - "location": "ORDER BY", - "from": "t.c + 1", - "to": "t.vc" - } -] +NULL explain select c + 1 from t group by c + 1; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t index NULL c 5 NULL 10000 Using index; Using temporary; Using filesort +Warnings: +Note 1105 Cannot substitute virtual column expression `t`.`c` + 1 -> vc due to type mismatch select json_detailed(json_extract(trace, '$**.virtual_column_substitution')) from information_schema.optimizer_trace; json_detailed(json_extract(trace, '$**.virtual_column_substitution')) -[ - { - "location": "GROUP BY", - "from": "t.c + 1", - "to": "t.vc" - } -] +NULL set optimizer_trace=@old_optimizer_trace; drop table t; create table t (c int, key (c)); @@ -53,42 +45,26 @@ set optimizer_trace=1; explain select * from t order by c + 1, 1 - c; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t index NULL c 5 NULL 10000 Using index; Using filesort +Warnings: +Note 1105 Cannot substitute virtual column expression `t`.`c` + 1 -> vc1 due to type mismatch +Note 1105 Cannot substitute virtual column expression 1 - `t`.`c` -> vc2 due to type mismatch select json_detailed(json_extract(trace, '$**.virtual_column_substitution')) from information_schema.optimizer_trace; json_detailed(json_extract(trace, '$**.virtual_column_substitution')) -[ - { - "location": "ORDER BY", - "from": "t.c + 1", - "to": "t.vc1" - }, - { - "location": "ORDER BY", - "from": "1 - t.c", - "to": "t.vc2" - } -] +NULL explain select * from t group by c + 1, 1 - c; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t index NULL c 5 NULL 10000 Using index; Using temporary; Using filesort +Warnings: +Note 1105 Cannot substitute virtual column expression `t`.`c` + 1 -> vc1 due to type mismatch +Note 1105 Cannot substitute virtual column expression 1 - `t`.`c` -> vc2 due to type mismatch select json_detailed(json_extract(trace, '$**.virtual_column_substitution')) from information_schema.optimizer_trace; json_detailed(json_extract(trace, '$**.virtual_column_substitution')) -[ - { - "location": "GROUP BY", - "from": "t.c + 1", - "to": "t.vc1" - }, - { - "location": "GROUP BY", - "from": "1 - t.c", - "to": "t.vc2" - } -] +NULL set optimizer_trace=@old_optimizer_trace; drop table t; diff --git a/mysql-test/suite/vcol/r/vcol_sargable.result b/mysql-test/suite/vcol/r/vcol_sargable.result index 427c71d743e74..3b17907222312 100644 --- a/mysql-test/suite/vcol/r/vcol_sargable.result +++ b/mysql-test/suite/vcol/r/vcol_sargable.result @@ -3,51 +3,79 @@ create table t1 (a int, vcol1 int as (a+1), index(vcol1)); insert into t1 (a) select seq from seq_1_to_100; explain select * from t1 where a+1=2; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref vcol1 vcol1 5 const 1 +1 SIMPLE t1 ALL NULL NULL NULL NULL 100 Using where +Warnings: +Note 1105 Cannot substitute virtual column expression `t1`.`a` + 1 -> vcol1 due to type mismatch # Try renaming the table explain select * from t1 as TBL where TBL.a+1=2; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE TBL ref vcol1 vcol1 5 const 1 +1 SIMPLE TBL ALL NULL NULL NULL NULL 100 Using where +Warnings: +Note 1105 Cannot substitute virtual column expression `tbl`.`a` + 1 -> vcol1 due to type mismatch explain select * from t1 where a+1<=2; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range vcol1 vcol1 5 NULL 1 Using index condition +1 SIMPLE t1 ALL NULL NULL NULL NULL 100 Using where +Warnings: +Note 1105 Cannot substitute virtual column expression `t1`.`a` + 1 -> vcol1 due to type mismatch explain select * from t1 where a+1<2; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range vcol1 vcol1 5 NULL 1 Using index condition +1 SIMPLE t1 ALL NULL NULL NULL NULL 100 Using where +Warnings: +Note 1105 Cannot substitute virtual column expression `t1`.`a` + 1 -> vcol1 due to type mismatch explain select * from t1 where a+1>100; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range vcol1 vcol1 5 NULL 6 Using index condition +1 SIMPLE t1 ALL NULL NULL NULL NULL 100 Using where +Warnings: +Note 1105 Cannot substitute virtual column expression `t1`.`a` + 1 -> vcol1 due to type mismatch explain select * from t1 where a+1>=100; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range vcol1 vcol1 5 NULL 13 Using index condition +1 SIMPLE t1 ALL NULL NULL NULL NULL 100 Using where +Warnings: +Note 1105 Cannot substitute virtual column expression `t1`.`a` + 1 -> vcol1 due to type mismatch explain select * from t1 where a+1 between 10 and 12; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range vcol1 vcol1 5 NULL 2 Using index condition +1 SIMPLE t1 ALL NULL NULL NULL NULL 100 Using where +Warnings: +Note 1105 Cannot substitute virtual column expression `t1`.`a` + 1 -> vcol1 due to type mismatch explain select * from t1 where (a+1) IS NULL; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref vcol1 vcol1 5 const 1 Using index condition +1 SIMPLE t1 ALL NULL NULL NULL NULL 100 Using where +Warnings: +Note 1105 Cannot substitute virtual column expression `t1`.`a` + 1 -> vcol1 due to type mismatch explain select * from t1 force index(vcol1) where (a+1) IS NOT NULL; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range vcol1 vcol1 5 NULL 100 Using index condition +1 SIMPLE t1 ALL NULL NULL NULL NULL 100 Using where +Warnings: +Note 1105 Cannot substitute virtual column expression `t1`.`a` + 1 -> vcol1 due to type mismatch explain select * from t1 where (a+1) in (1,2,3,4); id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range vcol1 vcol1 5 NULL 4 Using index condition +1 SIMPLE t1 ALL NULL NULL NULL NULL 100 Using where +Warnings: +Note 1105 Cannot substitute virtual column expression `t1`.`a` + 1 -> vcol1 due to type mismatch # Check UPDATE/DELETE: explain delete from t1 where a+1=2; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range vcol1 vcol1 5 NULL 1 Using where +1 SIMPLE t1 ALL NULL NULL NULL NULL 100 Using where +Warnings: +Note 1105 Cannot substitute virtual column expression `t1`.`a` + 1 -> vcol1 due to type mismatch explain update t1 set a=a+1 where a+1=2; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range vcol1 vcol1 5 NULL 1 Using where; Using buffer +1 SIMPLE t1 ALL NULL NULL NULL NULL 100 Using where +Warnings: +Note 1105 Cannot substitute virtual column expression `t1`.`a` + 1 -> vcol1 due to type mismatch # Try merged VIEWs: create view v1 as select * from t1; explain select * from v1 where a+1=2; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref vcol1 vcol1 5 const 1 +1 SIMPLE t1 ALL NULL NULL NULL NULL 100 Using where +Warnings: +Note 1105 Cannot substitute virtual column expression `t1`.`a` + 1 -> vcol1 due to type mismatch create view v2 as select a as A_COL from t1; explain select * from v2 where A_COL+1=2; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref vcol1 vcol1 5 const 1 +1 SIMPLE t1 ALL NULL NULL NULL NULL 100 Using where +Warnings: +Note 1105 Cannot substitute virtual column expression `t1`.`a` + 1 -> vcol1 due to type mismatch drop view v1; drop view v2; set names utf8mb4; @@ -73,18 +101,15 @@ id select_type table type possible_keys key key_len ref rows Extra # This will work: explain select * from t2 where concat('hello-', a)='hello-5'; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t2 ref vcol1 vcol1 131 const 1 Using index condition +1 SIMPLE t2 ALL NULL NULL NULL NULL 100 Using where +Warnings: +Note 1105 Cannot substitute virtual column expression concat('hello-',`t2`.`a`) -> vcol1 due to type mismatch select json_detailed(json_extract(trace, '$**.virtual_column_substitution')) from information_schema.optimizer_trace; json_detailed(json_extract(trace, '$**.virtual_column_substitution')) -[ - { - "condition": "WHERE", - "resulting_condition": "t2.vcol1 = 'hello-5'" - } -] +NULL # Try also ON expressions explain select * @@ -92,23 +117,17 @@ from t1 left join t2 on concat('hello-', t2.a)='hello-5' where t1.a+1=2; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref vcol1 vcol1 5 const 1 -1 SIMPLE t2 ref vcol1 vcol1 131 const 1 Using where +1 SIMPLE t1 ALL NULL NULL NULL NULL 100 Using where +1 SIMPLE t2 ALL NULL NULL NULL NULL 100 Using where; Using join buffer (flat, BNL join) +Warnings: +Note 1105 Cannot substitute virtual column expression `t1`.`a` + 1 -> vcol1 due to type mismatch +Note 1105 Cannot substitute virtual column expression concat('hello-',`t2`.`a`) -> vcol1 due to type mismatch select json_detailed(json_extract(trace, '$**.virtual_column_substitution')) from information_schema.optimizer_trace; json_detailed(json_extract(trace, '$**.virtual_column_substitution')) -[ - { - "condition": "WHERE", - "resulting_condition": "t1.vcol1 = 2" - }, - { - "condition": "ON expression", - "resulting_condition": "t2.vcol1 = 'hello-5'" - } -] +NULL create table t3 (a int); insert into t3 values (1),(2); explain @@ -119,19 +138,17 @@ t3 left join on t3.a<3; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t3 ALL NULL NULL NULL NULL 2 -1 SIMPLE t1 ref vcol1 vcol1 5 const 1 Using where -1 SIMPLE t2 ref vcol1 vcol1 131 const 1 Using where +1 SIMPLE t1 ALL NULL NULL NULL NULL 100 Using where; Using join buffer (flat, BNL join) +1 SIMPLE t2 ALL NULL NULL NULL NULL 100 Using where; Using join buffer (incremental, BNL join) +Warnings: +Note 1105 Cannot substitute virtual column expression concat('hello-',`t2`.`a`) -> vcol1 due to type mismatch +Note 1105 Cannot substitute virtual column expression `t1`.`a` + 1 -> vcol1 due to type mismatch select json_detailed(json_extract(trace, '$**.virtual_column_substitution')) from information_schema.optimizer_trace; json_detailed(json_extract(trace, '$**.virtual_column_substitution')) -[ - { - "condition": "ON expression", - "resulting_condition": "t3.a < 3 and t2.vcol1 = 'hello-5' and t1.vcol1 = 2" - } -] +NULL drop table t1,t2,t3; set optimizer_trace=@tmp_trace; # @@ -156,7 +173,7 @@ explain select * from t3 where concat('hello-', a)='abcd'; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t3 ALL NULL NULL NULL NULL 100 Using where Warnings: -Note 1105 Cannot substitute virtual column expression concat('hello-',`t3`.`a`) -> vcol2 due to collation mismatch +Note 1105 Cannot substitute virtual column expression concat('hello-',`t3`.`a`) -> vcol2 due to type mismatch drop table t3; # Try JSON_EXTRACT create table t1 (a int, js1 blob); @@ -171,7 +188,9 @@ alter table t1 add size1 int as (cast(json_extract(js1, '$.size') as int)); alter table t1 add index(size1); explain select * from t1 where cast(json_extract(js1,'$.size') as int)=5 ; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref size1 size1 5 const 1 +1 SIMPLE t1 ALL NULL NULL NULL NULL 100 Using where +Warnings: +Note 1105 Cannot substitute virtual column expression cast(json_extract(`t1`.`js1`,'$.size') as signed) -> size1 due to type mismatch alter table t1 add color varchar(100) COLLATE utf8mb4_bin as (json_unquote(json_extract(js1, '$.color'))); @@ -184,14 +203,20 @@ a js1 size1 color # Index is used: explain select * from t1 where json_unquote(json_extract(js1, '$.color'))='hue5'; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref color color 403 const 1 Using index condition +1 SIMPLE t1 ALL NULL NULL NULL NULL 100 Using where +Warnings: +Note 1105 Cannot substitute virtual column expression json_unquote(json_extract(`t1`.`js1`,'$.color')) -> color due to type mismatch explain select * from t1 where json_unquote(json_extract(js1, '$.color')) IS NULL; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref color color 403 const 1 Using index condition +1 SIMPLE t1 ALL NULL NULL NULL NULL 100 Using where +Warnings: +Note 1105 Cannot substitute virtual column expression json_unquote(json_extract(`t1`.`js1`,'$.color')) -> color due to type mismatch explain select * from t1 force index(color) where json_unquote(json_extract(js1, '$.color')) IS NOT NULL; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range color color 403 NULL 100 Using index condition +1 SIMPLE t1 ALL NULL NULL NULL NULL 100 Using where +Warnings: +Note 1105 Cannot substitute virtual column expression json_unquote(json_extract(`t1`.`js1`,'$.color')) -> color due to type mismatch alter table t1 drop column color; alter table t1 add color2 varchar(100) @@ -202,7 +227,7 @@ explain select * from t1 where json_unquote(json_extract(js1, '$.color'))='hue5' id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 100 Using where Warnings: -Note 1105 Cannot substitute virtual column expression json_unquote(json_extract(`t1`.`js1`,'$.color')) -> color2 due to collation mismatch +Note 1105 Cannot substitute virtual column expression json_unquote(json_extract(`t1`.`js1`,'$.color')) -> color2 due to type mismatch drop table t1; # # Tests with JSON_VALUE @@ -233,7 +258,9 @@ add color1 varchar(100) collate utf8mb4_bin as (json_value(js1, '$.color')), add index(color1); explain select * from t1 where json_value(js1, '$.color')='hue10'; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref color1 color1 403 const 1 Using index condition +1 SIMPLE t1 ALL NULL NULL NULL NULL 100 Using where +Warnings: +Note 1105 Cannot substitute virtual column expression json_value(`t1`.`js1`,'$.color') -> color1 due to type mismatch alter table t1 drop column color1; # Using different collation in column substitution prevents # the optimization from working: @@ -244,7 +271,7 @@ explain select * from t1 where json_value(js1, '$.color')='hue10'; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 100 Using where Warnings: -Note 1105 Cannot substitute virtual column expression json_value(`t1`.`js1`,'$.color') -> color2 due to collation mismatch +Note 1105 Cannot substitute virtual column expression json_value(`t1`.`js1`,'$.color') -> color2 due to type mismatch alter table t1 drop column color2; # Explicitly specifying the collation helps: alter table t1 @@ -255,7 +282,9 @@ explain select * from t1 where json_value(js1, '$.color') collate utf8mb4_unicode_ci='hue10'; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref color3 color3 403 const 1 Using index condition +1 SIMPLE t1 ALL NULL NULL NULL NULL 100 Using where +Warnings: +Note 1105 Cannot substitute virtual column expression json_value(`t1`.`js1`,'$.color') collate utf8mb4_unicode_ci -> color3 due to type mismatch # # Alternatively, one can store JSON in a column with the same # collation as default and then casts are not needed: @@ -271,7 +300,9 @@ explain select * from t2 where json_value(js1, '$.color')='hue10'; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t2 ref color3 color3 403 const 1 Using index condition +1 SIMPLE t2 ALL NULL NULL NULL NULL 100 Using where +Warnings: +Note 1105 Cannot substitute virtual column expression json_value(`t2`.`js1`,'$.color') -> color3 due to type mismatch drop table t1,t2; # # Test interplay with sargable_casefold optimization: @@ -387,16 +418,12 @@ EXPLAIN "table": { "delete": 1, "table_name": "t1", - "access_type": "range", - "possible_keys": ["a1"], - "key": "a1", - "key_length": "5", - "used_key_parts": ["a1"], + "access_type": "ALL", "rows": 2, - "attached_condition": "t1.a1 > 'a'" + "attached_condition": "t1.v2 + t1.v3 > 'a'" } } } Warnings: -Warning 1292 Truncated incorrect DECIMAL value: 'a' +Note 1105 Cannot substitute virtual column expression `t1`.`v2` + `t1`.`v3` -> a1 due to type mismatch drop table t1; diff --git a/sql/opt_vcol_substitution.cc b/sql/opt_vcol_substitution.cc index 2e65115512903..c6da00de02836 100644 --- a/sql/opt_vcol_substitution.cc +++ b/sql/opt_vcol_substitution.cc @@ -114,7 +114,7 @@ class Vcol_subst_context */ uint subst_count; - Vcol_subst_context(THD *thd_arg) : thd(thd_arg) {} + Vcol_subst_context(THD *thd_arg) : thd(thd_arg), context(NULL), subst_count(0) {} }; static Field *is_vcol_expr(Vcol_subst_context *ctx, const Item *item); @@ -339,7 +339,10 @@ bool substitute_indexed_vcols_for_table(TABLE *table, Item *item, return false; // Ok, nothing to do if (item) + { + ctx.context= select_lex ? &select_lex->context : NULL; subst_vcols_in_item(&ctx, item, "WHERE"); + } ctx.subst_count= 0; /* used in subst_vcol_in_order */ if (order) @@ -394,9 +397,9 @@ void print_vcol_subst_warning(THD *thd, Field *field, Item *expr, push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE, ER_UNKNOWN_ERROR, - "Cannot substitute virtual column expression %*s -> %*s " + "Cannot substitute virtual column expression %.*s -> %.*s " "due to %s", - (int) expr_length, expr_buffer.c_ptr_safe(), + (int) expr_length, expr_buffer.ptr(), (int) field->field_name.length, field->field_name.str, cause); } @@ -449,10 +452,14 @@ void subst_vcol_if_compatible(Vcol_subst_context *ctx, THD *thd= ctx->thd; const char *fail_cause= NULL; - if (vcol_expr->type_handler_for_comparison() != - vcol_field->type_handler_for_comparison() || - (vcol_expr->maybe_null() && !vcol_field->maybe_null())) + if (vcol_expr->type_handler() != vcol_field->type_handler()) fail_cause="type mismatch"; + else if (vcol_expr->max_length > vcol_field->field_length) + fail_cause="length mismatch"; + else if (vcol_expr->decimals > vcol_field->decimals()) + fail_cause="precision mismatch"; + else if (vcol_expr->maybe_null() && !vcol_field->maybe_null()) + fail_cause="nullability mismatch"; else { CHARSET_INFO *cs= cond ? cond->compare_collation() : NULL;