Summarized results of two previous commits (26 July, 25 August)

This commit is contained in:
Galina Shalygina 2017-08-29 02:32:39 +02:00
parent 3310076dbe
commit 570d2e7d0f
21 changed files with 3428 additions and 861 deletions

View File

@ -1,10 +1,10 @@
create table t1 (a int, b int);
insert into t1
insert into t1
values (1,2), (4,6), (9,7),
(1,1), (2,5), (7,8);
create table t2 (a int, b int, c int);
insert into t2
values (1,2,3), (5,1,2), (4,3,7),
insert into t2
values (1,2,3), (5,1,2), (4,3,7),
(8,9,0), (10,7,1), (5,5,1);
# optimization is not used
select * from t1 where a in (1,2);
@ -37,484 +37,436 @@ a b
1 2
1 1
2 5
select * from t1
where a in
select * from t1
where a in
(
select *
from (values (1),(2)) as new_tvc
select *
from (values (1),(2)) as tvc_0
);
a b
1 2
1 1
2 5
explain select * from t1 where a in (1,2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 2
1 PRIMARY t1 ALL NULL NULL NULL NULL 6 Using where; Using join buffer (flat, BNL join)
2 MATERIALIZED <derived3> ALL NULL NULL NULL NULL 2
3 DERIVED NULL NULL NULL NULL NULL NULL NULL No tables used
explain select * from t1
where a in
explain extended select * from t1 where a in (1,2);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 2 100.00
1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00 Using where; Using join buffer (flat, BNL join)
2 MATERIALIZED <derived3> ALL NULL NULL NULL NULL 2 100.00
3 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where `test`.`t1`.`a` = `tvc_0`.`1`
explain extended select * from t1
where a in
(
select *
from (values (1),(2)) as new_tvc
select *
from (values (1),(2)) as tvc_0
);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 2
1 PRIMARY t1 ALL NULL NULL NULL NULL 6 Using where; Using join buffer (flat, BNL join)
2 MATERIALIZED <derived3> ALL NULL NULL NULL NULL 2
3 DERIVED NULL NULL NULL NULL NULL NULL NULL No tables used
explain format=json select * from t1 where a in (1,2);
EXPLAIN
{
"query_block": {
"select_id": 1,
"table": {
"table_name": "<subquery2>",
"access_type": "ALL",
"possible_keys": ["distinct_key"],
"rows": 2,
"filtered": 100,
"materialized": {
"unique": 1,
"query_block": {
"select_id": 2,
"table": {
"table_name": "<derived3>",
"access_type": "ALL",
"rows": 2,
"filtered": 100,
"materialized": {
"query_block": {
"union_result": {
"table_name": "<unit3>",
"access_type": "ALL",
"query_specifications": [
{
"query_block": {
"select_id": 3,
"table": {
"message": "No tables used"
}
}
}
]
}
}
}
}
}
}
},
"block-nl-join": {
"table": {
"table_name": "t1",
"access_type": "ALL",
"rows": 6,
"filtered": 100
},
"buffer_type": "flat",
"buffer_size": "256Kb",
"join_type": "BNL",
"attached_condition": "t1.a = new_tvc.`1`"
}
}
}
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 2 100.00
1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00 Using where; Using join buffer (flat, BNL join)
2 MATERIALIZED <derived3> ALL NULL NULL NULL NULL 2 100.00
3 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where `test`.`t1`.`a` = `tvc_0`.`1`
# AND-condition with IN-predicates in WHERE-part
select * from t1
where a in (1,2) and
select * from t1
where a in (1,2) and
b in (1,5);
a b
1 1
2 5
select * from t1
where a in
select * from t1
where a in
(
select *
from (values (1),(2)) as new_tvc
)
select *
from (values (1),(2)) as tvc_0
)
and b in
(
select *
from (values (1),(5)) as new_tvc
select *
from (values (1),(5)) as tvc_1
);
a b
1 1
2 5
explain select * from t1
where a in (1,2) and
explain extended select * from t1
where a in (1,2) and
b in (1,5);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <subquery4> ALL distinct_key NULL NULL NULL 2
1 PRIMARY t1 ALL NULL NULL NULL NULL 6 Using where; Using join buffer (flat, BNL join)
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
4 MATERIALIZED <derived5> ALL NULL NULL NULL NULL 2
2 MATERIALIZED <derived3> ALL NULL NULL NULL NULL 2
5 DERIVED NULL NULL NULL NULL NULL NULL NULL No tables used
3 DERIVED NULL NULL NULL NULL NULL NULL NULL No tables used
explain select * from t1
where a in
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <subquery4> ALL distinct_key NULL NULL NULL 2 100.00
1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00 Using where; Using join buffer (flat, BNL join)
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 100.00 Using where
4 MATERIALIZED <derived5> ALL NULL NULL NULL NULL 2 100.00
2 MATERIALIZED <derived3> ALL NULL NULL NULL NULL 2 100.00
5 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
3 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) semi join ((values (1),(5)) `tvc_1`) where `tvc_0`.`1` = `test`.`t1`.`a` and `test`.`t1`.`b` = `tvc_1`.`1`
explain extended select * from t1
where a in
(
select *
from (values (1),(2)) as new_tvc
)
select *
from (values (1),(2)) as tvc_0
)
and b in
(
select *
from (values (1),(5)) as new_tvc
select *
from (values (1),(5)) as tvc_1
);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <subquery4> ALL distinct_key NULL NULL NULL 2
1 PRIMARY t1 ALL NULL NULL NULL NULL 6 Using where; Using join buffer (flat, BNL join)
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
4 MATERIALIZED <derived5> ALL NULL NULL NULL NULL 2
2 MATERIALIZED <derived3> ALL NULL NULL NULL NULL 2
5 DERIVED NULL NULL NULL NULL NULL NULL NULL No tables used
3 DERIVED NULL NULL NULL NULL NULL NULL NULL No tables used
explain format=json select * from t1
where a in (1,2) and
b in (1,5);
EXPLAIN
{
"query_block": {
"select_id": 1,
"table": {
"table_name": "<subquery4>",
"access_type": "ALL",
"possible_keys": ["distinct_key"],
"rows": 2,
"filtered": 100,
"materialized": {
"unique": 1,
"query_block": {
"select_id": 4,
"table": {
"table_name": "<derived5>",
"access_type": "ALL",
"rows": 2,
"filtered": 100,
"materialized": {
"query_block": {
"union_result": {
"table_name": "<unit5>",
"access_type": "ALL",
"query_specifications": [
{
"query_block": {
"select_id": 5,
"table": {
"message": "No tables used"
}
}
}
]
}
}
}
}
}
}
},
"block-nl-join": {
"table": {
"table_name": "t1",
"access_type": "ALL",
"rows": 6,
"filtered": 100
},
"buffer_type": "flat",
"buffer_size": "256Kb",
"join_type": "BNL",
"attached_condition": "t1.b = new_tvc.`1`"
},
"table": {
"table_name": "<subquery2>",
"access_type": "eq_ref",
"possible_keys": ["distinct_key"],
"key": "distinct_key",
"key_length": "4",
"used_key_parts": ["1"],
"ref": ["func"],
"rows": 1,
"filtered": 100,
"materialized": {
"unique": 1,
"query_block": {
"select_id": 2,
"table": {
"table_name": "<derived3>",
"access_type": "ALL",
"rows": 2,
"filtered": 100,
"materialized": {
"query_block": {
"union_result": {
"table_name": "<unit3>",
"access_type": "ALL",
"query_specifications": [
{
"query_block": {
"select_id": 3,
"table": {
"message": "No tables used"
}
}
}
]
}
}
}
}
}
}
}
}
}
# OR-condition with IN-predicates in WHERE-part
select * from t1
where a in (1,2) or
b in (4,5);
a b
1 2
1 1
2 5
select * from t1
where a in
(
select *
from (values (1),(2)) as new_tvc
)
or b in
(
select *
from (values (4),(5)) as new_tvc
);
a b
1 2
1 1
2 5
explain select * from t1
where a in (1,2) or
b in (4,5);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 6 Using where
4 MATERIALIZED <derived5> ALL NULL NULL NULL NULL 2
5 DERIVED NULL NULL NULL NULL NULL NULL NULL No tables used
2 MATERIALIZED <derived3> ALL NULL NULL NULL NULL 2
3 DERIVED NULL NULL NULL NULL NULL NULL NULL No tables used
explain select * from t1
where a in
(
select *
from (values (1),(2)) as new_tvc
)
or b in
(
select *
from (values (4),(5)) as new_tvc
);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 6 Using where
4 MATERIALIZED <derived5> ALL NULL NULL NULL NULL 2
5 DERIVED NULL NULL NULL NULL NULL NULL NULL No tables used
2 MATERIALIZED <derived3> ALL NULL NULL NULL NULL 2
3 DERIVED NULL NULL NULL NULL NULL NULL NULL No tables used
explain format=json select * from t1
where a in (1,2) or
b in (4,5);
EXPLAIN
{
"query_block": {
"select_id": 1,
"table": {
"table_name": "t1",
"access_type": "ALL",
"rows": 6,
"filtered": 100,
"attached_condition": "<in_optimizer>(t1.a,t1.a in (subquery#2)) or <in_optimizer>(t1.b,t1.b in (subquery#4))"
},
"subqueries": [
{
"query_block": {
"select_id": 4,
"table": {
"table_name": "<derived5>",
"access_type": "ALL",
"rows": 2,
"filtered": 100,
"materialized": {
"query_block": {
"union_result": {
"table_name": "<unit5>",
"access_type": "ALL",
"query_specifications": [
{
"query_block": {
"select_id": 5,
"table": {
"message": "No tables used"
}
}
}
]
}
}
}
}
}
},
{
"query_block": {
"select_id": 2,
"table": {
"table_name": "<derived3>",
"access_type": "ALL",
"rows": 2,
"filtered": 100,
"materialized": {
"query_block": {
"union_result": {
"table_name": "<unit3>",
"access_type": "ALL",
"query_specifications": [
{
"query_block": {
"select_id": 3,
"table": {
"message": "No tables used"
}
}
}
]
}
}
}
}
}
}
]
}
}
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <subquery4> ALL distinct_key NULL NULL NULL 2 100.00
1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00 Using where; Using join buffer (flat, BNL join)
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 100.00
4 MATERIALIZED <derived5> ALL NULL NULL NULL NULL 2 100.00
2 MATERIALIZED <derived3> ALL NULL NULL NULL NULL 2 100.00
5 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
3 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) semi join ((values (1),(5)) `tvc_1`) where `test`.`t1`.`b` = `tvc_1`.`1`
# subquery with IN-predicate
select * from t1
where a in
select * from t1
where a in
(
select a
select a
from t2 where b in (3,4)
)
;
);
a b
4 6
select * from t1
where a in (
select a from t2
where b in
select * from t1
where a in
(
select *
from (values (3),(4)) as new_tvc)
select a from t2
where b in
(
select *
from (values (3),(4)) as tvc_0
)
;
);
a b
4 6
explain select * from t1
where a in
explain extended select * from t1
where a in
(
select a
select a
from t2 where b in (3,4)
)
;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 6
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
2 MATERIALIZED <derived4> ALL NULL NULL NULL NULL 2
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 6 Using where; Using join buffer (flat, BNL join)
4 DERIVED NULL NULL NULL NULL NULL NULL NULL No tables used
explain select * from t1
where a in (
select a from t2
where b in
);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 100.00
2 MATERIALIZED <derived4> ALL NULL NULL NULL NULL 2 100.00
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 6 100.00 Using where; Using join buffer (flat, BNL join)
4 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (3),(4)) `tvc_0` join `test`.`t2`) where `test`.`t2`.`b` = `tvc_0`.`3`
explain extended select * from t1
where a in
(
select *
from (values (3),(4)) as new_tvc)
)
;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 6
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
2 MATERIALIZED <derived4> ALL NULL NULL NULL NULL 2
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 6 Using where; Using join buffer (flat, BNL join)
4 DERIVED NULL NULL NULL NULL NULL NULL NULL No tables used
explain format=json select * from t1
where a in
select a from t2
where b in
(
select a
from t2 where b in (3,4)
select *
from (values (3),(4)) as tvc_0
)
);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 100.00
2 MATERIALIZED <derived4> ALL NULL NULL NULL NULL 2 100.00
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 6 100.00 Using where; Using join buffer (flat, BNL join)
4 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (3),(4)) `tvc_0` join `test`.`t2`) where `test`.`t2`.`b` = `tvc_0`.`3`
# derived table with IN-predicate
select * from
(
select *
from t1
where a in (1,2)
) as dr_table;
a b
1 2
1 1
2 5
select * from
(
select *
from t1
where a in
(
select *
from (values (1),(2))
as tvc_0
)
) as dr_table;
a b
1 2
1 1
2 5
explain extended select * from
(
select *
from t1
where a in (1,2)
) as dr_table;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00 Using where
3 MATERIALIZED <derived4> ALL NULL NULL NULL NULL 2 100.00
4 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where <expr_cache><`test`.`t1`.`a`>(<in_optimizer>(`test`.`t1`.`a`,`test`.`t1`.`a` in ( <materialize> (/* select#3 */ select `tvc_0`.`1` from (values (1),(2)) `tvc_0` ), <primary_index_lookup>(`test`.`t1`.`a` in <temporary table> on distinct_key where `test`.`t1`.`a` = `<subquery3>`.`1`))))
explain extended select * from
(
select *
from t1
where a in
(
select *
from (values (1),(2))
as tvc_0
)
) as dr_table;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00 Using where
3 MATERIALIZED <derived4> ALL NULL NULL NULL NULL 2 100.00
4 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where <expr_cache><`test`.`t1`.`a`>(<in_optimizer>(`test`.`t1`.`a`,`test`.`t1`.`a` in ( <materialize> (/* select#3 */ select `tvc_0`.`1` from (values (1),(2)) `tvc_0` ), <primary_index_lookup>(`test`.`t1`.`a` in <temporary table> on distinct_key where `test`.`t1`.`a` = `<subquery3>`.`1`))))
# non-recursive CTE with IN-predicate
with tvc_0 as
(
select *
from t1
where a in (1,2)
)
select * from tvc_0;
a b
1 2
1 1
2 5
select * from
(
select *
from t1
where a in
(
select *
from (values (1),(2))
as tvc_0
)
) as dr_table;
a b
1 2
1 1
2 5
explain extended with tvc_0 as
(
select *
from t1
where a in (1,2)
)
select * from tvc_0;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00 Using where
3 MATERIALIZED <derived4> ALL NULL NULL NULL NULL 2 100.00
4 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
Note 1003 with tvc_0 as (/* select#2 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where `test`.`t1`.`a` in (1,2))/* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where <expr_cache><`test`.`t1`.`a`>(<in_optimizer>(`test`.`t1`.`a`,`test`.`t1`.`a` in ( <materialize> (/* select#3 */ select `tvc_0`.`1` from (values (1),(2)) `tvc_0` ), <primary_index_lookup>(`test`.`t1`.`a` in <temporary table> on distinct_key where `test`.`t1`.`a` = `<subquery3>`.`1`))))
explain extended select * from
(
select *
from t1
where a in
(
select *
from (values (1),(2))
as tvc_0
)
) as dr_table;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00 Using where
3 MATERIALIZED <derived4> ALL NULL NULL NULL NULL 2 100.00
4 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where <expr_cache><`test`.`t1`.`a`>(<in_optimizer>(`test`.`t1`.`a`,`test`.`t1`.`a` in ( <materialize> (/* select#3 */ select `tvc_0`.`1` from (values (1),(2)) `tvc_0` ), <primary_index_lookup>(`test`.`t1`.`a` in <temporary table> on distinct_key where `test`.`t1`.`a` = `<subquery3>`.`1`))))
# VIEW with IN-predicate
create view v1 as
select *
from t1
where a in (1,2);
create view v2 as
select *
from t1
where a in
(
select *
from (values (1),(2))
as tvc_0
)
;
EXPLAIN
{
"query_block": {
"select_id": 1,
"table": {
"table_name": "t1",
"access_type": "ALL",
"rows": 6,
"filtered": 100
},
"table": {
"table_name": "<subquery2>",
"access_type": "eq_ref",
"possible_keys": ["distinct_key"],
"key": "distinct_key",
"key_length": "4",
"used_key_parts": ["a"],
"ref": ["func"],
"rows": 1,
"filtered": 100,
"materialized": {
"unique": 1,
"query_block": {
"select_id": 2,
"table": {
"table_name": "<derived4>",
"access_type": "ALL",
"rows": 2,
"filtered": 100,
"materialized": {
"query_block": {
"union_result": {
"table_name": "<unit4>",
"access_type": "ALL",
"query_specifications": [
{
"query_block": {
"select_id": 4,
"table": {
"message": "No tables used"
}
}
}
]
}
}
}
},
"block-nl-join": {
"table": {
"table_name": "t2",
"access_type": "ALL",
"rows": 6,
"filtered": 100
},
"buffer_type": "flat",
"buffer_size": "256Kb",
"join_type": "BNL",
"attached_condition": "t2.b = new_tvc.`3`"
}
}
}
}
}
}
drop table t1;
select * from v1;
a b
1 2
1 1
2 5
select * from v2;
a b
1 2
1 1
2 5
explain extended select * from v1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00 Using where
3 MATERIALIZED <derived4> ALL NULL NULL NULL NULL 2 100.00
4 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where <expr_cache><`test`.`t1`.`a`>(<in_optimizer>(`test`.`t1`.`a`,`test`.`t1`.`a` in ( <materialize> (/* select#3 */ select `tvc_0`.`1` from (values (1),(2)) `tvc_0` ), <primary_index_lookup>(`test`.`t1`.`a` in <temporary table> on distinct_key where `test`.`t1`.`a` = `<subquery3>`.`1`))))
explain extended select * from v2;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00 Using where
3 MATERIALIZED <derived4> ALL NULL NULL NULL NULL 2 100.00
4 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where <expr_cache><`test`.`t1`.`a`>(<in_optimizer>(`test`.`t1`.`a`,`test`.`t1`.`a` in ( <materialize> (/* select#3 */ select `tvc_0`.`1` from (values (1),(2)) `tvc_0` ), <primary_index_lookup>(`test`.`t1`.`a` in <temporary table> on distinct_key where `test`.`t1`.`a` = `<subquery3>`.`1`))))
drop view v1,v2;
# subselect defined by derived table with IN-predicate
select * from t1
where a in
(
select 1
from
(
select *
from t1
where a in (1,2)
)
as dr_table
);
a b
1 2
1 1
select * from t1
where a in
(
select 1
from
(
select *
from t1
where a in
(
select *
from (values (1),(2))
as tvc_0
)
)
as dr_table
);
a b
1 2
1 1
explain extended select * from t1
where a in
(
select 1
from
(
select *
from t1
where a in (1,2)
)
as dr_table
);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00 Using where
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 100.00
2 MATERIALIZED t1 ALL NULL NULL NULL NULL 6 100.00 Using where
4 MATERIALIZED <derived5> ALL NULL NULL NULL NULL 2 100.00
5 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join (`test`.`t1`) where `test`.`t1`.`a` = 1 and <expr_cache><`test`.`t1`.`a`>(<in_optimizer>(`test`.`t1`.`a`,`test`.`t1`.`a` in ( <materialize> (/* select#4 */ select `tvc_0`.`1` from (values (1),(2)) `tvc_0` ), <primary_index_lookup>(`test`.`t1`.`a` in <temporary table> on distinct_key where `test`.`t1`.`a` = `<subquery4>`.`1`))))
explain extended select * from t1
where a in
(
select 1
from
(
select *
from t1
where a in
(
select *
from (values (1),(2))
as tvc_0
)
)
as dr_table
);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00 Using where
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 100.00
2 MATERIALIZED t1 ALL NULL NULL NULL NULL 6 100.00 Using where
4 MATERIALIZED <derived5> ALL NULL NULL NULL NULL 2 100.00
5 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join (`test`.`t1`) where `test`.`t1`.`a` = 1 and <expr_cache><`test`.`t1`.`a`>(<in_optimizer>(`test`.`t1`.`a`,`test`.`t1`.`a` in ( <materialize> (/* select#4 */ select `tvc_0`.`1` from (values (1),(2)) `tvc_0` ), <primary_index_lookup>(`test`.`t1`.`a` in <temporary table> on distinct_key where `test`.`t1`.`a` = `<subquery4>`.`1`))))
# derived table with IN-predicate and group by
select * from
(
select max(a),b
from t1
where b in (3,5)
group by b
) as dr_table;
max(a) b
2 5
select * from
(
select max(a),b
from t1
where b in
(
select *
from (values (3),(5))
as tvc_0
)
group by b
) as dr_table;
max(a) b
2 5
explain extended select * from
(
select max(a),b
from t1
where b in (3,5)
group by b
) as dr_table;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 12 100.00
2 DERIVED t1 ALL NULL NULL NULL NULL 6 100.00 Using temporary; Using filesort
2 DERIVED <subquery3> eq_ref distinct_key distinct_key 4 func 1 100.00 Using where
3 MATERIALIZED <derived4> ALL NULL NULL NULL NULL 2 100.00
4 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
Note 1003 /* select#1 */ select `dr_table`.`max(a)` AS `max(a)`,`dr_table`.`b` AS `b` from (/* select#2 */ select max(`test`.`t1`.`a`) AS `max(a)`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (3),(5)) `tvc_0`) where `tvc_0`.`3` = `test`.`t1`.`b` group by `test`.`t1`.`b`) `dr_table`
explain extended select * from
(
select max(a),b
from t1
where b in
(
select *
from (values (3),(5))
as tvc_0
)
group by b
) as dr_table;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 12 100.00
2 DERIVED t1 ALL NULL NULL NULL NULL 6 100.00 Using temporary; Using filesort
2 DERIVED <subquery3> eq_ref distinct_key distinct_key 4 func 1 100.00
3 MATERIALIZED <derived4> ALL NULL NULL NULL NULL 2 100.00
4 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
Note 1003 /* select#1 */ select `dr_table`.`max(a)` AS `max(a)`,`dr_table`.`b` AS `b` from (/* select#2 */ select max(`test`.`t1`.`a`) AS `max(a)`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (3),(5)) `tvc_0`) where 1 group by `test`.`t1`.`b`) `dr_table`
drop table t1, t2;
set @@in_subquery_conversion_threshold= default;

