Summarized results of two previous commits (26 July, 25 August)
This commit is contained in:
parent
3310076dbe
commit
570d2e7d0f
@ -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
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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;
|
||||
|
||||
/**
|
||||
|
@ -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,
|
||||
|
@ -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 ||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
570
sql/sql_tvc.cc
570
sql/sql_tvc.cc
@ -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;
|
||||
}
|
@ -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 */
|
@ -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();
|
||||
|
@ -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();
|
||||
}
|
||||
;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user