mirror of
https://github.com/MariaDB/server.git
synced 2025-09-02 09:41:40 +03:00
Bug #27363:
Validity checks for nested set functions were not taking into account that the enclosed set function may be on a nest level that is lower than the nest level of the enclosing set function. Fixed by : - propagating max_sum_func_level up the enclosing set functions chain. - updating the max_sum_func_level of the enclosing set function when the enclosed set function is aggregated above or on the same nest level of as the level of the enclosing set function. - updating the max_arg_level of the enclosing set function on a reference that refers to an item above or on the same nest level as the level of the enclosing set function. - Treating both Item_field and Item_ref as possibly referencing items from outer nest levels.
This commit is contained in:
35
mysql-test/r/bdb_notembedded.result
Normal file
35
mysql-test/r/bdb_notembedded.result
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
set autocommit=1;
|
||||||
|
reset master;
|
||||||
|
create table bug16206 (a int);
|
||||||
|
insert into bug16206 values(1);
|
||||||
|
start transaction;
|
||||||
|
insert into bug16206 values(2);
|
||||||
|
commit;
|
||||||
|
show binlog events;
|
||||||
|
Log_name Pos Event_type Server_id End_log_pos Info
|
||||||
|
f n Format_desc 1 n Server ver: VERSION, Binlog ver: 4
|
||||||
|
f n Query 1 n use `test`; create table bug16206 (a int)
|
||||||
|
f n Query 1 n use `test`; insert into bug16206 values(1)
|
||||||
|
f n Query 1 n use `test`; insert into bug16206 values(2)
|
||||||
|
drop table bug16206;
|
||||||
|
reset master;
|
||||||
|
create table bug16206 (a int) engine= bdb;
|
||||||
|
insert into bug16206 values(0);
|
||||||
|
insert into bug16206 values(1);
|
||||||
|
start transaction;
|
||||||
|
insert into bug16206 values(2);
|
||||||
|
commit;
|
||||||
|
insert into bug16206 values(3);
|
||||||
|
show binlog events;
|
||||||
|
Log_name Pos Event_type Server_id End_log_pos Info
|
||||||
|
f n Format_desc 1 n Server ver: VERSION, Binlog ver: 4
|
||||||
|
f n Query 1 n use `test`; create table bug16206 (a int) engine= bdb
|
||||||
|
f n Query 1 n use `test`; insert into bug16206 values(0)
|
||||||
|
f n Query 1 n use `test`; insert into bug16206 values(1)
|
||||||
|
f n Query 1 n use `test`; BEGIN
|
||||||
|
f n Query 1 n use `test`; insert into bug16206 values(2)
|
||||||
|
f n Query 1 n use `test`; COMMIT
|
||||||
|
f n Query 1 n use `test`; insert into bug16206 values(3)
|
||||||
|
drop table bug16206;
|
||||||
|
set autocommit=0;
|
||||||
|
End of 5.0 tests
|
@@ -3947,3 +3947,26 @@ WHERE (SELECT COUNT(t0.b) FROM t1 t WHERE t.b>20) GROUP BY a;
|
|||||||
ERROR HY000: Invalid use of group function
|
ERROR HY000: Invalid use of group function
|
||||||
SET @@sql_mode=default;
|
SET @@sql_mode=default;
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
CREATE TABLE t1 (a INT);
|
||||||
|
INSERT INTO t1 values (1),(1),(1),(1);
|
||||||
|
CREATE TABLE t2 (x INT);
|
||||||
|
INSERT INTO t1 values (1000),(1001),(1002);
|
||||||
|
SELECT SUM( (SELECT COUNT(a) FROM t2) ) FROM t1;
|
||||||
|
ERROR HY000: Invalid use of group function
|
||||||
|
SELECT SUM( (SELECT SUM(COUNT(a)) FROM t2) ) FROM t1;
|
||||||
|
ERROR HY000: Invalid use of group function
|
||||||
|
SELECT COUNT(1) FROM DUAL;
|
||||||
|
COUNT(1)
|
||||||
|
1
|
||||||
|
SELECT SUM( (SELECT AVG( (SELECT t1.a FROM t2) ) FROM DUAL) ) FROM t1;
|
||||||
|
ERROR HY000: Invalid use of group function
|
||||||
|
SELECT
|
||||||
|
SUM( (SELECT AVG( (SELECT COUNT(*) FROM t1 t HAVING t1.a < 12) ) FROM t2) )
|
||||||
|
FROM t1;
|
||||||
|
ERROR HY000: Invalid use of group function
|
||||||
|
SELECT t1.a as XXA,
|
||||||
|
SUM( (SELECT AVG( (SELECT COUNT(*) FROM t1 t HAVING XXA < 12) ) FROM t2) )
|
||||||
|
FROM t1;
|
||||||
|
ERROR HY000: Invalid use of group function
|
||||||
|
DROP TABLE t1,t2;
|
||||||
|
End of 5.0 tests.
|
||||||
|
38
mysql-test/t/bdb_notembedded.test
Normal file
38
mysql-test/t/bdb_notembedded.test
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
-- source include/not_embedded.inc
|
||||||
|
-- source include/have_bdb.inc
|
||||||
|
|
||||||
|
#
|
||||||
|
# Bug #16206: Superfluous COMMIT event in binlog when updating BDB in autocommit mode
|
||||||
|
#
|
||||||
|
set autocommit=1;
|
||||||
|
|
||||||
|
let $VERSION=`select version()`;
|
||||||
|
|
||||||
|
reset master;
|
||||||
|
create table bug16206 (a int);
|
||||||
|
insert into bug16206 values(1);
|
||||||
|
start transaction;
|
||||||
|
insert into bug16206 values(2);
|
||||||
|
commit;
|
||||||
|
--replace_result $VERSION VERSION
|
||||||
|
--replace_column 1 f 2 n 5 n
|
||||||
|
show binlog events;
|
||||||
|
drop table bug16206;
|
||||||
|
|
||||||
|
reset master;
|
||||||
|
create table bug16206 (a int) engine= bdb;
|
||||||
|
insert into bug16206 values(0);
|
||||||
|
insert into bug16206 values(1);
|
||||||
|
start transaction;
|
||||||
|
insert into bug16206 values(2);
|
||||||
|
commit;
|
||||||
|
insert into bug16206 values(3);
|
||||||
|
--replace_result $VERSION VERSION
|
||||||
|
--replace_column 1 f 2 n 5 n
|
||||||
|
show binlog events;
|
||||||
|
drop table bug16206;
|
||||||
|
|
||||||
|
set autocommit=0;
|
||||||
|
|
||||||
|
|
||||||
|
--echo End of 5.0 tests
|
@@ -2809,3 +2809,33 @@ SELECT a FROM t1 t0
|
|||||||
SET @@sql_mode=default;
|
SET @@sql_mode=default;
|
||||||
|
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Bug #27363: nested aggregates in outer, subquery / sum(select
|
||||||
|
# count(outer))
|
||||||
|
#
|
||||||
|
CREATE TABLE t1 (a INT); INSERT INTO t1 values (1),(1),(1),(1);
|
||||||
|
CREATE TABLE t2 (x INT); INSERT INTO t1 values (1000),(1001),(1002);
|
||||||
|
|
||||||
|
--error ER_INVALID_GROUP_FUNC_USE
|
||||||
|
SELECT SUM( (SELECT COUNT(a) FROM t2) ) FROM t1;
|
||||||
|
--error ER_INVALID_GROUP_FUNC_USE
|
||||||
|
SELECT SUM( (SELECT SUM(COUNT(a)) FROM t2) ) FROM t1;
|
||||||
|
SELECT COUNT(1) FROM DUAL;
|
||||||
|
|
||||||
|
--error ER_INVALID_GROUP_FUNC_USE
|
||||||
|
SELECT SUM( (SELECT AVG( (SELECT t1.a FROM t2) ) FROM DUAL) ) FROM t1;
|
||||||
|
|
||||||
|
--error ER_INVALID_GROUP_FUNC_USE
|
||||||
|
SELECT
|
||||||
|
SUM( (SELECT AVG( (SELECT COUNT(*) FROM t1 t HAVING t1.a < 12) ) FROM t2) )
|
||||||
|
FROM t1;
|
||||||
|
|
||||||
|
--error ER_INVALID_GROUP_FUNC_USE
|
||||||
|
SELECT t1.a as XXA,
|
||||||
|
SUM( (SELECT AVG( (SELECT COUNT(*) FROM t1 t HAVING XXA < 12) ) FROM t2) )
|
||||||
|
FROM t1;
|
||||||
|
|
||||||
|
DROP TABLE t1,t2;
|
||||||
|
|
||||||
|
--echo End of 5.0 tests.
|
||||||
|
28
sql/item.cc
28
sql/item.cc
@@ -3538,9 +3538,13 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference)
|
|||||||
thd->restore_active_arena(arena, &backup);
|
thd->restore_active_arena(arena, &backup);
|
||||||
fixed_as_field= 1;
|
fixed_as_field= 1;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
A reference is resolved to a nest level that's outer or the same as
|
||||||
|
the nest level of the enclosing set function : adjust the value of
|
||||||
|
max_arg_level for the function if it's needed.
|
||||||
|
*/
|
||||||
if (thd->lex->in_sum_func &&
|
if (thd->lex->in_sum_func &&
|
||||||
thd->lex->in_sum_func->nest_level ==
|
thd->lex->in_sum_func->nest_level >= select->nest_level)
|
||||||
thd->lex->current_select->nest_level)
|
|
||||||
{
|
{
|
||||||
Item::Type ref_type= (*reference)->type();
|
Item::Type ref_type= (*reference)->type();
|
||||||
set_if_bigger(thd->lex->in_sum_func->max_arg_level,
|
set_if_bigger(thd->lex->in_sum_func->max_arg_level,
|
||||||
@@ -5182,6 +5186,16 @@ bool Item_ref::fix_fields(THD *thd, Item **reference)
|
|||||||
thd->change_item_tree(reference, fld);
|
thd->change_item_tree(reference, fld);
|
||||||
mark_as_dependent(thd, last_checked_context->select_lex,
|
mark_as_dependent(thd, last_checked_context->select_lex,
|
||||||
thd->lex->current_select, this, fld);
|
thd->lex->current_select, this, fld);
|
||||||
|
/*
|
||||||
|
A reference is resolved to a nest level that's outer or the same as
|
||||||
|
the nest level of the enclosing set function : adjust the value of
|
||||||
|
max_arg_level for the function if it's needed.
|
||||||
|
*/
|
||||||
|
if (thd->lex->in_sum_func &&
|
||||||
|
thd->lex->in_sum_func->nest_level >=
|
||||||
|
last_checked_context->select_lex->nest_level)
|
||||||
|
set_if_bigger(thd->lex->in_sum_func->max_arg_level,
|
||||||
|
last_checked_context->select_lex->nest_level);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
if (ref == 0)
|
if (ref == 0)
|
||||||
@@ -5195,6 +5209,16 @@ bool Item_ref::fix_fields(THD *thd, Item **reference)
|
|||||||
DBUG_ASSERT(*ref && (*ref)->fixed);
|
DBUG_ASSERT(*ref && (*ref)->fixed);
|
||||||
mark_as_dependent(thd, last_checked_context->select_lex,
|
mark_as_dependent(thd, last_checked_context->select_lex,
|
||||||
context->select_lex, this, this);
|
context->select_lex, this, this);
|
||||||
|
/*
|
||||||
|
A reference is resolved to a nest level that's outer or the same as
|
||||||
|
the nest level of the enclosing set function : adjust the value of
|
||||||
|
max_arg_level for the function if it's needed.
|
||||||
|
*/
|
||||||
|
if (thd->lex->in_sum_func &&
|
||||||
|
thd->lex->in_sum_func->nest_level >=
|
||||||
|
last_checked_context->select_lex->nest_level)
|
||||||
|
set_if_bigger(thd->lex->in_sum_func->max_arg_level,
|
||||||
|
last_checked_context->select_lex->nest_level);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -175,13 +175,25 @@ bool Item_sum::check_sum_func(THD *thd, Item **ref)
|
|||||||
MYF(0));
|
MYF(0));
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
if (in_sum_func && in_sum_func->nest_level == nest_level)
|
if (in_sum_func)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
If the set function is nested adjust the value of
|
If the set function is nested adjust the value of
|
||||||
max_sum_func_level for the nesting set function.
|
max_sum_func_level for the nesting set function.
|
||||||
|
We take into account only enclosed set functions that are to be
|
||||||
|
aggregated on the same level or above of the nest level of
|
||||||
|
the enclosing set function.
|
||||||
|
But we must always pass up the max_sum_func_level because it is
|
||||||
|
the maximum nested level of all directly and indirectly enclosed
|
||||||
|
set functions. We must do that even for set functions that are
|
||||||
|
aggregated inside of their enclosing set function's nest level
|
||||||
|
because the enclosing function may contain another enclosing
|
||||||
|
function that is to be aggregated outside or on the same level
|
||||||
|
as its parent's nest level.
|
||||||
*/
|
*/
|
||||||
set_if_bigger(in_sum_func->max_sum_func_level, aggr_level);
|
if (in_sum_func->nest_level >= aggr_level)
|
||||||
|
set_if_bigger(in_sum_func->max_sum_func_level, aggr_level);
|
||||||
|
set_if_bigger(in_sum_func->max_sum_func_level, max_sum_func_level);
|
||||||
}
|
}
|
||||||
update_used_tables();
|
update_used_tables();
|
||||||
thd->lex->in_sum_func= in_sum_func;
|
thd->lex->in_sum_func= in_sum_func;
|
||||||
|
Reference in New Issue
Block a user