File diff suppressed because it is too large Load Diff

View File

@ -1,13 +1,13 @@
create table t1 (a int, b int);
insert into t1
insert into t1
values (1,2), (4,6), (9,7),
(1,1), (2,5), (7,8);
create table t2 (a int, b int, c int);
insert into t2
values (1,2,3), (5,1,2), (4,3,7),
insert into t2
values (1,2,3), (5,1,2), (4,3,7),
(8,9,0), (10,7,1), (5,5,1);
--echo # optimization is not used
@ -15,7 +15,7 @@ values (1,2,3), (5,1,2), (4,3,7),
let $query= select * from t1 where a in (1,2);
eval $query;
eval explain $query;
eval explain format=json $query;
eval explain format=json $query;
--echo # set minimum number of values in VALUEs list when optimization works to 2
@ -25,100 +25,212 @@ set @@in_subquery_conversion_threshold= 2;
let $query= select * from t1 where a in (1,2);
let $optimized_query=
select * from t1
where a in
let $optimized_query=
select * from t1
where a in
(
select *
from (values (1),(2)) as new_tvc
select *
from (values (1),(2)) as tvc_0
);
eval $query;
eval $optimized_query;
eval explain $query;
eval explain $optimized_query;
eval explain format=json $query;
eval explain extended $query;
eval explain extended $optimized_query;
--echo # AND-condition with IN-predicates in WHERE-part
let $query=
select * from t1
where a in (1,2) and
let $query=
select * from t1
where a in (1,2) and
b in (1,5);
let $optimized_query=
select * from t1
where a in
let $optimized_query=
select * from t1
where a in
(
select *
from (values (1),(2)) as new_tvc
)
select *
from (values (1),(2)) as tvc_0
)
and b in
(
select *
from (values (1),(5)) as new_tvc
select *
from (values (1),(5)) as tvc_1
);
eval $query;
eval $optimized_query;
eval explain $query;
eval explain $optimized_query;
eval explain format=json $query;
--echo # OR-condition with IN-predicates in WHERE-part
let $query=
select * from t1
where a in (1,2) or
b in (4,5);
let $optimized_query=
select * from t1
where a in
(
select *
from (values (1),(2)) as new_tvc
)
or b in
(
select *
from (values (4),(5)) as new_tvc
);
eval $query;
eval $optimized_query;
eval explain $query;
eval explain $optimized_query;
eval explain format=json $query;
eval explain extended $query;
eval explain extended $optimized_query;
--echo # subquery with IN-predicate
let $query=
select * from t1
where a in
(
select a
from t2 where b in (3,4)
)
;
let $query=
select * from t1
where a in
(
select a
from t2 where b in (3,4)
);
let $optimized_query=
select * from t1
where a in (
select a from t2
where b in
let $optimized_query=
select * from t1
where a in
(
select a from t2
where b in
(
select *
from (values (3),(4)) as new_tvc)
select *
from (values (3),(4)) as tvc_0
)
;
);
eval $query;
eval $optimized_query;
eval explain $query;
eval explain $optimized_query;
eval explain format=json $query;
eval explain extended $query;
eval explain extended $optimized_query;
drop table t1;
--echo # derived table with IN-predicate
let $query=
select * from
(
select *
from t1
where a in (1,2)
) as dr_table;
let $optimized_query=
select * from
(
select *
from t1
where a in
(
select *
from (values (1),(2))
as tvc_0
)
) as dr_table;
eval $query;
eval $optimized_query;
eval explain extended $query;
eval explain extended $optimized_query;
--echo # non-recursive CTE with IN-predicate
let $cte_query=
with tvc_0 as
(
select *
from t1
where a in (1,2)
)
select * from tvc_0;
eval $cte_query;
eval $optimized_query;
eval explain extended $cte_query;
eval explain extended $optimized_query;
--echo # VIEW with IN-predicate
create view v1 as
select *
from t1
where a in (1,2);
create view v2 as
select *
from t1
where a in
(
select *
from (values (1),(2))
as tvc_0
)
;
let $query= select * from v1;
let $optimized_query= select * from v2;
eval $query;
eval $optimized_query;
eval explain extended $query;
eval explain extended $optimized_query;
drop view v1,v2;
--echo # subselect defined by derived table with IN-predicate
let $query=
select * from t1
where a in
(
select 1
from
(
select *
from t1
where a in (1,2)
)
as dr_table
);
let $optimized_query=
select * from t1
where a in
(
select 1
from
(
select *
from t1
where a in
(
select *
from (values (1),(2))
as tvc_0
)
)
as dr_table
);
eval $query;
eval $optimized_query;
eval explain extended $query;
eval explain extended $optimized_query;
--echo # derived table with IN-predicate and group by
let $query=
select * from
(
select max(a),b
from t1
where b in (3,5)
group by b
) as dr_table;
let $optimized_query=
select * from
(
select max(a),b
from t1
where b in
(
select *
from (values (3),(5))
as tvc_0
)
group by b
) as dr_table;
eval $query;
eval $optimized_query;
eval explain extended $query;
eval explain extended $optimized_query;
drop table t1, t2;
set @@in_subquery_conversion_threshold= default;

