summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/explain_json.result59
-rw-r--r--mysql-test/t/explain_json.test14
-rw-r--r--sql/sql_explain.cc8
-rw-r--r--sql/sql_explain.h3
-rw-r--r--sql/sql_select.cc1
5 files changed, 85 insertions, 0 deletions
diff --git a/mysql-test/r/explain_json.result b/mysql-test/r/explain_json.result
index c9b65282047..0824132de05 100644
--- a/mysql-test/r/explain_json.result
+++ b/mysql-test/r/explain_json.result
@@ -719,3 +719,62 @@ EXPLAIN
}
drop table t1;
drop table t0;
+#
+# MDEV-7265: "Full scan on NULL key", the join case
+#
+CREATE TABLE t1 (a INT, KEY(a));
+INSERT INTO t1 VALUES (1),(2);
+CREATE TABLE t2 (b INT);
+INSERT INTO t2 VALUES (3),(4);
+EXPLAIN FORMAT=JSON SELECT * FROM t1 AS outer_t1 WHERE a <> ALL ( SELECT a FROM t1, t2 WHERE b <> outer_t1.a );
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "table": {
+ "table_name": "outer_t1",
+ "access_type": "index",
+ "key": "a",
+ "key_length": "5",
+ "used_key_parts": ["a"],
+ "rows": 2,
+ "filtered": 100,
+ "attached_condition": "(not(<in_optimizer>(outer_t1.a,<exists>(subquery#2))))",
+ "using_index": true
+ },
+ "subqueries": [
+ {
+ "query_block": {
+ "select_id": 2,
+ "full-scan-on-null_key": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ref_or_null",
+ "possible_keys": ["a"],
+ "key": "a",
+ "key_length": "5",
+ "used_key_parts": ["a"],
+ "ref": ["func"],
+ "rows": 2,
+ "filtered": 100,
+ "attached_condition": "trigcond(((<cache>(outer_t1.a) = t1.a) or isnull(t1.a)))",
+ "using_index": true
+ }
+ },
+ "block-nl-join": {
+ "table": {
+ "table_name": "t2",
+ "access_type": "ALL",
+ "rows": 2,
+ "filtered": 100
+ },
+ "buffer_type": "flat",
+ "join_type": "BNL",
+ "attached_condition": "((t2.b <> outer_t1.a) and trigcond(((<cache>(outer_t1.a) = t1.a) or isnull(t1.a))))"
+ }
+ }
+ }
+ ]
+ }
+}
+DROP TABLE t1,t2;
diff --git a/mysql-test/t/explain_json.test b/mysql-test/t/explain_json.test
index 0ecc09691e0..476cb0d3df6 100644
--- a/mysql-test/t/explain_json.test
+++ b/mysql-test/t/explain_json.test
@@ -153,3 +153,17 @@ select * from t1 tbl1, t1 tbl2 where tbl2.a < tbl1.b;
drop table t1;
drop table t0;
+--echo #
+--echo # MDEV-7265: "Full scan on NULL key", the join case
+--echo #
+
+CREATE TABLE t1 (a INT, KEY(a));
+INSERT INTO t1 VALUES (1),(2);
+
+CREATE TABLE t2 (b INT);
+INSERT INTO t2 VALUES (3),(4);
+
+EXPLAIN FORMAT=JSON SELECT * FROM t1 AS outer_t1 WHERE a <> ALL ( SELECT a FROM t1, t2 WHERE b <> outer_t1.a );
+
+DROP TABLE t1,t2;
+
diff --git a/sql/sql_explain.cc b/sql/sql_explain.cc
index ddd37dbbd87..800f2ce309b 100644
--- a/sql/sql_explain.cc
+++ b/sql/sql_explain.cc
@@ -1139,6 +1139,8 @@ void Explain_table_access::tag_to_json(Json_writer *writer, enum explain_extra_t
case ET_START_TEMPORARY:
case ET_END_TEMPORARY:
/* Handled as "duplicates_removal: { ... } */
+ case ET_FULL_SCAN_ON_NULL_KEY:
+ /* Handled in full_scan_on_null_key */
break;
case ET_FIRST_MATCH:
writer->add_member("first_match").add_str(firstmatch_table_name.c_ptr());
@@ -1188,6 +1190,9 @@ void Explain_table_access::print_explain_json(Explain_query *query,
add_json_keyset(writer, "keys", &possible_keys);
}
+ if (full_scan_on_null_key)
+ writer->add_member("full-scan-on-null_key").start_object();
+
writer->add_member("table").start_object();
writer->add_member("table_name").add_str(table_name);
@@ -1289,6 +1294,9 @@ void Explain_table_access::print_explain_json(Explain_query *query,
tag_to_json(writer, extra_tags.at(i));
}
+ if (full_scan_on_null_key)
+ writer->end_object(); //"full-scan-on-null_key"
+
if (range_checked_fer)
writer->end_object(); // "range-checked-for-each-record"
diff --git a/sql/sql_explain.h b/sql/sql_explain.h
index ba5a5c2e6ec..a7ef0beb649 100644
--- a/sql/sql_explain.h
+++ b/sql/sql_explain.h
@@ -562,6 +562,7 @@ public:
non_merged_sjm_number(0),
extra_tags(root),
range_checked_fer(NULL),
+ full_scan_on_null_key(false),
start_dups_weedout(false),
end_dups_weedout(false),
where_cond(NULL),
@@ -634,6 +635,8 @@ public:
/* Non-NULL values means this tab uses "range checked for each record" */
Explain_range_checked_fer *range_checked_fer;
+
+ bool full_scan_on_null_key;
// valid with ET_USING_JOIN_BUFFER
EXPLAIN_BKA_TYPE bka_type;
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index c923c003fcc..a1231152254 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -23687,6 +23687,7 @@ void JOIN_TAB::save_explain_data(Explain_table_access *eta, table_map prefix_tab
if (tab->ref.cond_guards[part])
{
eta->push_extra(ET_FULL_SCAN_ON_NULL_KEY);
+ eta->full_scan_on_null_key= true;
break;
}
}