summaryrefslogtreecommitdiff
path: root/sql/item_subselect.cc
diff options
context:
space:
mode:
authorunknown <bell@sanja.is.com.ua>2002-12-25 11:09:19 +0200
committerunknown <bell@sanja.is.com.ua>2002-12-25 11:09:19 +0200
commite10a32679096459ee0695d07cd4ae210e21ba227 (patch)
tree00c3c7c7800c85be561cb5d2b820e194ee9bd7f9 /sql/item_subselect.cc
parent4abcd967bad4f54181ab6710e1a4236aaeb9c370 (diff)
parenta05b0f087c02eb7165a26e531f5e4cc34db0b173 (diff)
downloadmariadb-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.cc282
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()