summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Babaev <igor@askmonty.org>2016-03-16 23:35:28 -0700
committerIgor Babaev <igor@askmonty.org>2016-03-16 23:35:28 -0700
commitc3ab9712b0bd30758abfca598c32e254b0e873be (patch)
tree7c0db1f676f45b7c46ef5b55d0f45ac4fb2db9a2
parent72a4969ecaddb7747e40a96b024fdbd374b81316 (diff)
downloadmariadb-git-c3ab9712b0bd30758abfca598c32e254b0e873be.tar.gz
Fixed the bug mdev-9719 concerning execution of prepared statements
with window functions. Added the test case for it. Also allowed to use aliases for set functions in partition and order lists that are specified in window functions.
-rw-r--r--mysql-test/r/win.result42
-rw-r--r--mysql-test/t/win.test45
-rw-r--r--sql/sql_select.cc3
-rw-r--r--sql/sql_window.cc7
-rw-r--r--sql/sql_window.h2
5 files changed, 96 insertions, 3 deletions
diff --git a/mysql-test/r/win.result b/mysql-test/r/win.result
index 291d939c43d..34bf7a30c3d 100644
--- a/mysql-test/r/win.result
+++ b/mysql-test/r/win.result
@@ -1177,3 +1177,45 @@ pk c cnt
9 2 0
10 2 0
drop table t0, t1;
+#
+# Window function in grouping query
+#
+create table t1 (
+username varchar(32),
+amount int
+);
+insert into t1 values
+('user1',1),
+('user1',5),
+('user1',3),
+('user2',10),
+('user2',20),
+('user2',30);
+select
+username,
+sum(amount) as s,
+rank() over (order by s desc)
+from t1
+group by username;
+username s rank() over (order by s desc)
+user1 9 2
+user2 60 1
+drop table t1;
+#
+# mdev-9719: Window function in prepared statement
+#
+create table t1(a int, b int, x char(32));
+insert into t1 values (2, 10, 'xx');
+insert into t1 values (2, 10, 'zz');
+insert into t1 values (2, 20, 'yy');
+insert into t1 values (3, 10, 'xxx');
+insert into t1 values (3, 20, 'vvv');
+prepare stmt from 'select a, row_number() over (partition by a order by b) from t1';
+execute stmt;
+a row_number() over (partition by a order by b)
+2 1
+2 2
+2 3
+3 1
+3 2
+drop table t1;
diff --git a/mysql-test/t/win.test b/mysql-test/t/win.test
index 8590c973c86..182e4715538 100644
--- a/mysql-test/t/win.test
+++ b/mysql-test/t/win.test
@@ -697,3 +697,48 @@ select
from t1;
drop table t0, t1;
+
+--echo #
+--echo # Window function in grouping query
+--echo #
+
+create table t1 (
+ username varchar(32),
+ amount int
+);
+
+insert into t1 values
+('user1',1),
+('user1',5),
+('user1',3),
+('user2',10),
+('user2',20),
+('user2',30);
+
+select
+ username,
+ sum(amount) as s,
+ rank() over (order by s desc)
+from t1
+group by username;
+
+drop table t1;
+
+--echo #
+--echo # mdev-9719: Window function in prepared statement
+--echo #
+
+create table t1(a int, b int, x char(32));
+insert into t1 values (2, 10, 'xx');
+insert into t1 values (2, 10, 'zz');
+insert into t1 values (2, 20, 'yy');
+insert into t1 values (3, 10, 'xxx');
+insert into t1 values (3, 20, 'vvv');
+
+prepare stmt from 'select a, row_number() over (partition by a order by b) from t1';
+execute stmt;
+
+drop table t1;
+
+
+
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 808dea2924d..736e5f21681 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -654,9 +654,10 @@ setup_without_group(THD *thd, Ref_ptr_array ref_pointer_array,
thd->lex->allow_sum_func&= ~((nesting_map)1 << select->nest_level);
res= res || setup_group(thd, ref_pointer_array, tables, fields, all_fields,
group, hidden_group_fields);
- thd->lex->allow_sum_func= save_allow_sum_func;
+ thd->lex->allow_sum_func|= (nesting_map)1 << select->nest_level;
res= res || setup_windows(thd, ref_pointer_array, tables, fields, all_fields,
win_specs);
+ thd->lex->allow_sum_func= save_allow_sum_func;
DBUG_RETURN(res);
}
diff --git a/sql/sql_window.cc b/sql/sql_window.cc
index 8c9b77b9392..f09241c3ff4 100644
--- a/sql/sql_window.cc
+++ b/sql/sql_window.cc
@@ -79,7 +79,7 @@ Window_frame::check_frame_bounds()
int
setup_windows(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables,
List<Item> &fields, List<Item> &all_fields,
- List<Window_spec> win_specs)
+ List<Window_spec> &win_specs)
{
Window_spec *win_spec;
DBUG_ENTER("setup_windows");
@@ -90,6 +90,8 @@ setup_windows(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables,
We could have avoided it if we had built two separate lists for
named and unnamed specifications.
*/
+ Query_arena *arena, backup;
+ arena= thd->activate_stmt_arena_if_needed(&backup);
uint i = 0;
uint elems= win_specs.elements;
while ((win_spec= it++) && i++ < elems)
@@ -100,6 +102,9 @@ setup_windows(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables,
win_specs.push_back(win_spec);
}
}
+ if (arena)
+ thd->restore_active_arena(arena, &backup);
+
it.rewind();
List_iterator_fast<Window_spec> itp(win_specs);
diff --git a/sql/sql_window.h b/sql/sql_window.h
index 18229eb04bc..361c4a7d67f 100644
--- a/sql/sql_window.h
+++ b/sql/sql_window.h
@@ -130,6 +130,6 @@ class Window_def : public Window_spec
int setup_windows(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables,
List<Item> &fields, List<Item> &all_fields,
- List<Window_spec> win_specs);
+ List<Window_spec> &win_specs);
#endif /* SQL_WINDOW_INCLUDED */