diff options
Diffstat (limited to 'sql/item_cmpfunc.cc')
-rw-r--r-- | sql/item_cmpfunc.cc | 44 |
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; |