summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVarun Gupta <varun.gupta@mariadb.com>2020-12-14 21:03:07 +0530
committerVarun Gupta <varun.gupta@mariadb.com>2020-12-18 12:54:33 +0530
commitdc1f28e78c22fde6a6446445a6574ab0dd7fcf93 (patch)
tree44493f3c88404faa4925660ca5a8ee1769d52eb4
parentcc16977aa84edcca540fdef0db8af67479165aef (diff)
downloadmariadb-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.result10
-rw-r--r--mysql-test/t/win.test9
-rw-r--r--sql/item.cc1
-rw-r--r--sql/item_cmpfunc.cc6
-rw-r--r--sql/item_func.h7
-rw-r--r--sql/item_subselect.cc1
-rw-r--r--sql/opt_subselect.cc3
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