1
0
mirror of https://github.com/MariaDB/server.git synced 2026-10-23 18:49:29 +03:00

MDEV-41228 Read the row of Item_func_interval through args[0]

A query like

  select * from (select a, b from t1 group by a, b) d
    where interval(d.a, 3, 7) = 1

returned no rows when the condition was pushed into the derived table,
although the row (5,20) matches, as condition_pushdown_for_derived=off
shows.

Item_func_interval kept its first argument, the Item_row, in a member
of its own as well as in args[0]. Condition pushdown copies the condition
with deep_copy(). The copy of the node got new arguments but kept the
member, so it went on reading the original row: the INTERVAL() pushed into
the derived table compared the original outer column, and the pushed
condition rejected every row.

Item_func_interval now reads the row through args[0] alone, so a copy
cannot point anywhere else.

This commit was prepared with Claude Code (Opus 5), which found the stale
member, made Item_func_interval read the row through args[0], wrote the
test and confirmed in a build of the parent commit that it fails without
the change, and ran main and the SQL-layer suites in normal and
--ps-protocol mode on the series that contains it.
This commit is contained in:
Rex Johnston
2026-10-19 09:35:25 +13:00
parent f28ef527a5
commit c0aa1a1d57
4 changed files with 40 additions and 19 deletions

View File

@@ -23789,3 +23789,13 @@ id id id
0 3 3
drop table t1,t2,t3;
# End of 10.11 tests
#
# MDEV-41228 INTERVAL() pushed into a derived table
#
create table t1 (a int, b int);
insert into t1 values (1,10),(5,20),(9,30);
select * from (select a, b from t1 group by a, b) d where interval(d.a, 3, 7) = 1;
a b
5 20
drop table t1;
# End of 13.2 tests

View File

@@ -4579,3 +4579,14 @@ select * from (select id from t1 union select id from t2) dt1,
drop table t1,t2,t3;
--echo # End of 10.11 tests
--echo #
--echo # MDEV-41228 INTERVAL() pushed into a derived table
--echo #
create table t1 (a int, b int);
insert into t1 values (1,10),(5,20),(9,30);
select * from (select a, b from t1 group by a, b) d where interval(d.a, 3, 7) = 1;
drop table t1;
--echo # End of 13.2 tests

View File

@@ -2014,17 +2014,17 @@ bool Item_func_opt_neg::eq(const Item *item, const Eq_config &config) const
bool Item_func_interval::fix_length_and_dec(THD *thd)
{
uint rows= row->cols();
uint rows= row()->cols();
for (uint i= 0 ; i < rows; i++)
{
if (row->element_index(i)->check_cols(1))
if (row()->element_index(i)->check_cols(1))
return true;
}
use_decimal_comparison= ((row->element_index(0)->result_type() ==
use_decimal_comparison= ((row()->element_index(0)->result_type() ==
DECIMAL_RESULT) ||
(row->element_index(0)->result_type() ==
(row()->element_index(0)->result_type() ==
INT_RESULT));
if (rows > 8)
{
@@ -2032,7 +2032,7 @@ bool Item_func_interval::fix_length_and_dec(THD *thd)
for (uint i= 1; not_null_consts && i < rows; i++)
{
Item *el= row->element_index(i);
Item *el= row()->element_index(i);
not_null_consts&= el->const_item() && !el->is_null();
}
@@ -2046,7 +2046,7 @@ bool Item_func_interval::fix_length_and_dec(THD *thd)
{
for (uint i= 1; i < rows; i++)
{
Item *el= row->element_index(i);
Item *el= row()->element_index(i);
interval_range *range= intervals + (i-1);
if ((el->result_type() == DECIMAL_RESULT) ||
(el->result_type() == INT_RESULT))
@@ -2070,16 +2070,16 @@ bool Item_func_interval::fix_length_and_dec(THD *thd)
{
for (uint i= 1; i < rows; i++)
{
intervals[i-1].dbl= row->element_index(i)->val_real();
intervals[i-1].dbl= row()->element_index(i)->val_real();
}
}
}
}
base_flags&= ~item_base_t::MAYBE_NULL;
max_length= 2;
used_tables_and_const_cache_join(row);
not_null_tables_cache= row->not_null_tables();
with_flags|= row->with_flags;
used_tables_and_const_cache_join(row());
not_null_tables_cache= row()->not_null_tables();
with_flags|= row()->with_flags;
return false;
}
@@ -2107,15 +2107,15 @@ longlong Item_func_interval::val_int()
if (use_decimal_comparison)
{
dec= row->element_index(0)->val_decimal(&dec_buf);
if (row->element_index(0)->null_value)
dec= row()->element_index(0)->val_decimal(&dec_buf);
if (row()->element_index(0)->null_value)
return -1;
my_decimal2double(E_DEC_FATAL_ERROR, dec, &value);
}
else
{
value= row->element_index(0)->val_real();
if (row->element_index(0)->null_value)
value= row()->element_index(0)->val_real();
if (row()->element_index(0)->null_value)
return -1;
}
@@ -2123,7 +2123,7 @@ longlong Item_func_interval::val_int()
{ // Use binary search to find interval
uint start,end;
start= 0;
end= row->cols()-2;
end= row()->cols()-2;
while (start != end)
{
uint mid= (start + end + 1) / 2;
@@ -2149,9 +2149,9 @@ longlong Item_func_interval::val_int()
value < range->dbl) ? 0 : start + 1;
}
for (i=1 ; i < row->cols() ; i++)
for (i=1 ; i < row()->cols() ; i++)
{
Item *el= row->element_index(i);
Item *el= row()->element_index(i);
if (use_decimal_comparison &&
((el->result_type() == DECIMAL_RESULT) ||
(el->result_type() == INT_RESULT)))

View File

@@ -1213,7 +1213,6 @@ struct interval_range
class Item_func_interval :public Item_long_func
{
Item_row *row;
bool use_decimal_comparison;
interval_range *intervals;
bool check_arguments() const override
@@ -1222,8 +1221,9 @@ class Item_func_interval :public Item_long_func
}
public:
Item_func_interval(THD *thd, Item_row *a):
Item_long_func(thd, a), row(a), intervals(0)
Item_long_func(thd, a), intervals(0)
{ }
Item_row *row() const { return static_cast<Item_row*>(args[0]); }
longlong val_int() override;
bool fix_length_and_dec(THD *thd) override;
LEX_CSTRING func_name_cstring() const override