Commit b63f2303 authored by bell@sanja.is.com.ua's avatar bell@sanja.is.com.ua

row IN subselects (SCRUM)

parent 54c7afd2
...@@ -773,3 +773,34 @@ a (select a,b,c from t1 where t1.a=t2.a) = ROW(a,4,'c') (select c from t1 where ...@@ -773,3 +773,34 @@ a (select a,b,c from t1 where t1.a=t2.a) = ROW(a,4,'c') (select c from t1 where
2 0 b 2 0 b
NULL NULL NULL NULL NULL NULL
drop table t1,t2; drop table t1,t2;
drop table if exists t;
create table t (a int, b real, c varchar(10));
insert into t values (1, 1, 'a'), (2,2,'b'), (NULL, 2, 'b');
select ROW(1, 1, 'a') IN (select a,b,c from t);
ROW(1, 1, 'a') IN (select a,b,c from t)
1
select ROW(1, 2, 'a') IN (select a,b,c from t);
ROW(1, 2, 'a') IN (select a,b,c from t)
NULL
select ROW(1, 1, 'a') IN (select b,a,c from t);
ROW(1, 1, 'a') IN (select b,a,c from t)
1
select ROW(1, 1, 'a') IN (select a,b,c from t where a is not null);
ROW(1, 1, 'a') IN (select a,b,c from t where a is not null)
1
select ROW(1, 2, 'a') IN (select a,b,c from t where a is not null);
ROW(1, 2, 'a') IN (select a,b,c from t where a is not null)
0
select ROW(1, 1, 'a') IN (select b,a,c from t where a is not null);
ROW(1, 1, 'a') IN (select b,a,c from t where a is not null)
1
select ROW(1, 1, 'a') IN (select a,b,c from t where c='b' or c='a');
ROW(1, 1, 'a') IN (select a,b,c from t where c='b' or c='a')
1
select ROW(1, 2, 'a') IN (select a,b,c from t where c='b' or c='a');
ROW(1, 2, 'a') IN (select a,b,c from t where c='b' or c='a')
NULL
select ROW(1, 1, 'a') IN (select b,a,c from t where c='b' or c='a');
ROW(1, 1, 'a') IN (select b,a,c from t where c='b' or c='a')
1
drop table if exists t;
...@@ -434,3 +434,17 @@ select a, (select a,b,c from t1 where t1.a=t2.a) = ROW(a,2,'a'),(select c from t ...@@ -434,3 +434,17 @@ select a, (select a,b,c from t1 where t1.a=t2.a) = ROW(a,2,'a'),(select c from t
select a, (select a,b,c from t1 where t1.a=t2.a) = ROW(a,3,'b'),(select c from t1 where a=t2.a) from t2; select a, (select a,b,c from t1 where t1.a=t2.a) = ROW(a,3,'b'),(select c from t1 where a=t2.a) from t2;
select a, (select a,b,c from t1 where t1.a=t2.a) = ROW(a,4,'c'),(select c from t1 where a=t2.a) from t2; select a, (select a,b,c from t1 where t1.a=t2.a) = ROW(a,4,'c'),(select c from t1 where a=t2.a) from t2;
drop table t1,t2; drop table t1,t2;
drop table if exists t;
create table t (a int, b real, c varchar(10));
insert into t values (1, 1, 'a'), (2,2,'b'), (NULL, 2, 'b');
select ROW(1, 1, 'a') IN (select a,b,c from t);
select ROW(1, 2, 'a') IN (select a,b,c from t);
select ROW(1, 1, 'a') IN (select b,a,c from t);
select ROW(1, 1, 'a') IN (select a,b,c from t where a is not null);
select ROW(1, 2, 'a') IN (select a,b,c from t where a is not null);
select ROW(1, 1, 'a') IN (select b,a,c from t where a is not null);
select ROW(1, 1, 'a') IN (select a,b,c from t where c='b' or c='a');
select ROW(1, 2, 'a') IN (select a,b,c from t where c='b' or c='a');
select ROW(1, 1, 'a') IN (select b,a,c from t where c='b' or c='a');
drop table if exists t;
...@@ -498,6 +498,27 @@ bool Item_asterisk_remover::fix_fields(THD *thd, ...@@ -498,6 +498,27 @@ bool Item_asterisk_remover::fix_fields(THD *thd,
DBUG_RETURN(res); DBUG_RETURN(res);
} }
bool Item_ref_on_list_position::fix_fields(THD *thd,
struct st_table_list *tables,
Item ** reference)
{
ref= 0;
List_iterator<Item> li(list);
Item *item;
uint i= 0;
for (; (item= li++) && i < pos; i++);
if (i == pos)
{
ref= li.ref();
return Item_ref_null_helper::fix_fields(thd, tables, reference);
}
else
{
my_error(ER_CARDINALITY_COL, MYF(0), pos);
return 1;
}
}
double Item_ref_null_helper::val() double Item_ref_null_helper::val()
{ {
double tmp= (*ref)->val_result(); double tmp= (*ref)->val_result();
...@@ -1196,6 +1217,8 @@ Item_cache* Item_cache::get_cache(Item_result type) ...@@ -1196,6 +1217,8 @@ Item_cache* Item_cache::get_cache(Item_result type)
return new Item_cache_real(); return new Item_cache_real();
case STRING_RESULT: case STRING_RESULT:
return new Item_cache_str(); return new Item_cache_str();
case ROW_RESULT:
return new Item_cache_row();
default: default:
// should never be in real life // should never be in real life
DBUG_ASSERT(0); DBUG_ASSERT(0);
...@@ -1241,6 +1264,92 @@ longlong Item_cache_str::val_int() ...@@ -1241,6 +1264,92 @@ longlong Item_cache_str::val_int()
return (longlong)0; return (longlong)0;
} }
bool Item_cache_row::allocate(uint num)
{
n= num;
THD *thd= current_thd;
if (!(values= (Item_cache **) thd->calloc(sizeof(Item_cache *)*n)))
{
my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
thd->fatal_error= 1;
return 1;
}
return 0;
}
bool Item_cache_row::setup(Item * item)
{
if (!values && allocate(item->cols()))
return 1;
for(uint i= 0; i < n; i++)
{
if (!(values[i]= Item_cache::get_cache(item->el(i)->result_type())))
{
my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
current_thd->fatal_error= 1;
return 1;
}
values[i]->setup(item->el(i));
}
return 0;
}
void Item_cache_row::store(Item * item)
{
null_value= 0;
item->bring_value();
for(uint i= 0; i < n; i++)
{
values[i]->store(item->el(i));
null_value|= values[i]->null_value;
}
}
void Item_cache_row::illegal_method_call(const char *method)
{
DBUG_ENTER("Item_cache_row::illegal_method_call");
DBUG_PRINT("error", ("!!! %s method was called for row item", method));
DBUG_ASSERT(0);
my_error(ER_CARDINALITY_COL, MYF(0), 1);
DBUG_VOID_RETURN;
}
bool Item_cache_row::check_cols(uint c)
{
if (c != n)
{
my_error(ER_CARDINALITY_COL, MYF(0), c);
return 1;
}
return 0;
}
bool Item_cache_row::null_inside()
{
for (uint i= 0; i < n; i++)
{
if (values[i]->cols() > 1)
{
if (values[i]->null_inside())
return 1;
}
else
{
values[i]->val_int();
if (values[i]->null_value)
return 1;
}
}
return 0;
}
void Item_cache_row::bring_value()
{
for (uint i= 0; i < n; i++)
values[i]->bring_value();
return;
}
/***************************************************************************** /*****************************************************************************
** Instantiate templates ** Instantiate templates
*****************************************************************************/ *****************************************************************************/
......
...@@ -501,7 +501,7 @@ protected: ...@@ -501,7 +501,7 @@ protected:
Item_in_subselect* owner; Item_in_subselect* owner;
public: public:
Item_ref_null_helper(Item_in_subselect* master, Item **item, Item_ref_null_helper(Item_in_subselect* master, Item **item,
char *table_name_par,char *field_name_par): char *table_name_par, char *field_name_par):
Item_ref(item, table_name_par, field_name_par), owner(master) {} Item_ref(item, table_name_par, field_name_par), owner(master) {}
double val(); double val();
longlong val_int(); longlong val_int();
...@@ -509,6 +509,24 @@ public: ...@@ -509,6 +509,24 @@ public:
bool get_date(TIME *ltime, bool fuzzydate); bool get_date(TIME *ltime, bool fuzzydate);
}; };
/*
Used to find item in list of select items after '*' items processing.
*/
class Item_ref_on_list_position: public Item_ref_null_helper
{
protected:
List<Item> &list;
uint pos;
public:
Item_ref_on_list_position(Item_in_subselect* master,
List<Item> &li, uint num,
char *table_name, char *field_name):
Item_ref_null_helper(master, 0, table_name, field_name),
list(li), pos(num) {}
bool fix_fields(THD *, struct st_table_list *, Item ** ref);
};
/* /*
To resolve '*' field moved to condition To resolve '*' field moved to condition
and register NULL values and register NULL values
...@@ -642,6 +660,8 @@ public: ...@@ -642,6 +660,8 @@ public:
class Item_cache: public Item class Item_cache: public Item
{ {
public: public:
virtual bool allocate(uint i) { return 0; };
virtual bool setup(Item *) { return 0; };
virtual void store(Item *)= 0; virtual void store(Item *)= 0;
void set_len_n_dec(uint32 max_len, uint8 dec) void set_len_n_dec(uint32 max_len, uint8 dec)
{ {
...@@ -705,6 +725,54 @@ public: ...@@ -705,6 +725,54 @@ public:
CHARSET_INFO *charset() const { return value->charset(); }; CHARSET_INFO *charset() const { return value->charset(); };
}; };
class Item_cache_row: public Item_cache
{
Item_cache **values;
uint n;
public:
Item_cache_row(): values(0), n(2) { fixed= 1; null_value= 1; }
/*
'allocate' used only in row transformer, to preallocate space for row
cache.
*/
bool allocate(uint num);
/*
'setup' is needed only by row => it not called by simple row subselect
(only by IN subselect (in subselect optimizer))
*/
bool setup(Item *item);
void store(Item *item);
void illegal_method_call(const char *);
void make_field(Send_field *)
{
illegal_method_call((const char*)"make_field");
};
double val()
{
illegal_method_call((const char*)"val");
return 0;
};
longlong val_int()
{
illegal_method_call((const char*)"val_int");
return 0;
};
String *val_str(String *)
{
illegal_method_call((const char*)"val_str");
return 0;
};
enum Item_result result_type() const { return ROW_RESULT; }
uint cols() { return n; }
Item* el(uint i) { return values[i]; }
Item** addr(uint i) { return (Item **) (values + i); }
bool check_cols(uint c);
bool null_inside();
void bring_value();
};
extern Item_buff *new_Item_buff(Item *item); extern Item_buff *new_Item_buff(Item *item);
extern Item_result item_cmp_type(Item_result a,Item_result b); extern Item_result item_cmp_type(Item_result a,Item_result b);
extern Item *resolve_const_item(Item *item,Item *cmp_item); extern Item *resolve_const_item(Item *item,Item *cmp_item);
......
...@@ -274,12 +274,19 @@ int Arg_comparator::compare_e_row() ...@@ -274,12 +274,19 @@ int Arg_comparator::compare_e_row()
return 1; return 1;
} }
bool Item_in_optimizer::preallocate_row()
{
if ((cache= Item_cache::get_cache(ROW_RESULT)))
return 0;
my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
current_thd->fatal_error= 1;
return 1;
}
bool Item_in_optimizer::fix_fields(THD *thd, struct st_table_list *tables, bool Item_in_optimizer::fix_fields(THD *thd, struct st_table_list *tables,
Item ** ref) Item ** ref)
{ {
if (args[0]->fix_fields(thd, tables, args))
if (args[0]->check_cols(allowed_arg_cols) ||
args[0]->fix_fields(thd, tables, args))
return 1; return 1;
if (args[0]->maybe_null) if (args[0]->maybe_null)
maybe_null=1; maybe_null=1;
...@@ -288,15 +295,21 @@ bool Item_in_optimizer::fix_fields(THD *thd, struct st_table_list *tables, ...@@ -288,15 +295,21 @@ bool Item_in_optimizer::fix_fields(THD *thd, struct st_table_list *tables,
with_sum_func= args[0]->with_sum_func; with_sum_func= args[0]->with_sum_func;
used_tables_cache= args[0]->used_tables(); used_tables_cache= args[0]->used_tables();
const_item_cache= args[0]->const_item(); const_item_cache= args[0]->const_item();
if (!(cache= Item_cache::get_cache(args[0]->result_type()))) if (!cache && !(cache= Item_cache::get_cache(args[0]->result_type())))
{ {
my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0)); my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
thd->fatal_error= 1; thd->fatal_error= 1;
return 1; return 1;
} }
if (args[1]->check_cols(allowed_arg_cols) || cache->setup(args[0]);
args[1]->fix_fields(thd, tables, args)) if (args[1]->fix_fields(thd, tables, args))
return 1;
Item_in_subselect * sub= (Item_in_subselect *)args[1];
if (args[0]->cols() != sub->engine->cols())
{
my_error(ER_CARDINALITY_COL, MYF(0), args[0]->cols());
return 1; return 1;
}
if (args[1]->maybe_null) if (args[1]->maybe_null)
maybe_null=1; maybe_null=1;
with_sum_func= with_sum_func || args[1]->with_sum_func; with_sum_func= with_sum_func || args[1]->with_sum_func;
...@@ -1215,7 +1228,7 @@ void cmp_item_row::store_value(Item *item) ...@@ -1215,7 +1228,7 @@ void cmp_item_row::store_value(Item *item)
{ {
THD *thd= current_thd; THD *thd= current_thd;
n= item->cols(); n= item->cols();
if ((comparators= (cmp_item **) thd->alloc(sizeof(cmp_item *)*n))) if ((comparators= (cmp_item **) thd->calloc(sizeof(cmp_item *)*n)))
{ {
item->bring_value(); item->bring_value();
item->null_value= 0; item->null_value= 0;
......
...@@ -91,14 +91,15 @@ class Item_in_optimizer: public Item_bool_func ...@@ -91,14 +91,15 @@ class Item_in_optimizer: public Item_bool_func
protected: protected:
Item_cache *cache; Item_cache *cache;
public: public:
Item_in_optimizer(Item *a,Item *b): Item_in_optimizer(Item *a, Item_in_subselect *b):
Item_bool_func(a,b), cache(0) {} Item_bool_func(a, (Item *)b), cache(0) {}
// used by row in transformer
bool preallocate_row();
bool fix_fields(THD *, struct st_table_list *, Item **); bool fix_fields(THD *, struct st_table_list *, Item **);
bool is_null(); bool is_null();
longlong val_int(); longlong val_int();
Item **get_cache() { return (Item**)&cache; } Item_cache **get_cache() { return &cache; }
}; };
class Item_bool_func2 :public Item_int_func class Item_bool_func2 :public Item_int_func
......
...@@ -41,7 +41,7 @@ void Item_row::illegal_method_call(const char *method) ...@@ -41,7 +41,7 @@ void Item_row::illegal_method_call(const char *method)
DBUG_ENTER("Item_row::illegal_method_call"); DBUG_ENTER("Item_row::illegal_method_call");
DBUG_PRINT("error", ("!!! %s method was called for row item", method)); DBUG_PRINT("error", ("!!! %s method was called for row item", method));
DBUG_ASSERT(0); DBUG_ASSERT(0);
my_error(ER_CARDINALITY_COL, MYF(0), arg_count); my_error(ER_CARDINALITY_COL, MYF(0), 1);
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
...@@ -100,3 +100,10 @@ bool Item_row::null_inside() ...@@ -100,3 +100,10 @@ bool Item_row::null_inside()
} }
return 0; return 0;
} }
void Item_row::bring_value()
{
for (uint i= 0; i < arg_count; i++)
items[i]->bring_value();
return;
}
...@@ -70,4 +70,5 @@ public: ...@@ -70,4 +70,5 @@ public:
Item** addr(uint i) { return items + i; } Item** addr(uint i) { return items + i; }
bool check_cols(uint c); bool check_cols(uint c);
bool null_inside(); bool null_inside();
void bring_value();
}; };
...@@ -127,36 +127,36 @@ inline table_map Item_subselect::used_tables() const ...@@ -127,36 +127,36 @@ inline table_map Item_subselect::used_tables() const
return (table_map) engine->depended() ? 1L : 0L; 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): st_select_lex *select_lex):
Item_subselect(), value(0) Item_subselect(), value(0)
{ {
DBUG_ENTER("Item_singleval_subselect::Item_singleval_subselect"); DBUG_ENTER("Item_singlerow_subselect::Item_singlerow_subselect");
init(thd, select_lex, new select_singleval_subselect(this)); init(thd, select_lex, new select_singlerow_subselect(this));
max_columns= 1; max_columns= 1;
maybe_null= 1; maybe_null= 1;
max_columns= UINT_MAX; max_columns= UINT_MAX;
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
void Item_singleval_subselect::reset() void Item_singlerow_subselect::reset()
{ {
null_value= 1; null_value= 1;
if (value) if (value)
value->null_value= 1; value->null_value= 1;
} }
void Item_singleval_subselect::store(uint i, Item *item) void Item_singlerow_subselect::store(uint i, Item *item)
{ {
row[i]->store(item); row[i]->store(item);
} }
enum Item_result Item_singleval_subselect::result_type() const enum Item_result Item_singlerow_subselect::result_type() const
{ {
return engine->type(); return engine->type();
} }
void Item_singleval_subselect::fix_length_and_dec() void Item_singlerow_subselect::fix_length_and_dec()
{ {
if ((max_columns= engine->cols()) == 1) if ((max_columns= engine->cols()) == 1)
{ {
...@@ -182,12 +182,12 @@ void Item_singleval_subselect::fix_length_and_dec() ...@@ -182,12 +182,12 @@ void Item_singleval_subselect::fix_length_and_dec()
} }
} }
uint Item_singleval_subselect::cols() uint Item_singlerow_subselect::cols()
{ {
return engine->cols(); return engine->cols();
} }
bool Item_singleval_subselect::check_cols(uint c) bool Item_singlerow_subselect::check_cols(uint c)
{ {
if (c != engine->cols()) if (c != engine->cols())
{ {
...@@ -197,7 +197,7 @@ bool Item_singleval_subselect::check_cols(uint c) ...@@ -197,7 +197,7 @@ bool Item_singleval_subselect::check_cols(uint c)
return 0; return 0;
} }
bool Item_singleval_subselect::null_inside() bool Item_singlerow_subselect::null_inside()
{ {
for (uint i= 0; i < max_columns ; i++) for (uint i= 0; i < max_columns ; i++)
{ {
...@@ -207,12 +207,12 @@ bool Item_singleval_subselect::null_inside() ...@@ -207,12 +207,12 @@ bool Item_singleval_subselect::null_inside()
return 0; return 0;
} }
void Item_singleval_subselect::bring_value() void Item_singlerow_subselect::bring_value()
{ {
engine->exec(); engine->exec();
} }
double Item_singleval_subselect::val () double Item_singlerow_subselect::val ()
{ {
if (!engine->exec() && !value->null_value) if (!engine->exec() && !value->null_value)
{ {
...@@ -226,7 +226,7 @@ double Item_singleval_subselect::val () ...@@ -226,7 +226,7 @@ double Item_singleval_subselect::val ()
} }
} }
longlong Item_singleval_subselect::val_int () longlong Item_singlerow_subselect::val_int ()
{ {
if (!engine->exec() && !value->null_value) if (!engine->exec() && !value->null_value)
{ {
...@@ -240,7 +240,7 @@ longlong Item_singleval_subselect::val_int () ...@@ -240,7 +240,7 @@ longlong Item_singleval_subselect::val_int ()
} }
} }
String *Item_singleval_subselect::val_str (String *str) String *Item_singlerow_subselect::val_str (String *str)
{ {
if (!engine->exec() && !value->null_value) if (!engine->exec() && !value->null_value)
{ {
...@@ -293,7 +293,7 @@ Item_allany_subselect::Item_allany_subselect(THD *thd, Item * left_exp, ...@@ -293,7 +293,7 @@ Item_allany_subselect::Item_allany_subselect(THD *thd, Item * left_exp,
left_expr= left_exp; left_expr= left_exp;
func= f; func= f;
init(thd, select_lex, new select_exists_subselect(this)); init(thd, select_lex, new select_exists_subselect(this));
max_columns= UINT_MAX; max_columns= 1;
reset(); reset();
// We need only 1 row to determinate existence // We need only 1 row to determinate existence
select_lex->master_unit()->global_parameters->select_limit= 1; select_lex->master_unit()->global_parameters->select_limit= 1;
...@@ -305,6 +305,7 @@ void Item_exists_subselect::fix_length_and_dec() ...@@ -305,6 +305,7 @@ void Item_exists_subselect::fix_length_and_dec()
{ {
decimals= 0; decimals= 0;
max_length= 1; max_length= 1;
max_columns= engine->cols();
} }
double Item_exists_subselect::val () double Item_exists_subselect::val ()
...@@ -409,7 +410,7 @@ void Item_in_subselect::single_value_transformer(st_select_lex *select_lex, ...@@ -409,7 +410,7 @@ 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 As far as Item_ref_in_optimizer do not substitude itself on fix_fields
we can use same item for all selects. we can use same item for all selects.
*/ */
Item *expr= new Item_ref(optimizer->get_cache(), Item *expr= new Item_ref((Item**)optimizer->get_cache(),
(char *)"<no matter>", (char *)"<no matter>",
(char*)"<left expr>"); (char*)"<left expr>");
select_lex->master_unit()->dependent= 1; select_lex->master_unit()->dependent= 1;
...@@ -440,7 +441,7 @@ void Item_in_subselect::single_value_transformer(st_select_lex *select_lex, ...@@ -440,7 +441,7 @@ void Item_in_subselect::single_value_transformer(st_select_lex *select_lex,
sl->having= item; sl->having= item;
else else
if (sl->where) if (sl->where)
sl->where= new Item_cond_and(sl->having, item); sl->where= new Item_cond_and(sl->where, item);
else else
sl->where= item; sl->where= item;
} }
...@@ -498,10 +499,68 @@ void Item_in_subselect::single_value_transformer(st_select_lex *select_lex, ...@@ -498,10 +499,68 @@ void Item_in_subselect::single_value_transformer(st_select_lex *select_lex,
DBUG_VOID_RETURN; 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) void Item_in_subselect::select_transformer(st_select_lex *select_lex)
{ {
single_value_transformer(select_lex, left_expr, if (left_expr->cols() == 1)
&Item_bool_func2::eq_creator); 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) void Item_allany_subselect::select_transformer(st_select_lex *select_lex)
......
...@@ -86,18 +86,19 @@ public: ...@@ -86,18 +86,19 @@ public:
bool check_loop(uint id); bool check_loop(uint id);
friend class select_subselect; friend class select_subselect;
friend class Item_in_optimizer;
}; };
/* single value subselect */ /* single value subselect */
class Item_cache; class Item_cache;
class Item_singleval_subselect :public Item_subselect class Item_singlerow_subselect :public Item_subselect
{ {
protected: protected:
Item_cache *value, **row; Item_cache *value, **row;
public: public:
Item_singleval_subselect(THD *thd, st_select_lex *select_lex); Item_singlerow_subselect(THD *thd, st_select_lex *select_lex);
Item_singleval_subselect(Item_singleval_subselect *item): Item_singlerow_subselect(Item_singlerow_subselect *item):
Item_subselect(item) Item_subselect(item)
{ {
value= item->value; value= item->value;
...@@ -109,7 +110,7 @@ public: ...@@ -109,7 +110,7 @@ public:
double val(); double val();
longlong val_int (); longlong val_int ();
String *val_str (String *); String *val_str (String *);
Item *new_item() { return new Item_singleval_subselect(this); } Item *new_item() { return new Item_singlerow_subselect(this); }
enum Item_result result_type() const; enum Item_result result_type() const;
void fix_length_and_dec(); void fix_length_and_dec();
...@@ -120,7 +121,7 @@ public: ...@@ -120,7 +121,7 @@ public:
bool null_inside(); bool null_inside();
void bring_value(); void bring_value();
friend class select_singleval_subselect; friend class select_singlerow_subselect;
}; };
/* exists subselect */ /* exists subselect */
...@@ -174,6 +175,7 @@ public: ...@@ -174,6 +175,7 @@ public:
virtual void select_transformer(st_select_lex *select_lex); virtual void select_transformer(st_select_lex *select_lex);
void single_value_transformer(st_select_lex *select_lex, void single_value_transformer(st_select_lex *select_lex,
Item *left_expr, compare_func_creator func); Item *left_expr, compare_func_creator func);
void row_value_transformer(st_select_lex *select_lex, Item *left_expr);
longlong val_int(); longlong val_int();
double val(); double val();
String *val_str(String*); String *val_str(String*);
......
...@@ -916,10 +916,10 @@ select_subselect::select_subselect(Item_subselect *item) ...@@ -916,10 +916,10 @@ select_subselect::select_subselect(Item_subselect *item)
this->item=item; this->item=item;
} }
bool select_singleval_subselect::send_data(List<Item> &items) bool select_singlerow_subselect::send_data(List<Item> &items)
{ {
DBUG_ENTER("select_singleval_subselect::send_data"); DBUG_ENTER("select_singlerow_subselect::send_data");
Item_singleval_subselect *it= (Item_singleval_subselect *)item; Item_singlerow_subselect *it= (Item_singlerow_subselect *)item;
if (it->assigned()) if (it->assigned())
{ {
my_message(ER_SUBSELECT_NO_1_ROW, ER(ER_SUBSELECT_NO_1_ROW), MYF(0)); my_message(ER_SUBSELECT_NO_1_ROW, ER(ER_SUBSELECT_NO_1_ROW), MYF(0));
......
...@@ -824,10 +824,10 @@ public: ...@@ -824,10 +824,10 @@ public:
}; };
/* Single value subselect interface class */ /* Single value subselect interface class */
class select_singleval_subselect :public select_subselect class select_singlerow_subselect :public select_subselect
{ {
public: public:
select_singleval_subselect(Item_subselect *item):select_subselect(item){} select_singlerow_subselect(Item_subselect *item):select_subselect(item){}
bool send_data(List<Item> &items); bool send_data(List<Item> &items);
}; };
......
...@@ -587,7 +587,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); ...@@ -587,7 +587,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
simple_ident select_item2 expr opt_expr opt_else sum_expr in_sum_expr simple_ident select_item2 expr opt_expr opt_else sum_expr in_sum_expr
table_wild opt_pad no_in_expr expr_expr simple_expr no_and_expr table_wild opt_pad no_in_expr expr_expr simple_expr no_and_expr
using_list expr_or_default set_expr_or_default using_list expr_or_default set_expr_or_default
param_marker singleval_subselect singleval_subselect_init param_marker singlerow_subselect singlerow_subselect_init
exists_subselect exists_subselect_init exists_subselect exists_subselect_init
%type <item_list> %type <item_list>
...@@ -2017,7 +2017,7 @@ simple_expr: ...@@ -2017,7 +2017,7 @@ simple_expr:
$$= new Item_row(*$5); $$= new Item_row(*$5);
} }
| EXISTS exists_subselect { $$= $2; } | EXISTS exists_subselect { $$= $2; }
| singleval_subselect { $$= $1; } | singlerow_subselect { $$= $1; }
| '{' ident expr '}' { $$= $3; } | '{' ident expr '}' { $$= $3; }
| MATCH ident_list_arg AGAINST '(' expr ')' | MATCH ident_list_arg AGAINST '(' expr ')'
{ Select->add_ftfunc_to_list((Item_func_match *) { Select->add_ftfunc_to_list((Item_func_match *)
...@@ -4487,17 +4487,17 @@ union_option: ...@@ -4487,17 +4487,17 @@ union_option:
/* empty */ {} /* empty */ {}
| ALL {Select->master_unit()->union_option= 1;}; | ALL {Select->master_unit()->union_option= 1;};
singleval_subselect: singlerow_subselect:
subselect_start singleval_subselect_init subselect_start singlerow_subselect_init
subselect_end subselect_end
{ {
$$= $2; $$= $2;
}; };
singleval_subselect_init: singlerow_subselect_init:
select_init2 select_init2
{ {
$$= new Item_singleval_subselect(YYTHD, $$= new Item_singlerow_subselect(YYTHD,
Lex->current_select->master_unit()-> Lex->current_select->master_unit()->
first_select()); first_select());
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment