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

subselect with union

new error handling
Item_ref bug fixed
parent 189d1dd6
...@@ -132,8 +132,13 @@ typedef struct st_net { ...@@ -132,8 +132,13 @@ typedef struct st_net {
unsigned int *return_status; unsigned int *return_status;
unsigned char reading_or_writing; unsigned char reading_or_writing;
char save_char; char save_char;
my_bool report_error; /* We should report error (we have unreported error) */
my_bool no_send_ok; my_bool no_send_ok;
gptr query_cache_query; /*
Pointer to query object in query cache, do not equal NULL (0) for
queries in cache that have not stored its results yet
*/
gptr query_cache_query;
} NET; } NET;
#define packet_error (~(unsigned long) 0) #define packet_error (~(unsigned long) 0)
......
...@@ -92,7 +92,8 @@ NULL NULL NULL ...@@ -92,7 +92,8 @@ NULL NULL NULL
0 0 0 0
select id >= 0 and id <= 5 as grp,count(*) from t1 group by grp; select id >= 0 and id <= 5 as grp,count(*) from t1 group by grp;
grp count(*) grp count(*)
0 7 NULL 1
0 6
1 6 1 6
SELECT DISTINCT FACILITY FROM t1; SELECT DISTINCT FACILITY FROM t1;
FACILITY FACILITY
......
select (select 2); select (select 2);
(select 2) (select 2)
2 2
drop table if exists t1,t2,t3,t4; drop table if exists t1,t2,t3,t4,t5;
create table t1 (a int); create table t1 (a int);
create table t2 (a int, b int); create table t2 (a int, b int);
create table t3 (a int); create table t3 (a int);
...@@ -82,4 +82,21 @@ select b,max(a) as ma from t4 group by b having b >= (select max(t2.a) ...@@ -82,4 +82,21 @@ select b,max(a) as ma from t4 group by b having b >= (select max(t2.a)
from t2 where t2.b=t4.b); from t2 where t2.b=t4.b);
b ma b ma
7 12 7 12
drop table t1,t2,t3,t4; create table t5 (a int);
select (select a from t1 where t1.a=t2.a union select a from t5 where t5.a=t2.a), a from t2;
(select a from t1 where t1.a=t2.a union select a from t5 where t5.a=t2.a) a
NULL 1
2 2
insert into t5 values (5);
select (select a from t1 where t1.a=t2.a union select a from t5 where t5.a=t2.a), a from t2;
(select a from t1 where t1.a=t2.a union select a from t5 where t5.a=t2.a) a
NULL 1
2 2
insert into t5 values (2);
select (select a from t1 where t1.a=t2.a union select a from t5 where t5.a=t2.a), a from t2;
(select a from t1 where t1.a=t2.a union select a from t5 where t5.a=t2.a) a
NULL 1
2 2
select (select a from t1 where t1.a=t2.a union all select a from t5 where t5.a=t2.a), a from t2;
Subselect return more than 1 record
drop table t1,t2,t3,t4,t5;
select (select 2); select (select 2);
drop table if exists t1,t2,t3,t4; drop table if exists t1,t2,t3,t4,t5;
create table t1 (a int); create table t1 (a int);
create table t2 (a int, b int); create table t2 (a int, b int);
create table t3 (a int); create table t3 (a int);
...@@ -33,4 +33,12 @@ select b,max(a) as ma from t4 group by b having b < (select max(t2.a) ...@@ -33,4 +33,12 @@ select b,max(a) as ma from t4 group by b having b < (select max(t2.a)
from t2 where t2.b=t4.b); from t2 where t2.b=t4.b);
select b,max(a) as ma from t4 group by b having b >= (select max(t2.a) select b,max(a) as ma from t4 group by b having b >= (select max(t2.a)
from t2 where t2.b=t4.b); from t2 where t2.b=t4.b);
drop table t1,t2,t3,t4; create table t5 (a int);
select (select a from t1 where t1.a=t2.a union select a from t5 where t5.a=t2.a), a from t2;
insert into t5 values (5);
select (select a from t1 where t1.a=t2.a union select a from t5 where t5.a=t2.a), a from t2;
insert into t5 values (2);
select (select a from t1 where t1.a=t2.a union select a from t5 where t5.a=t2.a), a from t2;
-- error 1230
select (select a from t1 where t1.a=t2.a union all select a from t5 where t5.a=t2.a), a from t2;
drop table t1,t2,t3,t4,t5;
...@@ -457,7 +457,7 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) ...@@ -457,7 +457,7 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
if (!field) // If field is not checked if (!field) // If field is not checked
{ {
Field *tmp; Field *tmp;
if (!(tmp=find_field_in_tables(thd,this,tables))) if (!(tmp=find_field_in_tables(thd, this, tables, 0)))
{ {
/* /*
We can't find table field in table list of current select, We can't find table field in table list of current select,
...@@ -473,9 +473,14 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) ...@@ -473,9 +473,14 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
sl && !tmp; sl && !tmp;
sl= sl->outer_select()) sl= sl->outer_select())
tmp=find_field_in_tables(thd, this, tmp=find_field_in_tables(thd, this,
(TABLE_LIST*)(last= sl)->table_list.first); (TABLE_LIST*)(last= sl)->table_list.first,
0);
if (!tmp) if (!tmp)
return 1; {
// Call to produce appropriate error message
find_field_in_tables(thd, this, tables, 1);
return -1;
}
else else
{ {
depended_from= last; depended_from= last;
...@@ -488,7 +493,8 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) ...@@ -488,7 +493,8 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
s= s->outer_select()) s= s->outer_select())
if( !s->depended ) if( !s->depended )
{ {
s->depended= 1; //Select is depended of outer select // Select is depended of outer select
s->depended= s->master_unit()->depended= 1;
//Tables will be reopened many times //Tables will be reopened many times
for (TABLE_LIST *tbl= for (TABLE_LIST *tbl=
(TABLE_LIST*)s->table_list.first; (TABLE_LIST*)s->table_list.first;
...@@ -803,7 +809,7 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) ...@@ -803,7 +809,7 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
{ {
if (!ref) if (!ref)
{ {
if (!(ref= find_item_in_list(this,thd->lex.select->item_list))) if (!(ref= find_item_in_list(this, thd->lex.select->item_list, 0)))
{ {
/* /*
We can't find table field in table list of current select, We can't find table field in table list of current select,
...@@ -818,9 +824,13 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) ...@@ -818,9 +824,13 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
for (SELECT_LEX *sl= thd->lex.select->outer_select(); for (SELECT_LEX *sl= thd->lex.select->outer_select();
sl && !ref; sl && !ref;
sl= sl->outer_select()) sl= sl->outer_select())
ref= find_item_in_list(this, (last= sl)->item_list); ref= find_item_in_list(this, (last= sl)->item_list, 0);
if (!ref) if (!ref)
{
// Call to report error
find_item_in_list(this, thd->lex.select->item_list, 1);
return 1; return 1;
}
else else
{ {
depended_from= last; depended_from= last;
...@@ -833,7 +843,8 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) ...@@ -833,7 +843,8 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
s= s->outer_select()) s= s->outer_select())
if( !s->depended ) if( !s->depended )
{ {
s->depended= 1; //Select is depended of outer select // Select is depended of outer select
s->depended= s->master_unit()->depended= 1;
//Tables will be reopened many times //Tables will be reopened many times
for (TABLE_LIST *tbl= for (TABLE_LIST *tbl=
(TABLE_LIST*)s->table_list.first; (TABLE_LIST*)s->table_list.first;
......
...@@ -1101,6 +1101,8 @@ Item_cond::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) ...@@ -1101,6 +1101,8 @@ Item_cond::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
used_tables_cache|=item->used_tables(); used_tables_cache|=item->used_tables();
with_sum_func= with_sum_func || item->with_sum_func; with_sum_func= with_sum_func || item->with_sum_func;
const_item_cache&=item->const_item(); const_item_cache&=item->const_item();
if (item->maybe_null)
maybe_null=1;
} }
if (thd) if (thd)
thd->cond_count+=list.elements; thd->cond_count+=list.elements;
......
...@@ -23,9 +23,6 @@ SUBSELECT TODO: ...@@ -23,9 +23,6 @@ SUBSELECT TODO:
- remove double 'having' & 'having_list' from JOIN - remove double 'having' & 'having_list' from JOIN
(sql_select.h/sql_select.cc) (sql_select.h/sql_select.cc)
- subselect in HAVING clause
- add subselect union select (sql_union.cc)
*/ */
#ifdef __GNUC__ #ifdef __GNUC__
...@@ -37,21 +34,17 @@ SUBSELECT TODO: ...@@ -37,21 +34,17 @@ SUBSELECT TODO:
Item_subselect::Item_subselect(THD *thd, st_select_lex *select_lex, Item_subselect::Item_subselect(THD *thd, st_select_lex *select_lex,
select_subselect *result): select_subselect *result):
assigned(0), executed(0), optimized(0), error(0) engine_owner(1), value_assigned(0)
{ {
DBUG_ENTER("Item_subselect::Item_subselect"); DBUG_ENTER("Item_subselect::Item_subselect");
DBUG_PRINT("subs", ("select_lex 0x%xl", (long) select_lex)); DBUG_PRINT("subs", ("select_lex 0x%xl", (long) select_lex));
this->result= result;
SELECT_LEX_UNIT *unit= select_lex->master_unit(); if (select_lex->next_select())
unit->offset_limit_cnt= unit->global_parameters->offset_limit; engine= new subselect_union_engine(thd, select_lex->master_unit(), result,
unit->select_limit_cnt= unit->global_parameters->select_limit+ this);
unit->global_parameters ->offset_limit; else
if (unit->select_limit_cnt < unit->global_parameters->select_limit) engine= new subselect_single_select_engine(thd, select_lex, result,
unit->select_limit_cnt= HA_POS_ERROR; // no limit this);
if (unit->select_limit_cnt == HA_POS_ERROR)
select_lex->options&= ~OPTION_FOUND_ROWS;
join= new JOIN(thd, select_lex->item_list, select_lex->options, result);
this->select_lex= select_lex;
assign_null(); assign_null();
/* /*
item value is NULL if select_subselect not changed this value item value is NULL if select_subselect not changed this value
...@@ -61,6 +54,12 @@ Item_subselect::Item_subselect(THD *thd, st_select_lex *select_lex, ...@@ -61,6 +54,12 @@ Item_subselect::Item_subselect(THD *thd, st_select_lex *select_lex,
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
Item_subselect::~Item_subselect()
{
if (engine_owner)
delete engine;
}
void Item_subselect::make_field (Send_field *tmp_field) void Item_subselect::make_field (Send_field *tmp_field)
{ {
if (null_value) if (null_value)
...@@ -78,62 +77,17 @@ void Item_subselect::make_field (Send_field *tmp_field) ...@@ -78,62 +77,17 @@ void Item_subselect::make_field (Send_field *tmp_field)
bool Item_subselect::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) bool Item_subselect::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
{ {
// Is it one field subselect? // Is it one field subselect?
if (select_lex->item_list.elements > max_columns) if (engine->cols() > max_columns)
{ {
my_printf_error(ER_SUBSELECT_NO_1_COL, ER(ER_SUBSELECT_NO_1_COL), MYF(0)); my_message(ER_SUBSELECT_NO_1_COL, ER(ER_SUBSELECT_NO_1_COL), MYF(0));
return 1; return 1;
} }
SELECT_LEX *save_select= thd->lex.select; return engine->prepare();
thd->lex.select= select_lex;
if(join->prepare((TABLE_LIST*) select_lex->table_list.first,
select_lex->where,
(ORDER*) select_lex->order_list.first,
(ORDER*) select_lex->group_list.first,
select_lex->having,
(ORDER*) 0, select_lex,
select_lex->master_unit()))
return 1;
thd->lex.select= save_select;
return 0;
}
int Item_subselect::exec()
{
DBUG_ENTER("Item_subselect::exec");
if (!optimized)
{
optimized=1;
if (join->optimize())
{
executed= 1;
DBUG_RETURN(join->error?join->error:1);
}
}
if (join->select_lex->depended && executed)
{
if (join->reinit())
{
error= 1;
DBUG_RETURN(1);
}
assign_null();
executed= assigned= 0;
}
if (!executed)
{
SELECT_LEX *save_select= join->thd->lex.select;
join->thd->lex.select= select_lex;
join->exec();
join->thd->lex.select= save_select;
executed= 1;
DBUG_RETURN(join->error);
}
DBUG_RETURN(0);
} }
inline table_map Item_subselect::used_tables() const inline table_map Item_subselect::used_tables() const
{ {
return (table_map) select_lex->depended ? 1L : 0L; return (table_map) engine->depended() ? 1L : 0L;
} }
Item_singleval_subselect::Item_singleval_subselect(THD *thd, Item_singleval_subselect::Item_singleval_subselect(THD *thd,
...@@ -151,21 +105,21 @@ Item::Type Item_subselect::type() const ...@@ -151,21 +105,21 @@ Item::Type Item_subselect::type() const
double Item_singleval_subselect::val () double Item_singleval_subselect::val ()
{ {
if (exec()) if (engine->exec())
return 0; return 0;
return real_value; return real_value;
} }
longlong Item_singleval_subselect::val_int () longlong Item_singleval_subselect::val_int ()
{ {
if (exec()) if (engine->exec())
return 0; return 0;
return int_value; return int_value;
} }
String *Item_singleval_subselect::val_str (String *str) String *Item_singleval_subselect::val_str (String *str)
{ {
if (exec() || null_value) if (engine->exec() || null_value)
return 0; return 0;
return &str_value; return &str_value;
} }
...@@ -183,23 +137,143 @@ Item_exists_subselect::Item_exists_subselect(THD *thd, ...@@ -183,23 +137,143 @@ Item_exists_subselect::Item_exists_subselect(THD *thd,
double Item_exists_subselect::val () double Item_exists_subselect::val ()
{ {
if (exec()) if (engine->exec())
return 0; return 0;
return (double) value; return (double) value;
} }
longlong Item_exists_subselect::val_int () longlong Item_exists_subselect::val_int ()
{ {
if (exec()) if (engine->exec())
return 0; return 0;
return value; return value;
} }
String *Item_exists_subselect::val_str(String *str) String *Item_exists_subselect::val_str(String *str)
{ {
if (exec()) if (engine->exec())
return 0; return 0;
str->set(value); str->set(value);
return str; return str;
} }
subselect_single_select_engine::subselect_single_select_engine(THD *thd,
st_select_lex *select,
select_subselect *result,
Item_subselect *item):
subselect_engine(thd, item, result),
executed(0), optimized(0)
{
select_lex= select;
SELECT_LEX_UNIT *unit= select_lex->master_unit();
unit->offset_limit_cnt= unit->global_parameters->offset_limit;
unit->select_limit_cnt= unit->global_parameters->select_limit+
unit->global_parameters ->offset_limit;
if (unit->select_limit_cnt < unit->global_parameters->select_limit)
unit->select_limit_cnt= HA_POS_ERROR; // no limit
if (unit->select_limit_cnt == HA_POS_ERROR)
select_lex->options&= ~OPTION_FOUND_ROWS;
join= new JOIN(thd, select_lex->item_list, select_lex->options, result);
if (!join || !result)
{
//out of memory
thd->fatal_error= 1;
my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
}
this->select_lex= select_lex;
}
subselect_union_engine::subselect_union_engine(THD *thd,
st_select_lex_unit *u,
select_subselect *result,
Item_subselect *item):
subselect_engine(thd, item, result)
{
unit= u;
if( !result)
{
//out of memory
thd->fatal_error= 1;
my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
}
unit->item= item;
}
int subselect_single_select_engine::prepare()
{
SELECT_LEX *save_select= thd->lex.select;
thd->lex.select= select_lex;
if(join->prepare((TABLE_LIST*) select_lex->table_list.first,
select_lex->where,
(ORDER*) select_lex->order_list.first,
(ORDER*) select_lex->group_list.first,
select_lex->having,
(ORDER*) 0, select_lex,
select_lex->master_unit(), 0))
return 1;
thd->lex.select= save_select;
return 0;
}
int subselect_union_engine::prepare()
{
return unit->prepare(thd, result);
}
int subselect_single_select_engine::exec()
{
DBUG_ENTER("subselect_single_select_engine::exec");
if (!optimized)
{
optimized=1;
if (join->optimize())
{
executed= 1;
DBUG_RETURN(join->error?join->error:1);
}
}
if (select_lex->depended && executed)
{
if (join->reinit())
DBUG_RETURN(1);
item->assign_null();
item->assigned((executed= 0));
}
if (!executed)
{
SELECT_LEX *save_select= join->thd->lex.select;
join->thd->lex.select= select_lex;
join->exec();
join->thd->lex.select= save_select;
executed= 1;
DBUG_RETURN(join->error||thd->fatal_error);
}
DBUG_RETURN(0);
}
int subselect_union_engine::exec()
{
return unit->exec();
}
uint subselect_single_select_engine::cols()
{
return select_lex->item_list.elements;
}
uint subselect_union_engine::cols()
{
return unit->first_select()->item_list.elements;
}
bool subselect_single_select_engine::depended()
{
return select_lex->depended;
}
bool subselect_union_engine::depended()
{
return unit->depended;
}
...@@ -20,31 +20,25 @@ ...@@ -20,31 +20,25 @@
#pragma interface /* gcc class implementation */ #pragma interface /* gcc class implementation */
#endif #endif
struct st_select_lex; class st_select_lex;
class st_select_lex_unit;
class JOIN; class JOIN;
class select_subselect; class select_subselect;
class subselect_engine;
/* base class for subselects */ /* base class for subselects */
class Item_subselect :public Item class Item_subselect :public Item
{ {
my_bool engine_owner; /* Is this item owner of engine */
my_bool value_assigned; /* value already assigned to subselect */
protected: protected:
/* engine that perform execution of subselect (single select or union) */
subselect_engine *engine;
/* allowed number of columns (1 for single value subqueries) */
uint max_columns; uint max_columns;
my_bool assigned; /* value already assigned to subselect */
my_bool executed; /* simple subselect is executed */
my_bool optimized; /* simple subselect is optimized */
my_bool error; /* error in query */
int exec();
virtual void assign_null()
{
null_value= 1;
}
public: public:
st_select_lex *select_lex;
JOIN *join;
select_subselect *result;
Item_subselect(THD *thd, st_select_lex *select_lex, Item_subselect(THD *thd, st_select_lex *select_lex,
select_subselect* result); select_subselect* result);
Item_subselect(Item_subselect *item) Item_subselect(Item_subselect *item)
...@@ -52,14 +46,17 @@ public: ...@@ -52,14 +46,17 @@ public:
null_value= item->null_value; null_value= item->null_value;
decimals= item->decimals; decimals= item->decimals;
max_columns= item->max_columns; max_columns= item->max_columns;
assigned= item->assigned; engine= item->engine;
executed= item->executed; engine_owner= 0;
select_lex= item->select_lex;
join= item->join;
result= item->result;
name= item->name; name= item->name;
error= item->error;
} }
~Item_subselect();
virtual void assign_null()
{
null_value= 1;
}
bool assigned() { return value_assigned; }
void assigned(bool a) { value_assigned= a; }
enum Type type() const; enum Type type() const;
bool is_null() { return null_value; } bool is_null() { return null_value; }
void make_field (Send_field *); void make_field (Send_field *);
...@@ -75,18 +72,10 @@ public: ...@@ -75,18 +72,10 @@ public:
class Item_singleval_subselect :public Item_subselect class Item_singleval_subselect :public Item_subselect
{ {
protected: protected:
longlong int_value; longlong int_value; /* here stored integer value of this item */
double real_value; double real_value; /* here stored real value of this item */
enum Item_result res_type; enum Item_result res_type; /* type of results */
virtual void assign_null()
{
null_value= 1;
int_value= 0;
real_value= 0;
max_length= 4;
res_type= STRING_RESULT;
}
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):
...@@ -98,6 +87,14 @@ public: ...@@ -98,6 +87,14 @@ public:
decimals= item->decimals; decimals= item->decimals;
res_type= item->res_type; res_type= item->res_type;
} }
virtual void assign_null()
{
null_value= 1;
int_value= 0;
real_value= 0;
max_length= 4;
res_type= STRING_RESULT;
}
double val (); double val ();
longlong val_int (); longlong val_int ();
String *val_str (String *); String *val_str (String *);
...@@ -112,12 +109,8 @@ public: ...@@ -112,12 +109,8 @@ public:
class Item_exists_subselect :public Item_subselect class Item_exists_subselect :public Item_subselect
{ {
protected: protected:
longlong value; longlong value; /* value of this item (boolean: exists/not-exists) */
virtual void assign_null()
{
value= 0;
}
public: public:
Item_exists_subselect(THD *thd, st_select_lex *select_lex); Item_exists_subselect(THD *thd, st_select_lex *select_lex);
Item_exists_subselect(Item_exists_subselect *item): Item_exists_subselect(Item_exists_subselect *item):
...@@ -125,6 +118,11 @@ public: ...@@ -125,6 +118,11 @@ public:
{ {
value= item->value; value= item->value;
} }
virtual void assign_null()
{
value= 0;
}
Item *new_item() { return new Item_exists_subselect(this); } Item *new_item() { return new Item_exists_subselect(this); }
enum Item_result result_type() const { return INT_RESULT;} enum Item_result result_type() const { return INT_RESULT;}
longlong val_int(); longlong val_int();
...@@ -133,3 +131,58 @@ public: ...@@ -133,3 +131,58 @@ public:
friend class select_exists_subselect; friend class select_exists_subselect;
}; };
class subselect_engine
{
protected:
select_subselect *result; /* results storage class */
THD *thd; /* pointer to current THD */
Item_subselect *item; /* item, that use this engine */
public:
static void *operator new(size_t size)
{
return (void*) sql_alloc((uint) size);
}
static void operator delete(void *ptr, size_t size) {}
subselect_engine(THD *thd, Item_subselect *si, select_subselect *res)
{
result= res;
item= si;
this->thd= thd;
}
virtual int prepare()= 0;
virtual int exec()= 0;
virtual uint cols()= 0; /* return number of columnss in select */
virtual bool depended()= 0; /* depended from outer select */
};
class subselect_single_select_engine: public subselect_engine
{
my_bool executed; /* simple subselect is executed */
my_bool optimized; /* simple subselect is optimized */
st_select_lex *select_lex; /* corresponding select_lex */
JOIN * join; /* corresponding JOIN structure */
public:
subselect_single_select_engine(THD *thd, st_select_lex *select,
select_subselect *result,
Item_subselect *item);
virtual int prepare();
virtual int exec();
virtual uint cols();
virtual bool depended();
};
class subselect_union_engine: public subselect_engine
{
st_select_lex_unit *unit; /* corresponding unit structure */
public:
subselect_union_engine(THD *thd,
st_select_lex_unit *u,
select_subselect *result,
Item_subselect *item);
virtual int prepare();
virtual int exec();
virtual uint cols();
virtual bool depended();
};
...@@ -373,7 +373,7 @@ int handle_select(THD *thd, LEX *lex, select_result *result); ...@@ -373,7 +373,7 @@ int handle_select(THD *thd, LEX *lex, select_result *result);
int mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &list,COND *conds, int mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &list,COND *conds,
ORDER *order, ORDER *group,Item *having,ORDER *proc_param, ORDER *order, ORDER *group,Item *having,ORDER *proc_param,
ulong select_type,select_result *result, ulong select_type,select_result *result,
SELECT_LEX_UNIT *unit); SELECT_LEX_UNIT *unit, bool fake_select_lex);
int mysql_union(THD *thd, LEX *lex,select_result *result); int mysql_union(THD *thd, LEX *lex,select_result *result);
int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *s, TABLE_LIST *t); int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *s, TABLE_LIST *t);
Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
...@@ -438,7 +438,8 @@ bool wait_for_tables(THD *thd); ...@@ -438,7 +438,8 @@ bool wait_for_tables(THD *thd);
bool table_is_used(TABLE *table, bool wait_for_name_lock); bool table_is_used(TABLE *table, bool wait_for_name_lock);
bool drop_locked_tables(THD *thd,const char *db, const char *table_name); bool drop_locked_tables(THD *thd,const char *db, const char *table_name);
void abort_locked_tables(THD *thd,const char *db, const char *table_name); void abort_locked_tables(THD *thd,const char *db, const char *table_name);
Field *find_field_in_tables(THD *thd,Item_field *item,TABLE_LIST *tables); Field *find_field_in_tables(THD *thd, Item_field *item, TABLE_LIST *tables,
bool report_error);
Field *find_field_in_table(THD *thd,TABLE *table,const char *name,uint length, Field *find_field_in_table(THD *thd,TABLE *table,const char *name,uint length,
bool check_grant,bool allow_rowid); bool check_grant,bool allow_rowid);
#ifdef HAVE_OPENSSL #ifdef HAVE_OPENSSL
...@@ -526,7 +527,7 @@ TABLE *unlink_open_table(THD *thd,TABLE *list,TABLE *find); ...@@ -526,7 +527,7 @@ TABLE *unlink_open_table(THD *thd,TABLE *list,TABLE *find);
SQL_SELECT *make_select(TABLE *head, table_map const_tables, SQL_SELECT *make_select(TABLE *head, table_map const_tables,
table_map read_tables, COND *conds, int *error); table_map read_tables, COND *conds, int *error);
Item ** find_item_in_list(Item *item,List<Item> &items); Item ** find_item_in_list(Item *item, List<Item> &items, bool report_error);
bool insert_fields(THD *thd,TABLE_LIST *tables, bool insert_fields(THD *thd,TABLE_LIST *tables,
const char *db_name, const char *table_name, const char *db_name, const char *table_name,
List_iterator<Item> *it); List_iterator<Item> *it);
......
...@@ -1608,8 +1608,9 @@ static int my_message_sql(uint error, const char *str, ...@@ -1608,8 +1608,9 @@ static int my_message_sql(uint error, const char *str,
NET *net; NET *net;
DBUG_ENTER("my_message_sql"); DBUG_ENTER("my_message_sql");
DBUG_PRINT("error",("Message: '%s'",str)); DBUG_PRINT("error",("Message: '%s'",str));
if ((net=my_pthread_getspecific_ptr(NET*,THR_NET))) if ((net= my_pthread_getspecific_ptr(NET*,THR_NET)))
{ {
net->report_error= 1;
if (!net->last_error[0]) // Return only first message if (!net->last_error[0]) // Return only first message
{ {
strmake(net->last_error,str,sizeof(net->last_error)-1); strmake(net->last_error,str,sizeof(net->last_error)-1);
......
...@@ -72,7 +72,10 @@ void send_error(NET *net, uint sql_errno, const char *err) ...@@ -72,7 +72,10 @@ void send_error(NET *net, uint sql_errno, const char *err)
} }
VOID(net_write_command(net,(uchar) 255,(char*) err,length)); VOID(net_write_command(net,(uchar) 255,(char*) err,length));
if (thd) if (thd)
thd->fatal_error=0; // Error message is given {
thd->fatal_error= 0; // Error message is given
thd->net.report_error= 0;
}
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
......
...@@ -113,6 +113,7 @@ int my_net_init(NET *net, Vio* vio) ...@@ -113,6 +113,7 @@ int my_net_init(NET *net, Vio* vio)
net->where_b = net->remain_in_buf=0; net->where_b = net->remain_in_buf=0;
net->last_errno=0; net->last_errno=0;
net->query_cache_query=0; net->query_cache_query=0;
net->report_error= 0;
if (vio != 0) /* If real connection */ if (vio != 0) /* If real connection */
{ {
...@@ -141,8 +142,9 @@ static my_bool net_realloc(NET *net, ulong length) ...@@ -141,8 +142,9 @@ static my_bool net_realloc(NET *net, ulong length)
if (length >= max_allowed_packet) if (length >= max_allowed_packet)
{ {
DBUG_PRINT("error",("Packet too large (%lu)", length)); DBUG_PRINT("error",("Packet too large (%lu)", length));
net->error=1; net->error= 1;
net->last_errno=ER_NET_PACKET_TOO_LARGE; net->report_error= 1;
net->last_errno= ER_NET_PACKET_TOO_LARGE;
return 1; return 1;
} }
pkt_length = (length+IO_SIZE-1) & ~(IO_SIZE-1); pkt_length = (length+IO_SIZE-1) & ~(IO_SIZE-1);
...@@ -152,9 +154,10 @@ static my_bool net_realloc(NET *net, ulong length) ...@@ -152,9 +154,10 @@ static my_bool net_realloc(NET *net, ulong length)
NET_HEADER_SIZE + COMP_HEADER_SIZE, NET_HEADER_SIZE + COMP_HEADER_SIZE,
MYF(MY_WME)))) MYF(MY_WME))))
{ {
net->error=1; net->error= 1;
net->report_error= 1;
#ifdef MYSQL_SERVER #ifdef MYSQL_SERVER
net->last_errno=ER_OUT_OF_RESOURCES; net->last_errno= ER_OUT_OF_RESOURCES;
#endif #endif
return 1; return 1;
} }
...@@ -348,10 +351,12 @@ net_real_write(NET *net,const char *packet,ulong len) ...@@ -348,10 +351,12 @@ net_real_write(NET *net,const char *packet,ulong len)
COMP_HEADER_SIZE, MYF(MY_WME)))) COMP_HEADER_SIZE, MYF(MY_WME))))
{ {
#ifdef MYSQL_SERVER #ifdef MYSQL_SERVER
net->last_errno=ER_OUT_OF_RESOURCES; net->last_errno= ER_OUT_OF_RESOURCES;
net->error=2; net->error= 2;
//TODO is it needed to set this variable if we have no socket
net->report_error= 1;
#endif #endif
net->reading_or_writing=0; net->reading_or_writing= 0;
DBUG_RETURN(1); DBUG_RETURN(1);
} }
memcpy(b+header_length,packet,len); memcpy(b+header_length,packet,len);
...@@ -401,7 +406,8 @@ net_real_write(NET *net,const char *packet,ulong len) ...@@ -401,7 +406,8 @@ net_real_write(NET *net,const char *packet,ulong len)
"%s: my_net_write: fcntl returned error %d, aborting thread\n", "%s: my_net_write: fcntl returned error %d, aborting thread\n",
my_progname,vio_errno(net->vio)); my_progname,vio_errno(net->vio));
#endif /* EXTRA_DEBUG */ #endif /* EXTRA_DEBUG */
net->error=2; /* Close socket */ net->error= 2; /* Close socket */
net->report_error= 1;
goto end; goto end;
} }
} }
...@@ -428,7 +434,8 @@ net_real_write(NET *net,const char *packet,ulong len) ...@@ -428,7 +434,8 @@ net_real_write(NET *net,const char *packet,ulong len)
continue; continue;
} }
#endif /* defined(THREAD_SAFE_CLIENT) && !defined(MYSQL_SERVER) */ #endif /* defined(THREAD_SAFE_CLIENT) && !defined(MYSQL_SERVER) */
net->error=2; /* Close socket */ net->error= 2; /* Close socket */
net->report_error= 1;
#ifdef MYSQL_SERVER #ifdef MYSQL_SERVER
net->last_errno= (interrupted ? ER_NET_WRITE_INTERRUPTED : net->last_errno= (interrupted ? ER_NET_WRITE_INTERRUPTED :
ER_NET_ERROR_ON_WRITE); ER_NET_ERROR_ON_WRITE);
...@@ -562,9 +569,10 @@ my_real_read(NET *net, ulong *complen) ...@@ -562,9 +569,10 @@ my_real_read(NET *net, ulong *complen)
my_progname,vio_errno(net->vio)); my_progname,vio_errno(net->vio));
#endif /* EXTRA_DEBUG */ #endif /* EXTRA_DEBUG */
len= packet_error; len= packet_error;
net->error=2; /* Close socket */ net->error= 2; /* Close socket */
net->report_error= 1;
#ifdef MYSQL_SERVER #ifdef MYSQL_SERVER
net->last_errno=ER_NET_FCNTL_ERROR; net->last_errno= ER_NET_FCNTL_ERROR;
#endif #endif
goto end; goto end;
} }
...@@ -593,7 +601,8 @@ my_real_read(NET *net, ulong *complen) ...@@ -593,7 +601,8 @@ my_real_read(NET *net, ulong *complen)
#endif #endif
DBUG_PRINT("error",("Couldn't read packet: remain: %lu errno: %d length: %ld alarmed: %d", remain,vio_errno(net->vio),length,alarmed)); DBUG_PRINT("error",("Couldn't read packet: remain: %lu errno: %d length: %ld alarmed: %d", remain,vio_errno(net->vio),length,alarmed));
len= packet_error; len= packet_error;
net->error=2; /* Close socket */ net->error= 2; /* Close socket */
net->report_error= 1;
#ifdef MYSQL_SERVER #ifdef MYSQL_SERVER
net->last_errno= (interrupted ? ER_NET_READ_INTERRUPTED : net->last_errno= (interrupted ? ER_NET_READ_INTERRUPTED :
ER_NET_READ_ERROR); ER_NET_READ_ERROR);
...@@ -622,6 +631,7 @@ my_real_read(NET *net, ulong *complen) ...@@ -622,6 +631,7 @@ my_real_read(NET *net, ulong *complen)
#endif #endif
} }
len= packet_error; len= packet_error;
net->report_error= 1;
#ifdef MYSQL_SERVER #ifdef MYSQL_SERVER
net->last_errno=ER_NET_PACKETS_OUT_OF_ORDER; net->last_errno=ER_NET_PACKETS_OUT_OF_ORDER;
#endif #endif
...@@ -794,7 +804,8 @@ my_net_read(NET *net) ...@@ -794,7 +804,8 @@ my_net_read(NET *net)
if (my_uncompress((byte*) net->buff + net->where_b, &packet_len, if (my_uncompress((byte*) net->buff + net->where_b, &packet_len,
&complen)) &complen))
{ {
net->error=2; /* caller will close socket */ net->error= 2; /* caller will close socket */
net->report_error= 1;
#ifdef MYSQL_SERVER #ifdef MYSQL_SERVER
net->last_errno=ER_NET_UNCOMPRESS_ERROR; net->last_errno=ER_NET_UNCOMPRESS_ERROR;
#endif #endif
......
...@@ -1711,7 +1711,8 @@ Field *find_field_in_table(THD *thd,TABLE *table,const char *name,uint length, ...@@ -1711,7 +1711,8 @@ Field *find_field_in_table(THD *thd,TABLE *table,const char *name,uint length,
Field * Field *
find_field_in_tables(THD *thd,Item_field *item,TABLE_LIST *tables) find_field_in_tables(THD *thd,Item_field *item,TABLE_LIST *tables,
bool report_error)
{ {
Field *found=0; Field *found=0;
const char *db=item->db_name; const char *db=item->db_name;
...@@ -1748,7 +1749,7 @@ find_field_in_tables(THD *thd,Item_field *item,TABLE_LIST *tables) ...@@ -1748,7 +1749,7 @@ find_field_in_tables(THD *thd,Item_field *item,TABLE_LIST *tables)
} }
if (found) if (found)
return found; return found;
if (!found_table) if (!found_table && report_error)
{ {
char buff[NAME_LEN*2+1]; char buff[NAME_LEN*2+1];
if (db) if (db)
...@@ -1760,8 +1761,9 @@ find_field_in_tables(THD *thd,Item_field *item,TABLE_LIST *tables) ...@@ -1760,8 +1761,9 @@ find_field_in_tables(THD *thd,Item_field *item,TABLE_LIST *tables)
thd->where); thd->where);
} }
else else
my_printf_error(ER_BAD_FIELD_ERROR,ER(ER_BAD_FIELD_ERROR),MYF(0), if (report_error)
item->full_name(),thd->where); my_printf_error(ER_BAD_FIELD_ERROR,ER(ER_BAD_FIELD_ERROR),MYF(0),
item->full_name(),thd->where);
return (Field*) 0; return (Field*) 0;
} }
bool allow_rowid= tables && !tables->next; // Only one table bool allow_rowid= tables && !tables->next; // Only one table
...@@ -1778,8 +1780,9 @@ find_field_in_tables(THD *thd,Item_field *item,TABLE_LIST *tables) ...@@ -1778,8 +1780,9 @@ find_field_in_tables(THD *thd,Item_field *item,TABLE_LIST *tables)
{ {
if (!thd->where) // Returns first found if (!thd->where) // Returns first found
break; break;
my_printf_error(ER_NON_UNIQ_ERROR,ER(ER_NON_UNIQ_ERROR),MYF(0), if (report_error)
name,thd->where); my_printf_error(ER_NON_UNIQ_ERROR,ER(ER_NON_UNIQ_ERROR),MYF(0),
name,thd->where);
return (Field*) 0; return (Field*) 0;
} }
found=field; found=field;
...@@ -1787,13 +1790,14 @@ find_field_in_tables(THD *thd,Item_field *item,TABLE_LIST *tables) ...@@ -1787,13 +1790,14 @@ find_field_in_tables(THD *thd,Item_field *item,TABLE_LIST *tables)
} }
if (found) if (found)
return found; return found;
my_printf_error(ER_BAD_FIELD_ERROR,ER(ER_BAD_FIELD_ERROR), if (report_error)
MYF(0),item->full_name(),thd->where); my_printf_error(ER_BAD_FIELD_ERROR, ER(ER_BAD_FIELD_ERROR),
MYF(0), item->full_name(), thd->where);
return (Field*) 0; return (Field*) 0;
} }
Item ** Item **
find_item_in_list(Item *find,List<Item> &items) find_item_in_list(Item *find,List<Item> &items, bool report_error)
{ {
List_iterator<Item> li(items); List_iterator<Item> li(items);
Item **found=0,*item; Item **found=0,*item;
...@@ -1841,9 +1845,9 @@ find_item_in_list(Item *find,List<Item> &items) ...@@ -1841,9 +1845,9 @@ find_item_in_list(Item *find,List<Item> &items)
break; break;
} }
} }
if (!found && current_thd->where) if (!found && report_error)
my_printf_error(ER_BAD_FIELD_ERROR,ER(ER_BAD_FIELD_ERROR),MYF(0), my_printf_error(ER_BAD_FIELD_ERROR, ER(ER_BAD_FIELD_ERROR), MYF(0),
find->full_name(),current_thd->where); find->full_name(), current_thd->where);
return found; return found;
} }
...@@ -2303,8 +2307,8 @@ bool remove_table_from_cache(THD *thd, const char *db, const char *table_name, ...@@ -2303,8 +2307,8 @@ bool remove_table_from_cache(THD *thd, const char *db, const char *table_name,
int setup_ftfuncs(THD *thd) int setup_ftfuncs(THD *thd)
{ {
List_iterator<Item_func_match> li(thd->lex.select->ftfunc_list), List_iterator<Item_func_match> li(*(thd->lex.select->ftfunc_list)),
lj(thd->lex.select->ftfunc_list); lj(*(thd->lex.select->ftfunc_list));
Item_func_match *ftf, *ftf2; Item_func_match *ftf, *ftf2;
while ((ftf=li++)) while ((ftf=li++))
...@@ -2324,9 +2328,9 @@ int setup_ftfuncs(THD *thd) ...@@ -2324,9 +2328,9 @@ int setup_ftfuncs(THD *thd)
int init_ftfuncs(THD *thd, bool no_order) int init_ftfuncs(THD *thd, bool no_order)
{ {
if (thd->lex.select->ftfunc_list.elements) if (thd->lex.select->ftfunc_list->elements)
{ {
List_iterator<Item_func_match> li(thd->lex.select->ftfunc_list); List_iterator<Item_func_match> li(*(thd->lex.select->ftfunc_list));
Item_func_match *ifm; Item_func_match *ifm;
DBUG_PRINT("info",("Performing FULLTEXT search")); DBUG_PRINT("info",("Performing FULLTEXT search"));
thd->proc_info="FULLTEXT initialization"; thd->proc_info="FULLTEXT initialization";
......
...@@ -407,13 +407,19 @@ bool select_send::send_data(List<Item> &items) ...@@ -407,13 +407,19 @@ bool select_send::send_data(List<Item> &items)
if (item->send(thd, packet)) if (item->send(thd, packet))
{ {
packet->free(); // Free used packet->free(); // Free used
my_error(ER_OUT_OF_RESOURCES,MYF(0)); my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
DBUG_RETURN(1); DBUG_RETURN(1);
} }
} }
thd->sent_row_count++; thd->sent_row_count++;
bool error=my_net_write(&thd->net,(char*) packet->ptr(),packet->length()); if (!thd->net.report_error)
DBUG_RETURN(error); {
DBUG_RETURN(my_net_write(&thd->net,
(char*) packet->ptr(),
packet->length()));
}
else
DBUG_RETURN(1);
} }
bool select_send::send_eof() bool select_send::send_eof()
...@@ -423,8 +429,13 @@ bool select_send::send_eof() ...@@ -423,8 +429,13 @@ bool select_send::send_eof()
{ {
mysql_unlock_tables(thd, thd->lock); thd->lock=0; mysql_unlock_tables(thd, thd->lock); thd->lock=0;
} }
::send_eof(&thd->net); if (!thd->net.report_error)
return 0; {
::send_eof(&thd->net);
return 0;
}
else
return 1;
} }
...@@ -460,7 +471,7 @@ select_export::prepare(List<Item> &list, SELECT_LEX_UNIT *u) ...@@ -460,7 +471,7 @@ select_export::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
option); option);
if (!access(path,F_OK)) if (!access(path,F_OK))
{ {
my_error(ER_FILE_EXISTS_ERROR,MYF(0),exchange->file_name); my_error(ER_FILE_EXISTS_ERROR, MYF(0), exchange->file_name);
return 1; return 1;
} }
/* Create the file world readable */ /* Create the file world readable */
...@@ -646,9 +657,9 @@ err: ...@@ -646,9 +657,9 @@ err:
} }
void select_export::send_error(uint errcode,const char *err) void select_export::send_error(uint errcode, const char *err)
{ {
::send_error(&thd->net,errcode,err); my_message(errcode, err, MYF(0));;
(void) end_io_cache(&cache); (void) end_io_cache(&cache);
(void) my_close(file,MYF(0)); (void) my_close(file,MYF(0));
file= -1; file= -1;
...@@ -660,9 +671,7 @@ bool select_export::send_eof() ...@@ -660,9 +671,7 @@ bool select_export::send_eof()
int error=test(end_io_cache(&cache)); int error=test(end_io_cache(&cache));
if (my_close(file,MYF(MY_WME))) if (my_close(file,MYF(MY_WME)))
error=1; error=1;
if (error) if (!error)
::send_error(&thd->net);
else
::send_ok(&thd->net,row_count); ::send_ok(&thd->net,row_count);
file= -1; file= -1;
return error; return error;
...@@ -735,7 +744,7 @@ bool select_dump::send_data(List<Item> &items) ...@@ -735,7 +744,7 @@ bool select_dump::send_data(List<Item> &items)
} }
if (row_count++ > 1) if (row_count++ > 1)
{ {
my_error(ER_TOO_MANY_ROWS,MYF(0)); my_error(ER_TOO_MANY_ROWS, MYF(0));
goto err; goto err;
} }
while ((item=li++)) while ((item=li++))
...@@ -760,7 +769,7 @@ err: ...@@ -760,7 +769,7 @@ err:
void select_dump::send_error(uint errcode,const char *err) void select_dump::send_error(uint errcode,const char *err)
{ {
::send_error(&thd->net,errcode,err); my_message(errcode, err, MYF(0));
(void) end_io_cache(&cache); (void) end_io_cache(&cache);
(void) my_close(file,MYF(0)); (void) my_close(file,MYF(0));
(void) my_delete(path,MYF(0)); // Delete file on error (void) my_delete(path,MYF(0)); // Delete file on error
...@@ -772,9 +781,7 @@ bool select_dump::send_eof() ...@@ -772,9 +781,7 @@ bool select_dump::send_eof()
int error=test(end_io_cache(&cache)); int error=test(end_io_cache(&cache));
if (my_close(file,MYF(MY_WME))) if (my_close(file,MYF(MY_WME)))
error=1; error=1;
if (error) if (!error)
::send_error(&thd->net);
else
::send_ok(&thd->net,row_count); ::send_ok(&thd->net,row_count);
file= -1; file= -1;
return error; return error;
...@@ -789,8 +796,9 @@ bool select_singleval_subselect::send_data(List<Item> &items) ...@@ -789,8 +796,9 @@ bool select_singleval_subselect::send_data(List<Item> &items)
{ {
DBUG_ENTER("select_singleval_subselect::send_data"); DBUG_ENTER("select_singleval_subselect::send_data");
Item_singleval_subselect *it= (Item_singleval_subselect *)item; Item_singleval_subselect *it= (Item_singleval_subselect *)item;
if (it->assigned){ if (it->assigned()){
my_printf_error(ER_SUBSELECT_NO_1_ROW, ER(ER_SUBSELECT_NO_1_ROW), MYF(0)); thd->fatal_error= 1;
my_message(ER_SUBSELECT_NO_1_ROW, ER(ER_SUBSELECT_NO_1_ROW), MYF(0));
DBUG_RETURN(1); DBUG_RETURN(1);
} }
if (unit->offset_limit_cnt) if (unit->offset_limit_cnt)
...@@ -816,7 +824,7 @@ bool select_singleval_subselect::send_data(List<Item> &items) ...@@ -816,7 +824,7 @@ bool select_singleval_subselect::send_data(List<Item> &items)
it->int_value= val_item->val_int(); it->int_value= val_item->val_int();
it->res_type= val_item->result_type(); it->res_type= val_item->result_type();
} }
it->assigned= 1; it->assigned(1);
DBUG_RETURN(0); DBUG_RETURN(0);
} }
...@@ -830,7 +838,7 @@ bool select_exists_subselect::send_data(List<Item> &items) ...@@ -830,7 +838,7 @@ bool select_exists_subselect::send_data(List<Item> &items)
DBUG_RETURN(0); DBUG_RETURN(0);
} }
it->value= 1; it->value= 1;
it->assigned= 1; it->assigned(1);
DBUG_RETURN(0); DBUG_RETURN(0);
} }
...@@ -453,7 +453,7 @@ public: ...@@ -453,7 +453,7 @@ public:
bool query_error, bootstrap, cleanup_done; bool query_error, bootstrap, cleanup_done;
bool safe_to_cache_query; bool safe_to_cache_query;
bool volatile killed; bool volatile killed;
bool prepare_command; bool prepare_command;
ulong param_count,current_param_number; ulong param_count,current_param_number;
Error<mysql_st_error> err_list; Error<mysql_st_error> err_list;
Error<mysql_st_error> warn_list; Error<mysql_st_error> warn_list;
...@@ -621,7 +621,7 @@ public: ...@@ -621,7 +621,7 @@ public:
virtual void initialize_tables (JOIN *join=0) {} virtual void initialize_tables (JOIN *join=0) {}
virtual void send_error(uint errcode,const char *err) virtual void send_error(uint errcode,const char *err)
{ {
::send_error(&thd->net,errcode,err); my_message(errcode, err, MYF(0));
} }
virtual bool send_eof()=0; virtual bool send_eof()=0;
virtual void abort() {} virtual void abort() {}
......
...@@ -99,7 +99,7 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t) ...@@ -99,7 +99,7 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
(ORDER*) sl->group_list.first, (ORDER*) sl->group_list.first,
sl->having, (ORDER*) NULL, sl->having, (ORDER*) NULL,
sl->options | thd->options | SELECT_NO_UNLOCK, sl->options | thd->options | SELECT_NO_UNLOCK,
derived_result, unit); derived_result, unit, 0);
if (!res) if (!res)
{ {
// Here we entirely fix both TABLE_LIST and list of SELECT's as there were no derived tables // Here we entirely fix both TABLE_LIST and list of SELECT's as there were no derived tables
......
...@@ -1331,6 +1331,7 @@ bool select_insert::send_data(List<Item> &values) ...@@ -1331,6 +1331,7 @@ bool select_insert::send_data(List<Item> &values)
void select_insert::send_error(uint errcode,const char *err) void select_insert::send_error(uint errcode,const char *err)
{ {
//TODO error should be sent at the query processing end
::send_error(&thd->net,errcode,err); ::send_error(&thd->net,errcode,err);
table->file->extra(HA_EXTRA_NO_CACHE); table->file->extra(HA_EXTRA_NO_CACHE);
table->file->activate_all_index(thd); table->file->activate_all_index(thd);
...@@ -1357,6 +1358,7 @@ bool select_insert::send_eof() ...@@ -1357,6 +1358,7 @@ bool select_insert::send_eof()
if (error) if (error)
{ {
table->file->print_error(error,MYF(0)); table->file->print_error(error,MYF(0));
//TODO error should be sent at the query processing end
::send_error(&thd->net); ::send_error(&thd->net);
return 1; return 1;
} }
......
...@@ -146,7 +146,8 @@ LEX *lex_start(THD *thd, uchar *buf,uint length) ...@@ -146,7 +146,8 @@ LEX *lex_start(THD *thd, uchar *buf,uint length)
lex->length=0; lex->length=0;
lex->select->in_sum_expr=0; lex->select->in_sum_expr=0;
lex->select->expr_list.empty(); lex->select->expr_list.empty();
lex->select->ftfunc_list.empty(); lex->select->ftfunc_list_alloc.empty();
lex->select->ftfunc_list= &lex->select->ftfunc_list_alloc;
lex->convert_set=(lex->thd=thd)->convert_set; lex->convert_set=(lex->thd=thd)->convert_set;
lex->yacc_yyss=lex->yacc_yyvs=0; lex->yacc_yyss=lex->yacc_yyvs=0;
lex->ignore_space=test(thd->sql_mode & MODE_IGNORE_SPACE); lex->ignore_space=test(thd->sql_mode & MODE_IGNORE_SPACE);
...@@ -918,6 +919,8 @@ void st_select_lex_unit::init_query() ...@@ -918,6 +919,8 @@ void st_select_lex_unit::init_query()
global_parameters= this; global_parameters= this;
select_limit_cnt= HA_POS_ERROR; select_limit_cnt= HA_POS_ERROR;
offset_limit_cnt= 0; offset_limit_cnt= 0;
optimized= 0;
item= 0;
} }
void st_select_lex::init_query() void st_select_lex::init_query()
...@@ -941,9 +944,11 @@ void st_select_lex::init_select() ...@@ -941,9 +944,11 @@ void st_select_lex::init_select()
expr_list.empty(); expr_list.empty();
interval_list.empty(); interval_list.empty();
use_index.empty(); use_index.empty();
ftfunc_list.empty(); ftfunc_list_alloc.empty();
ftfunc_list= &ftfunc_list_alloc;
linkage= UNSPECIFIED_TYPE; linkage= UNSPECIFIED_TYPE;
depended= having_fix_field= 0; depended= having_fix_field= 0;
} }
/* /*
......
...@@ -216,7 +216,22 @@ private: ...@@ -216,7 +216,22 @@ private:
*/ */
class st_lex; class st_lex;
class st_select_lex; class st_select_lex;
class THD;
class select_result;
class JOIN;
class select_union;
class st_select_lex_unit: public st_select_lex_node { class st_select_lex_unit: public st_select_lex_node {
protected:
List<Item> item_list;
List<JOIN*> joins; /* list of *JOINs, to delete it in cleanup() */
TABLE_LIST result_table_list;
select_union *union_result;
TABLE *table; /* temporary table using for appending UNION results */
THD *thd;
select_result *result;
int res;
bool describe, found_rows_for_union,
optimized; // optimize phase already performed for UNION (unit)
public: public:
/* /*
Pointer to 'last' select or pointer to unit where stored Pointer to 'last' select or pointer to unit where stored
...@@ -225,12 +240,21 @@ public: ...@@ -225,12 +240,21 @@ public:
st_select_lex_node *global_parameters; st_select_lex_node *global_parameters;
/* LIMIT clause runtime counters */ /* LIMIT clause runtime counters */
ha_rows select_limit_cnt, offset_limit_cnt; ha_rows select_limit_cnt, offset_limit_cnt;
bool depended; /* depended from outer select subselect */
/* not NULL if union used in subselect, point to subselect item */
Item_subselect *item;
void init_query(); void init_query();
bool create_total_list(THD *thd, st_lex *lex, TABLE_LIST **result); bool create_total_list(THD *thd, st_lex *lex, TABLE_LIST **result);
st_select_lex* outer_select() { return (st_select_lex*) master; } st_select_lex* outer_select() { return (st_select_lex*) master; }
st_select_lex* first_select() { return (st_select_lex*) slave; } st_select_lex* first_select() { return (st_select_lex*) slave; }
st_select_lex_unit* next_unit() { return (st_select_lex_unit*) next; } st_select_lex_unit* next_unit() { return (st_select_lex_unit*) next; }
/* UNION methods */
int prepare(THD *thd, select_result *result);
int exec();
int cleanup();
friend void mysql_init_query(THD *thd); friend void mysql_init_query(THD *thd);
private: private:
bool create_total_list_n_last_return(THD *thd, st_lex *lex, bool create_total_list_n_last_return(THD *thd, st_lex *lex,
...@@ -241,7 +265,6 @@ typedef struct st_select_lex_unit SELECT_LEX_UNIT; ...@@ -241,7 +265,6 @@ typedef struct st_select_lex_unit SELECT_LEX_UNIT;
/* /*
SELECT_LEX - store information of parsed SELECT_LEX statment SELECT_LEX - store information of parsed SELECT_LEX statment
*/ */
class JOIN;
class st_select_lex: public st_select_lex_node { class st_select_lex: public st_select_lex_node {
public: public:
char *db, *db1, *table1, *db2, *table2; /* For outer join using .. */ char *db, *db1, *table1, *db2, *table2; /* For outer join using .. */
...@@ -252,7 +275,12 @@ public: ...@@ -252,7 +275,12 @@ public:
List<Item> item_list; /* list of fields & expressions */ List<Item> item_list; /* list of fields & expressions */
List<String> interval_list, use_index, *use_index_ptr, List<String> interval_list, use_index, *use_index_ptr,
ignore_index, *ignore_index_ptr; ignore_index, *ignore_index_ptr;
List<Item_func_match> ftfunc_list; /*
Usualy it is pointer to ftfunc_list_alloc, but in union used to create fake
select_lex for calling mysql_select under results of union
*/
List<Item_func_match> *ftfunc_list;
List<Item_func_match> ftfunc_list_alloc;
JOIN *join; /* after JOIN::prepare it is pointer to corresponding JOIN */ JOIN *join; /* after JOIN::prepare it is pointer to corresponding JOIN */
uint in_sum_expr; uint in_sum_expr;
bool create_refs, bool create_refs,
......
...@@ -665,7 +665,7 @@ pthread_handler_decl(handle_one_connection,arg) ...@@ -665,7 +665,7 @@ pthread_handler_decl(handle_one_connection,arg)
if (thd->user_connect) if (thd->user_connect)
decrease_user_connections(thd->user_connect); decrease_user_connections(thd->user_connect);
free_root(&thd->mem_root,MYF(0)); free_root(&thd->mem_root,MYF(0));
if (net->error && net->vio != 0) if (net->error && net->vio != 0 && net->report_error)
{ {
if (!thd->killed && opt_warnings) if (!thd->killed && opt_warnings)
sql_print_error(ER(ER_NEW_ABORTING_CONNECTION), sql_print_error(ER(ER_NEW_ABORTING_CONNECTION),
...@@ -1169,6 +1169,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, ...@@ -1169,6 +1169,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
break; break;
} }
case COM_PING: case COM_PING:
DBUG_PRINT("info", ("query: PING"));
thread_safe_increment(com_other,&LOCK_thread_count); thread_safe_increment(com_other,&LOCK_thread_count);
send_ok(net); // Tell client we are alive send_ok(net); // Tell client we are alive
break; break;
...@@ -1257,6 +1258,7 @@ mysql_execute_command(void) ...@@ -1257,6 +1258,7 @@ mysql_execute_command(void)
SELECT_LEX_UNIT *unit= &lex->unit; SELECT_LEX_UNIT *unit= &lex->unit;
DBUG_ENTER("mysql_execute_command"); DBUG_ENTER("mysql_execute_command");
thd->net.report_error= 0;
if (thd->slave_thread) if (thd->slave_thread)
{ {
/* /*
...@@ -1864,7 +1866,7 @@ mysql_execute_command(void) ...@@ -1864,7 +1866,7 @@ mysql_execute_command(void)
(ORDER *)NULL, (ORDER *)NULL,
select_lex->options | thd->options | select_lex->options | thd->options |
SELECT_NO_JOIN_CACHE, SELECT_NO_JOIN_CACHE,
result, unit); result, unit, 0);
delete result; delete result;
} }
else else
...@@ -2029,13 +2031,13 @@ mysql_execute_command(void) ...@@ -2029,13 +2031,13 @@ mysql_execute_command(void)
lex->lock_option, lex->lock_option,
table_count))) table_count)))
{ {
res=mysql_select(thd,tables,select_lex->item_list, res= mysql_select(thd,tables,select_lex->item_list,
select_lex->where, select_lex->where,
(ORDER *)NULL,(ORDER *)NULL,(Item *)NULL, (ORDER *)NULL,(ORDER *)NULL,(Item *)NULL,
(ORDER *)NULL, (ORDER *)NULL,
select_lex->options | thd->options | select_lex->options | thd->options |
SELECT_NO_JOIN_CACHE, SELECT_NO_JOIN_CACHE,
result, unit); result, unit, 0);
delete result; delete result;
} }
else else
......
...@@ -178,9 +178,14 @@ int handle_select(THD *thd, LEX *lex, select_result *result) ...@@ -178,9 +178,14 @@ int handle_select(THD *thd, LEX *lex, select_result *result)
select_lex->having, select_lex->having,
(ORDER*) lex->proc_list.first, (ORDER*) lex->proc_list.first,
select_lex->options | thd->options, select_lex->options | thd->options,
result, &(lex->unit)); result, &(lex->unit), 0);
if (res && result) if (res && result)
result->abort(); result->abort();
if (res || thd->net.report_error)
{
send_error(&thd->net, 0, MYF(0));
res= 1;
}
delete result; delete result;
return res; return res;
} }
...@@ -198,9 +203,10 @@ int handle_select(THD *thd, LEX *lex, select_result *result) ...@@ -198,9 +203,10 @@ int handle_select(THD *thd, LEX *lex, select_result *result)
*/ */
int int
JOIN::prepare(TABLE_LIST *tables_init, JOIN::prepare(TABLE_LIST *tables_init,
COND *conds_init, ORDER *order_init, ORDER *group_init, COND *conds_init, ORDER *order_init, ORDER *group_init,
Item *having_init, Item *having_init,
ORDER *proc_param_init, SELECT_LEX *select, SELECT_LEX_UNIT *unit) ORDER *proc_param_init, SELECT_LEX *select,
SELECT_LEX_UNIT *unit, bool fake_select_lex)
{ {
DBUG_ENTER("JOIN::prepare"); DBUG_ENTER("JOIN::prepare");
...@@ -211,7 +217,8 @@ JOIN::prepare(TABLE_LIST *tables_init, ...@@ -211,7 +217,8 @@ JOIN::prepare(TABLE_LIST *tables_init,
proc_param= proc_param_init; proc_param= proc_param_init;
tables_list= tables_init; tables_list= tables_init;
select_lex= select; select_lex= select;
select->join= this; if (!fake_select_lex)
select->join= this;
union_part= (unit->first_select()->next_select() != 0); union_part= (unit->first_select()->next_select() != 0);
/* Check that all tables, fields, conds and order are ok */ /* Check that all tables, fields, conds and order are ok */
...@@ -231,7 +238,7 @@ JOIN::prepare(TABLE_LIST *tables_init, ...@@ -231,7 +238,7 @@ JOIN::prepare(TABLE_LIST *tables_init,
select_lex->having_fix_field= 1; select_lex->having_fix_field= 1;
bool having_fix_rc= having->fix_fields(thd, tables_list, &having); bool having_fix_rc= having->fix_fields(thd, tables_list, &having);
select_lex->having_fix_field= 0; select_lex->having_fix_field= 0;
if (having_fix_rc || thd->fatal_error) if (having_fix_rc || thd->net.report_error)
DBUG_RETURN(-1); /* purecov: inspected */ DBUG_RETURN(-1); /* purecov: inspected */
if (having->with_sum_func) if (having->with_sum_func)
having->split_sum_func(all_fields); having->split_sum_func(all_fields);
...@@ -538,7 +545,7 @@ JOIN::optimize() ...@@ -538,7 +545,7 @@ JOIN::optimize()
make_join_readinfo(this, make_join_readinfo(this,
(select_options & (SELECT_DESCRIBE | (select_options & (SELECT_DESCRIBE |
SELECT_NO_JOIN_CACHE)) | SELECT_NO_JOIN_CACHE)) |
(thd->lex.select->ftfunc_list.elements ? (thd->lex.select->ftfunc_list->elements ?
SELECT_NO_JOIN_CACHE : 0)); SELECT_NO_JOIN_CACHE : 0));
/* Need to tell Innobase that to play it safe, it should fetch all /* Need to tell Innobase that to play it safe, it should fetch all
...@@ -650,16 +657,16 @@ JOIN::exec() ...@@ -650,16 +657,16 @@ JOIN::exec()
result->send_fields(fields_list,1); result->send_fields(fields_list,1);
if (!having || having->val_int()) if (!having || having->val_int())
{ {
if (do_send_rows && result->send_data(fields_list)) if (do_send_rows && result->send_data(fields_list))
{ {
result->send_error(0,NullS); /* purecov: inspected */ result->send_error(0,NullS); /* purecov: inspected */
error=1; error= 1;
} }
else else
error=(int) result->send_eof(); error=(int) result->send_eof();
} }
else else
error=(int) result->send_eof(); error=(int) result->send_eof();
} }
delete procedure; delete procedure;
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
...@@ -995,8 +1002,9 @@ JOIN::cleanup(THD *thd) ...@@ -995,8 +1002,9 @@ JOIN::cleanup(THD *thd)
int int
mysql_select(THD *thd, TABLE_LIST *tables, List<Item> &fields, COND *conds, mysql_select(THD *thd, TABLE_LIST *tables, List<Item> &fields, COND *conds,
ORDER *order, ORDER *group,Item *having, ORDER *proc_param, ORDER *order, ORDER *group,Item *having, ORDER *proc_param,
ulong select_options, select_result *result, SELECT_LEX_UNIT *unit) ulong select_options, select_result *result,
SELECT_LEX_UNIT *unit, bool fake_select_lex)
{ {
JOIN *join = new JOIN(thd, fields, select_options, result); JOIN *join = new JOIN(thd, fields, select_options, result);
...@@ -1005,7 +1013,7 @@ mysql_select(THD *thd, TABLE_LIST *tables, List<Item> &fields, COND *conds, ...@@ -1005,7 +1013,7 @@ mysql_select(THD *thd, TABLE_LIST *tables, List<Item> &fields, COND *conds,
thd->used_tables=0; // Updated by setup_fields thd->used_tables=0; // Updated by setup_fields
if (join->prepare(tables, conds, order, group, having, proc_param, if (join->prepare(tables, conds, order, group, having, proc_param,
&(thd->lex.select_lex), unit)) &(thd->lex.select_lex), unit, fake_select_lex))
{ {
DBUG_RETURN(-1); DBUG_RETURN(-1);
} }
...@@ -1026,7 +1034,7 @@ err: ...@@ -1026,7 +1034,7 @@ err:
thd->limit_found_rows = join->send_records; thd->limit_found_rows = join->send_records;
thd->examined_row_count = join->examined_rows; thd->examined_row_count = join->examined_rows;
thd->proc_info="end"; thd->proc_info="end";
int error= join->cleanup(thd); int error= (fake_select_lex?0:join->cleanup(thd)) || thd->net.report_error;
delete join; delete join;
DBUG_RETURN(error); DBUG_RETURN(error);
} }
...@@ -1760,7 +1768,7 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab, ...@@ -1760,7 +1768,7 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab,
add_key_part(keyuse,field); add_key_part(keyuse,field);
} }
if (thd->lex.select->ftfunc_list.elements) if (thd->lex.select->ftfunc_list->elements)
{ {
add_ft_keys(keyuse,join_tab,cond,normal_tables); add_ft_keys(keyuse,join_tab,cond,normal_tables);
} }
...@@ -4329,7 +4337,7 @@ do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure) ...@@ -4329,7 +4337,7 @@ do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure)
VOID(table->file->extra(HA_EXTRA_WRITE_CACHE)); VOID(table->file->extra(HA_EXTRA_WRITE_CACHE));
empty_record(table); empty_record(table);
} }
join->tmp_table=table; /* Save for easy recursion */ join->tmp_table= table; /* Save for easy recursion */
join->fields= fields; join->fields= fields;
/* Set up select_end */ /* Set up select_end */
...@@ -4379,20 +4387,14 @@ do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure) ...@@ -4379,20 +4387,14 @@ do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure)
} }
else else
{ {
error=sub_select(join,join_tab,0); error= sub_select(join,join_tab,0);
if (error >= 0) if (error >= 0)
error=sub_select(join,join_tab,1); error= sub_select(join,join_tab,1);
if (error == -3) if (error == -3)
error=0; /* select_limit used */ error= 0; /* select_limit used */
} }
/* Return 1 if error is sent; -1 if error should be sent */ if (error >= 0)
if (error < 0)
{
join->result->send_error(0,NullS); /* purecov: inspected */
error=1; // Error sent
}
else
{ {
error=0; error=0;
if (!table) // If sending data to client if (!table) // If sending data to client
...@@ -6445,10 +6447,7 @@ find_order_in_list(THD *thd,TABLE_LIST *tables,ORDER *order,List<Item> &fields, ...@@ -6445,10 +6447,7 @@ find_order_in_list(THD *thd,TABLE_LIST *tables,ORDER *order,List<Item> &fields,
order->in_field_list=1; order->in_field_list=1;
return 0; return 0;
} }
const char *save_where=thd->where; Item **item=find_item_in_list(*order->item, fields, 0);
thd->where=0; // No error if not found
Item **item=find_item_in_list(*order->item,fields);
thd->where=save_where;
if (item) if (item)
{ {
order->item=item; // use it order->item=item; // use it
...@@ -6546,17 +6545,15 @@ setup_new_fields(THD *thd,TABLE_LIST *tables,List<Item> &fields, ...@@ -6546,17 +6545,15 @@ setup_new_fields(THD *thd,TABLE_LIST *tables,List<Item> &fields,
DBUG_ENTER("setup_new_fields"); DBUG_ENTER("setup_new_fields");
thd->set_query_id=1; // Not really needed, but... thd->set_query_id=1; // Not really needed, but...
thd->where=0; // Don't give error
for ( ; new_field ; new_field=new_field->next) for ( ; new_field ; new_field=new_field->next)
{ {
if ((item=find_item_in_list(*new_field->item,fields))) if ((item=find_item_in_list(*new_field->item, fields, 0)))
new_field->item=item; /* Change to shared Item */ new_field->item=item; /* Change to shared Item */
else else
{ {
thd->where="procedure list"; thd->where="procedure list";
if ((*new_field->item)->fix_fields(thd, tables, new_field->item)) if ((*new_field->item)->fix_fields(thd, tables, new_field->item))
DBUG_RETURN(1); /* purecov: inspected */ DBUG_RETURN(1); /* purecov: inspected */
thd->where=0;
all_fields.push_front(*new_field->item); all_fields.push_front(*new_field->item);
new_field->item=all_fields.head_ref(); new_field->item=all_fields.head_ref();
} }
......
...@@ -209,6 +209,7 @@ class JOIN :public Sql_alloc{ ...@@ -209,6 +209,7 @@ class JOIN :public Sql_alloc{
send_records(0), found_records(0), examined_rows(0), send_records(0), found_records(0), examined_rows(0),
thd(thd), thd(thd),
sum_funcs(0), sum_funcs(0),
procedure(0),
having(0), having(0),
select_options(select_options), select_options(select_options),
result(result), result(result),
...@@ -235,7 +236,8 @@ class JOIN :public Sql_alloc{ ...@@ -235,7 +236,8 @@ class JOIN :public Sql_alloc{
int prepare(TABLE_LIST *tables, int prepare(TABLE_LIST *tables,
COND *conds, ORDER *order, ORDER *group, Item *having, COND *conds, ORDER *order, ORDER *group, Item *having,
ORDER *proc_param, SELECT_LEX *select, SELECT_LEX_UNIT *unit); ORDER *proc_param, SELECT_LEX *select, SELECT_LEX_UNIT *unit,
bool fake_select_lex);
int optimize(); int optimize();
int global_optimize(); int global_optimize();
int reinit(); int reinit();
......
This diff is collapsed.
...@@ -642,6 +642,8 @@ bool multi_update::send_data(List<Item> &values) ...@@ -642,6 +642,8 @@ bool multi_update::send_data(List<Item> &values)
void multi_update::send_error(uint errcode,const char *err) void multi_update::send_error(uint errcode,const char *err)
{ {
//TODO error should be sent at the query processing end
/* First send error what ever it is ... */ /* First send error what ever it is ... */
::send_error(&thd->net,errcode,err); ::send_error(&thd->net,errcode,err);
...@@ -766,6 +768,7 @@ bool multi_update::send_eof() ...@@ -766,6 +768,7 @@ bool multi_update::send_eof()
if (error == -1) if (error == -1)
error = 0; error = 0;
thd->proc_info="end"; thd->proc_info="end";
//TODO error should be sent at the query processing end
if (error) if (error)
send_error(error,"An error occured in multi-table update"); send_error(error,"An error occured in multi-table update");
......
...@@ -1763,10 +1763,10 @@ simple_expr: ...@@ -1763,10 +1763,10 @@ simple_expr:
| singleval_subselect { $$= $1; } | singleval_subselect { $$= $1; }
| '{' ident expr '}' { $$= $3; } | '{' ident expr '}' { $$= $3; }
| MATCH ident_list_arg AGAINST '(' expr ')' | MATCH ident_list_arg AGAINST '(' expr ')'
{ Select->ftfunc_list.push_back((Item_func_match *) { Select->ftfunc_list->push_back((Item_func_match *)
($$=new Item_func_match_nl(*$2,$5))); } ($$=new Item_func_match_nl(*$2,$5))); }
| MATCH ident_list_arg AGAINST '(' expr IN_SYM BOOLEAN_SYM MODE_SYM ')' | MATCH ident_list_arg AGAINST '(' expr IN_SYM BOOLEAN_SYM MODE_SYM ')'
{ Select->ftfunc_list.push_back((Item_func_match *) { Select->ftfunc_list->push_back((Item_func_match *)
($$=new Item_func_match_bool(*$2,$5))); } ($$=new Item_func_match_bool(*$2,$5))); }
| BINARY expr %prec NEG { $$= new Item_func_binary($2); } | BINARY expr %prec NEG { $$= new Item_func_binary($2); }
| CAST_SYM '(' expr AS cast_type ')' { $$= create_func_cast($3, $5); } | CAST_SYM '(' expr AS cast_type ')' { $$= create_func_cast($3, $5); }
...@@ -3999,7 +3999,8 @@ singleval_subselect: ...@@ -3999,7 +3999,8 @@ singleval_subselect:
singleval_subselect_init: singleval_subselect_init:
select_init select_init
{ {
$$= new Item_singleval_subselect(current_thd, Lex->select); $$= new Item_singleval_subselect(current_thd,
Lex->select->master_unit()->first_select());
}; };
exists_subselect: exists_subselect:
...@@ -4012,7 +4013,8 @@ exists_subselect: ...@@ -4012,7 +4013,8 @@ exists_subselect:
exists_subselect_init: exists_subselect_init:
select_init select_init
{ {
$$= new Item_exists_subselect(current_thd, Lex->select); $$= new Item_exists_subselect(current_thd,
Lex->select->master_unit()->first_select());
}; };
subselect_start: subselect_start:
......
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