summaryrefslogtreecommitdiff
path: root/sql/item_cmpfunc.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/item_cmpfunc.cc')
-rw-r--r--sql/item_cmpfunc.cc31
1 files changed, 26 insertions, 5 deletions
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index d430d0d3c23..9443a2949d8 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -614,19 +614,38 @@ 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)
+ }
+ else 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()
{
(*a)->bring_value();
@@ -1903,6 +1922,8 @@ in_row::~in_row()
byte *in_row::get_value(Item *item)
{
tmp.store_value(item);
+ if (item->is_null())
+ return 0;
return (byte *)&tmp;
}
@@ -2791,7 +2812,7 @@ bool Item_func_like::fix_fields(THD *thd, Item **ref)
/* If we are on execution stage */
String *escape_str= escape_item->val_str(&tmp_value1);
escape= escape_str ? *(escape_str->ptr()) : '\\';
-
+
/*
We could also do boyer-more for non-const items, but as we would have to
recompute the tables for each row it's not worth it.