--- a/sql/item_cmpfunc.h Thu Mar 8 17:29:58 2007 +++ b/sql/item_cmpfunc.h Sun Apr 8 16:02:59 2007 @@ -472,65 +472,75 @@ class Item_func_ge :public Item_bool_rowready_func2 { public: - Item_func_ge(Item *a,Item *b) :Item_bool_rowready_func2(a,b) {}; + Item_func_ge(Item *a,Item *b) :Item_bool_rowready_func2(a,b) + { abort_on_null= TRUE; }; longlong val_int(); enum Functype functype() const { return GE_FUNC; } enum Functype rev_functype() const { return LE_FUNC; } cond_result eq_cmp_result() const { return COND_TRUE; } const char *func_name() const { return ">="; } Item *negated_item(); + void top_level_item() {} }; class Item_func_gt :public Item_bool_rowready_func2 { public: - Item_func_gt(Item *a,Item *b) :Item_bool_rowready_func2(a,b) {}; + Item_func_gt(Item *a,Item *b) :Item_bool_rowready_func2(a,b) + { abort_on_null= TRUE; }; longlong val_int(); enum Functype functype() const { return GT_FUNC; } enum Functype rev_functype() const { return LT_FUNC; } cond_result eq_cmp_result() const { return COND_FALSE; } const char *func_name() const { return ">"; } Item *negated_item(); + void top_level_item() {} }; class Item_func_le :public Item_bool_rowready_func2 { public: - Item_func_le(Item *a,Item *b) :Item_bool_rowready_func2(a,b) {}; + Item_func_le(Item *a,Item *b) :Item_bool_rowready_func2(a,b) + { abort_on_null= TRUE; }; longlong val_int(); enum Functype functype() const { return LE_FUNC; } enum Functype rev_functype() const { return GE_FUNC; } cond_result eq_cmp_result() const { return COND_TRUE; } const char *func_name() const { return "<="; } Item *negated_item(); + void top_level_item() {} }; class Item_func_lt :public Item_bool_rowready_func2 { public: - Item_func_lt(Item *a,Item *b) :Item_bool_rowready_func2(a,b) {} + Item_func_lt(Item *a,Item *b) :Item_bool_rowready_func2(a,b) + { abort_on_null= TRUE; }; longlong val_int(); enum Functype functype() const { return LT_FUNC; } enum Functype rev_functype() const { return GT_FUNC; } cond_result eq_cmp_result() const { return COND_FALSE; } const char *func_name() const { return "<"; } Item *negated_item(); + void top_level_item() {} }; class Item_func_ne :public Item_bool_rowready_func2 { public: - Item_func_ne(Item *a,Item *b) :Item_bool_rowready_func2(a,b) {} + Item_func_ne(Item *a,Item *b) :Item_bool_rowready_func2(a,b) + { abort_on_null= FALSE; }; longlong val_int(); enum Functype functype() const { return NE_FUNC; } cond_result eq_cmp_result() const { return COND_FALSE; } optimize_type select_optimize() const { return OPTIMIZE_KEY; } const char *func_name() const { return "<>"; } Item *negated_item(); + void top_level_item() {} }; --- a/sql/item_cmpfunc.cc Thu Mar 22 19:48:37 2007 +++ b/sql/item_cmpfunc.cc Sun Apr 8 15:14:15 2007 @@ -744,10 +744,41 @@ return (val1 >= 0) && test(val1 == val2); } +/* + compare_row - compare 2 rows for eq, ne, gt, ge, ... + + DESCRIPTION + compare_row and its optimization depend on the calling operation + + EQ + must compare all value pairs, even if a null result occured + (1,2) = (null, 2) returns NULL + (1,2) = (null, 3) returns FALSE + + EQ with abort_on_null + can return NULL instead of FALSE. + compare can be aborted, on a null result + + NE + (1,2) = (null, 2) returns NULL + (1,2) = (null, 3) returns TRUE + NE can not abort on abort_on_null, because it can be true + + GT, GE, LT, LE + compare_row must return on the first differnece encountered. + This includes NULL results too. + + This is archived by ensuring, that NE always has abort_on_null==0, + while GT, GE, LT, LE always have abort_on_null==1 + + <=> is handled in compare_e_row + */ int Arg_comparator::compare_row() { int res= 0; bool was_null= 0; + bool abort_on_null= owner->abort_on_null; + (*a)->bring_value(); (*b)->bring_value(); uint n= (*a)->cols(); @@ -757,7 +788,7 @@ if (owner->null_value) { // NULL was compared - if (owner->abort_on_null) + if (abort_on_null) return -1; // We do not need correct NULL returning was_null= 1; owner->null_value= 0; @@ -1036,6 +1067,7 @@ { DBUG_ASSERT(fixed == 1); int value= cmp.compare(); + // we don't need to test null_value, as it can only be true if result==-1 return value >= 0 ? 1 : 0; }