View File

@ -1,36 +0,0 @@
create table t1 (a int, b int);
insert into t1 values (1,2),(4,6),(9,7),(1,1),(2,5),(7,8);
values (1,2);
select 1,2 union values (1,2);
values (1,2) union select (1,2);
values (1,2), (3,4) union select 1,2;
select * from t1 where (t1.a,t1.b) in (select 5,7 union values (1,2),(2,3));
select * from t1 where (t1.a,t1.b) in (values (1,2),(2,3) union select 5,7);
let $drop_view= drop view v1;
create view v1 as values (1,2);
eval $drop_view;
create view v1 as values (1,2) union select 3,4;
eval $drop_view;
create view v1 as select 1,2 union values (3,4);
eval $drop_view;
create view v1 as select 1,2 union values (3,4),(5,6);
eval $drop_view;
drop table t1;

View File

@ -1,6 +1,7 @@
create table t1 (a int, b int);
insert into t1 values (1,2),(4,6),(9,7),(1,1),(2,5),(7,8);
insert into t1 values (1,2),(4,6),(9,7),
(1,1),(2,5),(7,8);
--echo # just VALUES
@ -10,164 +11,443 @@ values (1,2), (3,4), (5.6,0);
values ("abc", "def");
--echo # UNION using VALUES structure(s)
--echo # UNION that uses VALUES structure(s)
select 1,2 union values (1,2);
select 1,2
union
values (1,2);
values (1,2) union select 1,2;
values (1,2)
union
select 1,2;
select 1,2 union values (1,2),(3,4),(5,6),(7,8);
select 1,2
union
values (1,2),(3,4),(5,6),(7,8);
select 3,7 union values (1,2),(3,4),(5,6);
select 3,7
union
values (1,2),(3,4),(5,6);
select 3,7,4 union values (1,2,5),(4,5,6);
select 3,7,4
union
values (1,2,5),(4,5,6);
select 1,2 union values (1,7),(3,6.5);
select 1,2
union
values (1,7),(3,6.5);
select 1,2 union values (1,2.0),(3,6);
select 1,2
union
values (1,2.0),(3,6);
select 1.8,2 union values (1,2),(3,6);
select 1.8,2
union
values (1,2),(3,6);
values (1,2.4),(3,6) union select 2.8,9;
values (1,2.4),(3,6)
union
select 2.8,9;
values (1,2),(3,4),(5,6),(7,8) union select 5,6;
values (1,2),(3,4),(5,6),(7,8)
union
select 5,6;
select "ab","cdf" union values ("al","zl"),("we","q");
select "ab","cdf"
union
values ("al","zl"),("we","q");
values ("ab", "cdf") union select "ab","cdf";
values ("ab", "cdf")
union
select "ab","cdf";
values (1,2) union values (1,2),(5,6);
values (1,2)
union
values (1,2),(5,6);
values (1,2) union values (3,4),(5,6);
values (1,2)
union
values (3,4),(5,6);
values (1,2) union values (1,2) union values (4,5);
values (1,2)
union
values (1,2)
union values (4,5);
--echo # UNION ALL using VALUES structure
--echo # UNION ALL that uses VALUES structure
values (1,2),(3,4) union all select 5,6;
values (1,2),(3,4)
union all
select 5,6;
values (1,2),(3,4) union all select 1,2;
values (1,2),(3,4)
union all
select 1,2;
select 5,6 union all values (1,2),(3,4);
select 5,6
union all
values (1,2),(3,4);
select 1,2 union all values (1,2),(3,4);
select 1,2
union all
values (1,2),(3,4);
values (1,2)
union all
values (1,2),(5,6);
values (1,2) union all values (1,2),(5,6);
values (1,2) union all values (3,4),(5,6);
values (1,2) union all values (1,2) union all values (4,5);
values (1,2) union all values (1,2) union values (1,2);
values (1,2) union values (1,2) union all values (1,2);
--echo # EXCEPT using VALUES structure(s)
select 1,2 except values (3,4),(5,6);
select 1,2 except values (1,2),(3,4);
values (1,2),(3,4) except select 5,6;
values (1,2),(3,4) except select 1,2;
values (1,2),(3,4) except values (5,6);
values (1,2),(3,4) except values (1,2);
--echo # INTERSECT using VALUES structure(s)
select 1,2 intersect values (3,4),(5,6);
select 1,2 intersect values (1,2),(3,4);
values (1,2),(3,4) intersect select 5,6;
values (1,2),(3,4) intersect select 1,2;
values (1,2),(3,4) intersect values (5,6);
values (1,2),(3,4) intersect values (1,2);
--echo # combination of different structures using VALUES structures : UNION + EXCEPT
values (1,2),(3,4) except select 1,2 union values (1,2);
values (1,2),(3,4) except values (1,2) union values (1,2);
values (1,2),(3,4) except values (1,2) union values (3,4);
values (1,2),(3,4) union values (1,2) except values (1,2);
--echo # combination of different structures using VALUES structures : UNION ALL + EXCEPT
values (1,2),(3,4) except select 1,2 union all values (1,2);
values (1,2),(3,4) except values (1,2) union all values (1,2);
values (1,2),(3,4) except values (1,2) union all values (3,4);
values (1,2),(3,4) union all values (1,2) except values (1,2);
--echo # combination of different structures using VALUES structures : UNION + INTERSECT
values (1,2),(3,4) intersect select 1,2 union values (1,2);
values (1,2),(3,4) intersect values (1,2) union values (1,2);
values (1,2),(3,4) intersect values (1,2) union values (3,4);
values (1,2),(3,4) union values (1,2) intersect values (1,2);
--echo # combination of different structures using VALUES structures : UNION ALL + INTERSECT
values (1,2),(3,4) intersect select 1,2 union all values (1,2);
values (1,2),(3,4) intersect values (1,2) union all values (1,2);
values (1,2),(3,4) intersect values (1,2) union all values (3,4);
values (1,2),(3,4) union all values (1,2) intersect values (1,2);
--echo # combination of different structures using VALUES structures : UNION + UNION ALL
values (1,2),(3,4) union all select 1,2 union values (1,2);
values (1,2),(3,4) union all values (1,2) union values (1,2);
values (1,2),(3,4) union all values (1,2) union values (3,4);
values (1,2),(3,4) union values (1,2) union all values (1,2);
values (1,2) union values (1,2) union all values (1,2);
--echo # CTE using VALUES structure(s)
with t2 as (values (1,2),(3,4)) select * from t2;
with t2 as (select 1,2 union values (1,2)) select * from t2;
with t2 as (select 1,2 union values (1,2),(3,4)) select * from t2;
with t2 as (values (1,2) union select 1,2) select * from t2;
with t2 as (values (1,2),(3,4) union select 1,2) select * from t2;
with t2 as (values (5,6) union values (1,2),(3,4)) select * from t2;
with t2 as (values (1,2) union values (1,2),(3,4)) select * from t2;
with t2 as (select 1,2 union all values (1,2),(3,4)) select * from t2;
with t2 as (values (1,2),(3,4) union all select 1,2) select * from t2;
with t2 as (values (1,2) union all values (1,2),(3,4)) select * from t2;
--echo # Derived table using VALUES structure(s)
values (1,2)
union all
values (3,4),(5,6);
values (1,2)
union all
values (1,2)
union all
values (4,5);
values (1,2)
union all
values (1,2)
union values (1,2);
values (1,2)
union
values (1,2)
union all
values (1,2);
--echo # EXCEPT that uses VALUES structure(s)
select 1,2
except
values (3,4),(5,6);
select 1,2
except
values (1,2),(3,4);
values (1,2),(3,4)
except
select 5,6;
values (1,2),(3,4)
except
select 1,2;
values (1,2),(3,4)
except
values (5,6);
values (1,2),(3,4)
except
values (1,2);
--echo # INTERSECT that uses VALUES structure(s)
select 1,2
intersect
values (3,4),(5,6);
select 1,2
intersect
values (1,2),(3,4);
values (1,2),(3,4)
intersect
select 5,6;
values (1,2),(3,4)
intersect
select 1,2;
values (1,2),(3,4)
intersect
values (5,6);
values (1,2),(3,4)
intersect
values (1,2);
--echo # combination of different structures that uses VALUES structures : UNION + EXCEPT
values (1,2),(3,4)
except
select 1,2
union values (1,2);
values (1,2),(3,4)
except
values (1,2)
union
values (1,2);
values (1,2),(3,4)
except
values (1,2)
union
values (3,4);
values (1,2),(3,4)
union
values (1,2)
except
values (1,2);
--echo # combination of different structures that uses VALUES structures : UNION ALL + EXCEPT
values (1,2),(3,4)
except
select 1,2
union all
values (1,2);
values (1,2),(3,4)
except
values (1,2)
union all
values (1,2);
values (1,2),(3,4)
except
values (1,2)
union all
values (3,4);
values (1,2),(3,4)
union all
values (1,2)
except
values (1,2);
--echo # combination of different structures that uses VALUES structures : UNION + INTERSECT
values (1,2),(3,4)
intersect
select 1,2
union
values (1,2);
values (1,2),(3,4)
intersect
values (1,2)
union
values (1,2);
values (1,2),(3,4)
intersect
values (1,2)
union
values (3,4);
values (1,2),(3,4)
union
values (1,2)
intersect
values (1,2);
--echo # combination of different structures that uses VALUES structures : UNION ALL + INTERSECT
values (1,2),(3,4)
intersect
select 1,2
union all
values (1,2);
values (1,2),(3,4)
intersect
values (1,2)
union all
values (1,2);
values (1,2),(3,4)
intersect
values (1,2)
union all
values (3,4);
values (1,2),(3,4)
union all
values (1,2)
intersect
values (1,2);
--echo # combination of different structures that uses VALUES structures : UNION + UNION ALL
values (1,2),(3,4)
union all
select 1,2
union
values (1,2);
values (1,2),(3,4)
union all
values (1,2)
union
values (1,2);
values (1,2),(3,4)
union all
values (1,2)
union
values (3,4);
values (1,2),(3,4)
union
values (1,2)
union all
values (1,2);
values (1,2)
union
values (1,2)
union all
values (1,2);
--echo # CTE that uses VALUES structure(s) : non-recursive CTE
with t2 as
(
values (1,2),(3,4)
)
select * from t2;
with t2 as
(
select 1,2
union
values (1,2)
)
select * from t2;
with t2 as
(
select 1,2
union
values (1,2),(3,4)
)
select * from t2;
with t2 as
(
values (1,2)
union
select 1,2
)
select * from t2;
with t2 as
(
values (1,2),(3,4)
union
select 1,2
)
select * from t2;
with t2 as
(
values (5,6)
union
values (1,2),(3,4)
)
select * from t2;
with t2 as
(
values (1,2)
union
values (1,2),(3,4)
)
select * from t2;
with t2 as
(
select 1,2
union all
values (1,2),(3,4)
)
select * from t2;
with t2 as
(
values (1,2),(3,4)
union all
select 1,2
)
select * from t2;
with t2 as
(
values (1,2)
union all
values (1,2),(3,4)
)
select * from t2;
--echo # recursive CTE that uses VALUES structure(s) : singe VALUES structure as anchor
with recursive t2(a,b) as
(
values(1,1)
union
select t1.a, t1.b
from t1,t2
where t1.a=t2.a
)
select * from t2;
with recursive t2(a,b) as
(
values(1,1)
union
select t1.a+1, t1.b
from t1,t2
where t1.a=t2.a
)
select * from t2;
--echo # recursive CTE that uses VALUES structure(s) : several VALUES structures as anchors
with recursive t2(a,b) as
(
values(1,1)
union
values (3,4)
union
select t2.a+1, t1.b
from t1,t2
where t1.a=t2.a
)
select * from t2;
--echo # recursive CTE that uses VALUES structure(s) : that uses UNION ALL
with recursive t2(a,b,st) as
(
values(1,1,1)
union all
select t2.a, t1.b, t2.st+1
from t1,t2
where t1.a=t2.a and st<3
)
select * from t2;
--echo # recursive CTE that uses VALUES structure(s) : computation of factorial (first 10 elements)
with recursive fact(n,f) as
(
values(1,1)
union
select n+1,f*n from fact where n < 10
)
select * from fact;
--echo # Derived table that uses VALUES structure(s) : singe VALUES structure
select * from (values (1,2),(3,4)) as t2;
--echo # Derived table that uses VALUES structure(s) : UNION with VALUES structure(s)
select * from (select 1,2 union values (1,2)) as t2;
select * from (select 1,2 union values (1,2),(3,4)) as t2;
@ -180,13 +460,15 @@ select * from (values (5,6) union values (1,2),(3,4)) as t2;
select * from (values (1,2) union values (1,2),(3,4)) as t2;
--echo # Derived table that uses VALUES structure(s) : UNION ALL with VALUES structure(s)
select * from (select 1,2 union all values (1,2),(3,4)) as t2;
select * from (values (1,2),(3,4) union all select 1,2) as t2;
select * from (values (1,2) union all values (1,2),(3,4)) as t2;
--echo # CREATE VIEW using VALUES structure(s)
--echo # CREATE VIEW that uses VALUES structure(s) : singe VALUES structure
let $drop_view= drop view v1;
let $select_view= select * from v1;
@ -196,49 +478,378 @@ create view v1 as values (1,2),(3,4);
eval $select_view;
eval $drop_view;
create view v1 as select 1,2 union values (1,2);
--echo # CREATE VIEW that uses VALUES structure(s) : UNION with VALUES structure(s)
create view v1 as
select 1,2
union
values (1,2);
eval $select_view;
eval $drop_view;
create view v1 as select 1,2 union values (1,2),(3,4);
create view v1 as
select 1,2
union
values (1,2),(3,4);
eval $select_view;
eval $drop_view;
create view v1 as values (1,2) union select 1,2;
create view v1 as
values (1,2)
union
select 1,2;
eval $select_view;
eval $drop_view;
create view v1 as values (1,2),(3,4) union select 1,2;
create view v1 as
values (1,2),(3,4)
union
select 1,2;
eval $select_view;
eval $drop_view;
create view v1 as values (5,6) union values (1,2),(3,4);
create view v1 as
values (5,6)
union
values (1,2),(3,4);
eval $select_view;
eval $drop_view;
create view v1 as values (1,2) union values (1,2),(3,4);
--echo # CREATE VIEW that uses VALUES structure(s) : UNION ALL with VALUES structure(s)
create view v1 as
values (1,2)
union
values (1,2),(3,4);
eval $select_view;
eval $drop_view;
create view v1 as select 1,2 union all values (1,2),(3,4);
create view v1 as
select 1,2
union all
values (1,2),(3,4);
eval $select_view;
eval $drop_view;
create view v1 as values (1,2),(3,4) union all select 1,2;
create view v1 as
values (1,2),(3,4)
union all
select 1,2;
eval $select_view;
eval $drop_view;
create view v1 as values (1,2) union all values (1,2),(3,4);
create view v1 as
values (1,2)
union all
values (1,2),(3,4);
eval $select_view;
eval $drop_view;
--echo # prepare statement that uses VALUES structure(s): single VALUES structure
prepare stmt1 from "
values (1,2);
";
execute stmt1;
execute stmt1;
deallocate prepare stmt1;
--echo # prepare statement that uses VALUES structure(s): UNION with VALUES structure(s)
prepare stmt1 from "
select 1,2
union
values (1,2),(3,4);
";
execute stmt1;
execute stmt1;
deallocate prepare stmt1;
prepare stmt1 from "
values (1,2),(3,4)
union
select 1,2;
";
execute stmt1;
execute stmt1;
deallocate prepare stmt1;
prepare stmt1 from "
select 1,2
union
values (3,4)
union
values (1,2);
";
execute stmt1;
execute stmt1;
deallocate prepare stmt1;
prepare stmt1 from "
values (5,6)
union
values (1,2),(3,4);
";
execute stmt1;
execute stmt1;
deallocate prepare stmt1;
--echo # prepare statement that uses VALUES structure(s): UNION ALL with VALUES structure(s)
prepare stmt1 from "
select 1,2
union
values (1,2),(3,4);
";
execute stmt1;
execute stmt1;
deallocate prepare stmt1;
prepare stmt1 from "
values (1,2),(3,4)
union all
select 1,2;
";
execute stmt1;
execute stmt1;
deallocate prepare stmt1;
prepare stmt1 from "
select 1,2
union all
values (3,4)
union all
values (1,2);
";
execute stmt1;
execute stmt1;
deallocate prepare stmt1;
prepare stmt1 from "
values (1,2)
union all
values (1,2),(3,4);
";
execute stmt1;
execute stmt1;
deallocate prepare stmt1;
--echo # explain query that uses VALUES structure(s): single VALUES structure
explain
values (1,2);
explain format=json
values (1,2);
--echo # explain query that uses VALUES structure(s): UNION with VALUES structure(s)
explain
select 1,2
union
values (1,2),(3,4);
explain
values (1,2),(3,4)
union
select 1,2;
explain
values (5,6)
union
values (1,2),(3,4);
explain format=json
select 1,2
union
values (1,2),(3,4);
explain format=json
values (1,2),(3,4)
union
select 1,2;
explain format=json
values (5,6)
union
values (1,2),(3,4);
explain
select 1,2
union
values (3,4)
union
values (1,2);
explain format=json
select 1,2
union
values (3,4)
union
values (1,2);
--echo # explain query that uses VALUES structure(s): UNION ALL with VALUES structure(s)
explain
select 1,2
union
values (1,2),(3,4);
explain
values (1,2),(3,4)
union all
select 1,2;
explain
values (1,2)
union all
values (1,2),(3,4);
explain format=json
values (1,2),(3,4)
union all
select 1,2;
explain format=json
select 1,2
union
values (1,2),(3,4);
explain format=json
values (1,2)
union all
values (1,2),(3,4);
explain
select 1,2
union all
values (3,4)
union all
values (1,2);
explain format=json
select 1,2
union all
values (3,4)
union all
values (1,2);
--echo # analyze query that uses VALUES structure(s): single VALUES structure
analyze
values (1,2);
analyze format=json
values (1,2);
--echo # analyze query that uses VALUES structure(s): UNION with VALUES structure(s)
analyze
select 1,2
union
values (1,2),(3,4);
analyze
values (1,2),(3,4)
union
select 1,2;
analyze
values (5,6)
union
values (1,2),(3,4);
analyze format=json
select 1,2
union
values (1,2),(3,4);
analyze format=json
values (1,2),(3,4)
union
select 1,2;
analyze format=json
values (5,6)
union
values (1,2),(3,4);
analyze
select 1,2
union
values (3,4)
union
values (1,2);
analyze format=json
select 1,2
union
values (3,4)
union
values (1,2);
--echo # analyze query that uses VALUES structure(s): UNION ALL with VALUES structure(s)
analyze
select 1,2
union
values (1,2),(3,4);
analyze
values (1,2),(3,4)
union all
select 1,2;
analyze
values (1,2)
union all
values (1,2),(3,4);
analyze format=json
values (1,2),(3,4)
union all
select 1,2;
analyze format=json
select 1,2
union
values (1,2),(3,4);
analyze format=json
values (1,2)
union all
values (1,2),(3,4);
analyze
select 1,2
union all
values (3,4)
union all
values (1,2);
analyze format=json
select 1,2
union all
values (3,4)
union all
values (1,2);
drop table t1;

