Commit 1d0f1741 authored by Igor Babaev's avatar Igor Babaev

Fixed bug mdev-11313.

The fix for bug 11072 was not complete though it also fixed
the bug mdev-10800.
This patch resolves the problems of all three bugs.
parent b5b68b6b
...@@ -7087,10 +7087,10 @@ drop table t1; ...@@ -7087,10 +7087,10 @@ drop table t1;
# MDEV-11072: pushdown of the condition obtained # MDEV-11072: pushdown of the condition obtained
# after constant row substitution # after constant row substitution
# #
CREATE TABLE t1 (a INT); CREATE TABLE t1 (a INT) ENGINE=MyISAM;
CREATE TABLE t2 (b INT); CREATE TABLE t2 (b INT) ENGINE=MyISAM;
CREATE OR REPLACE VIEW v2 AS SELECT * FROM t2; CREATE OR REPLACE VIEW v2 AS SELECT * FROM t2;
CREATE TABLE t3 (c INT); CREATE TABLE t3 (c INT) ENGINE=MyISAM;
CREATE OR REPLACE ALGORITHM=TEMPTABLE VIEW v3 AS SELECT * FROM t3; CREATE OR REPLACE ALGORITHM=TEMPTABLE VIEW v3 AS SELECT * FROM t3;
SELECT * FROM t1 WHERE a IN ( SELECT * FROM t1 WHERE a IN (
SELECT b FROM v2 WHERE b < a OR b IN ( SELECT b FROM v2 WHERE b < a OR b IN (
...@@ -7165,8 +7165,154 @@ EXPLAIN ...@@ -7165,8 +7165,154 @@ EXPLAIN
] ]
} }
} }
DROP VIEW v2,v3; CREATE TABLE t4 (d INT, e INT) ENGINE=MyISAM;
DROP TABLE t1,t2,t3; INSERT INTO t4 VALUES (1,10),(3,11),(2,10),(2,20),(3,21);
CREATE OR REPLACE VIEW v4 AS
SELECT d, sum(e) AS s FROM t4 GROUP BY d;
set statement optimizer_switch='condition_pushdown_for_derived=off' for SELECT * FROM t1 WHERE a IN (
SELECT b FROM v2 WHERE b < a OR b IN (
SELECT d FROM v4 WHERE s > a
)
);
a
2
SELECT * FROM t1 WHERE a IN (
SELECT b FROM v2 WHERE b < a OR b IN (
SELECT d FROM v4 WHERE s > a
)
);
a
2
explain SELECT * FROM t1 WHERE a IN (
SELECT b FROM v2 WHERE b < a OR b IN (
SELECT d FROM v4 WHERE s > a
)
);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 system NULL NULL NULL NULL 1
1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Using where; FirstMatch(t1)
3 DEPENDENT SUBQUERY <derived5> index_subquery key0 key0 5 func 2 Using where
5 DERIVED t4 ALL NULL NULL NULL NULL 5 Using temporary; Using filesort
explain format=json SELECT * FROM t1 WHERE a IN (
SELECT b FROM v2 WHERE b < a OR b IN (
SELECT d FROM v4 WHERE s > 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": ["d"],
"ref": ["func"],
"rows": 2,
"filtered": 100,
"materialized": {
"query_block": {
"select_id": 5,
"filesort": {
"sort_key": "t4.d",
"temporary_table": {
"table": {
"table_name": "t4",
"access_type": "ALL",
"rows": 5,
"filtered": 100
}
}
}
}
}
}
}
}
]
}
}
DROP VIEW v2,v3,v4;
DROP TABLE t1,t2,t3,t4;
#
# MDEV-10800: pushdown of the condition obtained
# after constant row substitution
#
CREATE TABLE t1 (a INT) ENGINE=MyISAM;
INSERT INTO t1 VALUES (1);
CREATE TABLE t2 (b INT) ENGINE=MyISAM;
INSERT INTO t2 VALUES (3),(4);
CREATE OR REPLACE ALGORITHM=TEMPTABLE VIEW v2 AS SELECT * FROM t2;
SELECT * FROM
( SELECT * FROM t1
WHERE EXISTS ( SELECT * FROM v2 WHERE b = a ) ) AS sq;
a
EXPLAIN FORMAT=JSON
SELECT * FROM
( SELECT * FROM t1
WHERE EXISTS ( SELECT * FROM v2 WHERE b = a ) ) AS sq;
EXPLAIN
{
"query_block": {
"select_id": 1,
"const_condition": "<in_optimizer>(1,exists(subquery#3))",
"table": {
"table_name": "t1",
"access_type": "system",
"rows": 1,
"filtered": 100
},
"subqueries": [
{
"query_block": {
"select_id": 3,
"table": {
"table_name": "<derived4>",
"access_type": "ALL",
"rows": 2,
"filtered": 100,
"attached_condition": "(v2.b = 1)",
"materialized": {
"query_block": {
"select_id": 4,
"table": {
"table_name": "t2",
"access_type": "ALL",
"rows": 2,
"filtered": 100,
"attached_condition": "(t2.b = 1)"
}
}
}
}
}
}
]
}
}
DROP VIEW v2;
DROP TABLE t1,t2;
# #
# MDEV-11102: condition pushdown into materialized inner table # MDEV-11102: condition pushdown into materialized inner table
# of outer join is not applied as not being valid # of outer join is not applied as not being valid
...@@ -7376,3 +7522,107 @@ EXPLAIN ...@@ -7376,3 +7522,107 @@ EXPLAIN
} }
DROP VIEW v1,v2; DROP VIEW v1,v2;
DROP TABLE t1,t2; DROP TABLE t1,t2;
#
# MDEV-11313: pushdown of the condition obtained
# after constant row substitution
#
CREATE TABLE t1 (a INT) ENGINE=MyISAM;
INSERT INTO t1 VALUES (1),(2);
CREATE TABLE t2 (b INT) ENGINE=MyISAM;
INSERT INTO t2 VALUES (50);
CREATE ALGORITHM=TEMPTABLE VIEW v1 AS SELECT * FROM t1;
SELECT ( SELECT COUNT(*) FROM v1 WHERE a = t2.b ) AS f FROM t2 GROUP BY f;
f
0
EXPLAIN FORMAT=JSON
SELECT ( SELECT COUNT(*) FROM v1 WHERE a = t2.b ) AS f FROM t2 GROUP BY f;
EXPLAIN
{
"query_block": {
"select_id": 1,
"table": {
"table_name": "t2",
"access_type": "system",
"rows": 1,
"filtered": 100
},
"subqueries": [
{
"query_block": {
"select_id": 2,
"table": {
"table_name": "<derived3>",
"access_type": "ALL",
"rows": 2,
"filtered": 100,
"attached_condition": "(v1.a = 50)",
"materialized": {
"query_block": {
"select_id": 3,
"table": {
"table_name": "t1",
"access_type": "ALL",
"rows": 2,
"filtered": 100,
"attached_condition": "(t1.a = 50)"
}
}
}
}
}
}
]
}
}
CREATE TABLE t3 (a INT, b INT) ENGINE=MYISAM;
INSERT INTO t3 VALUES (1,10),(3,11),(2,10),(2,20),(3,21);
CREATE VIEW v2 AS SELECT a, sum(b) AS s FROM t3 GROUP BY a ;
SELECT ( SELECT COUNT(*) FROM v2 WHERE s < t2.b ) AS f FROM t2 GROUP BY f;
f
3
EXPLAIN FORMAT=JSON
SELECT ( SELECT COUNT(*) FROM v2 WHERE s < t2.b ) AS f FROM t2 GROUP BY f;
EXPLAIN
{
"query_block": {
"select_id": 1,
"table": {
"table_name": "t2",
"access_type": "system",
"rows": 1,
"filtered": 100
},
"subqueries": [
{
"query_block": {
"select_id": 2,
"table": {
"table_name": "<derived3>",
"access_type": "ALL",
"rows": 5,
"filtered": 100,
"attached_condition": "(v2.s < 50)",
"materialized": {
"query_block": {
"select_id": 3,
"filesort": {
"sort_key": "t3.a",
"temporary_table": {
"table": {
"table_name": "t3",
"access_type": "ALL",
"rows": 5,
"filtered": 100
}
}
}
}
}
}
}
}
]
}
}
DROP VIEW v1,v2;
DROP TABLE t1,t2,t3;
...@@ -957,10 +957,10 @@ drop table t1; ...@@ -957,10 +957,10 @@ drop table t1;
--echo # after constant row substitution --echo # after constant row substitution
--echo # --echo #
CREATE TABLE t1 (a INT); CREATE TABLE t1 (a INT) ENGINE=MyISAM;
CREATE TABLE t2 (b INT); CREATE TABLE t2 (b INT) ENGINE=MyISAM;
CREATE OR REPLACE VIEW v2 AS SELECT * FROM t2; CREATE OR REPLACE VIEW v2 AS SELECT * FROM t2;
CREATE TABLE t3 (c INT); CREATE TABLE t3 (c INT) ENGINE=MyISAM;
CREATE OR REPLACE ALGORITHM=TEMPTABLE VIEW v3 AS SELECT * FROM t3; CREATE OR REPLACE ALGORITHM=TEMPTABLE VIEW v3 AS SELECT * FROM t3;
SELECT * FROM t1 WHERE a IN ( SELECT * FROM t1 WHERE a IN (
...@@ -986,8 +986,50 @@ SELECT * FROM t1 WHERE a IN ( ...@@ -986,8 +986,50 @@ SELECT * FROM t1 WHERE a IN (
) )
); );
DROP VIEW v2,v3; CREATE TABLE t4 (d INT, e INT) ENGINE=MyISAM;
DROP TABLE t1,t2,t3; INSERT INTO t4 VALUES (1,10),(3,11),(2,10),(2,20),(3,21);
CREATE OR REPLACE VIEW v4 AS
SELECT d, sum(e) AS s FROM t4 GROUP BY d;
let $query =
SELECT * FROM t1 WHERE a IN (
SELECT b FROM v2 WHERE b < a OR b IN (
SELECT d FROM v4 WHERE s > a
)
);
eval $no_pushdown $query;
eval $query;
eval explain $query;
eval explain format=json $query;
DROP VIEW v2,v3,v4;
DROP TABLE t1,t2,t3,t4;
--echo #
--echo # MDEV-10800: pushdown of the condition obtained
--echo # after constant row substitution
--echo #
CREATE TABLE t1 (a INT) ENGINE=MyISAM;
INSERT INTO t1 VALUES (1);
CREATE TABLE t2 (b INT) ENGINE=MyISAM;
INSERT INTO t2 VALUES (3),(4);
CREATE OR REPLACE ALGORITHM=TEMPTABLE VIEW v2 AS SELECT * FROM t2;
SELECT * FROM
( SELECT * FROM t1
WHERE EXISTS ( SELECT * FROM v2 WHERE b = a ) ) AS sq;
EXPLAIN FORMAT=JSON
SELECT * FROM
( SELECT * FROM t1
WHERE EXISTS ( SELECT * FROM v2 WHERE b = a ) ) AS sq;
DROP VIEW v2;
DROP TABLE t1,t2;
--echo # --echo #
--echo # MDEV-11102: condition pushdown into materialized inner table --echo # MDEV-11102: condition pushdown into materialized inner table
...@@ -1058,3 +1100,29 @@ SELECT * FROM ( SELECT * FROM t1 ) AS sq ...@@ -1058,3 +1100,29 @@ SELECT * FROM ( SELECT * FROM t1 ) AS sq
DROP VIEW v1,v2; DROP VIEW v1,v2;
DROP TABLE t1,t2; DROP TABLE t1,t2;
--echo #
--echo # MDEV-11313: pushdown of the condition obtained
--echo # after constant row substitution
--echo #
CREATE TABLE t1 (a INT) ENGINE=MyISAM;
INSERT INTO t1 VALUES (1),(2);
CREATE TABLE t2 (b INT) ENGINE=MyISAM;
INSERT INTO t2 VALUES (50);
CREATE ALGORITHM=TEMPTABLE VIEW v1 AS SELECT * FROM t1;
SELECT ( SELECT COUNT(*) FROM v1 WHERE a = t2.b ) AS f FROM t2 GROUP BY f;
EXPLAIN FORMAT=JSON
SELECT ( SELECT COUNT(*) FROM v1 WHERE a = t2.b ) AS f FROM t2 GROUP BY f;
CREATE TABLE t3 (a INT, b INT) ENGINE=MYISAM;
INSERT INTO t3 VALUES (1,10),(3,11),(2,10),(2,20),(3,21);
CREATE VIEW v2 AS SELECT a, sum(b) AS s FROM t3 GROUP BY a ;
SELECT ( SELECT COUNT(*) FROM v2 WHERE s < t2.b ) AS f FROM t2 GROUP BY f;
EXPLAIN FORMAT=JSON
SELECT ( SELECT COUNT(*) FROM v2 WHERE s < t2.b ) AS f FROM t2 GROUP BY f;
DROP VIEW v1,v2;
DROP TABLE t1,t2,t3;
...@@ -1560,7 +1560,7 @@ class Item: public Value_source, ...@@ -1560,7 +1560,7 @@ class Item: public Value_source,
{ 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) virtual bool cleanup_excluding_const_fields_processor(void *arg)
{ return cleanup_processor(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;
...@@ -2664,8 +2664,8 @@ class Item_field :public Item_ident ...@@ -2664,8 +2664,8 @@ class Item_field :public Item_ident
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) bool cleanup_excluding_const_fields_processor(void *arg)
{ return depended_from ? 0 : cleanup_processor(arg); } { return field && const_item() ? 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); }
...@@ -4282,7 +4282,15 @@ class Item_ref :public Item_ident ...@@ -4282,7 +4282,15 @@ class Item_ref :public Item_ident
{ return depended_from != NULL; } { return depended_from != NULL; }
bool exclusive_dependence_on_grouping_fields_processor(void *arg) bool exclusive_dependence_on_grouping_fields_processor(void *arg)
{ return depended_from != NULL; } { return depended_from != NULL; }
}; bool cleanup_excluding_const_fields_processor(void *arg)
{
Item *item= real_item();
if (item && item->type() == FIELD_ITEM &&
((Item_field *) item)->field && item->const_item())
return 0;
return cleanup_processor(arg);
}
};
/* /*
......
...@@ -1196,7 +1196,7 @@ bool pushdown_cond_for_derived(THD *thd, Item *cond, TABLE_LIST *derived) ...@@ -1196,7 +1196,7 @@ bool pushdown_cond_for_derived(THD *thd, Item *cond, TABLE_LIST *derived)
if (extracted_cond_copy) if (extracted_cond_copy)
{ {
extracted_cond_copy->walk( extracted_cond_copy->walk(
&Item::cleanup_excluding_outer_fields_processor, 0, 0); &Item::cleanup_excluding_const_fields_processor, 0, 0);
sl->cond_pushed_into_where= extracted_cond_copy; sl->cond_pushed_into_where= extracted_cond_copy;
} }
...@@ -1232,7 +1232,7 @@ bool pushdown_cond_for_derived(THD *thd, Item *cond, TABLE_LIST *derived) ...@@ -1232,7 +1232,7 @@ 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( cond_over_grouping_fields->walk(
&Item::cleanup_excluding_outer_fields_processor, 0, 0); &Item::cleanup_excluding_const_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)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment