diff options
-rw-r--r-- | mysql-test/r/subselect4.result | 75 | ||||
-rw-r--r-- | mysql-test/t/subselect4.test | 15 | ||||
-rw-r--r-- | sql/sql_expression_cache.cc | 4 | ||||
-rw-r--r-- | sql/sql_expression_cache.h | 5 |
4 files changed, 98 insertions, 1 deletions
diff --git a/mysql-test/r/subselect4.result b/mysql-test/r/subselect4.result index 43e698d2b56..e2c81d17737 100644 --- a/mysql-test/r/subselect4.result +++ b/mysql-test/r/subselect4.result @@ -2841,4 +2841,79 @@ id select_type table type possible_keys key key_len ref rows Extra 2 DEPENDENT SUBQUERY tn eq_ref PRIMARY PRIMARY 32 test.tms.key1 1 Using where set optimizer_switch=@tmp_os; drop table t1, t10, t11; +# +# MDEV-28268: Server crashes in Expression_cache_tracker::fetch_current_stats +# +CREATE TABLE t1 (a INT, b INT); +INSERT INTO t1 VALUES (1,2),(3,4); +ANALYZE FORMAT=JSON +SELECT DISTINCT +(SELECT MIN(a) FROM t1 WHERE b <= ANY (SELECT a FROM t1)) AS f +FROM t1; +ANALYZE +{ + "query_block": { + "select_id": 1, + "r_loops": 1, + "r_total_time_ms": "REPLACED", + "duplicate_removal": { + "temporary_table": { + "table": { + "table_name": "t1", + "access_type": "ALL", + "r_loops": 1, + "rows": 2, + "r_rows": 2, + "r_total_time_ms": "REPLACED", + "filtered": 100, + "r_filtered": 100 + }, + "subqueries": [ + { + "expression_cache": { + "state": "disabled", + "r_loops": 0, + "query_block": { + "select_id": 2, + "r_loops": 1, + "r_total_time_ms": "REPLACED", + "table": { + "table_name": "t1", + "access_type": "ALL", + "r_loops": 1, + "rows": 2, + "r_rows": 2, + "r_total_time_ms": "REPLACED", + "filtered": 100, + "r_filtered": 50, + "attached_condition": "<nop>(<in_optimizer>(t1.b,(subquery#3) >= 4))" + }, + "subqueries": [ + { + "query_block": { + "select_id": 3, + "r_loops": 1, + "r_total_time_ms": "REPLACED", + "table": { + "table_name": "t1", + "access_type": "ALL", + "r_loops": 1, + "rows": 2, + "r_rows": 2, + "r_total_time_ms": "REPLACED", + "filtered": 100, + "r_filtered": 100 + } + } + } + ] + } + } + } + ] + } + } + } +} +DROP TABLE t1; # End of 10.2 tests diff --git a/mysql-test/t/subselect4.test b/mysql-test/t/subselect4.test index 1313d2e49e7..6641cdc4557 100644 --- a/mysql-test/t/subselect4.test +++ b/mysql-test/t/subselect4.test @@ -2351,4 +2351,19 @@ set optimizer_switch=@tmp_os; drop table t1, t10, t11; +--echo # +--echo # MDEV-28268: Server crashes in Expression_cache_tracker::fetch_current_stats +--echo # +CREATE TABLE t1 (a INT, b INT); +INSERT INTO t1 VALUES (1,2),(3,4); + +--source include/analyze-format.inc +ANALYZE FORMAT=JSON +SELECT DISTINCT + (SELECT MIN(a) FROM t1 WHERE b <= ANY (SELECT a FROM t1)) AS f +FROM t1; + +# Cleanup +DROP TABLE t1; + --echo # End of 10.2 tests diff --git a/sql/sql_expression_cache.cc b/sql/sql_expression_cache.cc index 4b6d4b4472e..5ce50a3fe52 100644 --- a/sql/sql_expression_cache.cc +++ b/sql/sql_expression_cache.cc @@ -63,7 +63,7 @@ void Expression_cache_tmptable::disable_cache() cache_table= NULL; update_tracker(); if (tracker) - tracker->cache= NULL; + tracker->detach_from_cache(); } @@ -188,6 +188,8 @@ Expression_cache_tmptable::~Expression_cache_tmptable() else { update_tracker(); + if (tracker) + tracker->detach_from_cache(); tracker= NULL; } } diff --git a/sql/sql_expression_cache.h b/sql/sql_expression_cache.h index 61e0c4c69b3..d4bb252dccb 100644 --- a/sql/sql_expression_cache.h +++ b/sql/sql_expression_cache.h @@ -83,7 +83,11 @@ public: cache(c), hit(0), miss(0), state(UNINITED) {} +private: + // This can be NULL if the cache is already deleted Expression_cache *cache; + +public: ulong hit, miss; enum expr_cache_state state; @@ -91,6 +95,7 @@ public: void set(ulong h, ulong m, enum expr_cache_state s) {hit= h; miss= m; state= s;} + void detach_from_cache() { cache= NULL; } void fetch_current_stats() { if (cache) |