diff --git a/mysql-test/main/derived_view.result b/mysql-test/main/derived_view.result index 77cc6cc01ec8b..26f4d6942685a 100644 --- a/mysql-test/main/derived_view.result +++ b/mysql-test/main/derived_view.result @@ -4506,4 +4506,39 @@ md5(a) IN (SELECT * FROM (SELECT '' FROM t1) as x) 0 DROP table t1; SET optimizer_switch=@save_optimizer_switch; +# +# MDEV-36059: 2nd PS exec crash w/nested VIEWs +# +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(2); +CREATE TABLE t2 (b INT); +INSERT INTO t2 VALUES (1),(2); +CREATE VIEW v1 AS SELECT b FROM t2; +CREATE VIEW v2 AS SELECT b FROM v1; +PREPARE stmt FROM 'DELETE FROM t1 WHERE a IN (SELECT b FROM v2)'; +EXECUTE stmt; +EXECUTE stmt; +DROP VIEW v2, v1; +DROP TABLE t1, t2; +# +# Same crash when the subquery view sits inside deep nest. +# +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(2),(3); +CREATE TABLE t2 (b INT); +INSERT INTO t2 VALUES (1),(2); +CREATE TABLE t3 (c INT); +INSERT INTO t3 VALUES (1),(2); +CREATE TABLE t4 (d INT); +INSERT INTO t4 VALUES (1),(2); +CREATE VIEW v1 AS SELECT b FROM t2; +CREATE VIEW v2 AS SELECT b FROM v1; +PREPARE stmt FROM 'DELETE FROM t1 WHERE a IN (SELECT t3.c FROM t3 LEFT JOIN (v2 JOIN t4 ON v2.b = t4.d) ON t3.c = v2.b)'; +EXECUTE stmt; +EXECUTE stmt; +SELECT a FROM t1; +a +3 +DROP VIEW v2, v1; +DROP TABLE t1, t2, t3, t4; # End of 11.4 tests diff --git a/mysql-test/main/derived_view.test b/mysql-test/main/derived_view.test index 0b7885cccf35d..b66be0a83e17d 100644 --- a/mysql-test/main/derived_view.test +++ b/mysql-test/main/derived_view.test @@ -2963,4 +2963,46 @@ SELECT md5(a) IN (SELECT * FROM (SELECT '' FROM t1) as x) FROM t1; DROP table t1; SET optimizer_switch=@save_optimizer_switch; +--echo # +--echo # MDEV-36059: 2nd PS exec crash w/nested VIEWs +--echo # + +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(2); +CREATE TABLE t2 (b INT); +INSERT INTO t2 VALUES (1),(2); + +CREATE VIEW v1 AS SELECT b FROM t2; +CREATE VIEW v2 AS SELECT b FROM v1; +PREPARE stmt FROM 'DELETE FROM t1 WHERE a IN (SELECT b FROM v2)'; +EXECUTE stmt; +EXECUTE stmt; + +DROP VIEW v2, v1; +DROP TABLE t1, t2; + +--echo # +--echo # Same crash when the subquery view sits inside deep nest. +--echo # + +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(2),(3); +CREATE TABLE t2 (b INT); +INSERT INTO t2 VALUES (1),(2); +CREATE TABLE t3 (c INT); +INSERT INTO t3 VALUES (1),(2); +CREATE TABLE t4 (d INT); +INSERT INTO t4 VALUES (1),(2); + +CREATE VIEW v1 AS SELECT b FROM t2; +CREATE VIEW v2 AS SELECT b FROM v1; +PREPARE stmt FROM 'DELETE FROM t1 WHERE a IN (SELECT t3.c FROM t3 LEFT JOIN (v2 JOIN t4 ON v2.b = t4.d) ON t3.c = v2.b)'; +EXECUTE stmt; +EXECUTE stmt; +--sorted_result +SELECT a FROM t1; + +DROP VIEW v2, v1; +DROP TABLE t1, t2, t3, t4; + --echo # End of 11.4 tests diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index 8a50a1ace01f9..531bd4d703c55 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -63,6 +63,21 @@ dt_processor processors[]= &mysql_derived_optimize_stage2 }; + +/* + Walk the embedding chain (nested tables) to see if there is + a IN converted to semijoin. +*/ + +static bool is_semijoin_inner_table(TABLE_LIST *tl) +{ + for (TABLE_LIST *emb= tl->embedding; emb; emb= emb->embedding) + if (emb->sj_subq_pred) + return true; + return false; +} + + /* Run specified phases on all derived tables/views in given LEX. @@ -110,7 +125,8 @@ mysql_handle_derived(LEX *lex, uint phases) cursor && !res; cursor= cursor->next_local) { - if (!cursor->is_view_or_derived() && phases == DT_MERGE_FOR_INSERT) + if (phases == DT_MERGE_FOR_INSERT && + (!cursor->is_view_or_derived() || is_semijoin_inner_table(cursor))) continue; uint allowed_phases= (cursor->is_merged_derived() ? DT_PHASES_MERGE : DT_PHASES_MATERIALIZE | DT_MERGE_FOR_INSERT);