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;
|
SELECT (SELECT 1) as a FROM (SELECT 1) b WHERE (SELECT a) IS NOT NULL;
|
||||||
a
|
a
|
||||||
1
|
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;
|
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8;
|
||||||
create table t1 (a int);
|
create table t1 (a int);
|
||||||
create table t2 (a int, b 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);
|
INSERT INTO t1 values (1),(1);
|
||||||
UPDATE t SET id=(SELECT * FROM t1);
|
UPDATE t SET id=(SELECT * FROM t1);
|
||||||
Subselect returns more than 1 record
|
Subselect returns more than 1 record
|
||||||
drop table t;
|
drop table t, t1;
|
||||||
create table t (a int);
|
create table t (a int);
|
||||||
insert into t values (1),(2),(3);
|
insert into t values (1),(2),(3);
|
||||||
select 1 IN (SELECT * from t);
|
select 1 IN (SELECT * from t);
|
||||||
@ -705,3 +753,23 @@ select 10.5 > ANY (SELECT * from t);
|
|||||||
10.5 > ANY (SELECT * from t)
|
10.5 > ANY (SELECT * from t)
|
||||||
1
|
1
|
||||||
drop table 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;
|
||||||
|
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 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 NULL;
|
||||||
SELECT (SELECT 1) as a FROM (SELECT 1) b WHERE (SELECT a) IS NOT 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;
|
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8;
|
||||||
create table t1 (a int);
|
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);
|
INSERT INTO t1 values (1),(1);
|
||||||
-- error 1240
|
-- error 1240
|
||||||
UPDATE t SET id=(SELECT * FROM t1);
|
UPDATE t SET id=(SELECT * FROM t1);
|
||||||
drop table t;
|
drop table t, t1;
|
||||||
|
|
||||||
|
|
||||||
#NULL test
|
#NULL test
|
||||||
@ -409,3 +425,12 @@ select 10.5 > ALL (SELECT * from t);
|
|||||||
select 1.5 > ANY (SELECT * from t);
|
select 1.5 > ANY (SELECT * from t);
|
||||||
select 10.5 > ANY (SELECT * from t);
|
select 10.5 > ANY (SELECT * from t);
|
||||||
drop table 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();
|
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
|
** Instantiate templates
|
||||||
|
26
sql/item.h
26
sql/item.h
@ -103,7 +103,9 @@ public:
|
|||||||
virtual Item** addr(uint i) { return 0; }
|
virtual Item** addr(uint i) { return 0; }
|
||||||
virtual bool check_cols(uint c);
|
virtual bool check_cols(uint c);
|
||||||
// It is not row => null inside is impossible
|
// 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;
|
decimals= dec;
|
||||||
}
|
}
|
||||||
enum Type type() const { return CACHE_ITEM; }
|
enum Type type() const { return CACHE_ITEM; }
|
||||||
|
static Item_cache* get_cache(Item_result type);
|
||||||
};
|
};
|
||||||
|
|
||||||
class Item_cache_int: public Item_cache
|
class Item_cache_int: public Item_cache
|
||||||
@ -766,24 +769,9 @@ class Item_cache_str: public Item_cache
|
|||||||
public:
|
public:
|
||||||
Item_cache_str() { fixed= 1; null_value= 1; }
|
Item_cache_str() { fixed= 1; null_value= 1; }
|
||||||
|
|
||||||
void store(Item *item)
|
void store(Item *item);
|
||||||
{
|
double val();
|
||||||
str_value.set(buffer, sizeof(buffer), item->charset());
|
longlong val_int();
|
||||||
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);
|
|
||||||
}
|
|
||||||
String* val_str(String *) { return value; }
|
String* val_str(String *) { return value; }
|
||||||
enum Item_result result_type() const { return STRING_RESULT; }
|
enum Item_result result_type() const { return STRING_RESULT; }
|
||||||
CHARSET_INFO *charset() const { return value->charset(); };
|
CHARSET_INFO *charset() const { return value->charset(); };
|
||||||
|
@ -247,6 +247,8 @@ int Arg_comparator::compare_e_int()
|
|||||||
int Arg_comparator::compare_row()
|
int Arg_comparator::compare_row()
|
||||||
{
|
{
|
||||||
int res= 0;
|
int res= 0;
|
||||||
|
(*a)->bring_value();
|
||||||
|
(*b)->bring_value();
|
||||||
uint n= (*a)->cols();
|
uint n= (*a)->cols();
|
||||||
for (uint i= 0; i<n; i++)
|
for (uint i= 0; i<n; i++)
|
||||||
{
|
{
|
||||||
@ -261,6 +263,8 @@ int Arg_comparator::compare_row()
|
|||||||
int Arg_comparator::compare_e_row()
|
int Arg_comparator::compare_e_row()
|
||||||
{
|
{
|
||||||
int res= 0;
|
int res= 0;
|
||||||
|
(*a)->bring_value();
|
||||||
|
(*b)->bring_value();
|
||||||
uint n= (*a)->cols();
|
uint n= (*a)->cols();
|
||||||
for (uint i= 0; i<n; i++)
|
for (uint i= 0; i<n; i++)
|
||||||
{
|
{
|
||||||
@ -1219,6 +1223,7 @@ void cmp_item_row::store_value(Item *item)
|
|||||||
n= item->cols();
|
n= item->cols();
|
||||||
if ((comparators= (cmp_item **) thd->alloc(sizeof(cmp_item *)*n)))
|
if ((comparators= (cmp_item **) thd->alloc(sizeof(cmp_item *)*n)))
|
||||||
{
|
{
|
||||||
|
item->bring_value();
|
||||||
item->null_value= 0;
|
item->null_value= 0;
|
||||||
for (uint i=0; i < n; i++)
|
for (uint i=0; i < n; i++)
|
||||||
if ((comparators[i]= cmp_item::get_comparator(item->el(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;
|
n= tmpl->n;
|
||||||
if ((comparators= (cmp_item **) sql_alloc(sizeof(cmp_item *)*n)))
|
if ((comparators= (cmp_item **) sql_alloc(sizeof(cmp_item *)*n)))
|
||||||
{
|
{
|
||||||
|
item->bring_value();
|
||||||
item->null_value= 0;
|
item->null_value= 0;
|
||||||
for (uint i=0; i < n; i++)
|
for (uint i=0; i < n; i++)
|
||||||
if ((comparators[i]= tmpl->comparators[i]->make_same()))
|
if ((comparators[i]= tmpl->comparators[i]->make_same()))
|
||||||
@ -1284,6 +1290,7 @@ int cmp_item_row::cmp(Item *arg)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
bool was_null= 0;
|
bool was_null= 0;
|
||||||
|
arg->bring_value();
|
||||||
for (uint i=0; i < n; i++)
|
for (uint i=0; i < n; i++)
|
||||||
if (comparators[i]->cmp(arg->el(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));
|
DBUG_RETURN(engine->check_loop(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Item::Type Item_subselect::type() const
|
||||||
|
{
|
||||||
|
return SUBSELECT_ITEM;
|
||||||
|
}
|
||||||
|
|
||||||
void Item_subselect::fix_length_and_dec()
|
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
|
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));
|
init(thd, select_lex, new select_singleval_subselect(this));
|
||||||
max_columns= 1;
|
max_columns= 1;
|
||||||
maybe_null= 1;
|
maybe_null= 1;
|
||||||
|
max_columns= UINT_MAX;
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,9 +146,9 @@ void Item_singleval_subselect::reset()
|
|||||||
value->null_value= 1;
|
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
|
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()
|
void Item_singleval_subselect::fix_length_and_dec()
|
||||||
{
|
{
|
||||||
engine->fix_length_and_dec();
|
if ((max_columns= engine->cols()) == 1)
|
||||||
switch (engine->type())
|
|
||||||
{
|
{
|
||||||
case INT_RESULT:
|
engine->fix_length_and_dec(row= &value);
|
||||||
value= new Item_cache_int();
|
if (!(value= Item_cache::get_cache(engine->type())))
|
||||||
break;
|
{
|
||||||
case REAL_RESULT:
|
my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
|
||||||
value= new Item_cache_real();
|
current_thd->fatal_error= 1;
|
||||||
break;
|
return;
|
||||||
case STRING_RESULT:
|
}
|
||||||
value= new Item_cache_str();
|
}
|
||||||
break;
|
else
|
||||||
default:
|
{
|
||||||
// should never be in real life
|
THD *thd= current_thd;
|
||||||
DBUG_ASSERT(0);
|
if (!(row= (Item_cache**)thd->alloc(sizeof(Item_cache*)*max_columns)))
|
||||||
return;
|
{
|
||||||
|
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 ()
|
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()
|
void Item_exists_subselect::fix_length_and_dec()
|
||||||
{
|
{
|
||||||
decimals=0;
|
decimals= 0;
|
||||||
max_length= 1;
|
max_length= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -540,31 +575,85 @@ int subselect_union_engine::prepare()
|
|||||||
return unit->prepare(thd, result);
|
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);
|
List_iterator_fast<Item> li(select_lex->item_list);
|
||||||
Item *sel_item= li++;
|
for (uint i= 0; (sel_item= li++); i++)
|
||||||
item->max_length= sel_item->max_length;
|
{
|
||||||
res_type= sel_item->result_type();
|
item->max_length= sel_item->max_length;
|
||||||
item->decimals= sel_item->decimals;
|
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;
|
DBUG_ASSERT(row || select_lex->item_list.elements==1);
|
||||||
Item *sel_item= 0;
|
res_type= set_row(select_lex, item, row);
|
||||||
for (SELECT_LEX *sl= unit->first_select(); sl; sl= sl->next_select())
|
}
|
||||||
|
|
||||||
|
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);
|
uint32 mlen= 0, len;
|
||||||
Item *s_item= li++;
|
Item *sel_item= 0;
|
||||||
if ((len= s_item->max_length))
|
for (SELECT_LEX *sl= unit->first_select(); sl; sl= sl->next_select())
|
||||||
mlen= len;
|
{
|
||||||
if (!sel_item)
|
List_iterator_fast<Item> li(sl->item_list);
|
||||||
sel_item= s_item;
|
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()
|
int subselect_single_select_engine::exec()
|
||||||
|
@ -94,8 +94,7 @@ class Item_cache;
|
|||||||
class Item_singleval_subselect :public Item_subselect
|
class Item_singleval_subselect :public Item_subselect
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
Item_cache *value;
|
Item_cache *value, **row;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Item_singleval_subselect(THD *thd, st_select_lex *select_lex);
|
Item_singleval_subselect(THD *thd, st_select_lex *select_lex);
|
||||||
Item_singleval_subselect(Item_singleval_subselect *item):
|
Item_singleval_subselect(Item_singleval_subselect *item):
|
||||||
@ -106,7 +105,7 @@ public:
|
|||||||
decimals= item->decimals;
|
decimals= item->decimals;
|
||||||
}
|
}
|
||||||
void reset();
|
void reset();
|
||||||
void store(Item* item);
|
void store(uint i, Item* item);
|
||||||
double val();
|
double val();
|
||||||
longlong val_int ();
|
longlong val_int ();
|
||||||
String *val_str (String *);
|
String *val_str (String *);
|
||||||
@ -114,6 +113,13 @@ public:
|
|||||||
enum Item_result result_type() const;
|
enum Item_result result_type() const;
|
||||||
void fix_length_and_dec();
|
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;
|
friend class select_singleval_subselect;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -212,7 +218,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual int prepare()= 0;
|
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 int exec()= 0;
|
||||||
virtual uint cols()= 0; /* return number of columnss in select */
|
virtual uint cols()= 0; /* return number of columnss in select */
|
||||||
virtual bool depended()= 0; /* depended from outer select */
|
virtual bool depended()= 0; /* depended from outer select */
|
||||||
@ -233,7 +239,7 @@ public:
|
|||||||
select_subselect *result,
|
select_subselect *result,
|
||||||
Item_subselect *item);
|
Item_subselect *item);
|
||||||
int prepare();
|
int prepare();
|
||||||
void fix_length_and_dec();
|
void fix_length_and_dec(Item_cache** row);
|
||||||
int exec();
|
int exec();
|
||||||
uint cols();
|
uint cols();
|
||||||
bool depended();
|
bool depended();
|
||||||
@ -250,7 +256,7 @@ public:
|
|||||||
select_subselect *result,
|
select_subselect *result,
|
||||||
Item_subselect *item);
|
Item_subselect *item);
|
||||||
int prepare();
|
int prepare();
|
||||||
void fix_length_and_dec();
|
void fix_length_and_dec(Item_cache** row);
|
||||||
int exec();
|
int exec();
|
||||||
uint cols();
|
uint cols();
|
||||||
bool depended();
|
bool depended();
|
||||||
|
@ -931,8 +931,9 @@ bool select_singleval_subselect::send_data(List<Item> &items)
|
|||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
List_iterator_fast<Item> li(items);
|
List_iterator_fast<Item> li(items);
|
||||||
Item *val_item= li++; // Only one (single value subselect)
|
Item *val_item;
|
||||||
it->store(val_item);
|
for (uint i= 0; (val_item= li++); i++)
|
||||||
|
it->store(i, val_item);
|
||||||
it->assigned(1);
|
it->assigned(1);
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user