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.cc44
1 files changed, 30 insertions, 14 deletions
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 3cd55934950..93e24525d06 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -26,8 +26,8 @@
/*
Test functions
- These returns 0LL if false and 1LL if true and null if some arg is null
- 'AND' and 'OR' never return null
+ Most of these returns 0LL if false and 1LL if true and
+ NULL if some arg is NULL.
*/
longlong Item_func_not::val_int()
@@ -533,6 +533,7 @@ Item_func_if::fix_length_and_dec()
else
cached_result_type=arg1_type; // Should be INT_RESULT
}
+ args[0]->top_level_item();
}
@@ -1128,6 +1129,8 @@ Item_cond::fix_fields(THD *thd,TABLE_LIST *tables)
const_item_cache&=item->const_item();
if (item->maybe_null)
maybe_null=1;
+ if (abort_on_null)
+ item->top_level_item();
}
if (thd)
thd->cond_count+=list.elements;
@@ -1196,28 +1199,41 @@ void Item_cond::print(String *str)
str->append(')');
}
+/*
+ Evalution of AND(expr, expr, expr ...)
+
+ NOTES:
+ abort_if_null is set for AND expressions for which we don't care if the
+ result is NULL or 0. This is set for:
+ - WHERE clause
+ - HAVING clause
+ - IF(expression)
+
+ RETURN VALUES
+ 1 If all expressions are true
+ 0 If all expressions are false or if we find a NULL expression and
+ 'abort_on_null' is set.
+ NULL if all expression are either 1 or NULL
+*/
+
longlong Item_cond_and::val_int()
{
List_iterator_fast<Item> li(list);
Item *item;
+ null_value= 0;
while ((item=li++))
{
if (item->val_int() == 0)
{
- /*
- TODO: In case of NULL, ANSI would require us to continue evaluation
- until we get a FALSE value or run out of values; This would
- require a lot of unnecessary evaluation, which we skip for now
- */
- null_value=item->null_value;
- return 0;
+ if (abort_on_null || !(null_value= item->null_value))
+ return 0; // return FALSE
}
}
- null_value=0;
- return 1;
+ return null_value ? 0 : 1;
}
+
longlong Item_cond_or::val_int()
{
List_iterator_fast<Item> li(list);
@@ -1260,15 +1276,15 @@ longlong Item_cond_or::val_int()
Item *and_expressions(Item *a, Item *b, Item **org_item)
{
if (!a)
- return (*org_item= (Item*) b);
+ return (*org_item= b);
if (a == *org_item)
{
Item_cond *res;
- if ((res= new Item_cond_and(a, (Item*) b)))
+ if ((res= new Item_cond_and(a, b)))
res->used_tables_cache= a->used_tables() | b->used_tables();
return res;
}
- if (((Item_cond_and*) a)->add((Item*) b))
+ if (((Item_cond_and*) a)->add(b))
return 0;
((Item_cond_and*) a)->used_tables_cache|= b->used_tables();
return a;