mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 12:02:42 +01:00
stop on NULL comparison only if it is allowed (BUG#12509)
mysql-test/r/row.result: Correct NULL handling in row comporison mysql-test/t/row.test: Correct NULL handling in row comporison (BUG#12509) sql/item_cmpfunc.cc: stop on NULL comparison only if it is allowed sql/item_cmpfunc.h: support optimisation in case of processing WHERE/HAVING, where NULL and FALSE are equal
This commit is contained in:
parent
4d2bf4befc
commit
341f822126
4 changed files with 38 additions and 6 deletions
|
@ -58,7 +58,7 @@ SELECT (1,2,3)=(1,NULL,3);
|
|||
NULL
|
||||
SELECT (1,2,3)=(1,NULL,0);
|
||||
(1,2,3)=(1,NULL,0)
|
||||
NULL
|
||||
0
|
||||
SELECT ROW(1,2,3)=ROW(1,2,3);
|
||||
ROW(1,2,3)=ROW(1,2,3)
|
||||
1
|
||||
|
@ -175,3 +175,9 @@ ROW(2,10) <=> ROW(3,4)
|
|||
SELECT ROW(NULL,10) <=> ROW(3,NULL);
|
||||
ROW(NULL,10) <=> ROW(3,NULL)
|
||||
0
|
||||
SELECT ROW(1,1,1) = ROW(1,1,1) as `1`, ROW(1,1,1) = ROW(1,2,1) as `0`, ROW(1,NULL,1) = ROW(2,2,1) as `0`, ROW(1,NULL,1) = ROW(1,2,2) as `0`, ROW(1,NULL,1) = ROW(1,2,1) as `null` ;
|
||||
1 0 0 0 null
|
||||
1 0 0 0 NULL
|
||||
select row(NULL,1)=(2,0);
|
||||
row(NULL,1)=(2,0)
|
||||
0
|
||||
|
|
|
@ -86,3 +86,9 @@ SELECT ROW(2,10) <=> ROW(3,4);
|
|||
SELECT ROW(NULL,10) <=> ROW(3,NULL);
|
||||
|
||||
# End of 4.1 tests
|
||||
|
||||
#
|
||||
# Correct NULL handling in row comporison (BUG#12509)
|
||||
#
|
||||
SELECT ROW(1,1,1) = ROW(1,1,1) as `1`, ROW(1,1,1) = ROW(1,2,1) as `0`, ROW(1,NULL,1) = ROW(2,2,1) as `0`, ROW(1,NULL,1) = ROW(1,2,2) as `0`, ROW(1,NULL,1) = ROW(1,2,1) as `null` ;
|
||||
select row(NULL,1)=(2,0);
|
||||
|
|
|
@ -614,17 +614,35 @@ int Arg_comparator::compare_e_int_diff_signedness()
|
|||
int Arg_comparator::compare_row()
|
||||
{
|
||||
int res= 0;
|
||||
bool was_null= 0;
|
||||
(*a)->bring_value();
|
||||
(*b)->bring_value();
|
||||
uint n= (*a)->cols();
|
||||
for (uint i= 0; i<n; i++)
|
||||
{
|
||||
if ((res= comparators[i].compare()))
|
||||
return res;
|
||||
res= comparators[i].compare();
|
||||
if (owner->null_value)
|
||||
return -1;
|
||||
{
|
||||
// NULL was compared
|
||||
if (owner->abort_on_null)
|
||||
return -1; // We do not need correct NULL returning
|
||||
was_null= 1;
|
||||
owner->null_value= 0;
|
||||
res= 0; // continue comparison (maybe we will meet explicit difference)
|
||||
}
|
||||
if (res)
|
||||
return res;
|
||||
}
|
||||
return res;
|
||||
if (was_null)
|
||||
{
|
||||
/*
|
||||
There was NULL(s) in comparison in some parts, but there was not
|
||||
explicit difference in other parts, so we have to return NULL
|
||||
*/
|
||||
owner->null_value= 1;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Arg_comparator::compare_e_row()
|
||||
|
|
|
@ -193,10 +193,11 @@ class Item_bool_func2 :public Item_int_func
|
|||
protected:
|
||||
Arg_comparator cmp;
|
||||
String tmp_value1,tmp_value2;
|
||||
bool abort_on_null;
|
||||
|
||||
public:
|
||||
Item_bool_func2(Item *a,Item *b)
|
||||
:Item_int_func(a,b), cmp(tmp_arg, tmp_arg+1) {}
|
||||
:Item_int_func(a,b), cmp(tmp_arg, tmp_arg+1), abort_on_null(FALSE) {}
|
||||
void fix_length_and_dec();
|
||||
void set_cmp_func()
|
||||
{
|
||||
|
@ -210,6 +211,7 @@ public:
|
|||
bool is_bool_func() { return 1; }
|
||||
CHARSET_INFO *compare_collation() { return cmp.cmp_collation.collation; }
|
||||
uint decimal_precision() const { return 1; }
|
||||
void top_level_item() { abort_on_null=1; }
|
||||
|
||||
friend class Arg_comparator;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue