row IN subselects (SCRUM)
mysql-test/r/subselect.result: test of row IN subslect mysql-test/t/subselect.test: test of row IN subslect sql/item.cc: New helper Item - reference on item list by number cache item for row sql/item.h: layout fixed New helper Item - reference on item list by number cache item for row sql/item_cmpfunc.cc: changed Item_in_optimizer to be able work with row sql/item_cmpfunc.h: changed Item_in_optimizer to be able work with row sql/item_row.cc: Fixed row Item to be compatible with row subselect sql/item_row.h: Fixed row Item to be compatible with row subselect sql/item_subselect.cc: changed name of class to corerectly reflex its function row IN subselect sql/item_subselect.h: changed name of class to corerectly reflex its function row IN subselect sql/sql_class.cc: changed name of class to corerectly reflex its function sql/sql_class.h: changed name of class to corerectly reflex its function sql/sql_yacc.yy: changed name of class to corerectly reflex its function
This commit is contained in:
parent
900a86f631
commit
a05b0f087c
@ -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
|
|||||||
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;
|
||||||
|
109
sql/item.cc
109
sql/item.cc
@ -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)
|
|||||||
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()
|
|||||||
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
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
70
sql/item.h
70
sql/item.h
@ -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:
|
|||||||
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:
|
|||||||
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:
|
|||||||
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()
|
|||||||
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,
|
|||||||
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;
|
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;
|
||||||
|
}
|
||||||
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)
|
|||||||
{
|
{
|
||||||
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
|
|||||||
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)
|
|||||||
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()
|
|||||||
}
|
}
|
||||||
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:
|
|||||||
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
|
|||||||
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()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
|||||||
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()
|
|||||||
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 ()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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 ()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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,
|
|||||||
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()
|
|||||||
{
|
{
|
||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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:
|
|||||||
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:
|
|||||||
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:
|
|||||||
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:
|
|||||||
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)
|
|||||||
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:
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* 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);
|
|||||||
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:
|
|||||||
$$= 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:
|
|||||||
/* 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());
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user