mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 20:12:31 +01:00
Fixed bug mdev-11072.
In a general case the conditions with outer fields cannot be pushed into materialized views / derived tables. However if the outer field in the condition refers to a single row table then the condition may be pushable. In this case a special care should be taken for outer fields when pushing the condition into a materialized view / derived table.
This commit is contained in:
parent
ebe5ebba16
commit
68e7d92c4c
4 changed files with 131 additions and 3 deletions
|
@ -7083,3 +7083,87 @@ a
|
||||||
3
|
3
|
||||||
6
|
6
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
#
|
||||||
|
# MDEV-11072: pushdown of the condition obtained
|
||||||
|
# after constant row substitution
|
||||||
|
#
|
||||||
|
CREATE TABLE t1 (a INT);
|
||||||
|
CREATE TABLE t2 (b INT);
|
||||||
|
CREATE OR REPLACE VIEW v2 AS SELECT * FROM t2;
|
||||||
|
CREATE TABLE t3 (c INT);
|
||||||
|
CREATE OR REPLACE ALGORITHM=TEMPTABLE VIEW v3 AS SELECT * FROM t3;
|
||||||
|
SELECT * FROM t1 WHERE a IN (
|
||||||
|
SELECT b FROM v2 WHERE b < a OR b IN (
|
||||||
|
SELECT c FROM v3 WHERE c = a
|
||||||
|
)
|
||||||
|
);
|
||||||
|
a
|
||||||
|
INSERT INTO t1 VALUES (2);
|
||||||
|
INSERT INTO t2 VALUES (3), (2);
|
||||||
|
INSERT INTO t3 VALUES (4), (1), (2), (7);
|
||||||
|
SELECT * FROM t1 WHERE a IN (
|
||||||
|
SELECT b FROM v2 WHERE b < a OR b IN (
|
||||||
|
SELECT c FROM v3 WHERE c = a
|
||||||
|
)
|
||||||
|
);
|
||||||
|
a
|
||||||
|
2
|
||||||
|
EXPLAIN FORMAT=JSON
|
||||||
|
SELECT * FROM t1 WHERE a IN (
|
||||||
|
SELECT b FROM v2 WHERE b < a OR b IN (
|
||||||
|
SELECT c FROM v3 WHERE c = a
|
||||||
|
)
|
||||||
|
);
|
||||||
|
EXPLAIN
|
||||||
|
{
|
||||||
|
"query_block": {
|
||||||
|
"select_id": 1,
|
||||||
|
"const_condition": "(0 or <in_optimizer>(2,<exists>(subquery#3)))",
|
||||||
|
"table": {
|
||||||
|
"table_name": "t1",
|
||||||
|
"access_type": "system",
|
||||||
|
"rows": 1,
|
||||||
|
"filtered": 100
|
||||||
|
},
|
||||||
|
"table": {
|
||||||
|
"table_name": "t2",
|
||||||
|
"access_type": "ALL",
|
||||||
|
"rows": 2,
|
||||||
|
"filtered": 100,
|
||||||
|
"attached_condition": "(t2.b = 2)",
|
||||||
|
"first_match": "t1"
|
||||||
|
},
|
||||||
|
"subqueries": [
|
||||||
|
{
|
||||||
|
"query_block": {
|
||||||
|
"select_id": 3,
|
||||||
|
"table": {
|
||||||
|
"table_name": "<derived5>",
|
||||||
|
"access_type": "index_subquery",
|
||||||
|
"possible_keys": ["key0"],
|
||||||
|
"key": "key0",
|
||||||
|
"key_length": "5",
|
||||||
|
"used_key_parts": ["c"],
|
||||||
|
"ref": ["func"],
|
||||||
|
"rows": 2,
|
||||||
|
"filtered": 100,
|
||||||
|
"materialized": {
|
||||||
|
"query_block": {
|
||||||
|
"select_id": 5,
|
||||||
|
"table": {
|
||||||
|
"table_name": "t3",
|
||||||
|
"access_type": "ALL",
|
||||||
|
"rows": 4,
|
||||||
|
"filtered": 100,
|
||||||
|
"attached_condition": "(t3.c = 2)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DROP VIEW v2,v3;
|
||||||
|
DROP TABLE t1,t2,t3;
|
||||||
|
|
|
@ -951,3 +951,40 @@ select * from
|
||||||
order by a limit 5) t where t.a not in (2,9);
|
order by a limit 5) t where t.a not in (2,9);
|
||||||
|
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # MDEV-11072: pushdown of the condition obtained
|
||||||
|
--echo # after constant row substitution
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
CREATE TABLE t1 (a INT);
|
||||||
|
CREATE TABLE t2 (b INT);
|
||||||
|
CREATE OR REPLACE VIEW v2 AS SELECT * FROM t2;
|
||||||
|
CREATE TABLE t3 (c INT);
|
||||||
|
CREATE OR REPLACE ALGORITHM=TEMPTABLE VIEW v3 AS SELECT * FROM t3;
|
||||||
|
|
||||||
|
SELECT * FROM t1 WHERE a IN (
|
||||||
|
SELECT b FROM v2 WHERE b < a OR b IN (
|
||||||
|
SELECT c FROM v3 WHERE c = a
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO t1 VALUES (2);
|
||||||
|
INSERT INTO t2 VALUES (3), (2);
|
||||||
|
INSERT INTO t3 VALUES (4), (1), (2), (7);
|
||||||
|
|
||||||
|
SELECT * FROM t1 WHERE a IN (
|
||||||
|
SELECT b FROM v2 WHERE b < a OR b IN (
|
||||||
|
SELECT c FROM v3 WHERE c = a
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
EXPLAIN FORMAT=JSON
|
||||||
|
SELECT * FROM t1 WHERE a IN (
|
||||||
|
SELECT b FROM v2 WHERE b < a OR b IN (
|
||||||
|
SELECT c FROM v3 WHERE c = a
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
DROP VIEW v2,v3;
|
||||||
|
DROP TABLE t1,t2,t3;
|
||||||
|
|
|
@ -1559,7 +1559,9 @@ public:
|
||||||
virtual bool exclusive_dependence_on_table_processor(void *map)
|
virtual bool exclusive_dependence_on_table_processor(void *map)
|
||||||
{ return 0; }
|
{ return 0; }
|
||||||
virtual bool exclusive_dependence_on_grouping_fields_processor(void *arg)
|
virtual bool exclusive_dependence_on_grouping_fields_processor(void *arg)
|
||||||
{ return 0; }
|
{ return 0; }
|
||||||
|
virtual bool cleanup_excluding_outer_fields_processor(void *arg)
|
||||||
|
{ return cleanup_processor(arg); }
|
||||||
|
|
||||||
virtual Item *get_copy(THD *thd, MEM_ROOT *mem_root)=0;
|
virtual Item *get_copy(THD *thd, MEM_ROOT *mem_root)=0;
|
||||||
|
|
||||||
|
@ -2662,6 +2664,9 @@ public:
|
||||||
virtual void print(String *str, enum_query_type query_type);
|
virtual void print(String *str, enum_query_type query_type);
|
||||||
bool exclusive_dependence_on_table_processor(void *map);
|
bool exclusive_dependence_on_table_processor(void *map);
|
||||||
bool exclusive_dependence_on_grouping_fields_processor(void *arg);
|
bool exclusive_dependence_on_grouping_fields_processor(void *arg);
|
||||||
|
bool cleanup_excluding_outer_fields_processor(void *arg)
|
||||||
|
{ return depended_from ? 0 :cleanup_processor(arg); }
|
||||||
|
|
||||||
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
|
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
|
||||||
{ return get_item_copy<Item_field>(thd, mem_root, this); }
|
{ return get_item_copy<Item_field>(thd, mem_root, this); }
|
||||||
bool is_outer_field() const
|
bool is_outer_field() const
|
||||||
|
|
|
@ -1195,7 +1195,8 @@ bool pushdown_cond_for_derived(THD *thd, Item *cond, TABLE_LIST *derived)
|
||||||
(uchar*) sl);
|
(uchar*) sl);
|
||||||
if (extracted_cond_copy)
|
if (extracted_cond_copy)
|
||||||
{
|
{
|
||||||
extracted_cond_copy->walk(&Item::cleanup_processor, 0, 0);
|
extracted_cond_copy->walk(
|
||||||
|
&Item::cleanup_excluding_outer_fields_processor, 0, 0);
|
||||||
sl->cond_pushed_into_where= extracted_cond_copy;
|
sl->cond_pushed_into_where= extracted_cond_copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1230,7 +1231,8 @@ bool pushdown_cond_for_derived(THD *thd, Item *cond, TABLE_LIST *derived)
|
||||||
*/
|
*/
|
||||||
extracted_cond_copy= remove_pushed_top_conjuncts(thd, extracted_cond_copy);
|
extracted_cond_copy= remove_pushed_top_conjuncts(thd, extracted_cond_copy);
|
||||||
|
|
||||||
cond_over_grouping_fields->walk(&Item::cleanup_processor, 0, 0);
|
cond_over_grouping_fields->walk(
|
||||||
|
&Item::cleanup_excluding_outer_fields_processor, 0, 0);
|
||||||
sl->cond_pushed_into_where= cond_over_grouping_fields;
|
sl->cond_pushed_into_where= cond_over_grouping_fields;
|
||||||
|
|
||||||
if (!extracted_cond_copy)
|
if (!extracted_cond_copy)
|
||||||
|
|
Loading…
Reference in a new issue