Commit 5e5a8eda authored by Monty's avatar Monty Committed by Sergei Petrunia

Derived tables and union can now create distinct keys

The idea is that instead of marking all select_lex's with DISTINCT, we
only mark those that really need distinct result.

Benefits of this change:
- Temporary tables used with derived tables, UNION, IN are now smaller
  as duplicates are removed already on the insert phase.
- The optimizer can now produce better plans with EQ_REF. This can be
  seen from the tests where several queries does not anymore materialize
  derived tables twice.
- Queries affected by 'in_predicate_conversion_threshold' where large IN
  lists are converted to sub query produces better plans.

Other things:
- Removed on duplicate call to sel->init_select() in
  LEX::add_primary_to_query_expression_body()
- I moved the testing of
  tab->table->pos_in_table_list->is_materialized_derived()
  in join_read_const_table() to the caller as it caused problems for
  derived tables that could be proven to be const tables.
  This also is likely to fix some bugs as if join_read_const_table()
  was aborted, the table was left marked as JT_CONST, which cannot
  be good.  I added an ASSERT there for now that can be removed when
  the code has been properly tested.
parent 868d577c
......@@ -183,7 +183,7 @@ where c in (select c from (select count(*) as c from t1
where b >= 'c' group by a) as t);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 4 Using where
1 PRIMARY <derived3> ref key0 key0 8 test.t2.c 2 Using where; FirstMatch(t2)
1 PRIMARY <derived3> eq_ref distinct_key distinct_key 8 test.t2.c 1 Using where
3 DERIVED t1 ALL NULL NULL NULL NULL 8 Using where; Using temporary; Using filesort
# two references to t specified by a query
# selecting a field: both in main query
......@@ -369,7 +369,7 @@ select c as a from t2 where c < 4)
select * from t2,t where t2.c=t.a;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 4 Using where
1 PRIMARY <derived2> ref key0 key0 5 test.t2.c 1
1 PRIMARY <derived2> eq_ref distinct_key distinct_key 5 test.t2.c 1
2 DERIVED t1 ALL NULL NULL NULL NULL 8 Using where
3 UNION t2 ALL NULL NULL NULL NULL 4 Using where
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL
......@@ -381,7 +381,7 @@ select c as a from t2 where c < 4) as t
where t2.c=t.a;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 4 Using where
1 PRIMARY <derived2> ref key0 key0 5 test.t2.c 1
1 PRIMARY <derived2> eq_ref distinct_key distinct_key 5 test.t2.c 1
2 DERIVED t1 ALL NULL NULL NULL NULL 8 Using where
3 UNION t2 ALL NULL NULL NULL NULL 4 Using where
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL
......
......@@ -370,6 +370,15 @@ a
2
3
3
set @save2_derived_optimizer_switch_bug=@@optimizer_switch;
set @@optimizer_switch=default;
select * from (select * from t1 union distinct select * from t2 union all select * from t3) X;
a
1
2
3
3
set @@optimizer_switch=@save2_derived_optimizer_switch_bug;
drop table t1, t2, t3;
create table t1 (a int);
create table t2 (a int);
......@@ -1290,7 +1299,7 @@ id select_type table type possible_keys key key_len ref rows r_rows filtered r_f
analyze select * from t1 , ( (select t2.a from t2 order by c) union (select t2.a from t2 order by c))q where t1.a=q.a;
id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 6 6.00 100.00 100.00 Using where
1 PRIMARY <derived2> ref key0 key0 5 test.t1.a 1 1.00 100.00 100.00
1 PRIMARY <derived2> eq_ref distinct_key distinct_key 5 test.t1.a 1 1.00 100.00 100.00
2 DERIVED t2 ALL NULL NULL NULL NULL 6 6.00 100.00 100.00
3 UNION t2 ALL NULL NULL NULL NULL 6 6.00 100.00 100.00
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL 6.00 NULL NULL
......@@ -1333,3 +1342,66 @@ DROP TABLE t1;
#
# End of 10.3 tests
#
#
# Test of "Derived tables and union can now create distinct keys"
#
create table t1 (a int);
insert into t1 values (100),(100);
create table duplicates_tbl (a int);
insert into duplicates_tbl select seq/100 from seq_1_to_10000;
explain
select
t1.a IN ( SELECT COUNT(*)
from (select a
from duplicates_tbl
limit 10000
) T
where T.a=5
) as 'A'
from t1;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2
2 MATERIALIZED <derived3> ALL NULL NULL NULL NULL 10000 Using where
3 DERIVED duplicates_tbl ALL NULL NULL NULL NULL 10000
select
t1.a IN ( SELECT COUNT(*)
from (select a
from duplicates_tbl
limit 10000
) T
where T.a=5
) as 'A'
from t1;
A
1
1
explain
select
t1.a = all ( SELECT COUNT(*)
from (select a
from duplicates_tbl
limit 10000
) T
where T.a=5
) as 'A'
from t1;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2
2 DEPENDENT SUBQUERY <derived3> ALL NULL NULL NULL NULL 10000 Using where
3 DERIVED duplicates_tbl ALL NULL NULL NULL NULL 10000
select
t1.a = all ( SELECT COUNT(*)
from (select a
from duplicates_tbl
limit 10000
) T
where T.a=5
) as 'A'
from t1;
A
1
1
drop table t1, duplicates_tbl;
#
# End of 11.0 tests
#
......@@ -260,6 +260,10 @@ insert into t2 values(2),(2);
insert into t3 values(3),(3);
select * from t1 union distinct select * from t2 union all select * from t3;
select * from (select * from t1 union distinct select * from t2 union all select * from t3) X;
set @save2_derived_optimizer_switch_bug=@@optimizer_switch;
set @@optimizer_switch=default;
select * from (select * from t1 union distinct select * from t2 union all select * from t3) X;
set @@optimizer_switch=@save2_derived_optimizer_switch_bug;
drop table t1, t2, t3;
#
......@@ -1128,7 +1132,6 @@ select * from t1 , ( (select t2.a from t2 order by c) union all (select t2.a fr
drop table t1,t2,t3;
--echo #
--echo # MDEV-16549: Server crashes in Item_field::fix_fields on query with
--echo # view and subquery, Assertion `context' failed, Assertion `field' failed
......@@ -1147,3 +1150,61 @@ DROP TABLE t1;
--echo #
--echo # End of 10.3 tests
--echo #
--echo #
--echo # Test of "Derived tables and union can now create distinct keys"
--echo #
create table t1 (a int);
insert into t1 values (100),(100);
create table duplicates_tbl (a int);
insert into duplicates_tbl select seq/100 from seq_1_to_10000;
explain
select
t1.a IN ( SELECT COUNT(*)
from (select a
from duplicates_tbl
limit 10000
) T
where T.a=5
) as 'A'
from t1;
select
t1.a IN ( SELECT COUNT(*)
from (select a
from duplicates_tbl
limit 10000
) T
where T.a=5
) as 'A'
from t1;
explain
select
t1.a = all ( SELECT COUNT(*)
from (select a
from duplicates_tbl
limit 10000
) T
where T.a=5
) as 'A'
from t1;
select
t1.a = all ( SELECT COUNT(*)
from (select a
from duplicates_tbl
limit 10000
) T
where T.a=5
) as 'A'
from t1;
drop table t1, duplicates_tbl;
--echo #
--echo # End of 11.0 tests
--echo #
......@@ -10433,7 +10433,7 @@ WHERE d_tab.e>1
;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 5 Using where
1 PRIMARY <derived3> ref key0 key0 10 test.t1.a,test.t1.b 2 FirstMatch(t1)
1 PRIMARY <derived3> eq_ref distinct_key distinct_key 10 test.t1.a,test.t1.b 1
3 DERIVED t2 ALL NULL NULL NULL NULL 5 Using where; Using temporary; Using filesort
EXPLAIN FORMAT=JSON SELECT * FROM t1
WHERE (t1.a,t1.b) IN
......@@ -10465,15 +10465,14 @@ EXPLAIN
{
"table": {
"table_name": "<derived3>",
"access_type": "ref",
"possible_keys": ["key0"],
"key": "key0",
"access_type": "eq_ref",
"possible_keys": ["distinct_key"],
"key": "distinct_key",
"key_length": "10",
"used_key_parts": ["e", "max_f"],
"ref": ["test.t1.a", "test.t1.b"],
"rows": 2,
"rows": 1,
"filtered": 100,
"first_match": "t1",
"materialized": {
"query_block": {
"select_id": 3,
......@@ -10532,7 +10531,7 @@ WHERE d_tab.max_f<25
;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 5 Using where
1 PRIMARY <derived3> ref key0 key0 10 test.t1.a,test.t1.b 2 FirstMatch(t1)
1 PRIMARY <derived3> eq_ref distinct_key distinct_key 10 test.t1.a,test.t1.b 1
3 DERIVED t2 ALL NULL NULL NULL NULL 5 Using temporary; Using filesort
EXPLAIN FORMAT=JSON SELECT * FROM t1
WHERE (t1.a,t1.b) IN
......@@ -10564,15 +10563,14 @@ EXPLAIN
{
"table": {
"table_name": "<derived3>",
"access_type": "ref",
"possible_keys": ["key0"],
"key": "key0",
"access_type": "eq_ref",
"possible_keys": ["distinct_key"],
"key": "distinct_key",
"key_length": "10",
"used_key_parts": ["e", "max_f"],
"ref": ["test.t1.a", "test.t1.b"],
"rows": 2,
"rows": 1,
"filtered": 100,
"first_match": "t1",
"materialized": {
"query_block": {
"select_id": 3,
......@@ -13399,7 +13397,7 @@ where
((d1.a<4) and (d1.c<200)));
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 9 Using where
1 PRIMARY <derived2> ref key0 key0 5 test.t2.b 2 Using where
1 PRIMARY <derived2> ref key1 key1 5 test.t2.b 2 Using where
2 DERIVED t1 ALL NULL NULL NULL NULL 18 Using where; Using temporary; Using filesort
3 INTERSECT t1 ALL NULL NULL NULL NULL 18 Using where; Using temporary; Using filesort
NULL INTERSECT RESULT <intersect2,3> ALL NULL NULL NULL NULL NULL
......@@ -13432,8 +13430,8 @@ EXPLAIN
"table": {
"table_name": "<derived2>",
"access_type": "ref",
"possible_keys": ["key0"],
"key": "key0",
"possible_keys": ["key1"],
"key": "key1",
"key_length": "5",
"used_key_parts": ["b"],
"ref": ["test.t2.b"],
......@@ -14446,7 +14444,7 @@ where
((d1.a>4) and (d1.c>500)));
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 9 Using where
1 PRIMARY <derived2> ref key0 key0 5 test.t2.b 2 Using where
1 PRIMARY <derived2> ref key1 key1 5 test.t2.b 2 Using where
2 DERIVED t1 ALL NULL NULL NULL NULL 18 Using where; Using temporary; Using filesort
3 EXCEPT t1 ALL NULL NULL NULL NULL 18 Using where; Using temporary; Using filesort
NULL EXCEPT RESULT <except2,3> ALL NULL NULL NULL NULL NULL
......@@ -14479,8 +14477,8 @@ EXPLAIN
"table": {
"table_name": "<derived2>",
"access_type": "ref",
"possible_keys": ["key0"],
"key": "key0",
"possible_keys": ["key1"],
"key": "key1",
"key_length": "5",
"used_key_parts": ["b"],
"ref": ["test.t2.b"],
......@@ -19543,7 +19541,7 @@ on (t1.id = t2.ro_id AND t2.flag = 1)
group by t1.id) dt);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL PRIMARY NULL NULL NULL 20 100.00
1 PRIMARY <derived3> ref key0 key0 4 test.t1.id 2 100.00 FirstMatch(t1)
1 PRIMARY <derived3> ref key1 key1 4 test.t1.id 2 100.00 FirstMatch(t1)
3 DERIVED t1 ALL PRIMARY NULL NULL NULL 20 100.00 Using temporary; Using filesort
3 DERIVED t2 ref ro_id ro_id 4 test.t1.id 1 100.00 Using where
Warnings:
......
......@@ -323,10 +323,9 @@ JOIN t1 AS tc ON (tb.pk = tc.pk)
JOIN t4 AS td ON tc.a = td.a) tu)
limit 10;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL #
1 PRIMARY <derived3> ALL NULL NULL NULL NULL #
1 PRIMARY tx eq_ref PRIMARY PRIMARY 4 tu.pk # Using index
1 PRIMARY ty eq_ref PRIMARY PRIMARY 4 tu.pk # Using index
2 MATERIALIZED <derived3> ALL NULL NULL NULL NULL #
3 DERIVED td system PRIMARY NULL NULL NULL # Using temporary
3 DERIVED tc ref PRIMARY,a a 3 const #
3 DERIVED ta eq_ref PRIMARY PRIMARY 4 test.tc.pk # Using index
......
......@@ -3069,14 +3069,14 @@ Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be
EXPLAIN UPDATE t1 SET a = 10 WHERE a IN (SELECT * FROM (SELECT b FROM t2 ORDER BY b LIMIT 2,2) x);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where
2 DEPENDENT SUBQUERY <derived3> index_subquery key0 key0 5 func 2
2 DEPENDENT SUBQUERY <derived3> unique_subquery distinct_key distinct_key 5 func 1
3 DERIVED t2 ALL NULL NULL NULL NULL 3 Using filesort
FLUSH STATUS;
FLUSH TABLES;
EXPLAIN EXTENDED UPDATE t1 SET a = 10 WHERE a IN (SELECT * FROM (SELECT b FROM t2 ORDER BY b LIMIT 2,2) x);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
2 DEPENDENT SUBQUERY <derived3> index_subquery key0 key0 5 func 2 100.00
2 DEPENDENT SUBQUERY <derived3> unique_subquery distinct_key distinct_key 5 func 1 100.00
3 DERIVED t2 ALL NULL NULL NULL NULL 3 100.00 Using filesort
# Status of EXPLAIN EXTENDED query
Variable_name Value
......@@ -3086,10 +3086,10 @@ FLUSH TABLES;
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a IN (SELECT * FROM (SELECT b FROM t2 ORDER BY b LIMIT 2,2) x);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
1 PRIMARY <derived3> ref key0 key0 5 test.t1.a 2 100.00 FirstMatch(t1)
1 PRIMARY <derived3> eq_ref distinct_key distinct_key 5 test.t1.a 1 100.00
3 DERIVED t2 ALL NULL NULL NULL NULL 3 100.00 Using filesort
Warnings:
Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` semi join ((/* select#3 */ select `test`.`t2`.`b` AS `b` from `test`.`t2` order by `test`.`t2`.`b` limit 2,2) `x`) where `x`.`b` = `test`.`t1`.`a`
Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a` from (/* select#3 */ select `test`.`t2`.`b` AS `b` from `test`.`t2` order by `test`.`t2`.`b` limit 2,2) `x` join `test`.`t1` where `x`.`b` = `test`.`t1`.`a`
# Status of EXPLAIN EXTENDED "equivalent" SELECT query execution
Variable_name Value
Handler_read_key 4
......@@ -3120,7 +3120,7 @@ Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be
EXPLAIN UPDATE t1, t2 SET a = 10 WHERE a IN (SELECT * FROM (SELECT b FROM t2 ORDER BY b LIMIT 2,2) x);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where
1 PRIMARY <derived3> ref key0 key0 5 test.t1.a 2 FirstMatch(t1)
1 PRIMARY <derived3> eq_ref distinct_key distinct_key 5 test.t1.a 1
1 PRIMARY t2 ALL NULL NULL NULL NULL 3
3 DERIVED t2 ALL NULL NULL NULL NULL 3 Using filesort
FLUSH STATUS;
......@@ -3128,7 +3128,7 @@ FLUSH TABLES;
EXPLAIN EXTENDED UPDATE t1, t2 SET a = 10 WHERE a IN (SELECT * FROM (SELECT b FROM t2 ORDER BY b LIMIT 2,2) x);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
1 PRIMARY <derived3> ref key0 key0 5 test.t1.a 2 100.00 FirstMatch(t1)
1 PRIMARY <derived3> eq_ref distinct_key distinct_key 5 test.t1.a 1 100.00
1 PRIMARY t2 ALL NULL NULL NULL NULL 3 100.00
3 DERIVED t2 ALL NULL NULL NULL NULL 3 100.00 Using filesort
# Status of EXPLAIN EXTENDED query
......@@ -3139,11 +3139,11 @@ FLUSH TABLES;
EXPLAIN EXTENDED SELECT * FROM t1, t2 WHERE a IN (SELECT * FROM (SELECT b FROM t2 ORDER BY b LIMIT 2,2) x);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
1 PRIMARY <derived3> ref key0 key0 5 test.t1.a 2 100.00 FirstMatch(t1)
1 PRIMARY <derived3> eq_ref distinct_key distinct_key 5 test.t1.a 1 100.00
1 PRIMARY t2 ALL NULL NULL NULL NULL 3 100.00 Using join buffer (flat, BNL join)
3 DERIVED t2 ALL NULL NULL NULL NULL 3 100.00 Using filesort
Warnings:
Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t1` semi join ((/* select#3 */ select `test`.`t2`.`b` AS `b` from `test`.`t2` order by `test`.`t2`.`b` limit 2,2) `x`) join `test`.`t2` where `x`.`b` = `test`.`t1`.`a`
Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t2`.`b` AS `b` from (/* select#3 */ select `test`.`t2`.`b` AS `b` from `test`.`t2` order by `test`.`t2`.`b` limit 2,2) `x` join `test`.`t1` join `test`.`t2` where `x`.`b` = `test`.`t1`.`a`
# Status of EXPLAIN EXTENDED "equivalent" SELECT query execution
Variable_name Value
Handler_read_key 4
......@@ -3173,7 +3173,7 @@ Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be
EXPLAIN UPDATE t1, (SELECT * FROM t2) y SET a = 10 WHERE a IN (SELECT * FROM (SELECT b FROM t2 ORDER BY b LIMIT 2,2) x);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where
1 PRIMARY <derived4> ref key0 key0 5 test.t1.a 2 FirstMatch(t1)
1 PRIMARY <derived4> eq_ref distinct_key distinct_key 5 test.t1.a 1
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 3
4 DERIVED t2 ALL NULL NULL NULL NULL 3 Using filesort
2 DERIVED t2 ALL NULL NULL NULL NULL 3
......@@ -3182,7 +3182,7 @@ FLUSH TABLES;
EXPLAIN EXTENDED UPDATE t1, (SELECT * FROM t2) y SET a = 10 WHERE a IN (SELECT * FROM (SELECT b FROM t2 ORDER BY b LIMIT 2,2) x);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
1 PRIMARY <derived4> ref key0 key0 5 test.t1.a 2 100.00 FirstMatch(t1)
1 PRIMARY <derived4> eq_ref distinct_key distinct_key 5 test.t1.a 1 100.00
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 3 100.00
4 DERIVED t2 ALL NULL NULL NULL NULL 3 100.00 Using filesort
2 DERIVED t2 ALL NULL NULL NULL NULL 3 100.00
......@@ -3194,11 +3194,11 @@ FLUSH TABLES;
EXPLAIN EXTENDED SELECT * FROM t1, (SELECT * FROM t2) y WHERE a IN (SELECT * FROM (SELECT b FROM t2 ORDER BY b LIMIT 2,2) x);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
1 PRIMARY <derived4> ref key0 key0 5 test.t1.a 2 100.00 FirstMatch(t1)
1 PRIMARY <derived4> eq_ref distinct_key distinct_key 5 test.t1.a 1 100.00
1 PRIMARY t2 ALL NULL NULL NULL NULL 3 100.00 Using join buffer (flat, BNL join)
4 DERIVED t2 ALL NULL NULL NULL NULL 3 100.00 Using filesort
Warnings:
Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t1` semi join ((/* select#4 */ select `test`.`t2`.`b` AS `b` from `test`.`t2` order by `test`.`t2`.`b` limit 2,2) `x`) join `test`.`t2` where `x`.`b` = `test`.`t1`.`a`
Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t2`.`b` AS `b` from (/* select#4 */ select `test`.`t2`.`b` AS `b` from `test`.`t2` order by `test`.`t2`.`b` limit 2,2) `x` join `test`.`t1` join `test`.`t2` where `x`.`b` = `test`.`t1`.`a`
# Status of EXPLAIN EXTENDED "equivalent" SELECT query execution
Variable_name Value
Handler_read_key 4
......
......@@ -11406,7 +11406,7 @@ set in_predicate_conversion_threshold=3;
explain select * from t0 where a in (1,2,3,4,5,6);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t0 ALL NULL NULL NULL NULL 10 Using where
1 PRIMARY <derived3> ref key0 key0 4 test.t0.a 2 FirstMatch(t0)
1 PRIMARY <derived3> eq_ref distinct_key distinct_key 4 test.t0.a 1
3 DERIVED NULL NULL NULL NULL NULL NULL NULL No tables used
select json_detailed(json_extract(trace, '$**.in_to_subquery_conversion'))
from information_schema.optimizer_trace;
......
This diff is collapsed.
......@@ -54,6 +54,23 @@ eval $optimized_query;
eval explain extended $query;
eval explain extended $optimized_query;
let $query= select * from t1 where a in (1,2,2,2,3,4,5,6,7);
let $optimized_query=
select * from t1
where a in
(
select *
from (values (1),(2),(2),(2),(2),(3),(4),(5),(6),(7)) as tvc_0
);
eval $query;
eval $optimized_query;
eval explain extended $query;
eval explain extended $optimized_query;
--echo # AND-condition with IN-predicates in WHERE-part
let $query=
......
......@@ -221,7 +221,7 @@ NULL UNIT RESULT <unit8,9,12> ALL NULL NULL NULL NULL NULL NULL
16 EXCEPT NULL NULL NULL NULL NULL NULL NULL NULL No tables used
NULL UNIT RESULT <unit1,15,16> ALL NULL NULL NULL NULL NULL NULL
Warnings:
Note 1003 /* select#1 */ select `__14`.`1` AS `1` from (/* select#8 */ select `__7`.`1` AS `1` from (/* select#2 */ select 1 AS `1` except /* select#3 */ select 5 AS `5` union /* select#4 */ select 6 AS `6`) `__7` union /* select#9 */ select `__8`.`2` AS `2` from (/* select#5 */ select 2 AS `2` intersect /* select#6 */ select 3 AS `3` intersect /* select#7 */ select 4 AS `4`) `__8` except /* select#12 */ select `__11`.`7` AS `7` from (/* select#10 */ select 7 AS `7` intersect /* select#11 */ select 8 AS `8`) `__11`) `__14` union all /* select#15 */ select `__15`.`9` AS `9` from (/* select#13 */ select 9 AS `9` union all /* select#14 */ select 10 AS `10`) `__15` except all /* select#16 */ select 11 AS `11`
Note 1003 /* select#1 */ select `__14`.`1` AS `1` from (/* select#8 */ select `__7`.`1` AS `1` from (/* select#2 */ select 1 AS `1` except /* select#3 */ select 5 AS `5` union all /* select#4 */ select 6 AS `6`) `__7` union /* select#9 */ select `__8`.`2` AS `2` from (/* select#5 */ select 2 AS `2` intersect /* select#6 */ select 3 AS `3` intersect /* select#7 */ select 4 AS `4`) `__8` except /* select#12 */ select `__11`.`7` AS `7` from (/* select#10 */ select 7 AS `7` intersect /* select#11 */ select 8 AS `8`) `__11`) `__14` union all /* select#15 */ select `__15`.`9` AS `9` from (/* select#13 */ select 9 AS `9` union all /* select#14 */ select 10 AS `10`) `__15` except all /* select#16 */ select 11 AS `11`
(select 1 union all select 2)
union
(select 3 union all select 4);
......@@ -242,7 +242,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
5 UNION NULL NULL NULL NULL NULL NULL NULL NULL No tables used
NULL UNION RESULT <union1,6> ALL NULL NULL NULL NULL NULL NULL
Warnings:
Note 1003 /* select#1 */ select `__5`.`1` AS `1` from (/* select#2 */ select 1 AS `1` union /* select#3 */ select 2 AS `2`) `__5` union /* select#6 */ select `__6`.`3` AS `3` from (/* select#4 */ select 3 AS `3` union /* select#5 */ select 4 AS `4`) `__6`
Note 1003 /* select#1 */ select `__5`.`1` AS `1` from (/* select#2 */ select 1 AS `1` union all /* select#3 */ select 2 AS `2`) `__5` union /* select#6 */ select `__6`.`3` AS `3` from (/* select#4 */ select 3 AS `3` union /* select#5 */ select 4 AS `4`) `__6`
(select 1 intersect all select 2)
except
select 3;
......@@ -258,7 +258,7 @@ NULL INTERSECT RESULT <intersect2,3> ALL NULL NULL NULL NULL NULL NULL
4 EXCEPT NULL NULL NULL NULL NULL NULL NULL NULL No tables used
NULL EXCEPT RESULT <except1,4> ALL NULL NULL NULL NULL NULL NULL
Warnings:
Note 1003 /* select#1 */ select `__4`.`1` AS `1` from (/* select#2 */ select 1 AS `1` intersect /* select#3 */ select 2 AS `2`) `__4` except /* select#4 */ select 3 AS `3`
Note 1003 /* select#1 */ select `__4`.`1` AS `1` from (/* select#2 */ select 1 AS `1` intersect all /* select#3 */ select 2 AS `2`) `__4` except /* select#4 */ select 3 AS `3`
(select 1 intersect all select 2 intersect all select 3)
intersect
(select 4 intersect all select 5);
......@@ -278,7 +278,7 @@ NULL INTERSECT RESULT <intersect2,3,4> ALL NULL NULL NULL NULL NULL NULL
NULL INTERSECT RESULT <intersect5,6> ALL NULL NULL NULL NULL NULL NULL
NULL INTERSECT RESULT <intersect1,7> ALL NULL NULL NULL NULL NULL NULL
Warnings:
Note 1003 /* select#1 */ select `__6`.`1` AS `1` from (/* select#2 */ select 1 AS `1` intersect /* select#3 */ select 2 AS `2` intersect /* select#4 */ select 3 AS `3`) `__6` intersect /* select#7 */ select `__7`.`4` AS `4` from (/* select#5 */ select 4 AS `4` intersect /* select#6 */ select 5 AS `5`) `__7`
Note 1003 /* select#1 */ select `__6`.`1` AS `1` from (/* select#2 */ select 1 AS `1` intersect all /* select#3 */ select 2 AS `2` intersect all /* select#4 */ select 3 AS `3`) `__6` intersect /* select#7 */ select `__7`.`4` AS `4` from (/* select#5 */ select 4 AS `4` intersect /* select#6 */ select 5 AS `5`) `__7`
# test set operations with table value constructor
(values (1,1),(1,1),(1,1),(2,2),(2,2),(3,3),(9,9))
INTERSECT ALL
......
This diff is collapsed.
......@@ -1575,6 +1575,9 @@ values ((values (4)), (select 5)), ((select 2), (values (8)));
values ((values (1) union values (1)));
--error ER_SUBQUERY_NO_1_ROW
values ((values (1) union all values (1)));
values ((values (1) union values (1) union values (1)));
values ((values ((values (4)))));
......
......@@ -2783,3 +2783,70 @@ drop table t1;
#
# End of 10.3 tests
#
# check union all & union disctinct
select 1 as res union select 2 union select 1 union select 2;
res
1
2
select 1 as res union distinct select 2 union distinct select 1 union distinct select 2;
res
1
2
select 1 as res union all select 2 union all select 1 union all select 2;
res
1
2
1
2
select truncate(seq/2,0)+1 as res from seq_1_to_6 union select 2;
res
1
2
3
4
select truncate(seq/2,0)+1 as res from seq_1_to_6 union distinct select 2;
res
1
2
3
4
select truncate(seq/2,0)+1 as res from seq_1_to_6 union all select 2;
res
1
2
2
3
3
4
2
select 1 as res union all select 2 union distinct select 1 union all select 2;
res
1
2
2
select 1 as res union select 2 union all select 1 union distinct select 3;
res
1
2
3
select 1 as res union select 2 union all select 1 union distinct select 3 union all select 2;
res
1
2
3
2
select 1 as res union select 2 union all select 1 union distinct select 3 union all select 2 union distinct select 5;
res
1
2
3
5
select truncate(seq/2,0)+1 as res from seq_1_to_6 union all select 2 union all select 1 union distinct select 3 union all select 2;
res
1
2
3
4
2
#
# Test of unions
#
--source include/have_sequence.inc
CREATE TABLE t1 (a int not null, b char (10) not null);
insert into t1 values(1,'a'),(2,'b'),(3,'c'),(3,'c');
......@@ -2010,3 +2012,21 @@ drop table t1;
--echo #
--echo # End of 10.3 tests
--echo #
--echo
--echo # check union all & union disctinct
--echo
select 1 as res union select 2 union select 1 union select 2;
select 1 as res union distinct select 2 union distinct select 1 union distinct select 2;
select 1 as res union all select 2 union all select 1 union all select 2;
select truncate(seq/2,0)+1 as res from seq_1_to_6 union select 2;
select truncate(seq/2,0)+1 as res from seq_1_to_6 union distinct select 2;
select truncate(seq/2,0)+1 as res from seq_1_to_6 union all select 2;
select 1 as res union all select 2 union distinct select 1 union all select 2;
select 1 as res union select 2 union all select 1 union distinct select 3;
select 1 as res union select 2 union all select 1 union distinct select 3 union all select 2;
select 1 as res union select 2 union all select 1 union distinct select 3 union all select 2 union distinct select 5;
select truncate(seq/2,0)+1 as res from seq_1_to_6 union all select 2 union all select 1 union distinct select 3 union all select 2;
......@@ -298,7 +298,7 @@ SELECT * FROM federated.t1 WHERE id >= 5) t
WHERE federated.t3.name=t.name;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t3 ALL NULL NULL NULL NULL 7
1 PRIMARY <derived2> ref key0 key0 18 federated.t3.name 2
1 PRIMARY <derived2> ref key1 key1 18 federated.t3.name 2
2 PUSHED DERIVED NULL NULL NULL NULL NULL NULL NULL NULL
#
# MDEV-21887: federatedx crashes on SELECT ... INTO query in select_handler code
......
......@@ -1588,8 +1588,9 @@ Item_exists_subselect::Item_exists_subselect(THD *thd,
{
DBUG_ENTER("Item_exists_subselect::Item_exists_subselect");
init(select_lex, new (thd->mem_root) select_exists_subselect(thd, this));
select_lex->distinct= 1;
select_lex->master_unit()->distinct= 1;
max_columns= UINT_MAX;
null_value= FALSE; //can't be NULL
base_flags&= ~item_base_t::MAYBE_NULL; //can't be NULL
......@@ -1640,6 +1641,39 @@ Item_in_subselect::Item_in_subselect(THD *thd, Item * left_exp,
Item_row(thd, static_cast<Item_row*>(left_exp));
func= &eq_creator;
init(select_lex, new (thd->mem_root) select_exists_subselect(thd, this));
select_lex->distinct= 1;
/*
If the IN subquery (xxx IN (SELECT ...) is a join without grouping,
we don't need duplicates from the tables it is joining. These
tables can be derived tables, like shown in the following
example. In this case, it's useful to indicate that we don't need
duplicates from them either.
Example:
col IN (SELECT ... -- this is the select_lex
FROM
(SELECT ... FROM t1) AS t1, -- child1, first_inner_init().
(SELECT ... FROM t2) AS t2, -- child2
WHERE
...
)
We don't need duplicates from either child1 or child2.
We only indicate this to child1 (select_lex->first_inner_unit()), as that
catches most of practically important use cases.
(The check for item==NULL is to make sure the subquery is a derived table
and not any other kind of subquery like another IN (SELECT ...) or a scalar-
context (SELECT 'foo'))
*/
select_lex->master_unit()->distinct= 1;
if (!select_lex->with_sum_func &&
select_lex->first_inner_unit() &&
select_lex->first_inner_unit()->item == NULL)
select_lex->first_inner_unit()->distinct= 1;
max_columns= UINT_MAX;
set_maybe_null();
reset();
......@@ -1667,6 +1701,16 @@ Item_allany_subselect::Item_allany_subselect(THD *thd, Item * left_exp,
Item_row(thd, static_cast<Item_row*>(left_exp));
func= func_creator(all_arg);
init(select_lex, new (thd->mem_root) select_exists_subselect(thd, this));
select_lex->distinct= 1;
/*
If this is is 'xxx IN (SELECT ...) mark that the we are only interested in
unique values for the select
*/
select_lex->master_unit()->distinct= 1;
if (!select_lex->with_sum_func &&
select_lex->first_inner_unit() &&
select_lex->first_inner_unit()->item == NULL)
select_lex->first_inner_unit()->distinct= 1;
max_columns= 1;
reset();
//if test_limit will fail then error will be reported to client
......
......@@ -870,18 +870,20 @@ bool mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *derived)
goto exit;
/*
Temp table is created so that it hounours if UNION without ALL is to be
Temp table is created so that it honors if UNION without ALL is to be
processed
As 'distinct' parameter we always pass FALSE (0), because underlying
query will control distinct condition by itself. Correct test of
distinct underlying query will be is_unit_op &&
As 'distinct' parameter we pass unit->distinct, which tells us if
the values should be uniq.
Note that the underlying query will also control distinct condition.
Correct test of distinct underlying query will be is_unit_op &&
!unit->union_distinct->next_select() (i.e. it is union and last distinct
SELECT is last SELECT of UNION).
*/
thd->create_tmp_table_for_derived= TRUE;
if (!(derived->table) &&
derived->derived_result->create_result_table(thd, &unit->types, FALSE,
derived->derived_result->create_result_table(thd, &unit->types,
unit->distinct,
(first_select->options |
thd->variables.option_bits |
TMP_TABLE_ALL_COLUMNS),
......
......@@ -2873,7 +2873,7 @@ void st_select_lex_node::init_query_common()
{
options= 0;
set_linkage(UNSPECIFIED_TYPE);
distinct= TRUE;
distinct= FALSE;
no_table_names_allowed= 0;
uncacheable= 0;
}
......@@ -10146,6 +10146,7 @@ SELECT_LEX_UNIT *LEX::parsed_select_expr_start(SELECT_LEX *s1, SELECT_LEX *s2,
if (res == NULL)
return NULL;
res->pre_last_parse= sel1;
res->distinct= distinct;
push_select(res->fake_select_lex);
return res;
}
......@@ -10392,7 +10393,6 @@ bool LEX::parsed_TVC_start()
insert_list= 0;
if (!(sel= alloc_select(TRUE)) || push_select(sel))
return true;
sel->init_select();
sel->braces= FALSE; // just initialisation
return false;
}
......
......@@ -2613,8 +2613,12 @@ int JOIN::optimize_stage2()
if (select_lex->handle_derived(thd->lex, DT_OPTIMIZE))
DBUG_RETURN(1);
if (optimizer_flag(thd, OPTIMIZER_SWITCH_DERIVED_WITH_KEYS))
drop_unused_derived_keys();
/*
We have to call drop_unused_derived_keys() even if we don't have any
generated keys (enabled with OPTIMIZER_SWITCH_DERIVED_WITH_KEYS)
as we may still have unique constraints we have to get rid of.
*/
drop_unused_derived_keys();
if (rollup.state != ROLLUP::STATE_NONE)
{
......@@ -5698,7 +5702,14 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
base_const_ref.intersect(base_part);
base_eq_part= eq_part;
base_eq_part.intersect(base_part);
if (table->actual_key_flags(keyinfo) & HA_NOSAME)
/*
We can read the const record if we are using a full unique key and
if the table is not an unopened to be materialized table/view.
*/
if ((table->actual_key_flags(keyinfo) & HA_NOSAME) &&
(!s->table->pos_in_table_list->is_materialized_derived() ||
s->table->pos_in_table_list->fill_me))
{
if (base_const_ref == base_eq_part &&
......@@ -13573,9 +13584,12 @@ void JOIN::drop_unused_derived_keys()
if (tab->ref.key >= 0 && tab->ref.key < MAX_KEY)
tab->ref.key= 0;
else
{
tmp_tbl->s->keys= 0;
tmp_tbl->s->uniques= 0;
}
}
tab->keys= (key_map) (tmp_tbl->s->keys ? 1 : 0);
tab->keys= (key_map) (tmp_tbl->s->keys || tmp_tbl->s->uniques ? 1 : 0);
}
}
......@@ -22708,12 +22722,16 @@ join_read_const_table(THD *thd, JOIN_TAB *tab, POSITION *pos)
if (tab->table->pos_in_table_list->is_materialized_derived() &&
!tab->table->pos_in_table_list->fill_me)
{
DBUG_ASSERT(0);
//TODO: don't get here at all
/* Skip materialized derived tables/views. */
/*
Skip materialized derived tables/views as they temporary table is not
opened yet.
*/
DBUG_RETURN(0);
}
else if (tab->table->pos_in_table_list->jtbm_subselect &&
tab->table->pos_in_table_list->jtbm_subselect->is_jtbm_const_tab)
else if (tab->table->pos_in_table_list->jtbm_subselect &&
tab->table->pos_in_table_list->jtbm_subselect->is_jtbm_const_tab)
{
/* Row will not be found */
int res;
......@@ -705,11 +705,11 @@ st_select_lex *wrap_tvc(THD *thd, st_select_lex *tvc_sl,
goto err;
wrapper_sl->select_number= ++thd->lex->stmt_lex->current_select_number;
wrapper_sl->parent_lex= lex; /* Used in init_query. */
wrapper_sl->init_query();
wrapper_sl->init_select();
wrapper_sl->make_empty_select();
wrapper_sl->nest_level= tvc_sl->nest_level;
wrapper_sl->parsing_place= tvc_sl->parsing_place;
wrapper_sl->distinct= tvc_sl->distinct;
wrapper_sl->set_linkage(tvc_sl->get_linkage());
wrapper_sl->exclude_from_table_unique_test=
tvc_sl->exclude_from_table_unique_test;
......@@ -737,6 +737,7 @@ st_select_lex *wrap_tvc(THD *thd, st_select_lex *tvc_sl,
derived_unit->init_query();
derived_unit->thd= thd;
derived_unit->include_down(wrapper_sl);
derived_unit->distinct= tvc_sl->distinct;
/*
Attach the select used of TVC as the only slave to the unit for
......@@ -1011,7 +1012,9 @@ Item *Item_func_in::in_predicate_to_in_subs_transformer(THD *thd,
lex->init_select();
tvc_select= lex->current_select;
derived_unit= tvc_select->master_unit();
derived_unit->distinct= 1;
tvc_select->set_linkage(DERIVED_TABLE_TYPE);
tvc_select->distinct= 1;
/* Create TVC used in the transformation */
if (create_value_list_for_tvc(thd, &values))
......
......@@ -1302,6 +1302,7 @@ bool st_select_lex_unit::prepare(TABLE_LIST *derived_arg,
bool instantiate_tmp_table= false;
bool single_tvc= !first_sl->next_select() && first_sl->tvc;
bool single_tvc_wo_order= single_tvc && !first_sl->order_list.elements;
bool distinct_key= 0;
DBUG_ENTER("st_select_lex_unit::prepare");
DBUG_ASSERT(thd == current_thd);
......@@ -1405,15 +1406,17 @@ bool st_select_lex_unit::prepare(TABLE_LIST *derived_arg,
{
case INTERSECT_TYPE:
have_intersect= TRUE;
if (!s->distinct){
have_except_all_or_intersect_all= true;
}
if (!s->distinct)
have_except_all_or_intersect_all= TRUE;
break;
case EXCEPT_TYPE:
have_except= TRUE;
if (!s->distinct){
if (!s->distinct)
have_except_all_or_intersect_all= TRUE;
}
break;
case DERIVED_TABLE_TYPE:
if (s->distinct)
distinct_key= 1;
break;
default:
break;
......@@ -1620,7 +1623,8 @@ bool st_select_lex_unit::prepare(TABLE_LIST *derived_arg,
if (join_union_item_types(thd, types, union_part_count + 1))
goto err;
if (union_result->create_result_table(thd, &types,
MY_TEST(union_distinct),
(MY_TEST(union_distinct) ||
distinct_key),
create_options,
&derived_arg->alias, false,
instantiate_tmp_table, false,
......@@ -1643,7 +1647,7 @@ bool st_select_lex_unit::prepare(TABLE_LIST *derived_arg,
res= derived_arg->derived_result->create_result_table(thd,
&types,
FALSE,
distinct_key,
create_options,
&derived_arg->alias,
FALSE, FALSE,
......@@ -1767,9 +1771,9 @@ bool st_select_lex_unit::prepare(TABLE_LIST *derived_arg,
union_result->create_result_table(thd, &types,
MY_TEST(union_distinct) ||
have_except_all_or_intersect_all ||
have_intersect,
create_options, &empty_clex_str, false,
instantiate_tmp_table, false,
have_intersect || distinct_key,
create_options, &empty_clex_str,
false, instantiate_tmp_table, false,
hidden);
union_result->addon_cnt= hidden;
for (uint i= 0; i < hidden; i++)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment