support of simple row subselects (SCRUM)
mysql-test/r/subselect.result: test of simple row subselect fixed table droping mysql-test/t/subselect.test: test of simple row subselect fixed table dropimg sql/item.cc: Item_cache_str fixed to correctly store NULL and copy string value sql/item.h: Item_cache_str fixed to correctly store NULL and copy string value sql/item_cmpfunc.cc: support of simple row subselects sql/item_subselect.cc: support of simple row subselects sql/item_subselect.h: support of simple row subselects sql/sql_class.cc: support of simple row subselects
This commit is contained in:
parent
ea4f406baf
commit
86ccbe3727
@ -52,6 +52,54 @@ a
|
||||
SELECT (SELECT 1) as a FROM (SELECT 1) b WHERE (SELECT a) IS NOT NULL;
|
||||
a
|
||||
1
|
||||
SELECT (SELECT 1,2,3) = ROW(1,2,3);
|
||||
(SELECT 1,2,3) = ROW(1,2,3)
|
||||
1
|
||||
SELECT (SELECT 1,2,3) = ROW(1,2,1);
|
||||
(SELECT 1,2,3) = ROW(1,2,1)
|
||||
0
|
||||
SELECT (SELECT 1,2,3) < ROW(1,2,1);
|
||||
(SELECT 1,2,3) < ROW(1,2,1)
|
||||
0
|
||||
SELECT (SELECT 1,2,3) > ROW(1,2,1);
|
||||
(SELECT 1,2,3) > ROW(1,2,1)
|
||||
1
|
||||
SELECT (SELECT 1,2,3) = ROW(1,2,NULL);
|
||||
(SELECT 1,2,3) = ROW(1,2,NULL)
|
||||
NULL
|
||||
SELECT ROW(1,2,3) = (SELECT 1,2,3);
|
||||
ROW(1,2,3) = (SELECT 1,2,3)
|
||||
1
|
||||
SELECT ROW(1,2,3) = (SELECT 1,2,1);
|
||||
ROW(1,2,3) = (SELECT 1,2,1)
|
||||
0
|
||||
SELECT ROW(1,2,3) < (SELECT 1,2,1);
|
||||
ROW(1,2,3) < (SELECT 1,2,1)
|
||||
0
|
||||
SELECT ROW(1,2,3) > (SELECT 1,2,1);
|
||||
ROW(1,2,3) > (SELECT 1,2,1)
|
||||
1
|
||||
SELECT ROW(1,2,3) = (SELECT 1,2,NULL);
|
||||
ROW(1,2,3) = (SELECT 1,2,NULL)
|
||||
NULL
|
||||
SELECT (SELECT 1.5,2,'a') = ROW(1.5,2,'a');
|
||||
(SELECT 1.5,2,'a') = ROW(1.5,2,'a')
|
||||
1
|
||||
SELECT (SELECT 1.5,2,'a') = ROW(1.5,2,'b');
|
||||
(SELECT 1.5,2,'a') = ROW(1.5,2,'b')
|
||||
0
|
||||
SELECT (SELECT 1.5,2,'a') = ROW('b',2,'b');
|
||||
(SELECT 1.5,2,'a') = ROW('b',2,'b')
|
||||
0
|
||||
SELECT (SELECT 'b',2,'a') = ROW(1.5,2,'a');
|
||||
(SELECT 'b',2,'a') = ROW(1.5,2,'a')
|
||||
0
|
||||
SELECT (SELECT 1.5,2,'a') = ROW(1.5,'c','a');
|
||||
(SELECT 1.5,2,'a') = ROW(1.5,'c','a')
|
||||
0
|
||||
SELECT (SELECT 1.5,'c','a') = ROW(1.5,2,'a');
|
||||
(SELECT 1.5,'c','a') = ROW(1.5,2,'a')
|
||||
0
|
||||
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8;
|
||||
create table t1 (a int);
|
||||
create table t2 (a int, b int);
|
||||
@ -602,7 +650,7 @@ CREATE TABLE t1 (id int(11) default NULL, KEY id (id)) TYPE=MyISAM CHARSET=latin
|
||||
INSERT INTO t1 values (1),(1);
|
||||
UPDATE t SET id=(SELECT * FROM t1);
|
||||
Subselect returns more than 1 record
|
||||
drop table t;
|
||||
drop table t, t1;
|
||||
create table t (a int);
|
||||
insert into t values (1),(2),(3);
|
||||
select 1 IN (SELECT * from t);
|
||||
@ -705,3 +753,23 @@ select 10.5 > ANY (SELECT * from t);
|
||||
10.5 > ANY (SELECT * from t)
|
||||
1
|
||||
drop table t;
|
||||
create table t1 (a int, b int, c varchar(10));
|
||||
create table t2 (a int);
|
||||
insert into t1 values (1,2,'a'),(2,3,'b'),(3,4,'c');
|
||||
insert into t2 values (1),(2),(NULL);
|
||||
select a, (select a,b,c from t1 where t1.a=t2.a) = ROW(a,2,'a'),(select c from t1 where a=t2.a) from t2;
|
||||
a (select a,b,c from t1 where t1.a=t2.a) = ROW(a,2,'a') (select c from t1 where a=t2.a)
|
||||
1 1 a
|
||||
2 0 b
|
||||
NULL NULL NULL
|
||||
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;
|
||||
a (select a,b,c from t1 where t1.a=t2.a) = ROW(a,3,'b') (select c from t1 where a=t2.a)
|
||||
1 0 a
|
||||
2 1 b
|
||||
NULL NULL NULL
|
||||
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;
|
||||
a (select a,b,c from t1 where t1.a=t2.a) = ROW(a,4,'c') (select c from t1 where a=t2.a)
|
||||
1 0 a
|
||||
2 0 b
|
||||
NULL NULL NULL
|
||||
drop table t1,t2;
|
||||
|
@ -26,6 +26,22 @@ select (SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE(1));
|
||||
SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE((SELECT 1));
|
||||
SELECT (SELECT 1) as a FROM (SELECT 1) b WHERE (SELECT a) IS NULL;
|
||||
SELECT (SELECT 1) as a FROM (SELECT 1) b WHERE (SELECT a) IS NOT NULL;
|
||||
SELECT (SELECT 1,2,3) = ROW(1,2,3);
|
||||
SELECT (SELECT 1,2,3) = ROW(1,2,1);
|
||||
SELECT (SELECT 1,2,3) < ROW(1,2,1);
|
||||
SELECT (SELECT 1,2,3) > ROW(1,2,1);
|
||||
SELECT (SELECT 1,2,3) = ROW(1,2,NULL);
|
||||
SELECT ROW(1,2,3) = (SELECT 1,2,3);
|
||||
SELECT ROW(1,2,3) = (SELECT 1,2,1);
|
||||
SELECT ROW(1,2,3) < (SELECT 1,2,1);
|
||||
SELECT ROW(1,2,3) > (SELECT 1,2,1);
|
||||
SELECT ROW(1,2,3) = (SELECT 1,2,NULL);
|
||||
SELECT (SELECT 1.5,2,'a') = ROW(1.5,2,'a');
|
||||
SELECT (SELECT 1.5,2,'a') = ROW(1.5,2,'b');
|
||||
SELECT (SELECT 1.5,2,'a') = ROW('b',2,'b');
|
||||
SELECT (SELECT 'b',2,'a') = ROW(1.5,2,'a');
|
||||
SELECT (SELECT 1.5,2,'a') = ROW(1.5,'c','a');
|
||||
SELECT (SELECT 1.5,'c','a') = ROW(1.5,2,'a');
|
||||
|
||||
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8;
|
||||
create table t1 (a int);
|
||||
@ -363,7 +379,7 @@ CREATE TABLE t1 (id int(11) default NULL, KEY id (id)) TYPE=MyISAM CHARSET=latin
|
||||
INSERT INTO t1 values (1),(1);
|
||||
-- error 1240
|
||||
UPDATE t SET id=(SELECT * FROM t1);
|
||||
drop table t;
|
||||
drop table t, t1;
|
||||
|
||||
|
||||
#NULL test
|
||||
@ -409,3 +425,12 @@ select 10.5 > ALL (SELECT * from t);
|
||||
select 1.5 > ANY (SELECT * from t);
|
||||
select 10.5 > ANY (SELECT * from t);
|
||||
drop table t;
|
||||
|
||||
create table t1 (a int, b int, c varchar(10));
|
||||
create table t2 (a int);
|
||||
insert into t1 values (1,2,'a'),(2,3,'b'),(3,4,'c');
|
||||
insert into t2 values (1),(2),(NULL);
|
||||
select a, (select a,b,c from t1 where t1.a=t2.a) = ROW(a,2,'a'),(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;
|
||||
drop table t1,t2;
|
||||
|
54
sql/item.cc
54
sql/item.cc
@ -1217,6 +1217,60 @@ bool field_is_equal_to_item(Field *field,Item *item)
|
||||
return result == field->val_real();
|
||||
}
|
||||
|
||||
Item_cache* Item_cache::get_cache(Item_result type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case INT_RESULT:
|
||||
return new Item_cache_int();
|
||||
case REAL_RESULT:
|
||||
return new Item_cache_real();
|
||||
case STRING_RESULT:
|
||||
return new Item_cache_str();
|
||||
default:
|
||||
// should never be in real life
|
||||
DBUG_ASSERT(0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Item_cache_str::store(Item *item)
|
||||
{
|
||||
str_value.set(buffer, sizeof(buffer), item->charset());
|
||||
value= item->str_result(&str_value);
|
||||
if ((null_value= item->null_value))
|
||||
value= 0;
|
||||
else if (value != &str_value)
|
||||
{
|
||||
/*
|
||||
We copy string value to avoid changing value if 'item' is table field
|
||||
in queries like following (where t1.c is varchar):
|
||||
select a,
|
||||
(select a,b,c from t1 where t1.a=t2.a) = ROW(a,2,'a'),
|
||||
(select c from t1 where a=t2.a)
|
||||
from t2;
|
||||
*/
|
||||
str_value.copy(*value);
|
||||
value= &str_value;
|
||||
}
|
||||
|
||||
}
|
||||
double Item_cache_str::val()
|
||||
{
|
||||
if (value)
|
||||
return my_strntod(value->charset(), value->ptr(),
|
||||
value->length(), (char**)0);
|
||||
else
|
||||
return (double)0;
|
||||
}
|
||||
longlong Item_cache_str::val_int()
|
||||
{
|
||||
if (value)
|
||||
return my_strntoll(value->charset(), value->ptr(),
|
||||
value->length(), (char**) 0, 10);
|
||||
else
|
||||
return (longlong)0;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
** Instantiate templates
|
||||
|
26
sql/item.h
26
sql/item.h
@ -103,7 +103,9 @@ public:
|
||||
virtual Item** addr(uint i) { return 0; }
|
||||
virtual bool check_cols(uint c);
|
||||
// It is not row => null inside is impossible
|
||||
virtual bool null_inside() { return 0; };
|
||||
virtual bool null_inside() { return 0; }
|
||||
// used in row subselects to get value of elements
|
||||
virtual void bring_value() {}
|
||||
};
|
||||
|
||||
|
||||
@ -719,6 +721,7 @@ public:
|
||||
decimals= dec;
|
||||
}
|
||||
enum Type type() const { return CACHE_ITEM; }
|
||||
static Item_cache* get_cache(Item_result type);
|
||||
};
|
||||
|
||||
class Item_cache_int: public Item_cache
|
||||
@ -766,24 +769,9 @@ class Item_cache_str: public Item_cache
|
||||
public:
|
||||
Item_cache_str() { fixed= 1; null_value= 1; }
|
||||
|
||||
void store(Item *item)
|
||||
{
|
||||
str_value.set(buffer, sizeof(buffer), item->charset());
|
||||
value= item->str_result(&str_value);
|
||||
// TODO remove if str_value charset have no side effect for now
|
||||
str_value.set_charset(value->charset());
|
||||
null_value= item->null_value;
|
||||
}
|
||||
double val()
|
||||
{
|
||||
return my_strntod(value->charset(), value->ptr(),
|
||||
value->length(), (char**)0);
|
||||
}
|
||||
longlong val_int()
|
||||
{
|
||||
return my_strntoll(value->charset(), value->ptr(),
|
||||
value->length(), (char**) 0, 10);
|
||||
}
|
||||
void store(Item *item);
|
||||
double val();
|
||||
longlong val_int();
|
||||
String* val_str(String *) { return value; }
|
||||
enum Item_result result_type() const { return STRING_RESULT; }
|
||||
CHARSET_INFO *charset() const { return value->charset(); };
|
||||
|
@ -247,6 +247,8 @@ int Arg_comparator::compare_e_int()
|
||||
int Arg_comparator::compare_row()
|
||||
{
|
||||
int res= 0;
|
||||
(*a)->bring_value();
|
||||
(*b)->bring_value();
|
||||
uint n= (*a)->cols();
|
||||
for (uint i= 0; i<n; i++)
|
||||
{
|
||||
@ -261,6 +263,8 @@ int Arg_comparator::compare_row()
|
||||
int Arg_comparator::compare_e_row()
|
||||
{
|
||||
int res= 0;
|
||||
(*a)->bring_value();
|
||||
(*b)->bring_value();
|
||||
uint n= (*a)->cols();
|
||||
for (uint i= 0; i<n; i++)
|
||||
{
|
||||
@ -1219,6 +1223,7 @@ void cmp_item_row::store_value(Item *item)
|
||||
n= item->cols();
|
||||
if ((comparators= (cmp_item **) thd->alloc(sizeof(cmp_item *)*n)))
|
||||
{
|
||||
item->bring_value();
|
||||
item->null_value= 0;
|
||||
for (uint i=0; i < n; i++)
|
||||
if ((comparators[i]= cmp_item::get_comparator(item->el(i))))
|
||||
@ -1252,6 +1257,7 @@ void cmp_item_row::store_value_by_template(cmp_item *t, Item *item)
|
||||
n= tmpl->n;
|
||||
if ((comparators= (cmp_item **) sql_alloc(sizeof(cmp_item *)*n)))
|
||||
{
|
||||
item->bring_value();
|
||||
item->null_value= 0;
|
||||
for (uint i=0; i < n; i++)
|
||||
if ((comparators[i]= tmpl->comparators[i]->make_same()))
|
||||
@ -1284,6 +1290,7 @@ int cmp_item_row::cmp(Item *arg)
|
||||
return 1;
|
||||
}
|
||||
bool was_null= 0;
|
||||
arg->bring_value();
|
||||
for (uint i=0; i < n; i++)
|
||||
if (comparators[i]->cmp(arg->el(i)))
|
||||
{
|
||||
|
@ -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
|
||||
@ -130,6 +135,7 @@ Item_singleval_subselect::Item_singleval_subselect(THD *thd,
|
||||
init(thd, select_lex, new select_singleval_subselect(this));
|
||||
max_columns= 1;
|
||||
maybe_null= 1;
|
||||
max_columns= UINT_MAX;
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
@ -140,9 +146,9 @@ void Item_singleval_subselect::reset()
|
||||
value->null_value= 1;
|
||||
}
|
||||
|
||||
void Item_singleval_subselect::store(Item *item)
|
||||
void Item_singleval_subselect::store(uint i, Item *item)
|
||||
{
|
||||
value->store(item);
|
||||
row[i]->store(item);
|
||||
}
|
||||
|
||||
enum Item_result Item_singleval_subselect::result_type() const
|
||||
@ -152,29 +158,58 @@ enum Item_result Item_singleval_subselect::result_type() const
|
||||
|
||||
void Item_singleval_subselect::fix_length_and_dec()
|
||||
{
|
||||
engine->fix_length_and_dec();
|
||||
switch (engine->type())
|
||||
if ((max_columns= engine->cols()) == 1)
|
||||
{
|
||||
case INT_RESULT:
|
||||
value= new Item_cache_int();
|
||||
break;
|
||||
case REAL_RESULT:
|
||||
value= new Item_cache_real();
|
||||
break;
|
||||
case STRING_RESULT:
|
||||
value= new Item_cache_str();
|
||||
break;
|
||||
default:
|
||||
// should never be in real life
|
||||
DBUG_ASSERT(0);
|
||||
return;
|
||||
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;
|
||||
}
|
||||
value->set_len_n_dec(max_length, decimals);
|
||||
}
|
||||
|
||||
Item::Type Item_subselect::type() const
|
||||
uint Item_singleval_subselect::cols()
|
||||
{
|
||||
return SUBSELECT_ITEM;
|
||||
return engine->cols();
|
||||
}
|
||||
|
||||
bool Item_singleval_subselect::check_cols(uint c)
|
||||
{
|
||||
if (c != engine->cols())
|
||||
{
|
||||
my_error(ER_CARDINALITY_COL, MYF(0), c);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool Item_singleval_subselect::null_inside()
|
||||
{
|
||||
for (uint i= 0; i < max_columns ; i++)
|
||||
{
|
||||
if (row[i]->null_value)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Item_singleval_subselect::bring_value()
|
||||
{
|
||||
engine->exec();
|
||||
}
|
||||
|
||||
double Item_singleval_subselect::val ()
|
||||
@ -268,7 +303,7 @@ 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;
|
||||
}
|
||||
|
||||
@ -540,31 +575,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()
|
||||
|
@ -94,8 +94,7 @@ class Item_cache;
|
||||
class Item_singleval_subselect :public Item_subselect
|
||||
{
|
||||
protected:
|
||||
Item_cache *value;
|
||||
|
||||
Item_cache *value, **row;
|
||||
public:
|
||||
Item_singleval_subselect(THD *thd, st_select_lex *select_lex);
|
||||
Item_singleval_subselect(Item_singleval_subselect *item):
|
||||
@ -106,7 +105,7 @@ public:
|
||||
decimals= item->decimals;
|
||||
}
|
||||
void reset();
|
||||
void store(Item* item);
|
||||
void store(uint i, Item* item);
|
||||
double val();
|
||||
longlong val_int ();
|
||||
String *val_str (String *);
|
||||
@ -114,6 +113,13 @@ public:
|
||||
enum Item_result result_type() const;
|
||||
void fix_length_and_dec();
|
||||
|
||||
uint cols();
|
||||
Item* el(uint i) { return (Item*)row[i]; }
|
||||
Item** addr(uint i) { return (Item**)row + i; }
|
||||
bool check_cols(uint c);
|
||||
bool null_inside();
|
||||
void bring_value();
|
||||
|
||||
friend class select_singleval_subselect;
|
||||
};
|
||||
|
||||
@ -212,7 +218,7 @@ public:
|
||||
}
|
||||
|
||||
virtual int prepare()= 0;
|
||||
virtual void fix_length_and_dec()= 0;
|
||||
virtual void fix_length_and_dec(Item_cache** row)= 0;
|
||||
virtual int exec()= 0;
|
||||
virtual uint cols()= 0; /* return number of columnss in select */
|
||||
virtual bool depended()= 0; /* depended from outer select */
|
||||
@ -233,7 +239,7 @@ public:
|
||||
select_subselect *result,
|
||||
Item_subselect *item);
|
||||
int prepare();
|
||||
void fix_length_and_dec();
|
||||
void fix_length_and_dec(Item_cache** row);
|
||||
int exec();
|
||||
uint cols();
|
||||
bool depended();
|
||||
@ -250,7 +256,7 @@ public:
|
||||
select_subselect *result,
|
||||
Item_subselect *item);
|
||||
int prepare();
|
||||
void fix_length_and_dec();
|
||||
void fix_length_and_dec(Item_cache** row);
|
||||
int exec();
|
||||
uint cols();
|
||||
bool depended();
|
||||
|
@ -931,8 +931,9 @@ bool select_singleval_subselect::send_data(List<Item> &items)
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
List_iterator_fast<Item> li(items);
|
||||
Item *val_item= li++; // Only one (single value subselect)
|
||||
it->store(val_item);
|
||||
Item *val_item;
|
||||
for (uint i= 0; (val_item= li++); i++)
|
||||
it->store(i, val_item);
|
||||
it->assigned(1);
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user