Commit 341f8221 authored by unknown's avatar unknown

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
parent 4d2bf4be
...@@ -58,7 +58,7 @@ SELECT (1,2,3)=(1,NULL,3); ...@@ -58,7 +58,7 @@ SELECT (1,2,3)=(1,NULL,3);
NULL NULL
SELECT (1,2,3)=(1,NULL,0); SELECT (1,2,3)=(1,NULL,0);
(1,2,3)=(1,NULL,0) (1,2,3)=(1,NULL,0)
NULL 0
SELECT ROW(1,2,3)=ROW(1,2,3); SELECT ROW(1,2,3)=ROW(1,2,3);
ROW(1,2,3)=ROW(1,2,3) ROW(1,2,3)=ROW(1,2,3)
1 1
...@@ -175,3 +175,9 @@ ROW(2,10) <=> ROW(3,4) ...@@ -175,3 +175,9 @@ ROW(2,10) <=> ROW(3,4)
SELECT ROW(NULL,10) <=> ROW(3,NULL); SELECT ROW(NULL,10) <=> ROW(3,NULL);
ROW(NULL,10) <=> ROW(3,NULL) ROW(NULL,10) <=> ROW(3,NULL)
0 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); ...@@ -86,3 +86,9 @@ SELECT ROW(2,10) <=> ROW(3,4);
SELECT ROW(NULL,10) <=> ROW(3,NULL); SELECT ROW(NULL,10) <=> ROW(3,NULL);
# End of 4.1 tests # 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() ...@@ -614,17 +614,35 @@ int Arg_comparator::compare_e_int_diff_signedness()
int Arg_comparator::compare_row() int Arg_comparator::compare_row()
{ {
int res= 0; int res= 0;
bool was_null= 0;
(*a)->bring_value(); (*a)->bring_value();
(*b)->bring_value(); (*b)->bring_value();
uint n= (*a)->cols(); uint n= (*a)->cols();
for (uint i= 0; i<n; i++) for (uint i= 0; i<n; i++)
{ {
if ((res= comparators[i].compare())) res= comparators[i].compare();
return res;
if (owner->null_value) 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() int Arg_comparator::compare_e_row()
......
...@@ -193,10 +193,11 @@ class Item_bool_func2 :public Item_int_func ...@@ -193,10 +193,11 @@ class Item_bool_func2 :public Item_int_func
protected: protected:
Arg_comparator cmp; Arg_comparator cmp;
String tmp_value1,tmp_value2; String tmp_value1,tmp_value2;
bool abort_on_null;
public: public:
Item_bool_func2(Item *a,Item *b) 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 fix_length_and_dec();
void set_cmp_func() void set_cmp_func()
{ {
...@@ -210,6 +211,7 @@ public: ...@@ -210,6 +211,7 @@ public:
bool is_bool_func() { return 1; } bool is_bool_func() { return 1; }
CHARSET_INFO *compare_collation() { return cmp.cmp_collation.collation; } CHARSET_INFO *compare_collation() { return cmp.cmp_collation.collation; }
uint decimal_precision() const { return 1; } uint decimal_precision() const { return 1; }
void top_level_item() { abort_on_null=1; }
friend class Arg_comparator; friend class Arg_comparator;
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment