mirror of
https://github.com/MariaDB/server.git
synced 2026-10-23 18:49:29 +03:00
MDEV-36295 INTERVAL function returns inconsistent results when used in a WHERE clause
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).
This commit is contained in:
committed by
Sergei Petrunia
parent
85534724fa
commit
032986055f
@@ -21808,3 +21808,13 @@ id id id
|
||||
0 3 3
|
||||
drop table t1,t2,t3;
|
||||
# End of 10.11 tests
|
||||
#
|
||||
# MDEV-36295 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
|
||||
|
||||
@@ -4372,3 +4372,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-36295 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
|
||||
|
||||
@@ -1947,17 +1947,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)
|
||||
{
|
||||
@@ -1965,7 +1965,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();
|
||||
}
|
||||
|
||||
@@ -1979,7 +1979,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))
|
||||
@@ -2003,16 +2003,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;
|
||||
}
|
||||
|
||||
@@ -2040,15 +2040,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;
|
||||
}
|
||||
|
||||
@@ -2056,7 +2056,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;
|
||||
@@ -2082,9 +2082,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)))
|
||||
|
||||
@@ -1159,7 +1159,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
|
||||
@@ -1168,8 +1167,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
|
||||
|
||||
Reference in New Issue
Block a user