revision-id: 1169dbc8e72255d059f4309dddd939e95abdb902 (mariadb-10.2.18-22-g1169dbc) parent(s): 00b6c7d8fc8a75b023f78d5f08324cba000002b3 author: Igor Babaev committer: Igor Babaev timestamp: 2018-10-12 11:44:19 -0700 message: MDEV-17354 Server crashes in add_key_field / .. / Item_func_null_predicate::add_key_fields upon INSERT .. SELECT The function Item *Item_direct_view_ref::derived_field_transformer_for_where() erroneously did not strip off ref wrappers from references to materialized derived tables / views. As a result the expressions that contained some references of the type Item_direct_view_ref to columns of a materialized derived table / view V were pushed into V incorrectly. This could cause crashes for some INSERT ... SELECT statements. --- mysql-test/r/derived_cond_pushdown.result | 146 ++++++++++++++++++++++++++++++ mysql-test/t/derived_cond_pushdown.test | 33 +++++++ sql/item.cc | 2 +- 3 files changed, 180 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/derived_cond_pushdown.result b/mysql-test/r/derived_cond_pushdown.result index 9ef3488..9d9d1e7 100644 --- a/mysql-test/r/derived_cond_pushdown.result +++ b/mysql-test/r/derived_cond_pushdown.result @@ -10241,3 +10241,149 @@ a b c 1 2 2 3 2 2 DROP TABLE t1; +# +# MDEV-17354: INSERT SELECT with condition pushdown into derived +# +CREATE TABLE t1 (f INT NOT NULL); +INSERT INTO t1 VALUES (3), (7), (3); +CREATE ALGORITHM= TEMPTABLE VIEW v1 AS SELECT * FROM ( SELECT * FROM t1 ) AS sq; +INSERT INTO t1 +SELECT * FROM ( SELECT t1.f FROM v1 JOIN t1 ) AS t WHERE f IS NOT NULL; +EXPLAIN INSERT INTO t1 +SELECT * FROM ( SELECT t1.f FROM v1 JOIN t1 ) AS t WHERE f IS NOT NULL; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY <derived2> ALL NULL NULL NULL NULL 144 Using where +2 DERIVED <derived3> ALL NULL NULL NULL NULL 12 +2 DERIVED t1 ALL NULL NULL NULL NULL 12 Using where; Using join buffer (flat, BNL join) +3 DERIVED t1 ALL NULL NULL NULL NULL 12 +EXPLAIN FORMAT=JSON INSERT INTO t1 +SELECT * FROM ( SELECT t1.f FROM v1 JOIN t1 ) AS t WHERE f IS NOT NULL; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "<derived2>", + "access_type": "ALL", + "rows": 144, + "filtered": 100, + "attached_condition": "t.f is not null", + "materialized": { + "query_block": { + "select_id": 2, + "table": { + "table_name": "<derived3>", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "materialized": { + "query_block": { + "select_id": 3, + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows": 12, + "filtered": 100 + } + } + } + }, + "block-nl-join": { + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "t1.f is not null" + }, + "buffer_type": "flat", + "buffer_size": "256Kb", + "join_type": "BNL" + } + } + } + } + } +} +SELECT * FROM t1; +f +3 +7 +3 +3 +3 +3 +7 +7 +7 +3 +3 +3 +DELETE FROM t1; +INSERT INTO t1 VALUES (3), (7), (3); +INSERT INTO t1 +SELECT * FROM ( SELECT t1.f FROM v1 JOIN t1 ON v1.f=t1.f) AS t +WHERE f IS NOT NULL; +EXPLAIN FORMAT=JSON INSERT INTO t1 +SELECT * FROM ( SELECT t1.f FROM v1 JOIN t1 ON v1.f=t1.f) AS t +WHERE f IS NOT NULL; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "<derived2>", + "access_type": "ALL", + "rows": 16, + "filtered": 100, + "attached_condition": "t.f is not null", + "materialized": { + "query_block": { + "select_id": 2, + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows": 8, + "filtered": 100, + "attached_condition": "t1.f is not null" + }, + "table": { + "table_name": "<derived3>", + "access_type": "ref", + "possible_keys": ["key0"], + "key": "key0", + "key_length": "4", + "used_key_parts": ["f"], + "ref": ["test.t1.f"], + "rows": 2, + "filtered": 100, + "materialized": { + "query_block": { + "select_id": 3, + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows": 8, + "filtered": 100, + "attached_condition": "t1.f is not null" + } + } + } + } + } + } + } + } +} +SELECT * FROM t1; +f +3 +7 +3 +3 +3 +7 +3 +3 +DROP VIEW v1; +DROP TABLE t1; diff --git a/mysql-test/t/derived_cond_pushdown.test b/mysql-test/t/derived_cond_pushdown.test index 2310966..476a3d7 100644 --- a/mysql-test/t/derived_cond_pushdown.test +++ b/mysql-test/t/derived_cond_pushdown.test @@ -2042,3 +2042,36 @@ SELECT * FROM WHERE ((a,b) IN ((1,2),(3,2))); DROP TABLE t1; + +--echo # +--echo # MDEV-17354: INSERT SELECT with condition pushdown into derived +--echo # + +CREATE TABLE t1 (f INT NOT NULL); +INSERT INTO t1 VALUES (3), (7), (3); + +CREATE ALGORITHM= TEMPTABLE VIEW v1 AS SELECT * FROM ( SELECT * FROM t1 ) AS sq; + +let $q1= +INSERT INTO t1 +SELECT * FROM ( SELECT t1.f FROM v1 JOIN t1 ) AS t WHERE f IS NOT NULL; + +eval $q1; +eval EXPLAIN $q1; +eval EXPLAIN FORMAT=JSON $q1; +SELECT * FROM t1; + +DELETE FROM t1; +INSERT INTO t1 VALUES (3), (7), (3); + +let $q2= +INSERT INTO t1 +SELECT * FROM ( SELECT t1.f FROM v1 JOIN t1 ON v1.f=t1.f) AS t + WHERE f IS NOT NULL; + +eval $q2; +eval EXPLAIN FORMAT=JSON $q2; +SELECT * FROM t1; + +DROP VIEW v1; +DROP TABLE t1; diff --git a/sql/item.cc b/sql/item.cc index 35de01b..2adec33 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -7214,7 +7214,7 @@ Item *Item_direct_view_ref::derived_field_transformer_for_where(THD *thd, DBUG_ASSERT (producing_item != NULL); return producing_item->build_clone(thd, thd->mem_root); } - return this; + return (*ref); } static