diff options
Diffstat (limited to 'sql')
-rw-r--r-- | sql/item.cc | 27 | ||||
-rw-r--r-- | sql/item.h | 10 | ||||
-rw-r--r-- | sql/item_cmpfunc.cc | 2 | ||||
-rw-r--r-- | sql/item_subselect.cc | 49 | ||||
-rw-r--r-- | sql/item_subselect.h | 6 |
5 files changed, 78 insertions, 16 deletions
diff --git a/sql/item.cc b/sql/item.cc index e633964270b..45f40874ddb 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -9690,7 +9690,7 @@ bool Item_cache_int::cache_value() return FALSE; value_cached= TRUE; value= example->val_int_result(); - null_value= example->null_value; + null_value_inside= null_value= example->null_value; unsigned_flag= example->unsigned_flag; return TRUE; } @@ -9860,7 +9860,7 @@ bool Item_cache_temporal::cache_value() return true; value= pack_time(<ime); } - null_value= example->null_value; + null_value_inside= null_value= example->null_value; return true; } @@ -9955,7 +9955,7 @@ bool Item_cache_real::cache_value() return FALSE; value_cached= TRUE; value= example->val_result(); - null_value= example->null_value; + null_value_inside= null_value= example->null_value; return TRUE; } @@ -10017,7 +10017,8 @@ bool Item_cache_decimal::cache_value() return FALSE; value_cached= TRUE; my_decimal *val= example->val_decimal_result(&decimal_value); - if (!(null_value= example->null_value) && val != &decimal_value) + if (!(null_value_inside= null_value= example->null_value) && + val != &decimal_value) my_decimal2decimal(val, &decimal_value); return TRUE; } @@ -10083,11 +10084,14 @@ Item *Item_cache_decimal::convert_to_basic_const_item(THD *thd) bool Item_cache_str::cache_value() { if (!example) + { + DBUG_ASSERT(value_cached == FALSE); return FALSE; + } value_cached= TRUE; value_buff.set(buffer, sizeof(buffer), example->collation.collation); value= example->str_result(&value_buff); - if ((null_value= example->null_value)) + if ((null_value= null_value_inside= example->null_value)) value= 0; else if (value != &value_buff) { @@ -10186,6 +10190,8 @@ Item *Item_cache_str::convert_to_basic_const_item(THD *thd) bool Item_cache_row::setup(THD *thd, Item *item) { example= item; + null_value= true; + if (!values && allocate(thd, item->cols())) return 1; for (uint i= 0; i < item_count; i++) @@ -10218,12 +10224,19 @@ bool Item_cache_row::cache_value() if (!example) return FALSE; value_cached= TRUE; - null_value= 0; + null_value= TRUE; + null_value_inside= false; example->bring_value(); + + /* + For Item_cache_row null_value is set to TRUE only when ALL the values + inside the cache are NULL + */ for (uint i= 0; i < item_count; i++) { values[i]->cache_value(); - null_value|= values[i]->null_value; + null_value&= values[i]->null_value; + null_value_inside|= values[i]->null_value; } return TRUE; } diff --git a/sql/item.h b/sql/item.h index 823ffd873b6..cb1e8519b27 100644 --- a/sql/item.h +++ b/sql/item.h @@ -5658,6 +5658,14 @@ protected: */ bool value_cached; public: + /* + This is set if at least one of the values of a sub query is NULL + Item_cache_row returns this with null_inside(). + For not row items, it's set to the value of null_value + It is set after cache_value() is called. + */ + bool null_value_inside; + Item_cache(THD *thd): Item_basic_constant(thd), Type_handler_hybrid_field_type(MYSQL_TYPE_STRING), @@ -5667,6 +5675,7 @@ public: fixed= 1; maybe_null= 1; null_value= 1; + null_value_inside= true; } protected: Item_cache(THD *thd, enum_field_types field_type_arg): @@ -5678,6 +5687,7 @@ protected: fixed= 1; maybe_null= 1; null_value= 1; + null_value_inside= true; } public: diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index d5b89f13f04..7b7604053e3 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -1598,7 +1598,7 @@ longlong Item_in_optimizer::val_int() DBUG_RETURN(res); } - if (cache->null_value) + if (cache->null_value_inside) { DBUG_PRINT("info", ("Left NULL...")); /* diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 3424df1eb91..4b8f118ca43 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -851,7 +851,7 @@ bool Item_subselect::expr_cache_is_needed(THD *thd) inline bool Item_in_subselect::left_expr_has_null() { - return (*(optimizer->get_cache()))->null_value; + return (*(optimizer->get_cache()))->null_value_inside; } @@ -1319,7 +1319,17 @@ bool Item_singlerow_subselect::null_inside() void Item_singlerow_subselect::bring_value() { if (!exec() && assigned()) - null_value= 0; + { + null_value= true; + for (uint i= 0; i < max_columns ; i++) + { + if (!row[i]->null_value) + { + null_value= false; + return; + } + } + } else reset(); } @@ -1345,7 +1355,11 @@ longlong Item_singlerow_subselect::val_int() { DBUG_ASSERT(fixed == 1); if (forced_const) - return value->val_int(); + { + longlong val= value->val_int(); + null_value= value->null_value; + return val; + } if (!exec() && !value->null_value) { null_value= FALSE; @@ -1354,6 +1368,7 @@ longlong Item_singlerow_subselect::val_int() else { reset(); + DBUG_ASSERT(null_value); return 0; } } @@ -1362,7 +1377,11 @@ String *Item_singlerow_subselect::val_str(String *str) { DBUG_ASSERT(fixed == 1); if (forced_const) - return value->val_str(str); + { + String *res= value->val_str(str); + null_value= value->null_value; + return res; + } if (!exec() && !value->null_value) { null_value= FALSE; @@ -1371,6 +1390,7 @@ String *Item_singlerow_subselect::val_str(String *str) else { reset(); + DBUG_ASSERT(null_value); return 0; } } @@ -1380,7 +1400,11 @@ my_decimal *Item_singlerow_subselect::val_decimal(my_decimal *decimal_value) { DBUG_ASSERT(fixed == 1); if (forced_const) - return value->val_decimal(decimal_value); + { + my_decimal *val= value->val_decimal(decimal_value); + null_value= value->null_value; + return val; + } if (!exec() && !value->null_value) { null_value= FALSE; @@ -1389,6 +1413,7 @@ my_decimal *Item_singlerow_subselect::val_decimal(my_decimal *decimal_value) else { reset(); + DBUG_ASSERT(null_value); return 0; } } @@ -1398,7 +1423,11 @@ bool Item_singlerow_subselect::val_bool() { DBUG_ASSERT(fixed == 1); if (forced_const) - return value->val_bool(); + { + bool val= value->val_bool(); + null_value= value->null_value; + return val; + } if (!exec() && !value->null_value) { null_value= FALSE; @@ -1407,6 +1436,7 @@ bool Item_singlerow_subselect::val_bool() else { reset(); + DBUG_ASSERT(null_value); return 0; } } @@ -1416,7 +1446,11 @@ bool Item_singlerow_subselect::get_date(MYSQL_TIME *ltime,ulonglong fuzzydate) { DBUG_ASSERT(fixed == 1); if (forced_const) - return value->get_date(ltime, fuzzydate); + { + bool val= value->get_date(ltime, fuzzydate); + null_value= value->null_value; + return val; + } if (!exec() && !value->null_value) { null_value= FALSE; @@ -1425,6 +1459,7 @@ bool Item_singlerow_subselect::get_date(MYSQL_TIME *ltime,ulonglong fuzzydate) else { reset(); + DBUG_ASSERT(null_value); return 1; } } diff --git a/sql/item_subselect.h b/sql/item_subselect.h index 9116238c640..130f90839e3 100644 --- a/sql/item_subselect.h +++ b/sql/item_subselect.h @@ -48,7 +48,11 @@ class Cached_item; class Item_subselect :public Item_result_field, protected Used_tables_and_const_cache { - bool value_assigned; /* value already assigned to subselect */ + /* + Set to TRUE if the value is assigned for the subselect + FALSE: subquery not executed or the subquery returns an empty result + */ + bool value_assigned; bool own_engine; /* the engine was not taken from other Item_subselect */ protected: /* thread handler, will be assigned in fix_fields only */ |