diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 65c942a75ce..7028147067e 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -180,6 +180,7 @@ void Item_singlerow_subselect::fix_length_and_dec() engine->fix_length_and_dec(row); value= *row; } + maybe_null= engine->may_be_null(); } uint Item_singlerow_subselect::cols() @@ -663,7 +664,7 @@ int subselect_union_engine::prepare() } static Item_result set_row(SELECT_LEX *select_lex, Item * item, - Item_cache **row) + Item_cache **row, bool *maybe_null) { Item_result res_type= STRING_RESULT; Item *sel_item; @@ -673,6 +674,7 @@ static Item_result set_row(SELECT_LEX *select_lex, Item * item, item->max_length= sel_item->max_length; res_type= sel_item->result_type(); item->decimals= sel_item->decimals; + *maybe_null= sel_item->maybe_null; if (row) { if (!(row[i]= Item_cache::get_cache(res_type))) @@ -692,7 +694,9 @@ static Item_result set_row(SELECT_LEX *select_lex, Item * item, void subselect_single_select_engine::fix_length_and_dec(Item_cache **row) { DBUG_ASSERT(row || select_lex->item_list.elements==1); - res_type= set_row(select_lex, item, row); + res_type= set_row(select_lex, item, row, &maybe_null); + if (cols() != 1) + maybe_null= 0; } void subselect_union_engine::fix_length_and_dec(Item_cache **row) @@ -711,6 +715,7 @@ void subselect_union_engine::fix_length_and_dec(Item_cache **row) mlen= len; if (!sel_item) sel_item= s_item; + maybe_null!= s_item->maybe_null; } item->max_length= mlen; res_type= sel_item->result_type(); @@ -729,7 +734,8 @@ void subselect_union_engine::fix_length_and_dec(Item_cache **row) else { SELECT_LEX *sl= unit->first_select(); - res_type= set_row(sl, item, row); + bool fake= 0; + res_type= set_row(sl, item, row, &fake); for(sl= sl->next_select(); sl; sl->next_select()) { List_iterator_fast li(sl->item_list); diff --git a/sql/item_subselect.h b/sql/item_subselect.h index 6063730d6a8..41490dd2669 100644 --- a/sql/item_subselect.h +++ b/sql/item_subselect.h @@ -197,19 +197,15 @@ public: virtual void select_transformer(st_select_lex_unit *unit); }; -class subselect_engine +class subselect_engine: public Sql_alloc { protected: select_subselect *result; /* results storage class */ THD *thd; /* pointer to current THD */ Item_subselect *item; /* item, that use this engine */ enum Item_result res_type; /* type of results */ + bool maybe_null; /* may be null (first item in select) */ public: - static void *operator new(size_t size) - { - return (void*) sql_alloc((uint) size); - } - static void operator delete(void *ptr, size_t size) {} subselect_engine(THD *thd, Item_subselect *si, select_subselect *res) { @@ -217,7 +213,9 @@ public: item= si; this->thd= thd; res_type= STRING_RESULT; + maybe_null= 0; } + virtual ~subselect_engine() {}; // to satisfy compiler virtual int prepare()= 0; virtual void fix_length_and_dec(Item_cache** row)= 0; @@ -227,6 +225,7 @@ public: enum Item_result type() { return res_type; } virtual bool check_loop(uint id)= 0; virtual void exclude()= 0; + bool may_be_null() { return maybe_null; }; }; class subselect_single_select_engine: public subselect_engine