View File

@ -1667,6 +1667,8 @@ public:
virtual Item *derived_grouping_field_transformer_for_where(THD *thd,
uchar *arg)
{ return this; }
virtual Item *in_predicate_to_in_subs_transformer(THD *thd, uchar *arg)
{ return this; }
virtual bool expr_cache_is_needed(THD *) { return FALSE; }
virtual Item *safe_charset_converter(THD *thd, CHARSET_INFO *tocs);
bool needs_charset_converter(uint32 length, CHARSET_INFO *tocs)

View File

@ -4327,6 +4327,16 @@ longlong Item_func_in::val_int()
}
void Item_func_in::mark_as_condition_AND_part(TABLE_LIST *embedding)
{
THD *thd= current_thd;
if (can_be_transformed_in_tvc(thd))
thd->lex->current_select->in_funcs.push_back(this, thd->mem_root);
emb_on_expr_nest= embedding;
}
longlong Item_func_bit_or::val_int()
{
DBUG_ASSERT(fixed == 1);

View File

@ -2144,11 +2144,13 @@ public:
*/
bool arg_types_compatible;
TABLE_LIST *emb_on_expr_nest;
Item_func_in(THD *thd, List<Item> &list):
Item_func_opt_neg(thd, list),
Predicant_to_list_comparator(thd, arg_count - 1),
array(0), have_null(0),
arg_types_compatible(FALSE)
arg_types_compatible(FALSE), emb_on_expr_nest(0)
{ }
longlong val_int();
bool fix_fields(THD *, Item **);
@ -2240,7 +2242,10 @@ public:
return NULL;
}
return clone;
}
}
void mark_as_condition_AND_part(TABLE_LIST *embedding);
bool can_be_transformed_in_tvc(THD *thd);
Item *in_predicate_to_in_subs_transformer(THD *thd, uchar *arg);
};
class cmp_item_row :public cmp_item

