diff options
author | Varun Gupta <varun.gupta@mariadb.com> | 2020-12-14 21:03:07 +0530 |
---|---|---|
committer | Varun Gupta <varun.gupta@mariadb.com> | 2020-12-18 12:54:33 +0530 |
commit | dc1f28e78c22fde6a6446445a6574ab0dd7fcf93 (patch) | |
tree | 44493f3c88404faa4925660ca5a8ee1769d52eb4 | |
parent | cc16977aa84edcca540fdef0db8af67479165aef (diff) | |
download | mariadb-git-10.2-wf.tar.gz |
MDEV-15296: wrong result with window function inside a subquery10.2-wf
Window Functions were treated as a constant in a dependent tables less subquery.
Made sure that the behaviour of window functions is same as the aggregate function
for dependent tables less subquery.
Also propagted Item::with_window_func for few missing cases.
-rw-r--r-- | mysql-test/r/win.result | 10 | ||||
-rw-r--r-- | mysql-test/t/win.test | 9 | ||||
-rw-r--r-- | sql/item.cc | 1 | ||||
-rw-r--r-- | sql/item_cmpfunc.cc | 6 | ||||
-rw-r--r-- | sql/item_func.h | 7 | ||||
-rw-r--r-- | sql/item_subselect.cc | 1 | ||||
-rw-r--r-- | sql/opt_subselect.cc | 3 |
7 files changed, 35 insertions, 2 deletions
diff --git a/mysql-test/r/win.result b/mysql-test/r/win.result index 79c116b0eeb..7209df49dc8 100644 --- a/mysql-test/r/win.result +++ b/mysql-test/r/win.result @@ -3889,5 +3889,15 @@ SELECT 1 UNION SELECT a FROM t1 ORDER BY (row_number() over ()); ERROR HY000: Expression #1 of ORDER BY contains aggregate function and applies to a UNION DROP TABLE t1; # +# MDEV-15296: wrong result with window function inside a subquery +# +CREATE TABLE t1(a INT); +INSERT INTO t1 VALUES (1), (2); +SELECT (SELECT SUM(a) OVER (partition BY a)) FROM t1; +(SELECT SUM(a) OVER (partition BY a)) +1 +2 +DROP TABLE t1; +# # End of 10.2 tests # diff --git a/mysql-test/t/win.test b/mysql-test/t/win.test index b1a8277c575..9d2c67bf478 100644 --- a/mysql-test/t/win.test +++ b/mysql-test/t/win.test @@ -2554,5 +2554,14 @@ SELECT 1 UNION SELECT a FROM t1 ORDER BY (row_number() over ()); DROP TABLE t1; --echo # +--echo # MDEV-15296: wrong result with window function inside a subquery +--echo # + +CREATE TABLE t1(a INT); +INSERT INTO t1 VALUES (1), (2); +SELECT (SELECT SUM(a) OVER (partition BY a)) FROM t1; +DROP TABLE t1; + +--echo # --echo # End of 10.2 tests --echo # diff --git a/sql/item.cc b/sql/item.cc index 994d45a9dc3..9820ccc249a 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -8172,6 +8172,7 @@ Item_cache_wrapper::Item_cache_wrapper(THD *thd, Item *item_arg): Type_std_attributes::set(orig_item); maybe_null= orig_item->maybe_null; with_sum_func= orig_item->with_sum_func; + with_window_func= orig_item->with_window_func; with_param= orig_item->with_param; with_field= orig_item->with_field; name= item_arg->name; diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 2a0972216f8..f460acf2cd4 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -1366,6 +1366,7 @@ bool Item_in_optimizer::fix_left(THD *thd) } eval_not_null_tables(NULL); with_sum_func= args[0]->with_sum_func; + DBUG_ASSERT(!args[0]->with_window_func); with_param= args[0]->with_param || args[1]->with_param; with_field= args[0]->with_field; if ((const_item_cache= args[0]->const_item())) @@ -1414,6 +1415,7 @@ bool Item_in_optimizer::fix_fields(THD *thd, Item **ref) maybe_null=1; with_subselect= 1; with_sum_func= with_sum_func || args[1]->with_sum_func; + with_window_func= with_window_func || args[1]->with_window_func; with_field= with_field || args[1]->with_field; with_param= args[0]->with_param || args[1]->with_param; used_tables_and_const_cache_join(args[1]); @@ -1969,6 +1971,7 @@ bool Item_func_interval::fix_length_and_dec() used_tables_and_const_cache_join(row); not_null_tables_cache= row->not_null_tables(); with_sum_func= with_sum_func || row->with_sum_func; + with_window_func= with_window_func || row->with_window_func; with_param= with_param || row->with_param; with_field= with_field || row->with_field; return FALSE; @@ -6744,7 +6747,8 @@ bool Item_equal::fix_fields(THD *thd, Item **ref) used_tables_cache|= item->used_tables(); tmp_table_map= item->not_null_tables(); not_null_tables_cache|= tmp_table_map; - DBUG_ASSERT(!item->with_sum_func && !item->with_subselect); + DBUG_ASSERT(!item->with_sum_func && !item->with_subselect && + !item->with_window_func); if (item->maybe_null) maybe_null= 1; if (!item->get_item_equal()) diff --git a/sql/item_func.h b/sql/item_func.h index 496109b0e24..1b6a8f0eb6a 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -82,6 +82,7 @@ public: with_sum_func= a->with_sum_func; with_param= a->with_param; with_field= a->with_field; + DBUG_ASSERT(!a->with_window_func); } Item_func(THD *thd, Item *a, Item *b): Item_func_or_sum(thd, a, b), allowed_arg_cols(1) @@ -89,6 +90,7 @@ public: with_sum_func= a->with_sum_func || b->with_sum_func; with_param= a->with_param || b->with_param; with_field= a->with_field || b->with_field; + DBUG_ASSERT(!(a->with_window_func || b->with_window_func)); } Item_func(THD *thd, Item *a, Item *b, Item *c): Item_func_or_sum(thd, a, b, c), allowed_arg_cols(1) @@ -96,6 +98,7 @@ public: with_sum_func= a->with_sum_func || b->with_sum_func || c->with_sum_func; with_field= a->with_field || b->with_field || c->with_field; with_param= a->with_param || b->with_param || c->with_param; + DBUG_ASSERT(!(a->with_window_func || b->with_window_func || c->with_window_func)); } Item_func(THD *thd, Item *a, Item *b, Item *c, Item *d): Item_func_or_sum(thd, a, b, c, d), allowed_arg_cols(1) @@ -106,6 +109,8 @@ public: c->with_field || d->with_field; with_param= a->with_param || b->with_param || c->with_param || d->with_param; + DBUG_ASSERT(!(a->with_window_func || b->with_window_func || c->with_window_func || + d->with_window_func)); } Item_func(THD *thd, Item *a, Item *b, Item *c, Item *d, Item* e): Item_func_or_sum(thd, a, b, c, d, e), allowed_arg_cols(1) @@ -116,6 +121,8 @@ public: c->with_field || d->with_field || e->with_field; with_param= a->with_param || b->with_param || c->with_param || d->with_param || e->with_param; + DBUG_ASSERT(!(a->with_window_func || b->with_window_func || c->with_window_func || + d->with_window_func)); } Item_func(THD *thd, List<Item> &list): Item_func_or_sum(thd, list), allowed_arg_cols(1) diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index a6d28a5c5c1..2fe601dadc9 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -1138,6 +1138,7 @@ Item_singlerow_subselect::select_transformer(JOIN *join) !select_lex->table_list.elements && select_lex->item_list.elements == 1 && !select_lex->item_list.head()->with_sum_func && + !select_lex->item_list.head()->with_window_func && /* We can't change name of Item_field or Item_ref, because it will prevent its correct resolving, but we should save name of diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc index fec4e8b2828..68d4977bac4 100644 --- a/sql/opt_subselect.cc +++ b/sql/opt_subselect.cc @@ -651,7 +651,7 @@ int check_and_do_in_subquery_rewrites(JOIN *join) 1. Subquery predicate is an IN/=ANY subq predicate 2. Subquery is a single SELECT (not a UNION) 3. Subquery does not have GROUP BY or ORDER BY - 4. Subquery does not use aggregate functions or HAVING + 4. Subquery does not use aggregate functions or HAVING or window functions 5. Subquery predicate is at the AND-top-level of ON/WHERE clause 6. We are not in a subquery of a single table UPDATE/DELETE that doesn't have a JOIN (TODO: We should handle this at some @@ -669,6 +669,7 @@ int check_and_do_in_subquery_rewrites(JOIN *join) !select_lex->is_part_of_union() && // 2 !select_lex->group_list.elements && !join->order && // 3 !join->having && !select_lex->with_sum_func && // 4 + !select_lex->have_window_funcs() && // 4 in_subs->emb_on_expr_nest && // 5 select_lex->outer_select()->join && // 6 parent_unit->first_select()->leaf_tables.elements && // 7 |