diff options
author | unknown <bell@sanja.is.com.ua> | 2002-12-25 11:09:19 +0200 |
---|---|---|
committer | unknown <bell@sanja.is.com.ua> | 2002-12-25 11:09:19 +0200 |
commit | e10a32679096459ee0695d07cd4ae210e21ba227 (patch) | |
tree | 00c3c7c7800c85be561cb5d2b820e194ee9bd7f9 /sql/item_subselect.cc | |
parent | 4abcd967bad4f54181ab6710e1a4236aaeb9c370 (diff) | |
parent | a05b0f087c02eb7165a26e531f5e4cc34db0b173 (diff) | |
download | mariadb-git-e10a32679096459ee0695d07cd4ae210e21ba227.tar.gz |
merging
sql/item.cc:
Auto merged
sql/item_subselect.cc:
Auto merged
sql/sql_class.cc:
Auto merged
Diffstat (limited to 'sql/item_subselect.cc')
-rw-r--r-- | sql/item_subselect.cc | 282 |
1 files changed, 238 insertions, 44 deletions
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 4b9e9c256d1..74824fc7757 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -112,9 +112,14 @@ bool Item_subselect::check_loop(uint id) DBUG_RETURN(engine->check_loop(id)); } +Item::Type Item_subselect::type() const +{ + return SUBSELECT_ITEM; +} + void Item_subselect::fix_length_and_dec() { - engine->fix_length_and_dec(); + engine->fix_length_and_dec(0); } inline table_map Item_subselect::used_tables() const @@ -122,56 +127,131 @@ inline table_map Item_subselect::used_tables() const return (table_map) engine->depended() ? 1L : 0L; } -Item_singleval_subselect::Item_singleval_subselect(THD *thd, +Item_singlerow_subselect::Item_singlerow_subselect(THD *thd, st_select_lex *select_lex): - Item_subselect() + Item_subselect(), value(0) { - DBUG_ENTER("Item_singleval_subselect::Item_singleval_subselect"); - init(thd, select_lex, new select_singleval_subselect(this)); + DBUG_ENTER("Item_singlerow_subselect::Item_singlerow_subselect"); + init(thd, select_lex, new select_singlerow_subselect(this)); max_columns= 1; maybe_null= 1; + max_columns= UINT_MAX; DBUG_VOID_RETURN; } -void Item_singleval_subselect::fix_length_and_dec() +void Item_singlerow_subselect::reset() { - engine->fix_length_and_dec(); - res_type= engine->type(); + null_value= 1; + if (value) + value->null_value= 1; } -Item::Type Item_subselect::type() const +void Item_singlerow_subselect::store(uint i, Item *item) { - return SUBSELECT_ITEM; + row[i]->store(item); } -double Item_singleval_subselect::val () +enum Item_result Item_singlerow_subselect::result_type() const { - if (engine->exec()) + return engine->type(); +} + +void Item_singlerow_subselect::fix_length_and_dec() +{ + if ((max_columns= engine->cols()) == 1) + { + engine->fix_length_and_dec(row= &value); + if (!(value= Item_cache::get_cache(engine->type()))) + { + my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0)); + current_thd->fatal_error= 1; + return; + } + } + else + { + THD *thd= current_thd; + if (!(row= (Item_cache**)thd->alloc(sizeof(Item_cache*)*max_columns))) + { + my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0)); + thd->fatal_error= 1; + return; + } + engine->fix_length_and_dec(row); + value= *row; + } +} + +uint Item_singlerow_subselect::cols() +{ + return engine->cols(); +} + +bool Item_singlerow_subselect::check_cols(uint c) +{ + if (c != engine->cols()) + { + my_error(ER_CARDINALITY_COL, MYF(0), c); + return 1; + } + return 0; +} + +bool Item_singlerow_subselect::null_inside() +{ + for (uint i= 0; i < max_columns ; i++) + { + if (row[i]->null_value) + return 1; + } + return 0; +} + +void Item_singlerow_subselect::bring_value() +{ + engine->exec(); +} + +double Item_singlerow_subselect::val () +{ + if (!engine->exec() && !value->null_value) + { + null_value= 0; + return value->val(); + } + else { reset(); return 0; } - return real_value; } -longlong Item_singleval_subselect::val_int () +longlong Item_singlerow_subselect::val_int () { - if (engine->exec()) + if (!engine->exec() && !value->null_value) + { + null_value= 0; + return value->val_int(); + } + else { reset(); return 0; } - return int_value; } -String *Item_singleval_subselect::val_str (String *str) +String *Item_singlerow_subselect::val_str (String *str) { - if (engine->exec() || null_value) + if (!engine->exec() && !value->null_value) + { + null_value= 0; + return value->val_str(str); + } + else { reset(); return 0; } - return &string_value; } Item_exists_subselect::Item_exists_subselect(THD *thd, @@ -213,7 +293,7 @@ Item_allany_subselect::Item_allany_subselect(THD *thd, Item * left_exp, left_expr= left_exp; func= f; init(thd, select_lex, new select_exists_subselect(this)); - max_columns= UINT_MAX; + max_columns= 1; reset(); // We need only 1 row to determinate existence select_lex->master_unit()->global_parameters->select_limit= 1; @@ -223,8 +303,9 @@ Item_allany_subselect::Item_allany_subselect(THD *thd, Item * left_exp, void Item_exists_subselect::fix_length_and_dec() { - decimals=0; + decimals= 0; max_length= 1; + max_columns= engine->cols(); } double Item_exists_subselect::val () @@ -336,8 +417,9 @@ void Item_in_subselect::single_value_transformer(st_select_lex *select_lex, As far as Item_ref_in_optimizer do not substitude itself on fix_fields we can use same item for all selects. */ - Item *expr= new Item_ref_in_optimizer(optimizer, (char *)"<no matter>", - (char*)"<left expr>"); + Item *expr= new Item_ref((Item**)optimizer->get_cache(), + (char *)"<no matter>", + (char*)"<left expr>"); select_lex->master_unit()->dependent= 1; for (SELECT_LEX * sl= select_lex; sl; sl= sl->next_select()) { @@ -373,7 +455,7 @@ void Item_in_subselect::single_value_transformer(st_select_lex *select_lex, sl->having= item; else if (sl->where) - sl->where= new Item_cond_and(sl->having, item); + sl->where= new Item_cond_and(sl->where, item); else sl->where= item; } @@ -431,10 +513,68 @@ void Item_in_subselect::single_value_transformer(st_select_lex *select_lex, DBUG_VOID_RETURN; } +void Item_in_subselect::row_value_transformer(st_select_lex *select_lex, + Item *left_expr) +{ + DBUG_ENTER("Item_in_subselect::row_value_transformer"); + Item_in_optimizer *optimizer; + substitution= optimizer= new Item_in_optimizer(left_expr, this); + if (!optimizer) + { + current_thd->fatal_error= 1; + DBUG_VOID_RETURN; + } + select_lex->master_unit()->dependent= 1; + uint n= left_expr->cols(); + if (optimizer->preallocate_row() || (*optimizer->get_cache())->allocate(n)) + DBUG_VOID_RETURN; + for (SELECT_LEX * sl= select_lex; sl; sl= sl->next_select()) + { + select_lex->dependent= 1; + + Item *item= 0; + List_iterator_fast<Item> li(sl->item_list); + for (uint i= 0; i < n; i++) + { + Item *func= + new Item_ref_on_list_position(this, sl->item_list, i, + (char *) "<no matter>", + (char *) "<list ref>"); + func= + Item_bool_func2::eq_creator(new Item_ref((*optimizer->get_cache())-> + addr(i), + (char *)"<no matter>", + (char *)"<left expr>"), + func); + if (!item) + item= func; + else + item= new Item_cond_and(item, func); + } + + if (sl->having || sl->with_sum_func || sl->group_list.first || + !sl->table_list.elements) + if (sl->having) + sl->having= new Item_cond_and(sl->having, item); + else + sl->having= item; + else + if (sl->where) + sl->where= new Item_cond_and(sl->where, item); + else + sl->where= item; + } + DBUG_VOID_RETURN; +} + + void Item_in_subselect::select_transformer(st_select_lex *select_lex) { - single_value_transformer(select_lex, left_expr, - &Item_bool_func2::eq_creator); + if (left_expr->cols() == 1) + single_value_transformer(select_lex, left_expr, + &Item_bool_func2::eq_creator); + else + row_value_transformer(select_lex, left_expr); } void Item_allany_subselect::select_transformer(st_select_lex *select_lex) @@ -509,31 +649,85 @@ int subselect_union_engine::prepare() return unit->prepare(thd, result); } -void subselect_single_select_engine::fix_length_and_dec() +static Item_result set_row(SELECT_LEX *select_lex, Item * item, + Item_cache **row) { + Item_result res_type= STRING_RESULT; + Item *sel_item; List_iterator_fast<Item> li(select_lex->item_list); - Item *sel_item= li++; - item->max_length= sel_item->max_length; - res_type= sel_item->result_type(); - item->decimals= sel_item->decimals; + for (uint i= 0; (sel_item= li++); i++) + { + item->max_length= sel_item->max_length; + res_type= sel_item->result_type(); + item->decimals= sel_item->decimals; + if (row) + { + if (!(row[i]= Item_cache::get_cache(res_type))) + { + my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0)); + current_thd->fatal_error= 1; + return STRING_RESULT; // we should return something + } + row[i]->set_len_n_dec(sel_item->max_length, sel_item->decimals); + } + } + if (select_lex->item_list.elements > 1) + res_type= ROW_RESULT; + return res_type; } -void subselect_union_engine::fix_length_and_dec() +void subselect_single_select_engine::fix_length_and_dec(Item_cache **row) { - uint32 mlen= 0, len; - Item *sel_item= 0; - for (SELECT_LEX *sl= unit->first_select(); sl; sl= sl->next_select()) + DBUG_ASSERT(row || select_lex->item_list.elements==1); + res_type= set_row(select_lex, item, row); +} + +void subselect_union_engine::fix_length_and_dec(Item_cache **row) +{ + DBUG_ASSERT(row || unit->first_select()->item_list.elements==1); + + if (unit->first_select()->item_list.elements == 1) { - List_iterator_fast<Item> li(sl->item_list); - Item *s_item= li++; - if ((len= s_item->max_length)) - mlen= len; - if (!sel_item) - sel_item= s_item; + uint32 mlen= 0, len; + Item *sel_item= 0; + for (SELECT_LEX *sl= unit->first_select(); sl; sl= sl->next_select()) + { + List_iterator_fast<Item> li(sl->item_list); + Item *s_item= li++; + if ((len= s_item->max_length) > mlen) + mlen= len; + if (!sel_item) + sel_item= s_item; + } + item->max_length= mlen; + res_type= sel_item->result_type(); + item->decimals= sel_item->decimals; + if (row) + { + if (!(row[0]= Item_cache::get_cache(res_type))) + { + my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0)); + current_thd->fatal_error= 1; + return; + } + row[0]->set_len_n_dec(mlen, sel_item->decimals); + } + } + else + { + SELECT_LEX *sl= unit->first_select(); + res_type= set_row(sl, item, row); + for(sl= sl->next_select(); sl; sl->next_select()) + { + List_iterator_fast<Item> li(sl->item_list); + Item *sel_item; + for (uint i= 0; (sel_item= li++); i++) + { + if (sel_item->max_length > row[i]->max_length) + row[i]->max_length= sel_item->max_length; + } + } } - item->max_length= mlen; - res_type= sel_item->result_type(); - item->decimals= sel_item->decimals; } int subselect_single_select_engine::exec() |