View File

@ -1047,6 +1047,8 @@ bool convert_join_subqueries_to_semijoins(JOIN *join)
DBUG_RETURN(1);
if (subq_sel->handle_derived(thd->lex, DT_MERGE))
DBUG_RETURN(TRUE);
if (subq_sel->join->transform_in_predicate_into_tvc(thd))
DBUG_RETURN(TRUE);
subq_sel->update_used_tables();
}

View File

@ -7490,3 +7490,5 @@ ER_WRONG_INSERT_INTO_SEQUENCE
eng "Wrong INSERT into a SEQUENCE. One can only do single table INSERT into a squence object (like with mysqldump). If you want to change the SEQUENCE, use ALTER SEQUENCE instead."
ER_SP_STACK_TRACE
eng "At line %u in %s"
ER_WRONG_NUMBER_OF_COLUMNS_IN_TABLE_VALUE_CONSTRUCTOR
eng "The used TABLE VALUE CONSTRUCTOR has a different number of columns"

View File

@ -691,6 +691,7 @@ typedef struct system_variables
uint idle_transaction_timeout;
uint idle_readonly_transaction_timeout;
uint idle_readwrite_transaction_timeout;
ulong in_subquery_conversion_threshold;
} SV;
/**

View File

@ -2224,6 +2224,7 @@ void st_select_lex::init_query()
m_agg_func_used= false;
window_specs.empty();
window_funcs.empty();
tvc= 0;
}
void st_select_lex::init_select()
@ -2263,6 +2264,8 @@ void st_select_lex::init_select()
join= 0;
lock_type= TL_READ_DEFAULT;
tvc= 0;
in_funcs.empty();
cur_tvc= 0;
}
/*
@ -2807,7 +2810,10 @@ void st_select_lex_unit::print(String *str, enum_query_type query_type)
}
if (sl->braces)
str->append('(');
sl->print(thd, str, query_type);
if (sl->tvc)
sl->tvc->print(thd, str, query_type);
else
sl->print(thd, str, query_type);
if (sl->braces)
str->append(')');
}
@ -4188,6 +4194,22 @@ bool SELECT_LEX::merge_subquery(THD *thd, TABLE_LIST *derived,
if (in_subq->emb_on_expr_nest == NO_JOIN_NEST)
in_subq->emb_on_expr_nest= derived;
}
uint cnt= sizeof(expr_cache_may_be_used)/sizeof(bool);
for (uint i= 0; i < cnt; i++)
{
if (subq_select->expr_cache_may_be_used[i])
expr_cache_may_be_used[i]= true;
}
List_iterator_fast<Item_func_in> it(subq_select->in_funcs);
Item_func_in *in_func;
while ((in_func= it++))
{
in_funcs.push_back(in_func, thd->mem_root);
if (in_func->emb_on_expr_nest == NO_JOIN_NEST)
in_func->emb_on_expr_nest= derived;
}
}
/* Walk through child's tables and adjust table map, tablenr,

View File

@ -864,6 +864,17 @@ public:
those converted to jtbm nests. The list is emptied when conversion is done.
*/
List<Item_in_subselect> sj_subselects;
/*
List of IN-predicates in this st_select_lex that
can be transformed into IN-subselect defined with TVC.
*/
List<Item_func_in> in_funcs;
/*
Number of current derived table made with TVC during the
transformation of IN-predicate into IN-subquery for this
st_select_lex.
*/
uint cur_tvc;
/*
Needed to correctly generate 'PRIMARY' or 'SIMPLE' for select_type column
@ -1215,7 +1226,7 @@ public:
bool have_window_funcs() const { return (window_funcs.elements !=0); }
bool cond_pushdown_is_allowed() const
{ return !have_window_funcs() && !olap && !explicit_limit; }
{ return !have_window_funcs() && !olap && !explicit_limit && !tvc; }
private:
bool m_non_agg_field_used;
@ -1239,7 +1250,12 @@ typedef class st_select_lex SELECT_LEX;
inline bool st_select_lex_unit::is_unit_op ()
{
if (!first_select()->next_select())
return 0;
{
if (first_select()->tvc)
return 1;
else
return 0;
}
enum sub_select_type linkage= first_select()->next_select()->linkage;
return linkage == UNION_TYPE || linkage == INTERSECT_TYPE ||

View File

@ -347,7 +347,8 @@ bool handle_select(THD *thd, LEX *lex, select_result *result,
MYSQL_SELECT_START(thd->query());
if (select_lex->master_unit()->is_unit_op() ||
select_lex->master_unit()->fake_select_lex)
select_lex->master_unit()->fake_select_lex ||
select_lex->tvc)
res= mysql_union(thd, lex, result, &lex->unit, setup_tables_done_option);
else
{
@ -1187,6 +1188,11 @@ JOIN::optimize_inner()
DBUG_RETURN(TRUE);
table_count= select_lex->leaf_tables.elements;
}
if (select_lex->first_cond_optimization &&
transform_in_predicate_into_tvc(thd))
DBUG_RETURN(1);
// Update used tables after all handling derived table procedures
select_lex->update_used_tables();
@ -13628,8 +13634,9 @@ static int compare_fields_by_table_order(Item *field1,
static TABLE_LIST* embedding_sjm(Item *item)
{
Item_field *item_field= (Item_field *) (item->real_item());
TABLE_LIST *nest= item_field->field->table->pos_in_table_list->embedding;
if (nest && nest->sj_mat_info && nest->sj_mat_info->is_used)
TABLE_LIST *tbl= item_field->field->table->pos_in_table_list;
TABLE_LIST *nest= tbl->embedding;
if (nest && nest->sj_mat_info && nest->sj_mat_info->is_used && !tbl->is_for_tvc)
return nest;
else
return NULL;
@ -13706,6 +13713,7 @@ Item *eliminate_item_equal(THD *thd, COND *cond, COND_EQUAL *upper_levels,
Item *head;
TABLE_LIST *current_sjm= NULL;
Item *current_sjm_head= NULL;
bool force_producing_equality= false;
DBUG_ASSERT(!cond ||
cond->type() == Item::INT_ITEM ||
@ -13727,6 +13735,8 @@ Item *eliminate_item_equal(THD *thd, COND *cond, COND_EQUAL *upper_levels,
TABLE_LIST *emb_nest;
head= item_equal->get_first(NO_PARTICULAR_TAB, NULL);
it++;
if (((Item_field *)(head->real_item()))->field->table->pos_in_table_list->is_for_tvc)
force_producing_equality= true;
if ((emb_nest= embedding_sjm(head)))
{
current_sjm= emb_nest;
@ -13794,7 +13804,7 @@ Item *eliminate_item_equal(THD *thd, COND *cond, COND_EQUAL *upper_levels,
produce_equality= FALSE;
}
if (produce_equality)
if (produce_equality || force_producing_equality)
{
if (eq_item && eq_list.push_back(eq_item, thd->mem_root))
return 0;
@ -13809,7 +13819,8 @@ Item *eliminate_item_equal(THD *thd, COND *cond, COND_EQUAL *upper_levels,
equals on top level, or the constant.
*/
Item *head_item= (!item_const && current_sjm &&
current_sjm_head != field_item) ? current_sjm_head: head;
current_sjm_head != field_item &&
!force_producing_equality) ? current_sjm_head: head;
Item *head_real_item= head_item->real_item();
if (head_real_item->type() == Item::FIELD_ITEM)
head_item= head_real_item;

