mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
MDEV-14520: Custom aggregate functions work incorrectly with WITH ROLLUP clause
Queries involving rollup need all aggregate function to have copy_or_same function where we create a copy of item_sum items for each sum level. Implemented copy_or_same function for the custom aggregate function class (Item_sum_sp)
This commit is contained in:
@ -1123,3 +1123,33 @@ t1 CREATE TABLE `t1` (
|
|||||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
DROP FUNCTION f1;
|
DROP FUNCTION f1;
|
||||||
|
#
|
||||||
|
# MDEV-14520: Custom aggregate functions work incorrectly with WITH ROLLUP clause
|
||||||
|
#
|
||||||
|
create aggregate function agg_sum(x INT) returns INT
|
||||||
|
begin
|
||||||
|
declare z int default 0;
|
||||||
|
declare continue handler for not found return z;
|
||||||
|
loop
|
||||||
|
fetch group next row;
|
||||||
|
set z= z+x;
|
||||||
|
end loop;
|
||||||
|
end|
|
||||||
|
create table t1 (i int);
|
||||||
|
insert into t1 values (1),(2),(2),(3);
|
||||||
|
select i, agg_sum(i) from t1 group by i with rollup;
|
||||||
|
i agg_sum(i)
|
||||||
|
1 1
|
||||||
|
2 4
|
||||||
|
3 3
|
||||||
|
NULL 8
|
||||||
|
#
|
||||||
|
# Compare with
|
||||||
|
select i, sum(i) from t1 group by i with rollup;
|
||||||
|
i sum(i)
|
||||||
|
1 1
|
||||||
|
2 4
|
||||||
|
3 3
|
||||||
|
NULL 8
|
||||||
|
drop function agg_sum;
|
||||||
|
drop table t1;
|
||||||
|
@ -939,3 +939,29 @@ SHOW CREATE TABLE t1;
|
|||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
DROP FUNCTION f1;
|
DROP FUNCTION f1;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # MDEV-14520: Custom aggregate functions work incorrectly with WITH ROLLUP clause
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
--delimiter |
|
||||||
|
create aggregate function agg_sum(x INT) returns INT
|
||||||
|
begin
|
||||||
|
declare z int default 0;
|
||||||
|
declare continue handler for not found return z;
|
||||||
|
loop
|
||||||
|
fetch group next row;
|
||||||
|
set z= z+x;
|
||||||
|
end loop;
|
||||||
|
end|
|
||||||
|
--delimiter ;
|
||||||
|
|
||||||
|
create table t1 (i int);
|
||||||
|
insert into t1 values (1),(2),(2),(3);
|
||||||
|
select i, agg_sum(i) from t1 group by i with rollup;
|
||||||
|
--echo #
|
||||||
|
--echo # Compare with
|
||||||
|
select i, sum(i) from t1 group by i with rollup;
|
||||||
|
|
||||||
|
# Cleanup
|
||||||
|
drop function agg_sum;
|
||||||
|
drop table t1;
|
||||||
|
11
sql/item.cc
11
sql/item.cc
@ -2802,6 +2802,17 @@ Item_sp::Item_sp(THD *thd, Name_resolution_context *context_arg,
|
|||||||
memset(&sp_mem_root, 0, sizeof(sp_mem_root));
|
memset(&sp_mem_root, 0, sizeof(sp_mem_root));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Item_sp::Item_sp(THD *thd, Item_sp *item):
|
||||||
|
context(item->context), m_name(item->m_name),
|
||||||
|
m_sp(item->m_sp), func_ctx(NULL), sp_result_field(NULL)
|
||||||
|
{
|
||||||
|
dummy_table= (TABLE*) thd->calloc(sizeof(TABLE)+ sizeof(TABLE_SHARE) +
|
||||||
|
sizeof(Query_arena));
|
||||||
|
dummy_table->s= (TABLE_SHARE*) (dummy_table+1);
|
||||||
|
sp_query_arena= (Query_arena *) (dummy_table->s + 1);
|
||||||
|
memset(&sp_mem_root, 0, sizeof(sp_mem_root));
|
||||||
|
}
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
Item_sp::func_name(THD *thd) const
|
Item_sp::func_name(THD *thd) const
|
||||||
{
|
{
|
||||||
|
@ -4658,6 +4658,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
Field *sp_result_field;
|
Field *sp_result_field;
|
||||||
Item_sp(THD *thd, Name_resolution_context *context_arg, sp_name *name_arg);
|
Item_sp(THD *thd, Name_resolution_context *context_arg, sp_name *name_arg);
|
||||||
|
Item_sp(THD *thd, Item_sp *item);
|
||||||
const char *func_name(THD *thd) const;
|
const char *func_name(THD *thd) const;
|
||||||
void cleanup();
|
void cleanup();
|
||||||
bool sp_check_access(THD *thd);
|
bool sp_check_access(THD *thd);
|
||||||
|
@ -1269,6 +1269,12 @@ Item_sum_sp::Item_sum_sp(THD *thd, Name_resolution_context *context_arg,
|
|||||||
m_sp= sp;
|
m_sp= sp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Item_sum_sp::Item_sum_sp(THD *thd, Item_sum_sp *item):
|
||||||
|
Item_sum(thd, item), Item_sp(thd, item)
|
||||||
|
{
|
||||||
|
maybe_null= item->maybe_null;
|
||||||
|
quick_group= item->quick_group;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Item_sum_sp::fix_fields(THD *thd, Item **ref)
|
Item_sum_sp::fix_fields(THD *thd, Item **ref)
|
||||||
@ -1400,6 +1406,14 @@ Item_sum_sp::func_name() const
|
|||||||
return Item_sp::func_name(thd);
|
return Item_sp::func_name(thd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Item* Item_sum_sp::copy_or_same(THD *thd)
|
||||||
|
{
|
||||||
|
Item_sum_sp *copy_item= new (thd->mem_root) Item_sum_sp(thd, this);
|
||||||
|
copy_item->init_result_field(thd, max_length, maybe_null,
|
||||||
|
©_item->null_value, ©_item->name);
|
||||||
|
return copy_item;
|
||||||
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
** reset and add of sum_func
|
** reset and add of sum_func
|
||||||
***********************************************************************/
|
***********************************************************************/
|
||||||
|
@ -1292,6 +1292,7 @@ public:
|
|||||||
|
|
||||||
Item_sum_sp(THD *thd, Name_resolution_context *context_arg, sp_name *name,
|
Item_sum_sp(THD *thd, Name_resolution_context *context_arg, sp_name *name,
|
||||||
sp_head *sp, List<Item> &list);
|
sp_head *sp, List<Item> &list);
|
||||||
|
Item_sum_sp(THD *thd, Item_sum_sp *item);
|
||||||
|
|
||||||
enum Sumfunctype sum_func () const
|
enum Sumfunctype sum_func () const
|
||||||
{
|
{
|
||||||
@ -1361,6 +1362,7 @@ public:
|
|||||||
}
|
}
|
||||||
Item *get_copy(THD *thd)
|
Item *get_copy(THD *thd)
|
||||||
{ return get_item_copy<Item_sum_sp>(thd, this); }
|
{ return get_item_copy<Item_sum_sp>(thd, this); }
|
||||||
|
Item *copy_or_same(THD *thd);
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Items to get the value of a stored sum function */
|
/* Items to get the value of a stored sum function */
|
||||||
|
Reference in New Issue
Block a user