From 9b4dfdaa5a1e1ca84a2e9e65dd3066b382f65ae7 Mon Sep 17 00:00:00 2001 From: Sergei Petrunia Date: Thu, 18 Jan 2018 15:25:40 +0300 Subject: [PATCH] MDEV-13352: Server crashes in st_join_table::remove_duplicates join_tab->distinct=true means "Before doing record read with this join_tab, call join_tab->remove_duplicates() to eliminate duplicates". remove_duplicates() assumes that - there is a temporary table $T with rows that are to be de-duplicated - there is a previous join_tab (e.g. with join_tab->fields) which was used to populate the temp.table $T. When the query has "Impossible WHERE" and window function, then the above conditions are not met (but we still might need a window function computation step when the query has implicit grouping). The fix is to not add remove_duplicates step if the select execution is degenerate (and we'll have at most one row in the output anyway). --- mysql-test/r/win.result | 10 ++++++++++ mysql-test/t/win.test | 10 ++++++++++ sql/sql_select.cc | 10 +++++++++- 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/win.result b/mysql-test/r/win.result index 7e0c86b1668..e3cb40e8343 100644 --- a/mysql-test/r/win.result +++ b/mysql-test/r/win.result @@ -3289,3 +3289,13 @@ SELECT id, window FROM door as window; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'window' at line 2 DROP TABLE door; +# +# MDEV-13352: Server crashes in st_join_table::remove_duplicates +# +CREATE TABLE t1 (i INT); +INSERT INTO t1 VALUES (1),(2); +SELECT DISTINCT ROW_NUMBER() OVER(), i FROM t1 WHERE 0; +ROW_NUMBER() OVER() i +SELECT ROW_NUMBER() OVER(), i FROM t1 WHERE 0; +ROW_NUMBER() OVER() i +DROP TABLE t1; diff --git a/mysql-test/t/win.test b/mysql-test/t/win.test index 1e747e59a1a..95ffb6d9909 100644 --- a/mysql-test/t/win.test +++ b/mysql-test/t/win.test @@ -2057,3 +2057,13 @@ SELECT id, window FROM door as window; DROP TABLE door; + +--echo # +--echo # MDEV-13352: Server crashes in st_join_table::remove_duplicates +--echo # +CREATE TABLE t1 (i INT); +INSERT INTO t1 VALUES (1),(2); +SELECT DISTINCT ROW_NUMBER() OVER(), i FROM t1 WHERE 0; +SELECT ROW_NUMBER() OVER(), i FROM t1 WHERE 0; +DROP TABLE t1; + diff --git a/sql/sql_select.cc b/sql/sql_select.cc index e80c02b52b4..6b1d406bf8a 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -2670,7 +2670,15 @@ bool JOIN::make_aggr_tables_info() curr_tab->having= having; having->update_used_tables(); } - curr_tab->distinct= true; + /* + We only need DISTINCT operation if the join is not degenerate. + If it is, we must not request DISTINCT processing, because + remove_duplicates() assumes there is a preceding computation step (and + in the degenerate join, there's none) + */ + if (top_join_tab_count) + curr_tab->distinct= true; + having= NULL; select_distinct= false; }