View File

@ -1648,6 +1648,7 @@ public:
bool need_order, bool distinct,
const char *message);
JOIN_TAB *first_breadth_first_tab() { return join_tab; }
bool transform_in_predicate_into_tvc(THD *thd_arg);
private:
/**
Create a temporary table to be used for processing DISTINCT/ORDER

View File

@ -1,14 +1,40 @@
#include "sql_list.h"
#include "sql_tvc.h"
#include "sql_class.h"
#include "opt_range.h"
#include "sql_select.h"
#include "sql_explain.h"
#include "sql_parse.h"
/**
The method searches types of columns for temporary table where values from TVC will be stored
@brief
Defines types of matrix columns elements where matrix rows are defined by
some lists of values.
@param
@param thd_arg The context of the statement
@param li The iterator on the list of lists
@param holders The structure where types of matrix columns are stored
@param first_list_el_count Count of the list values that should be. It should
be the same for each list of lists elements. It contains
number of elements of the first list from list of lists.
@details
For each list list_a from list of lists the procedure gets its elements types and
aggregates them with the previous ones stored in holders. If list_a is the first
one in the list of lists its elements types are put in holders.
The errors can be reported when count of list_a elements is different from the
first_list_el_count. Also error can be reported when aggregation can't be made.
@retval
true if an error was reported
false otherwise
*/
bool join_type_handlers_for_tvc(List_iterator_fast<List_item> &li,
Type_holder *holders, uint cnt)
bool join_type_handlers_for_tvc(THD *thd_arg, List_iterator_fast<List_item> &li,
Type_holder *holders, uint first_list_el_count)
{
DBUG_ENTER("join_type_handlers_for_tvc");
List_item *lst;
li.rewind();
bool first= true;
@ -18,10 +44,12 @@ bool join_type_handlers_for_tvc(List_iterator_fast<List_item> &li,
List_iterator_fast<Item> it(*lst);
Item *item;
if (cnt != lst->elements)
if (first_list_el_count != lst->elements)
{
/*error wrong number of values*/
return true;
my_message(ER_WRONG_NUMBER_OF_COLUMNS_IN_TABLE_VALUE_CONSTRUCTOR,
ER_THD(thd_arg, ER_WRONG_NUMBER_OF_COLUMNS_IN_TABLE_VALUE_CONSTRUCTOR),
MYF(0));
DBUG_RETURN(true);
}
for (uint pos= 0; (item=it++); pos++)
{
@ -30,54 +58,105 @@ bool join_type_handlers_for_tvc(List_iterator_fast<List_item> &li,
holders[pos].set_handler(item_type_handler);
else if (holders[pos].aggregate_for_result(item_type_handler))
{
/*error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION*/
return true;
my_error(ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION, MYF(0),
holders[pos].type_handler()->name().ptr(),
item_type_handler->name().ptr(),
"TABLE VALUE CONSTRUCTOR");
DBUG_RETURN(true);
}
}
first= false;
}
return false;
DBUG_RETURN(false);
}
/**
The method searches names of columns for temporary table where values from TVC will be stored
@brief
Defines attributes of matrix columns elements where matrix rows are defined by
some lists of values.
@param
@param thd_arg The context of the statement
@param li The iterator on the list of lists
@param holders The structure where names of matrix columns are stored
@param count_of_lists Count of list of lists elements
@param first_list_el_count Count of the list values that should be. It should
be the same for each list of lists elements. It contains
number of elements of the first list from list of lists.
@details
For each list list_a from list of lists the procedure gets its elements attributes and
aggregates them with the previous ones stored in holders.
The errors can be reported when aggregation can't be made.
@retval
true if an error was reported
false otherwise
*/
bool get_type_attributes_for_tvc(THD *thd_arg,
List_iterator_fast<List_item> &li,
Type_holder *holders, uint count)
Type_holder *holders, uint count_of_lists,
uint first_list_el_count)
{
DBUG_ENTER("get_type_attributes_for_tvc");
List_item *lst;
li.rewind();
lst= li++;
uint first_list_el_count= lst->elements;
for (uint pos= 0; pos < first_list_el_count; pos++)
{
if (holders[pos].alloc_arguments(thd_arg, count))
return true;
if (holders[pos].alloc_arguments(thd_arg, count_of_lists))
DBUG_RETURN(true);
}
List_iterator_fast<Item> it(*lst);
Item *item;
for (uint holder_pos= 0 ; (item= it++); holder_pos++)
while ((lst=li++))
{
DBUG_ASSERT(item->fixed);
holders[holder_pos].add_argument(item);
List_iterator_fast<Item> it(*lst);
Item *item;
for (uint holder_pos= 0 ; (item= it++); holder_pos++)
{
DBUG_ASSERT(item->fixed);
holders[holder_pos].add_argument(item);
}
}
for (uint pos= 0; pos < first_list_el_count; pos++)
{
if (holders[pos].aggregate_attributes(thd_arg))
return true;
DBUG_RETURN(true);
}
return false;
DBUG_RETURN(false);
}
bool table_value_constr::prepare(THD *thd_arg, SELECT_LEX *sl, select_result *tmp_result)
/**
@brief
Prepare of TVC
@param
@param thd_arg The context of the statement
@param sl The select where this TVC is defined
@param tmp_result Structure that contains the information
about where result of the query should be sent
@param unit_arg The union where sl is defined
@details
Gets types and attributes of values of this TVC that will be used
for temporary table creation for this TVC. It creates Item_type_holders
for each element of the first list from list of lists (VALUES from tvc),
using its elements name, defined type and attribute.
@retval
true if an error was reported
false otherwise
*/
bool table_value_constr::prepare(THD *thd_arg, SELECT_LEX *sl,
select_result *tmp_result,
st_select_lex_unit *unit_arg)
{
DBUG_ENTER("table_value_constr::prepare");
List_iterator_fast<List_item> li(lists_of_values);
List_item *first_elem= li++;
@ -86,9 +165,11 @@ bool table_value_constr::prepare(THD *thd_arg, SELECT_LEX *sl, select_result *tm
if (!(holders= new (thd_arg->mem_root)
Type_holder[cnt]) ||
join_type_handlers_for_tvc(li, holders, cnt) ||
get_type_attributes_for_tvc(thd_arg, li, holders, cnt))
return true;
join_type_handlers_for_tvc(thd_arg, li, holders,
cnt) ||
get_type_attributes_for_tvc(thd_arg, li, holders,
lists_of_values.elements, cnt))
DBUG_RETURN(true);
List_iterator_fast<Item> it(*first_elem);
Item *item;
@ -108,21 +189,448 @@ bool table_value_constr::prepare(THD *thd_arg, SELECT_LEX *sl, select_result *tm
}
if (thd_arg->is_fatal_error)
return true; // out of memory
DBUG_RETURN(true); // out of memory
result= tmp_result;
return false;
if (result && result->prepare(sl->item_list, unit_arg))
DBUG_RETURN(true);
DBUG_RETURN(false);
}
bool table_value_constr::exec()
/**
Save Query Plan Footprint
*/
int table_value_constr::save_explain_data_intern(THD *thd_arg,
Explain_query *output)
{
const char *message= "No tables used";
DBUG_ENTER("table_value_constr::save_explain_data_intern");
DBUG_PRINT("info", ("Select 0x%lx, type %s, message %s",
(ulong)select_lex, select_lex->type,
message));
DBUG_ASSERT(have_query_plan == QEP_AVAILABLE);
/* There should be no attempts to save query plans for merged selects */
DBUG_ASSERT(!select_lex->master_unit()->derived ||
select_lex->master_unit()->derived->is_materialized_derived() ||
select_lex->master_unit()->derived->is_with_table());
explain= new (output->mem_root) Explain_select(output->mem_root,
thd_arg->lex->analyze_stmt);
select_lex->set_explain_type(true);
explain->select_id= select_lex->select_number;
explain->select_type= select_lex->type;
explain->linkage= select_lex->linkage;
explain->using_temporary= NULL;
explain->using_filesort= NULL;
/* Setting explain->message means that all other members are invalid */
explain->message= message;
if (select_lex->master_unit()->derived)
explain->connection_type= Explain_node::EXPLAIN_NODE_DERIVED;
output->add_node(explain);
if (select_lex->is_top_level_node())
output->query_plan_ready();
DBUG_RETURN(0);
}
/**
Optimization of TVC
*/
void table_value_constr::optimize(THD *thd_arg)
{
create_explain_query_if_not_exists(thd_arg->lex, thd_arg->mem_root);
have_query_plan= QEP_AVAILABLE;
if (select_lex->select_number != UINT_MAX &&
select_lex->select_number != INT_MAX /* this is not a UNION's "fake select */ &&
have_query_plan != QEP_NOT_PRESENT_YET &&
thd_arg->lex->explain && // for "SET" command in SPs.
(!thd_arg->lex->explain->get_select(select_lex->select_number)))
{
save_explain_data_intern(thd_arg, thd_arg->lex->explain);
}
}
/**
Execute of TVC
*/
bool table_value_constr::exec(SELECT_LEX *sl)
{
DBUG_ENTER("table_value_constr::exec");
List_iterator_fast<List_item> li(lists_of_values);
List_item *elem;
if (select_options & SELECT_DESCRIBE)
DBUG_RETURN(false);
if (result->send_result_set_metadata(sl->item_list,
Protocol::SEND_NUM_ROWS |
Protocol::SEND_EOF))
{
DBUG_RETURN(true);
}
while ((elem=li++))
{
result->send_data(*elem);
}
if (result->send_eof())
DBUG_RETURN(true);
DBUG_RETURN(false);
}
/**
@brief
Print list of lists
@param str Where to print to
@param query_type The mode of printing
@param values List of lists that needed to be print
@details
The method prints a string representation of list of lists in the
string str. The parameter query_type specifies the mode of printing.
*/
void print_list_of_lists(String *str,
enum_query_type query_type,
List<List_item> *values)
{
str->append(STRING_WITH_LEN("values "));
bool first= 1;
List_iterator_fast<List_item> li(*values);
List_item *list;
while ((list=li++))
{
if (first)
first= 0;
else
str->append(',');
str->append('(');
List_iterator_fast<Item> it(*list);
Item *item;
first= 1;
while ((item=it++))
{
if (first)
first= 0;
else
str->append(',');
item->print(str, query_type);
}
str->append(')');
}
}
/**
@brief
Print this TVC
@param thd_arg The context of the statement
@param str Where to print to
@param query_type The mode of printing
@details
The method prints a string representation of this TVC in the
string str. The parameter query_type specifies the mode of printing.
*/
void table_value_constr::print(THD *thd_arg, String *str,
enum_query_type query_type)
{
DBUG_ASSERT(thd_arg);
print_list_of_lists(str, query_type, &lists_of_values);
}
/**
@brief
Creates new SELECT defined by TVC as derived table
@param thd_arg The context of the statement
@param values List of values that defines TVC
@details
The method creates this SELECT statement:
SELECT * FROM (VALUES values) AS new_tvc
If during creation of SELECT statement some action is
unsuccesfull backup is made to the state in which system
was at the beginning of the method.
@retval
pointer to the created SELECT statement
NULL - if creation was unsuccesfull
*/
st_select_lex *make_new_subselect_for_tvc(THD *thd_arg,
List<List_item> *values)
{
LEX *lex= thd_arg->lex;
Item *item;
SELECT_LEX *sel;
SELECT_LEX_UNIT *unit;
TABLE_LIST *new_tab;
Table_ident *ti;
Query_arena backup;
Query_arena *arena= thd_arg->activate_stmt_arena_if_needed(&backup);
char buff[6];
LEX_CSTRING alias;
alias.length= my_snprintf(buff, sizeof(buff),
"tvc_%u", thd_arg->lex->current_select->cur_tvc);
alias.str= thd_arg->strmake(buff, alias.length);
if (!alias.str)
goto err;
/*
Creation of SELECT statement: SELECT * FROM ...
*/
if (mysql_new_select(lex, 1, NULL))
goto err;
mysql_init_select(lex);
lex->current_select->parsing_place= SELECT_LIST;
item= new (thd_arg->mem_root)
Item_field(thd_arg, &lex->current_select->context,
NULL, NULL, &star_clex_str);
if (item == NULL)
goto err;
if (add_item_to_list(thd_arg, item))
goto err;
(lex->current_select->with_wild)++;
/*
Creation of TVC as derived table
*/
lex->derived_tables|= DERIVED_SUBQUERY;
if (mysql_new_select(lex, 1, NULL))
goto err;
mysql_init_select(lex);
sel= lex->current_select;
unit= sel->master_unit();
sel->linkage= DERIVED_TABLE_TYPE;
if (!(sel->tvc=
new (thd_arg->mem_root)
table_value_constr(*values,
sel,
sel->options)))
goto err;
lex->check_automatic_up(UNSPECIFIED_TYPE);
lex->current_select= sel= unit->outer_select();
ti= new (thd_arg->mem_root) Table_ident(unit);
if (ti == NULL)
goto err;
if (!(new_tab= sel->add_table_to_list(thd_arg,
ti, &alias, 0,
TL_READ, MDL_SHARED_READ)))
goto err;
new_tab->is_for_tvc= true; //shows that this derived table is defined by TVC
sel->add_joined_table(new_tab);
new_tab->select_lex->add_where_field(new_tab->derived->first_select());
sel->context.table_list=
sel->context.first_name_resolution_table=
sel->table_list.first;
sel->where= 0;
sel->set_braces(false);
unit->with_clause= 0;
return sel;
err:
if (arena)
thd_arg->restore_active_arena(arena, &backup);
return NULL;
}
/**
@brief
Transforms IN-predicate in IN-subselect
@param thd_arg The context of the statement
@param arg Argument is 0 in this context
@details
The method creates this SELECT statement:
SELECT * FROM (VALUES values) AS new_tvc
If during creation of SELECT statement some action is
unsuccesfull backup is made to the state in which system
was at the beginning of the procedure.
@retval
pointer to the created SELECT statement
NULL - if creation was unsuccesfull
*/
Item *Item_func_in::in_predicate_to_in_subs_transformer(THD *thd,
uchar *arg)
{
SELECT_LEX *old_select= thd->lex->current_select;
List<List_item> values;
bool list_of_lists= false;
if (args[1]->type() == Item::ROW_ITEM)
list_of_lists= true;
for (uint i=1; i < arg_count; i++)
{
List<Item> *new_value= new (thd->mem_root) List<Item>();
if (list_of_lists)
{
Item_row *in_list= (Item_row *)(args[i]);
for (uint j=0; j < in_list->cols(); i++)
new_value->push_back(in_list->element_index(j), thd->mem_root);
}
else
new_value->push_back(args[i]);
values.push_back(new_value, thd->mem_root);
}
st_select_lex *new_subselect=
make_new_subselect_for_tvc(thd, &values);
if (new_subselect)
{
new_subselect->parsing_place= old_select->parsing_place;
new_subselect->table_list.first->derived_type= 10;
Item_in_subselect *in_subs= new (thd->mem_root) Item_in_subselect
(thd, args[0], new_subselect);
thd->lex->derived_tables |= DERIVED_SUBQUERY;
in_subs->emb_on_expr_nest= emb_on_expr_nest;
in_subs->fix_fields(thd, (Item **)&in_subs);
old_select->cur_tvc++;
thd->lex->current_select= old_select;
return in_subs;
}
thd->lex->current_select= old_select;
return this;
}
/**
@brief
Checks if this IN-predicate can be transformed in IN-subquery
with TVC
@param thd The context of the statement
@details
Compares the number of elements in the list of
values in this IN-predicate with the
in_subquery_conversion_threshold special variable
@retval
true if transformation can be made
false otherwise
*/
bool Item_func_in::can_be_transformed_in_tvc(THD *thd)
{
uint opt_can_be_used= arg_count;
if (args[1]->type() == Item::ROW_ITEM)
opt_can_be_used*= ((Item_row *)(args[1]))->cols();
if (opt_can_be_used < thd->variables.in_subquery_conversion_threshold)
return false;
return true;
}
/**
@brief
Calls transformer that transforms IN-predicate into IN-subquery
for this select
@param thd_arg The context of the statement
@details
Calls in_predicate_to_in_subs_transformer
for WHERE-part and each table from join list of this SELECT
*/
bool JOIN::transform_in_predicate_into_tvc(THD *thd_arg)
{
if (!select_lex->in_funcs.elements)
return false;
SELECT_LEX *old_select= thd_arg->lex->current_select;
enum_parsing_place old_parsing_place= select_lex->parsing_place;
thd_arg->lex->current_select= select_lex;
if (conds)
{
select_lex->parsing_place= IN_WHERE;
conds=
conds->transform(thd_arg,
&Item::in_predicate_to_in_subs_transformer,
(uchar*) 0);
select_lex->where= conds;
}
if (join_list)
{
TABLE_LIST *table;
List_iterator<TABLE_LIST> li(*join_list);
select_lex->parsing_place= IN_ON;
while ((table= li++))
{
if (table->on_expr)
{
table->on_expr=
table->on_expr->transform(thd_arg,
&Item::in_predicate_to_in_subs_transformer,
(uchar*) 0);
}
}
}
select_lex->parsing_place= old_parsing_place;
thd_arg->lex->current_select= old_select;
return false;
}

