diff --git a/mysql-test/main/mdev_40698.result b/mysql-test/main/mdev_40698.result new file mode 100644 index 0000000000000..cf91f431df294 --- /dev/null +++ b/mysql-test/main/mdev_40698.result @@ -0,0 +1,55 @@ +# +# MDEV-40698: ROLLUP query returns incorrect result with empty result set +# +CREATE TABLE t0(a INT, b INT, c INT); +SELECT *, COUNT(0) FROM t0 GROUP BY a, b, c WITH ROLLUP; +a b c COUNT(0) +NULL NULL NULL 0 +SELECT *, COUNT(0) FROM t0 WHERE 1=0 GROUP BY a, b, c WITH ROLLUP; +a b c COUNT(0) +NULL NULL NULL 0 +SELECT *, COUNT(0), ROW_NUMBER() OVER () FROM t0 GROUP BY a, b, c WITH ROLLUP; +a b c COUNT(0) ROW_NUMBER() OVER () +NULL NULL NULL 0 1 +INSERT INTO t0 VALUES (0, 0, 0); +INSERT INTO t0 VALUES (0, 0, 0); +SELECT *, COUNT(0) FROM t0 WHERE a > 0 GROUP BY a, b, c WITH ROLLUP; +a b c COUNT(0) +NULL NULL NULL 0 +SELECT EXISTS (SELECT t0.a FROM t0 x WHERE 1=0 GROUP BY x.a WITH ROLLUP) AS e +FROM t0; +e +1 +1 +SELECT DISTINCT a FROM t0 GROUP BY a, b WITH ROLLUP; +a +0 +NULL +CREATE TABLE t1 (a INT, b INT, c INT) ENGINE=InnoDB; +SELECT *, COUNT(0) FROM t1 GROUP BY a, b, c WITH ROLLUP; +a b c COUNT(0) +NULL NULL NULL 0 +SELECT *, COUNT(0) FROM t1 WHERE 1=0 GROUP BY a, b, c WITH ROLLUP; +a b c COUNT(0) +NULL NULL NULL 0 +SELECT *, COUNT(0), ROW_NUMBER() OVER () FROM t1 GROUP BY a, b, c WITH ROLLUP; +a b c COUNT(0) ROW_NUMBER() OVER () +NULL NULL NULL 0 1 +INSERT INTO t1 VALUES (0, 0, 0); +INSERT INTO t1 VALUES (0, 0, 0); +SELECT *, COUNT(0) FROM t1 WHERE a > 0 GROUP BY a, b, c WITH ROLLUP; +a b c COUNT(0) +NULL NULL NULL 0 +SELECT EXISTS (SELECT t1.a FROM t1 x WHERE 1=0 GROUP BY x.a WITH ROLLUP) AS e +FROM t1; +e +1 +1 +SELECT DISTINCT a FROM t1 GROUP BY a, b WITH ROLLUP; +a +0 +NULL +DROP TABLE t0, t1; +# +# End of 10.11 tests +# diff --git a/mysql-test/main/mdev_40698.test b/mysql-test/main/mdev_40698.test new file mode 100644 index 0000000000000..482d095a48341 --- /dev/null +++ b/mysql-test/main/mdev_40698.test @@ -0,0 +1,33 @@ +--source include/have_innodb.inc + +--echo # +--echo # MDEV-40698: ROLLUP query returns incorrect result with empty result set +--echo # + +CREATE TABLE t0(a INT, b INT, c INT); +SELECT *, COUNT(0) FROM t0 GROUP BY a, b, c WITH ROLLUP; +SELECT *, COUNT(0) FROM t0 WHERE 1=0 GROUP BY a, b, c WITH ROLLUP; +SELECT *, COUNT(0), ROW_NUMBER() OVER () FROM t0 GROUP BY a, b, c WITH ROLLUP; +INSERT INTO t0 VALUES (0, 0, 0); +INSERT INTO t0 VALUES (0, 0, 0); +SELECT *, COUNT(0) FROM t0 WHERE a > 0 GROUP BY a, b, c WITH ROLLUP; +SELECT EXISTS (SELECT t0.a FROM t0 x WHERE 1=0 GROUP BY x.a WITH ROLLUP) AS e + FROM t0; +SELECT DISTINCT a FROM t0 GROUP BY a, b WITH ROLLUP; + +CREATE TABLE t1 (a INT, b INT, c INT) ENGINE=InnoDB; +SELECT *, COUNT(0) FROM t1 GROUP BY a, b, c WITH ROLLUP; +SELECT *, COUNT(0) FROM t1 WHERE 1=0 GROUP BY a, b, c WITH ROLLUP; +SELECT *, COUNT(0), ROW_NUMBER() OVER () FROM t1 GROUP BY a, b, c WITH ROLLUP; +INSERT INTO t1 VALUES (0, 0, 0); +INSERT INTO t1 VALUES (0, 0, 0); +SELECT *, COUNT(0) FROM t1 WHERE a > 0 GROUP BY a, b, c WITH ROLLUP; +SELECT EXISTS (SELECT t1.a FROM t1 x WHERE 1=0 GROUP BY x.a WITH ROLLUP) AS e + FROM t1; +SELECT DISTINCT a FROM t1 GROUP BY a, b WITH ROLLUP; + +DROP TABLE t0, t1; + +--echo # +--echo # End of 10.11 tests +--echo # diff --git a/mysql-test/main/ps_error.result b/mysql-test/main/ps_error.result index ad178f869155a..f3fa78a1bbe36 100644 --- a/mysql-test/main/ps_error.result +++ b/mysql-test/main/ps_error.result @@ -10,6 +10,7 @@ EXECUTE stmt; ERROR 22007: Truncated incorrect DOUBLE value: 'foo' SELECT a FROM t1 GROUP BY NULL WITH ROLLUP; a +NULL DROP TABLE t1; SET sql_mode=DEFAULT; SET SQL_MODE= 'STRICT_ALL_TABLES'; diff --git a/mysql-test/main/win.result b/mysql-test/main/win.result index 8f38c424ddf9c..7891c737dfd43 100644 --- a/mysql-test/main/win.result +++ b/mysql-test/main/win.result @@ -3503,6 +3503,7 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables select distinct 1, row_number() over (order by 1) from t1 where a=0 group by a with rollup; 1 row_number() over (order by 1) +1 1 drop table t1; explain SELECT DISTINCT BIT_OR(100) OVER () FROM dual diff --git a/mysql-test/suite/encryption/r/tempfiles_encrypted.result b/mysql-test/suite/encryption/r/tempfiles_encrypted.result index aff2b9306aa73..f856ff1a465f1 100644 --- a/mysql-test/suite/encryption/r/tempfiles_encrypted.result +++ b/mysql-test/suite/encryption/r/tempfiles_encrypted.result @@ -3509,6 +3509,7 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables select distinct 1, row_number() over (order by 1) from t1 where a=0 group by a with rollup; 1 row_number() over (order by 1) +1 1 drop table t1; explain SELECT DISTINCT BIT_OR(100) OVER () FROM dual diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 05d3bae186c8b..36ac4367bbb47 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -24496,6 +24496,7 @@ end_send_group(JOIN *join, JOIN_TAB *join_tab, bool end_of_records) join->fields. */ List *fields= join_tab ? (join_tab-1)->fields : join->fields; + bool empty_set_send_rollup_total= 0; DBUG_ENTER("end_send_group"); if (!join->items3.is_null() && !join->set_group_rpa) @@ -24511,7 +24512,8 @@ end_send_group(JOIN *join, JOIN_TAB *join_tab, bool end_of_records) if (!join->group_sent && (join->first_record || - (end_of_records && !join->group && !join->group_optimized_away))) + join->need_empty_set_row(end_of_records, + &empty_set_send_rollup_total))) { table_map cleared_tables= (table_map) 0; if (join->procedure) @@ -24567,7 +24569,8 @@ end_send_group(JOIN *join, JOIN_TAB *join_tab, bool end_of_records) join->send_records++; join->group_sent= true; } - if (unlikely(join->rollup.state != ROLLUP::STATE_NONE && error <= 0)) + if (unlikely(join->rollup.state != ROLLUP::STATE_NONE && + !empty_set_send_rollup_total && error <= 0)) { if (join->rollup_send_data((uint) (idx+1))) error= 1; @@ -24888,13 +24891,15 @@ end_write_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), { TABLE *table= join_tab->table; int idx= -1; + bool empty_set_send_rollup_total= 0; DBUG_ENTER("end_write_group"); join->accepted_rows++; if (!join->first_record || end_of_records || (idx=test_if_group_changed(join->group_fields)) >= 0) { - if (join->first_record || (end_of_records && !join->group)) + if (join->first_record || + join->need_empty_set_row(end_of_records, &empty_set_send_rollup_total)) { table_map cleared_tables= (table_map) 0; if (join->procedure) @@ -24919,7 +24924,8 @@ end_write_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), error, 0, NULL)) DBUG_RETURN(NESTED_LOOP_ERROR); } - if (unlikely(join->rollup.state != ROLLUP::STATE_NONE)) + if (unlikely(join->rollup.state != ROLLUP::STATE_NONE && + !empty_set_send_rollup_total)) { if (unlikely(join->rollup_write_data((uint) (idx+1), join_tab->tmp_table_param, diff --git a/sql/sql_select.h b/sql/sql_select.h index 1c607883be91e..d03edab058186 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -1746,12 +1746,27 @@ class JOIN :public Sql_alloc void cleanup(bool full); void clear(table_map *cleared_tables); void inline clear_sum_funcs(); + bool need_empty_set_row(bool end_of_records, + bool *empty_set_send_rollup_total) const + { + *empty_set_send_rollup_total= + end_of_records && !first_record && rollup.state != ROLLUP::STATE_NONE; + return (end_of_records && !first_record && !group && + !group_optimized_away) || + *empty_set_send_rollup_total; + } bool send_row_on_empty_set() { - return (do_send_rows && implicit_grouping && !group_optimized_away && + return (do_send_rows && + (select_lex->olap == ROLLUP_TYPE || + (implicit_grouping && !group_optimized_away)) && having_value != Item::COND_FALSE); } - bool empty_result() { return (zero_result_cause && !implicit_grouping); } + bool empty_result() + { + return (zero_result_cause && !implicit_grouping && + select_lex->olap != ROLLUP_TYPE); + } bool change_result(select_result *new_result, select_result *old_result); bool is_top_level_join() const {