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

Merge sanja.is.com.ua:/home/bell/mysql/mysql-4.1

into sanja.is.com.ua:/home/bell/mysql/work-row-4.1
parents d85a01db 521ec316
...@@ -52,6 +52,54 @@ a ...@@ -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);
...@@ -586,7 +634,7 @@ EXPLAIN SELECT * FROM t WHERE id IN (SELECT 1 UNION SELECT 3); ...@@ -586,7 +634,7 @@ EXPLAIN SELECT * FROM t WHERE id IN (SELECT 1 UNION SELECT 3);
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t index NULL id 5 NULL 2 Using where; Using index 1 PRIMARY t index NULL id 5 NULL 2 Using where; Using index
2 DEPENDENT SUBSELECT NULL NULL NULL NULL NULL NULL NULL No tables used 2 DEPENDENT SUBSELECT NULL NULL NULL NULL NULL NULL NULL No tables used
3 UNION NULL NULL NULL NULL NULL NULL NULL No tables used 3 DEPENDENT UNION NULL NULL NULL NULL NULL NULL NULL No tables used
SELECT * FROM t WHERE id IN (SELECT 5 UNION SELECT 3); SELECT * FROM t WHERE id IN (SELECT 5 UNION SELECT 3);
id id
SELECT * FROM t WHERE id IN (SELECT 5 UNION SELECT 2); SELECT * FROM t WHERE id IN (SELECT 5 UNION SELECT 2);
...@@ -602,7 +650,7 @@ CREATE TABLE t1 (id int(11) default NULL, KEY id (id)) TYPE=MyISAM CHARSET=latin ...@@ -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);
...@@ -711,3 +759,56 @@ This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery' ...@@ -711,3 +759,56 @@ This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
select 10.5 IN (SELECT * from t LIMIT 1 UNION SELECT 1.5); select 10.5 IN (SELECT * from t LIMIT 1 UNION SELECT 1.5);
This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery' This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
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;
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
select ROW(1, 1, 'a') IN (select b,a,c from t limit 2);
This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
drop table if exists t;
...@@ -26,6 +26,22 @@ select (SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE(1)); ...@@ -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 ...@@ -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
...@@ -416,4 +432,28 @@ create table t (a float); ...@@ -416,4 +432,28 @@ create table t (a float);
select 10.5 IN (SELECT * from t LIMIT 1); select 10.5 IN (SELECT * from t LIMIT 1);
-- error 1235 -- error 1235
select 10.5 IN (SELECT * from t LIMIT 1 UNION SELECT 1.5); select 10.5 IN (SELECT * from t LIMIT 1 UNION SELECT 1.5);
drop table t; drop table t;
\ No newline at end of file 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;
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');
-- error 1235
select ROW(1, 1, 'a') IN (select b,a,c from t limit 2);
drop table if exists t;
...@@ -47,11 +47,6 @@ Item::Item(): ...@@ -47,11 +47,6 @@ Item::Item():
loop_id= 0; loop_id= 0;
} }
Item_ref_in_optimizer::Item_ref_in_optimizer(Item_in_optimizer *master,
char *table_name_par,
char *field_name_par):
Item_ref(master->args, table_name_par, field_name_par), owner(master) {}
bool Item::check_loop(uint id) bool Item::check_loop(uint id)
{ {
...@@ -437,20 +432,6 @@ String *Item_copy_string::val_str(String *str) ...@@ -437,20 +432,6 @@ String *Item_copy_string::val_str(String *str)
return &str_value; return &str_value;
} }
double Item_ref_in_optimizer::val()
{
return owner->get_cache();
}
longlong Item_ref_in_optimizer::val_int()
{
return owner->get_cache_int();
}
String* Item_ref_in_optimizer::val_str(String* s)
{
return owner->get_cache_str(s);
}
/* /*
Functions to convert item to field (for send_fields) Functions to convert item to field (for send_fields)
*/ */
...@@ -464,18 +445,6 @@ bool Item::fix_fields(THD *thd, ...@@ -464,18 +445,6 @@ bool Item::fix_fields(THD *thd,
return 0; return 0;
} }
bool Item_outer_select_context_saver::fix_fields(THD *thd,
struct st_table_list *list,
Item ** ref)
{
DBUG_ENTER("Item_outer_select_context_saver::fix_fields");
bool res= item->fix_fields(thd,
0, // do not show current subselect fields
&item);
*ref= item;
DBUG_RETURN(res);
}
bool Item_asterisk_remover::fix_fields(THD *thd, bool Item_asterisk_remover::fix_fields(THD *thd,
struct st_table_list *list, struct st_table_list *list,
Item ** ref) Item ** ref)
...@@ -529,6 +498,27 @@ bool Item_asterisk_remover::fix_fields(THD *thd, ...@@ -529,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();
...@@ -1221,6 +1211,148 @@ bool field_is_equal_to_item(Field *field,Item *item) ...@@ -1221,6 +1211,148 @@ 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();
case ROW_RESULT:
return new Item_cache_row();
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;
}
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
......
...@@ -31,12 +31,12 @@ class Item { ...@@ -31,12 +31,12 @@ class Item {
static void *operator new(size_t size) {return (void*) sql_alloc((uint) size); } static void *operator new(size_t size) {return (void*) sql_alloc((uint) size); }
static void operator delete(void *ptr,size_t size) {} /*lint -e715 */ static void operator delete(void *ptr,size_t size) {} /*lint -e715 */
enum Type {FIELD_ITEM,FUNC_ITEM,SUM_FUNC_ITEM,STRING_ITEM, enum Type {FIELD_ITEM, FUNC_ITEM, SUM_FUNC_ITEM, STRING_ITEM,
INT_ITEM,REAL_ITEM,NULL_ITEM,VARBIN_ITEM, INT_ITEM, REAL_ITEM, NULL_ITEM, VARBIN_ITEM,
COPY_STR_ITEM,FIELD_AVG_ITEM, DEFAULT_ITEM, COPY_STR_ITEM, FIELD_AVG_ITEM, DEFAULT_ITEM,
PROC_ITEM,COND_ITEM,REF_ITEM,FIELD_STD_ITEM, PROC_ITEM,COND_ITEM, REF_ITEM, FIELD_STD_ITEM,
FIELD_VARIANCE_ITEM,CONST_ITEM, FIELD_VARIANCE_ITEM, CONST_ITEM,
SUBSELECT_ITEM, ROW_ITEM}; SUBSELECT_ITEM, ROW_ITEM, CACHE_ITEM};
enum cond_result { COND_UNDEF,COND_OK,COND_TRUE,COND_FALSE }; enum cond_result { COND_UNDEF,COND_OK,COND_TRUE,COND_FALSE };
String str_value; /* used to store value */ String str_value; /* used to store value */
...@@ -103,64 +103,12 @@ class Item { ...@@ -103,64 +103,12 @@ class Item {
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() {}
}; };
/*
Wrapper base class
*/
class Item_wrapper :public Item
{
protected:
Item *item;
public:
/*
Following methods should not be used, because fix_fields exclude this
item (it assign '*ref' with field 'item' in derived classes)
*/
enum Type type() const { return item->type(); }
enum_field_types field_type() const { return item->field_type(); }
double val() { return item->val(); }
longlong val_int() { return item->val_int(); }
String* val_str(String* s) { return item->val_str(s); }
bool check_cols(uint col) { return item->check_cols(col); }
bool eq(const Item *item, bool binary_cmp) const
{ return item->eq(item, binary_cmp); }
bool is_null()
{
item->val_int();
return item->null_value;
}
bool get_date(TIME *ltime, bool fuzzydate)
{
return (null_value=item->get_date(ltime, fuzzydate));
}
bool send(Protocol *prot, String *tmp) { return item->send(prot, tmp); }
int save_in_field(Field *field, bool no_conversions)
{
return item->save_in_field(field, no_conversions);
}
void save_org_in_field(Field *field) { item->save_org_in_field(field); }
enum Item_result result_type () const { return item->result_type(); }
table_map used_tables() const { return item->used_tables(); }
};
/*
Save context of name resolution for Item, used in subselect transformer.
*/
class Item_outer_select_context_saver :public Item_wrapper
{
public:
Item_outer_select_context_saver(Item *it)
{
item= it;
}
bool fix_fields(THD *, struct st_table_list *, Item ** ref);
};
class st_select_lex; class st_select_lex;
class Item_ident :public Item class Item_ident :public Item
{ {
...@@ -381,7 +329,8 @@ class Item_string :public Item ...@@ -381,7 +329,8 @@ class Item_string :public Item
name=(char*) str_value.ptr(); name=(char*) str_value.ptr();
decimals=NOT_FIXED_DEC; decimals=NOT_FIXED_DEC;
} }
Item_string(const char *name_par,const char *str,uint length,CHARSET_INFO *cs) Item_string(const char *name_par, const char *str, uint length,
CHARSET_INFO *cs)
{ {
str_value.set(str,length,cs); str_value.set(str,length,cs);
max_length=length; max_length=length;
...@@ -392,11 +341,13 @@ class Item_string :public Item ...@@ -392,11 +341,13 @@ class Item_string :public Item
enum Type type() const { return STRING_ITEM; } enum Type type() const { return STRING_ITEM; }
double val() double val()
{ {
return my_strntod(str_value.charset(),str_value.ptr(),str_value.length(),(char**)NULL); return my_strntod(str_value.charset(), str_value.ptr(),
str_value.length(), (char**) 0);
} }
longlong val_int() longlong val_int()
{ {
return my_strntoll(str_value.charset(),str_value.ptr(),str_value.length(),(char**) 0,10); return my_strntoll(str_value.charset(), str_value.ptr(),
str_value.length(), (char**) 0, 10);
} }
String *val_str(String*) { return (String*) &str_value; } String *val_str(String*) { return (String*) &str_value; }
int save_in_field(Field *field, bool no_conversions); int save_in_field(Field *field, bool no_conversions);
...@@ -550,7 +501,7 @@ class Item_ref_null_helper: public Item_ref ...@@ -550,7 +501,7 @@ class Item_ref_null_helper: public Item_ref
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();
...@@ -558,6 +509,24 @@ class Item_ref_null_helper: public Item_ref ...@@ -558,6 +509,24 @@ class Item_ref_null_helper: public Item_ref
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
...@@ -574,24 +543,6 @@ class Item_asterisk_remover :public Item_ref_null_helper ...@@ -574,24 +543,6 @@ class Item_asterisk_remover :public Item_ref_null_helper
bool fix_fields(THD *, struct st_table_list *, Item ** ref); bool fix_fields(THD *, struct st_table_list *, Item ** ref);
}; };
class Item_in_optimizer;
class Item_ref_in_optimizer: public Item_ref
{
protected:
Item_in_optimizer* owner;
public:
Item_ref_in_optimizer(Item_in_optimizer* master,
char *table_name_par,char *field_name_par);
double val();
longlong val_int();
String* val_str(String* s);
bool fix_fields(THD *, struct st_table_list *, Item ** ref)
{
fixed= 1;
return 0;
}
};
/* /*
The following class is used to optimize comparing of date columns The following class is used to optimize comparing of date columns
We need to save the original item, to be able to set the field to the We need to save the original item, to be able to set the field to the
...@@ -706,6 +657,122 @@ class Item_field_buff :public Item_buff ...@@ -706,6 +657,122 @@ class Item_field_buff :public Item_buff
bool cmp(void); bool cmp(void);
}; };
class Item_cache: public Item
{
public:
virtual bool allocate(uint i) { return 0; };
virtual bool setup(Item *) { return 0; };
virtual void store(Item *)= 0;
void set_len_n_dec(uint32 max_len, uint8 dec)
{
max_length= max_len;
decimals= dec;
}
enum Type type() const { return CACHE_ITEM; }
static Item_cache* get_cache(Item_result type);
};
class Item_cache_int: public Item_cache
{
longlong value;
public:
Item_cache_int() { fixed= 1; null_value= 1; }
void store(Item *item)
{
value= item->val_int_result();
null_value= item->null_value;
}
double val() { return (double) value; }
longlong val_int() { return value; }
String* val_str(String *str) { str->set(value, thd_charset()); return str; }
enum Item_result result_type() const { return INT_RESULT; }
};
class Item_cache_real: public Item_cache
{
double value;
public:
Item_cache_real() { fixed= 1; null_value= 1; }
void store(Item *item)
{
value= item->val_result();
null_value= item->null_value;
}
double val() { return value; }
longlong val_int() { return (longlong) (value+(value > 0 ? 0.5 : -0.5)); }
String* val_str(String *str)
{
str->set(value, decimals, thd_charset());
return str;
}
enum Item_result result_type() const { return REAL_RESULT; }
};
class Item_cache_str: public Item_cache
{
char buffer[80];
String *value;
public:
Item_cache_str() { fixed= 1; null_value= 1; }
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(); };
};
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);
......
...@@ -247,6 +247,8 @@ int Arg_comparator::compare_e_int() ...@@ -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() ...@@ -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++)
{ {
...@@ -270,60 +274,67 @@ int Arg_comparator::compare_e_row() ...@@ -270,60 +274,67 @@ int Arg_comparator::compare_e_row()
return 1; return 1;
} }
longlong Item_in_optimizer::val_int() bool Item_in_optimizer::preallocate_row()
{ {
int_cache_ok= 1; if ((cache= Item_cache::get_cache(ROW_RESULT)))
flt_cache_ok= 0;
str_cache_ok= 0;
int_cache= args[0]->val_int_result();
if (args[0]->null_value)
{
null_value= 1;
return 0; return 0;
} my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
longlong tmp= args[1]->val_int_result(); current_thd->fatal_error= 1;
null_value= args[1]->null_value; return 1;
return tmp;
} }
longlong Item_in_optimizer::get_cache_int() bool Item_in_optimizer::fix_fields(THD *thd, struct st_table_list *tables,
Item ** ref)
{ {
if (!int_cache_ok) if (args[0]->fix_fields(thd, tables, args))
return 1;
if (args[0]->maybe_null)
maybe_null=1;
if (args[0]->binary())
set_charset(my_charset_bin);
with_sum_func= args[0]->with_sum_func;
used_tables_cache= args[0]->used_tables();
const_item_cache= args[0]->const_item();
if (!cache && !(cache= Item_cache::get_cache(args[0]->result_type())))
{
my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
thd->fatal_error= 1;
return 1;
}
cache->setup(args[0]);
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())
{ {
int_cache_ok= 1; my_error(ER_CARDINALITY_COL, MYF(0), args[0]->cols());
flt_cache_ok= 0; return 1;
str_cache_ok= 0;
int_cache= args[0]->val_int_result();
null_value= args[0]->null_value;
} }
return int_cache; if (args[1]->maybe_null)
maybe_null=1;
with_sum_func= with_sum_func || args[1]->with_sum_func;
used_tables_cache|= args[1]->used_tables();
const_item_cache&= args[1]->const_item();
return 0;
} }
double Item_in_optimizer::get_cache() longlong Item_in_optimizer::val_int()
{ {
if (!flt_cache_ok) cache->store(args[0]);
if (cache->null_value)
{ {
flt_cache_ok= 1; null_value= 1;
int_cache_ok= 0; return 0;
str_cache_ok= 0;
flt_cache= args[0]->val_result();
null_value= args[0]->null_value;
} }
return flt_cache; longlong tmp= args[1]->val_int_result();
null_value= args[1]->null_value;
return tmp;
} }
String *Item_in_optimizer::get_cache_str(String *s) bool Item_in_optimizer::is_null()
{ {
if (!str_cache_ok) cache->store(args[0]);
{ return (null_value= (cache->null_value || args[1]->is_null()));
str_cache_ok= 1;
int_cache_ok= 0;
flt_cache_ok= 0;
str_value.set(buffer, sizeof(buffer), s->charset());
str_cache= args[0]->str_result(&str_value);
null_value= args[0]->null_value;
}
return str_cache;
} }
longlong Item_func_eq::val_int() longlong Item_func_eq::val_int()
...@@ -1217,8 +1228,9 @@ void cmp_item_row::store_value(Item *item) ...@@ -1217,8 +1228,9 @@ 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->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 +1264,7 @@ void cmp_item_row::store_value_by_template(cmp_item *t, Item *item) ...@@ -1252,6 +1264,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 +1297,7 @@ int cmp_item_row::cmp(Item *arg) ...@@ -1284,6 +1297,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)))
{ {
......
...@@ -85,25 +85,21 @@ class Item_bool_func :public Item_int_func ...@@ -85,25 +85,21 @@ class Item_bool_func :public Item_int_func
void fix_length_and_dec() { decimals=0; max_length=1; } void fix_length_and_dec() { decimals=0; max_length=1; }
}; };
class Item_cache;
class Item_in_optimizer: public Item_bool_func class Item_in_optimizer: public Item_bool_func
{ {
protected: protected:
char buffer[80]; Item_cache *cache;
longlong int_cache; public:
double flt_cache; Item_in_optimizer(Item *a, Item_in_subselect *b):
String *str_cache; Item_bool_func(a, (Item *)b), cache(0) {}
bool int_cache_ok, flt_cache_ok, str_cache_ok; // used by row in transformer
public: bool preallocate_row();
Item_in_optimizer(Item *a,Item *b): bool fix_fields(THD *, struct st_table_list *, Item **);
Item_bool_func(a,b), int_cache_ok(0), flt_cache_ok(0), str_cache_ok(0) {} bool is_null();
bool is_null() { return test(args[0]->is_null() || args[1]->is_null()); }
longlong val_int(); longlong val_int();
double get_cache(); Item_cache **get_cache() { return &cache; }
longlong get_cache_int();
String *get_cache_str(String *s);
friend class Item_ref_in_optimizer;
}; };
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 @@ class Item_row: public Item ...@@ -70,4 +70,5 @@ class Item_row: public Item
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();
}; };
This diff is collapsed.
...@@ -71,7 +71,7 @@ class Item_subselect :public Item_result_field ...@@ -71,7 +71,7 @@ class Item_subselect :public Item_result_field
{ {
null_value= 1; null_value= 1;
} }
virtual void select_transformer(st_select_lex *select_lex); virtual void select_transformer(st_select_lex_unit *unit);
bool assigned() { return value_assigned; } bool assigned() { return value_assigned; }
void assigned(bool a) { value_assigned= a; } void assigned(bool a) { value_assigned= a; }
enum Type type() const; enum Type type() const;
...@@ -86,51 +86,42 @@ class Item_subselect :public Item_result_field ...@@ -86,51 +86,42 @@ class Item_subselect :public Item_result_field
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_singleval_subselect :public Item_subselect class Item_cache;
class Item_singlerow_subselect :public Item_subselect
{ {
protected: protected:
longlong int_value; /* Here stored integer value of this item */ Item_cache *value, **row;
double real_value; /* Here stored real value of this item */
/*
Here stored string value of this item.
(str_value used only as temporary buffer, because it can be changed
by Item::save_field)
*/
String string_value;
enum Item_result res_type; /* type of results */
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)
{ {
int_value= item->int_value; value= item->value;
real_value= item->real_value;
string_value.set(item->string_value, 0, item->string_value.length());
max_length= item->max_length; max_length= item->max_length;
decimals= item->decimals; decimals= item->decimals;
res_type= item->res_type;
}
virtual void reset()
{
null_value= 1;
int_value= 0;
real_value= 0;
max_length= 4;
res_type= STRING_RESULT;
} }
double val (); void reset();
void store(uint i, Item* item);
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 { return res_type; } enum Item_result result_type() const;
void fix_length_and_dec(); void fix_length_and_dec();
friend class select_singleval_subselect; 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_singlerow_subselect;
}; };
/* exists subselect */ /* exists subselect */
...@@ -149,7 +140,7 @@ class Item_exists_subselect :public Item_subselect ...@@ -149,7 +140,7 @@ class Item_exists_subselect :public Item_subselect
} }
Item_exists_subselect(): Item_subselect() {} Item_exists_subselect(): Item_subselect() {}
virtual void reset() void reset()
{ {
value= 0; value= 0;
} }
...@@ -181,9 +172,10 @@ class Item_in_subselect :public Item_exists_subselect ...@@ -181,9 +172,10 @@ class Item_in_subselect :public Item_exists_subselect
null_value= 0; null_value= 0;
was_null= 0; was_null= 0;
} }
virtual void select_transformer(st_select_lex *select_lex); virtual void select_transformer(st_select_lex_unit *unit);
void single_value_transformer(st_select_lex *select_lex, void single_value_transformer(st_select_lex_unit *unit,
Item *left_expr, compare_func_creator func); Item *left_expr, compare_func_creator func);
void row_value_transformer(st_select_lex_unit *unit, Item *left_expr);
longlong val_int(); longlong val_int();
double val(); double val();
String *val_str(String*); String *val_str(String*);
...@@ -202,7 +194,7 @@ class Item_allany_subselect :public Item_in_subselect ...@@ -202,7 +194,7 @@ class Item_allany_subselect :public Item_in_subselect
Item_allany_subselect(THD *thd, Item * left_expr, compare_func_creator f, Item_allany_subselect(THD *thd, Item * left_expr, compare_func_creator f,
st_select_lex *select_lex); st_select_lex *select_lex);
Item_allany_subselect(Item_allany_subselect *item); Item_allany_subselect(Item_allany_subselect *item);
virtual void select_transformer(st_select_lex *select_lex); virtual void select_transformer(st_select_lex_unit *unit);
}; };
class subselect_engine class subselect_engine
...@@ -228,7 +220,7 @@ class subselect_engine ...@@ -228,7 +220,7 @@ class subselect_engine
} }
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 */
...@@ -249,7 +241,7 @@ class subselect_single_select_engine: public subselect_engine ...@@ -249,7 +241,7 @@ class subselect_single_select_engine: public subselect_engine
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();
...@@ -266,7 +258,7 @@ class subselect_union_engine: public subselect_engine ...@@ -266,7 +258,7 @@ class subselect_union_engine: public subselect_engine
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();
......
...@@ -917,10 +917,10 @@ select_subselect::select_subselect(Item_subselect *item) ...@@ -917,10 +917,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));
...@@ -932,32 +932,9 @@ bool select_singleval_subselect::send_data(List<Item> &items) ...@@ -932,32 +932,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;
/* for (uint i= 0; (val_item= li++); i++)
Following val() call have to be first, because function AVG() & STD() it->store(i, val_item);
calculate value on it & determinate "is it NULL?".
*/
it->real_value= val_item->val_result();
if ((it->null_value= val_item->null_value))
{
it->reset();
}
else
{
it->max_length= val_item->max_length;
it->decimals= val_item->decimals;
it->set_charset(val_item->charset());
it->int_value= val_item->val_int_result();
String *s= val_item->str_result(&it->string_value);
if (s != &it->string_value)
{
it->string_value.set(*s, 0, s->length());
}
// TODO: remove when correct charset handling appeared for Item
it->str_value.set(*s, 0, s->length()); // store charset
it->res_type= val_item->result_type();
}
it->assigned(1); it->assigned(1);
DBUG_RETURN(0); DBUG_RETURN(0);
} }
......
...@@ -824,10 +824,10 @@ class select_subselect :public select_result ...@@ -824,10 +824,10 @@ class select_subselect :public select_result
}; };
/* 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>
...@@ -2018,7 +2018,7 @@ simple_expr: ...@@ -2018,7 +2018,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 *)
...@@ -4488,17 +4488,17 @@ union_option: ...@@ -4488,17 +4488,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