View File

@ -6,26 +6,45 @@
typedef List<Item> List_item;
class select_result;
class Explain_select;
class Explain_query;
class Item_func_in;
/**
@class table_value_constr
@brief Definition of a Table Value Construction(TVC)
It contains a list of lists of values that this TVC contains.
It contains a list of lists of values which this TVC is defined by and
reference on SELECT where this TVC is defined.
*/
class table_value_constr : public Sql_alloc
{
public:
List<List_item> lists_of_values;
select_result *result;
SELECT_LEX *select_lex;
enum { QEP_NOT_PRESENT_YET, QEP_AVAILABLE} have_query_plan;
Explain_select *explain;
ulonglong select_options;
table_value_constr(List<List_item> tvc_values) :
lists_of_values(tvc_values), result(0)
{ }
table_value_constr(List<List_item> tvc_values, SELECT_LEX *sl,
ulonglong select_options_arg) :
lists_of_values(tvc_values), result(0), select_lex(sl),
have_query_plan(QEP_NOT_PRESENT_YET), explain(0),
select_options(select_options_arg)
{ };
bool prepare(THD *thd_arg, SELECT_LEX *sl,
select_result *tmp_result);
bool exec();
};
select_result *tmp_result,
st_select_lex_unit *unit_arg);
int save_explain_data_intern(THD *thd_arg,
Explain_query *output);
void optimize(THD *thd_arg);
bool exec(SELECT_LEX *sl);
void print(THD *thd_arg, String *str, enum_query_type query_type);
};
#endif /* SQL_TVC_INCLUDED */

