MDEV-32907 Spider: do not create gbh if encountering Item_aggregate_ref

When spider encounters Item_aggregate_ref that is valid at gbh
creation, it could become invalid at gbh execution due to item list
substitution*. Therefore we ban Item_aggregate_ref for spider gbh
creation. To that end, we also make sure that str is NULL if and only
if in the creation stage, not the execution stage, including removing
a redundant check when str is not NULL.

*: Note that it is likely the same scenario as in MDEV-25116.
This commit is contained in:
Yuchen Pei 2025-07-10 16:22:47 +10:00
commit 998e765060
No known key found for this signature in database
GPG key ID: 3DD1B35105743563
4 changed files with 68 additions and 13 deletions

View file

@ -0,0 +1,21 @@
for master_1
for child2
for child3
set spider_same_server_link= 1;
CREATE SERVER srv FOREIGN DATA WRAPPER mysql
OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root');
create table t2 (c int);
create table t1 (c int) ENGINE=Spider
COMMENT='WRAPPER "mysql", srv "srv",TABLE "t2"';
insert into t1 values (3), (NULL);
explain select nvl(sum(c), 0) from t1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2
select nvl(sum(c), 0) from t1;
nvl(sum(c), 0)
3
drop table t1, t2;
drop server srv;
for master_1
for child2
for child3

View file

@ -0,0 +1,26 @@
--disable_query_log
--disable_result_log
--source ../../t/test_init.inc
--enable_result_log
--enable_query_log
set spider_same_server_link= 1;
evalp CREATE SERVER srv FOREIGN DATA WRAPPER mysql
OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root');
create table t2 (c int);
create table t1 (c int) ENGINE=Spider
COMMENT='WRAPPER "mysql", srv "srv",TABLE "t2"';
insert into t1 values (3), (NULL);
explain select nvl(sum(c), 0) from t1;
select nvl(sum(c), 0) from t1;
drop table t1, t2;
drop server srv;
--disable_query_log
--disable_result_log
--source ../../t/test_deinit.inc
--enable_result_log
--enable_query_log

View file

@ -7919,11 +7919,21 @@ int spider_db_print_item_type(
DBUG_ENTER("spider_db_print_item_type");
DBUG_PRINT("info",("spider COND type=%d", item->type()));
if (item->type() == Item::REF_ITEM &&
((Item_ref*)item)->ref_type() == Item_ref::DIRECT_REF)
if (item->type() == Item::REF_ITEM)
{
item= item->real_item();
DBUG_PRINT("info",("spider new COND type=%d", item->type()));
const auto rtype= ((Item_ref*)item)->ref_type();
/*
The presence of an Item_aggregate_ref tends to lead to the query
being broken at the execution stage.
*/
if (rtype == Item_ref::AGGREGATE_REF && !str)
DBUG_RETURN(ER_SPIDER_COND_SKIP_NUM);
DBUG_ASSERT(rtype != Item_ref::AGGREGATE_REF);
if (rtype == Item_ref::DIRECT_REF)
{
item= item->real_item();
DBUG_PRINT("info", ("spider new COND type=%d", item->type()));
}
}
switch (item->type())
{
@ -8353,6 +8363,10 @@ int spider_db_open_item_ref(
}
DBUG_RETURN(0);
}
/*
TODO: MDEV-25116 is the same case as MDEV-32907 (having an
Item_aggregate_ref). Perhaps the following is redundant.
*/
DBUG_RETURN(ER_SPIDER_COND_SKIP_NUM); // MDEV-25116
}
DBUG_RETURN(spider_db_open_item_ident((Item_ident *) item_ref, spider, str,

View file

@ -4855,13 +4855,9 @@ int spider_db_mbase_util::open_item_func(
) {
DBUG_ENTER("spider_db_mbase_util::open_item_func");
int error = check_item_func(item_func, spider, alias,
alias_length, use_fields, fields);
if (error)
DBUG_RETURN(error);
if (!str)
DBUG_RETURN(0);
DBUG_RETURN(check_item_func(item_func, spider, alias,
alias_length, use_fields, fields));
DBUG_RETURN(print_item_func(item_func, spider, str, alias,
alias_length, use_fields, fields));
}
@ -5021,8 +5017,6 @@ int spider_db_mbase_util::print_item_func(
int use_pushdown_udf, case_when_start, case_when_count;
bool merge_func = FALSE, case_with_else;
DBUG_ENTER("spider_db_mbase_util::print_item_func");
DBUG_ASSERT(!check_item_func(item_func, spider, alias, alias_length,
use_fields, fields));
DBUG_ASSERT(str);
if (str->reserve(SPIDER_SQL_OPEN_PAREN_LEN))