View File

@ -819,6 +819,7 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
bool is_union_select;
bool have_except= FALSE, have_intersect= FALSE;
bool instantiate_tmp_table= false;
bool single_tvc= !first_sl->next_select() && first_sl->tvc;
DBUG_ENTER("st_select_lex_unit::prepare");
DBUG_ASSERT(thd == thd_arg);
DBUG_ASSERT(thd == current_thd);
@ -845,16 +846,26 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
/* fast reinit for EXPLAIN */
for (sl= first_sl; sl; sl= sl->next_select())
{
sl->join->result= result;
select_limit_cnt= HA_POS_ERROR;
offset_limit_cnt= 0;
if (!sl->join->procedure &&
result->prepare(sl->join->fields_list, this))
if (sl->tvc)
{
DBUG_RETURN(TRUE);
sl->tvc->result= result;
if (result->prepare(sl->item_list, this))
DBUG_RETURN(TRUE);
sl->tvc->select_options|= SELECT_DESCRIBE;
}
else
{
sl->join->result= result;
select_limit_cnt= HA_POS_ERROR;
offset_limit_cnt= 0;
if (!sl->join->procedure &&
result->prepare(sl->join->fields_list, this))
{
DBUG_RETURN(TRUE);
}
sl->join->select_options|= SELECT_DESCRIBE;
sl->join->reinit();
}
sl->join->select_options|= SELECT_DESCRIBE;
sl->join->reinit();
}
}
DBUG_RETURN(FALSE);
@ -864,7 +875,7 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
thd_arg->lex->current_select= sl= first_sl;
found_rows_for_union= first_sl->options & OPTION_FOUND_ROWS;
is_union_select= is_unit_op() || fake_select_lex;
is_union_select= is_unit_op() || fake_select_lex || single_tvc;
for (SELECT_LEX *s= first_sl; s; s= s->next_select())
{
@ -884,8 +895,8 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
if (is_union_select || is_recursive)
{
if (is_unit_op() && !union_needs_tmp_table() &&
!have_except && !have_intersect)
if ((is_unit_op() && !union_needs_tmp_table() &&
!have_except && !have_intersect) || single_tvc)
{
SELECT_LEX *last= first_select();
while (last->next_select())
@ -922,7 +933,7 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
{
if (sl->tvc)
{
if (sl->tvc->prepare(thd_arg, sl, tmp_result))
if (sl->tvc->prepare(thd_arg, sl, tmp_result, this))
goto err;
}
else if (prepare_join(thd_arg, first_sl, tmp_result, additional_options,
@ -936,7 +947,7 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
{
if (sl->tvc)
{
if (sl->tvc->prepare(thd_arg, sl, tmp_result))
if (sl->tvc->prepare(thd_arg, sl, tmp_result, this))
goto err;
}
else if (prepare_join(thd_arg, sl, tmp_result, additional_options,
@ -1249,7 +1260,13 @@ bool st_select_lex_unit::optimize()
for (SELECT_LEX *sl= select_cursor; sl; sl= sl->next_select())
{
if (sl->tvc)
{
sl->tvc->select_options=
(select_limit_cnt == HA_POS_ERROR || sl->braces) ?
sl->options & ~OPTION_FOUND_ROWS : sl->options | found_rows_for_union;
sl->tvc->optimize(thd);
continue;
}
thd->lex->current_select= sl;
if (optimized)
@ -1273,7 +1290,7 @@ bool st_select_lex_unit::optimize()
we don't calculate found_rows() per union part.
Otherwise, SQL_CALC_FOUND_ROWS should be done on all sub parts.
*/
sl->join->select_options=
sl->join->select_options=
(select_limit_cnt == HA_POS_ERROR || sl->braces) ?
sl->options & ~OPTION_FOUND_ROWS : sl->options | found_rows_for_union;
@ -1357,7 +1374,14 @@ bool st_select_lex_unit::exec()
we don't calculate found_rows() per union part.
Otherwise, SQL_CALC_FOUND_ROWS should be done on all sub parts.
*/
if (!sl->tvc)
if (sl->tvc)
{
sl->tvc->select_options=
(select_limit_cnt == HA_POS_ERROR || sl->braces) ?
sl->options & ~OPTION_FOUND_ROWS : sl->options | found_rows_for_union;
sl->tvc->optimize(thd);
}
else
{
sl->join->select_options=
(select_limit_cnt == HA_POS_ERROR || sl->braces) ?
@ -1369,7 +1393,7 @@ bool st_select_lex_unit::exec()
{
records_at_start= table->file->stats.records;
if (sl->tvc)
sl->tvc->exec();
sl->tvc->exec(sl);
else
sl->join->exec();
if (sl == union_distinct && !(with_element && with_element->is_recursive))
@ -1611,8 +1635,13 @@ bool st_select_lex_unit::exec_recursive()
for (st_select_lex *sl= start ; sl != end; sl= sl->next_select())
{
thd->lex->current_select= sl;
sl->join->exec();
saved_error= sl->join->error;
if (sl->tvc)
sl->tvc->exec(sl);
else
{
sl->join->exec();
saved_error= sl->join->error;
}
if (!saved_error)
{
examined_rows+= thd->get_examined_row_count();

View File

@ -1782,7 +1782,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
table_primary_ident table_primary_derived
select_derived derived_table_list
select_derived_union
derived_simple_table
derived_query_specification
derived_table_value_constructor
%type <date_time_type> date_time_type;
%type <interval> interval
@ -8546,6 +8548,15 @@ select_paren_view:
/* The equivalent of select_paren for nested queries. */
select_paren_derived:
{
Lex->current_select->set_braces(true);
}
table_value_constructor
{
DBUG_ASSERT(Lex->current_select->braces);
$$= Lex->current_select->master_unit()->first_select();
}
|
{
Lex->current_select->set_braces(true);
}
@ -11250,9 +11261,9 @@ select_derived_union:
}
}
union_list_derived_part2
| derived_query_specification opt_select_lock_type
| derived_query_specification order_or_limit opt_select_lock_type
| derived_query_specification opt_select_lock_type union_list_derived
| derived_simple_table opt_select_lock_type
| derived_simple_table order_or_limit opt_select_lock_type
| derived_simple_table opt_select_lock_type union_list_derived
;
union_list_derived_part2:
@ -11307,6 +11318,10 @@ select_derived:
}
;
derived_simple_table:
derived_query_specification { $$= $1; }
| derived_table_value_constructor { $$= $1; }
;
/*
Similar to query_specification, but for derived tables.
Example: the inner parenthesized SELECT in this query:
@ -11321,6 +11336,41 @@ derived_query_specification:
}
;
derived_table_value_constructor:
VALUES
{
LEX *lex=Lex;
lex->field_list.empty();
lex->many_values.empty();
lex->insert_list=0;
}
values_list
{
LEX *lex= Lex;
lex->derived_tables|= DERIVED_SUBQUERY;
if (!lex->expr_allows_subselect ||
lex->sql_command == (int)SQLCOM_PURGE)
{
thd->parse_error();
MYSQL_YYABORT;
}
if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE ||
mysql_new_select(lex, 1, NULL))
MYSQL_YYABORT;
mysql_init_select(lex);
lex->current_select->linkage= DERIVED_TABLE_TYPE;
if (!(lex->current_select->tvc=
new (lex->thd->mem_root) table_value_constr(lex->many_values,
lex->current_select,
lex->current_select->options)))
MYSQL_YYABORT;
lex->many_values.empty();
$$= NULL;
}
;
select_derived2:
{
LEX *lex= Lex;
@ -16273,13 +16323,22 @@ simple_table:
;
table_value_constructor:
VALUES values_list
VALUES
{
LEX *lex=Lex;
lex->field_list.empty();
lex->many_values.empty();
lex->insert_list=0;
}
values_list
{
LEX *lex=Lex;
$$= Lex->current_select;
$$= lex->current_select;
mysql_init_select(Lex);
table_value_constr tvc(lex->many_values);
$$->tvc= &tvc;
if (!($$->tvc=
new (lex->thd->mem_root) table_value_constr(lex->many_values, $$, $$->options)))
MYSQL_YYABORT;
lex->many_values.empty();
}
;

View File

@ -5550,4 +5550,11 @@ static Sys_var_mybool Sys_session_track_state_change(
ON_CHECK(0),
ON_UPDATE(update_session_track_state_change));
static Sys_var_ulong Sys_in_subquery_conversion_threshold(
"in_subquery_conversion_threshold",
"The minimum number of scalar elements in the value list of"
"IN predicate that triggers its conversion to IN subquery",
SESSION_VAR(in_subquery_conversion_threshold), CMD_LINE(OPT_ARG),
VALID_RANGE(0, ULONG_MAX), DEFAULT(1000), BLOCK_SIZE(1));
#endif //EMBEDDED_LIBRARY

View File

@ -1930,6 +1930,7 @@ struct TABLE_LIST
*/
st_select_lex_unit *derived; /* SELECT_LEX_UNIT of derived table */
With_element *with; /* With element defining this table (if any) */
bool is_for_tvc; /* If specification of this table contains tvc*/
/* Bitmap of the defining with element */
table_map with_internal_reference_map;
bool block_handle_derived;