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

merged

parents 6b20a480 b07aaeb2
......@@ -132,8 +132,13 @@ typedef struct st_net {
unsigned int *return_status;
unsigned char reading_or_writing;
char save_char;
my_bool report_error; /* We should report error (we have unreported error) */
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;
#define packet_error (~(unsigned long) 0)
......
......@@ -92,7 +92,8 @@ NULL NULL NULL
0 0
select id >= 0 and id <= 5 as grp,count(*) from t1 group by grp;
grp count(*)
0 7
NULL 1
0 6
1 6
SELECT DISTINCT FACILITY FROM t1;
FACILITY
......
select (select 2);
(select 2)
2
drop table if exists t1,t2,t3,t4,attend,clinic;
drop table if exists t1,t2,t3,t4,t5,attend,clinic;
create table t1 (a int);
create table t2 (a int, b int);
create table t3 (a int);
......@@ -82,6 +82,23 @@ select b,max(a) as ma from t4 group by b having b >= (select max(t2.a)
from t2 where t2.b=t4.b);
b ma
7 12
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
create table attend (patient_uq int, clinic_uq int, index i1 (clinic_uq));
create table clinic( uq int primary key, name char(25));
insert into clinic values(1,"Oblastnaia bolnitsa"),(2,"Bolnitsa Krasnogo Kresta");
......@@ -91,4 +108,4 @@ patient_uq clinic_uq
1 1
1 2
2 2
drop table t1,t2,t3,t4,attend,clinic;
drop table t1,t2,t3,t4,t5,attend,clinic;
select (select 2);
drop table if exists t1,t2,t3,t4,attend,clinic;
drop table if exists t1,t2,t3,t4,t5,attend,clinic;
create table t1 (a int);
create table t2 (a int, b int);
create table t3 (a int);
......@@ -33,11 +33,18 @@ select b,max(a) as ma from t4 group by b having b < (select max(t2.a)
from t2 where t2.b=t4.b);
select b,max(a) as ma from t4 group by b having b >= (select max(t2.a)
from t2 where t2.b=t4.b);
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;
create table attend (patient_uq int, clinic_uq int, index i1 (clinic_uq));
create table clinic( uq int primary key, name char(25));
insert into clinic values(1,"Oblastnaia bolnitsa"),(2,"Bolnitsa Krasnogo Kresta");
insert into attend values (1,1),(1,2),(2,2),(1,3);
select * from attend where exists (select * from clinic where uq = clinic_uq);
drop table t1,t2,t3,t4,attend,clinic;
drop table t1,t2,t3,t4,t5,attend,clinic;
......@@ -454,7 +454,7 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
if (!field) // If field is not checked
{
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,
......@@ -470,9 +470,14 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
sl && !tmp;
sl= sl->outer_select())
tmp=find_field_in_tables(thd, this,
(TABLE_LIST*)(last= sl)->table_list.first);
(TABLE_LIST*)(last= sl)->table_list.first,
0);
if (!tmp)
return 1;
{
// Call to produce appropriate error message
find_field_in_tables(thd, this, tables, 1);
return -1;
}
else
{
depended_from= last;
......@@ -485,7 +490,8 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
s= s->outer_select())
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
for (TABLE_LIST *tbl=
(TABLE_LIST*)s->table_list.first;
......@@ -799,7 +805,7 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
{
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,
......@@ -814,9 +820,13 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
for (SELECT_LEX *sl= thd->lex.select->outer_select();
sl && !ref;
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)
{
// Call to report error
find_item_in_list(this, thd->lex.select->item_list, 1);
return 1;
}
else
{
depended_from= last;
......@@ -829,7 +839,8 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
s= s->outer_select())
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
for (TABLE_LIST *tbl=
(TABLE_LIST*)s->table_list.first;
......
......@@ -1102,6 +1102,8 @@ Item_cond::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
used_tables_cache|=item->used_tables();
with_sum_func= with_sum_func || item->with_sum_func;
const_item_cache&=item->const_item();
if (item->maybe_null)
maybe_null=1;
}
if (thd)
thd->cond_count+=list.elements;
......
......@@ -23,9 +23,6 @@ SUBSELECT TODO:
- remove double 'having' & 'having_list' from JOIN
(sql_select.h/sql_select.cc)
- subselect in HAVING clause
- add subselect union select (sql_union.cc)
*/
#ifdef __GNUC__
......@@ -37,27 +34,17 @@ SUBSELECT TODO:
Item_subselect::Item_subselect(THD *thd, st_select_lex *select_lex,
select_subselect *result):
assigned(0), executed(0), optimized(0), error(0)
engine_owner(1), value_assigned(0)
{
DBUG_ENTER("Item_subselect::Item_subselect");
DBUG_PRINT("subs", ("select_lex 0x%xl", (long) select_lex));
this->result= result;
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_printf_error(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
}
this->select_lex= select_lex;
if (select_lex->next_select())
engine= new subselect_union_engine(thd, select_lex->master_unit(), result,
this);
else
engine= new subselect_single_select_engine(thd, select_lex, result,
this);
assign_null();
/*
item value is NULL if select_subselect not changed this value
......@@ -67,6 +54,12 @@ Item_subselect::Item_subselect(THD *thd, st_select_lex *select_lex,
DBUG_VOID_RETURN;
}
Item_subselect::~Item_subselect()
{
if (engine_owner)
delete engine;
}
void Item_subselect::make_field (Send_field *tmp_field)
{
if (null_value)
......@@ -84,62 +77,17 @@ void Item_subselect::make_field (Send_field *tmp_field)
bool Item_subselect::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
{
// 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;
}
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()))
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);
return engine->prepare();
}
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,
......@@ -157,21 +105,21 @@ Item::Type Item_subselect::type() const
double Item_singleval_subselect::val ()
{
if (exec())
if (engine->exec())
return 0;
return real_value;
}
longlong Item_singleval_subselect::val_int ()
{
if (exec())
if (engine->exec())
return 0;
return int_value;
}
String *Item_singleval_subselect::val_str (String *str)
{
if (exec() || null_value)
if (engine->exec() || null_value)
return 0;
return &str_value;
}
......@@ -189,23 +137,143 @@ Item_exists_subselect::Item_exists_subselect(THD *thd,
double Item_exists_subselect::val ()
{
if (exec())
if (engine->exec())
return 0;
return (double) value;
}
longlong Item_exists_subselect::val_int ()
{
if (exec())
if (engine->exec())
return 0;
return value;
}
String *Item_exists_subselect::val_str(String *str)
{
if (exec())
if (engine->exec())
return 0;
str->set(value);
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;
}
......@@ -21,30 +21,24 @@
#endif
class st_select_lex;
class st_select_lex_unit;
class JOIN;
class select_subselect;
class subselect_engine;
/* base class for subselects */
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:
/* 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;
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:
st_select_lex *select_lex;
JOIN *join;
select_subselect *result;
Item_subselect(THD *thd, st_select_lex *select_lex,
select_subselect* result);
Item_subselect(Item_subselect *item)
......@@ -52,14 +46,17 @@ public:
null_value= item->null_value;
decimals= item->decimals;
max_columns= item->max_columns;
assigned= item->assigned;
executed= item->executed;
select_lex= item->select_lex;
join= item->join;
result= item->result;
engine= item->engine;
engine_owner= 0;
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;
bool is_null() { return null_value; }
void make_field (Send_field *);
......@@ -75,18 +72,10 @@ public:
class Item_singleval_subselect :public Item_subselect
{
protected:
longlong int_value;
double real_value;
enum Item_result res_type;
longlong int_value; /* here stored integer value of this item */
double real_value; /* here stored real value of this item */
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:
Item_singleval_subselect(THD *thd, st_select_lex *select_lex);
Item_singleval_subselect(Item_singleval_subselect *item):
......@@ -98,6 +87,14 @@ public:
decimals= item->decimals;
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 ();
longlong val_int ();
String *val_str (String *);
......@@ -112,12 +109,8 @@ public:
class Item_exists_subselect :public Item_subselect
{
protected:
longlong value;
longlong value; /* value of this item (boolean: exists/not-exists) */
virtual void assign_null()
{
value= 0;
}
public:
Item_exists_subselect(THD *thd, st_select_lex *select_lex);
Item_exists_subselect(Item_exists_subselect *item):
......@@ -125,6 +118,11 @@ public:
{
value= item->value;
}
virtual void assign_null()
{
value= 0;
}
Item *new_item() { return new Item_exists_subselect(this); }
enum Item_result result_type() const { return INT_RESULT;}
longlong val_int();
......@@ -133,3 +131,58 @@ public:
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);
int mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &list,COND *conds,
ORDER *order, ORDER *group,Item *having,ORDER *proc_param,
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_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,
......@@ -442,7 +442,8 @@ bool wait_for_tables(THD *thd);
bool table_is_used(TABLE *table, bool wait_for_name_lock);
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);
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,
bool check_grant,bool allow_rowid);
#ifdef HAVE_OPENSSL
......@@ -530,7 +531,7 @@ TABLE *unlink_open_table(THD *thd,TABLE *list,TABLE *find);
SQL_SELECT *make_select(TABLE *head, table_map const_tables,
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,
const char *db_name, const char *table_name,
List_iterator<Item> *it);
......
......@@ -1608,8 +1608,9 @@ static int my_message_sql(uint error, const char *str,
NET *net;
DBUG_ENTER("my_message_sql");
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
{
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)
}
VOID(net_write_command(net,(uchar) 255,(char*) err,length));
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;
}
......
......@@ -113,6 +113,7 @@ int my_net_init(NET *net, Vio* vio)
net->where_b = net->remain_in_buf=0;
net->last_errno=0;
net->query_cache_query=0;
net->report_error= 0;
if (vio != 0) /* If real connection */
{
......@@ -141,8 +142,9 @@ static my_bool net_realloc(NET *net, ulong length)
if (length >= max_allowed_packet)
{
DBUG_PRINT("error",("Packet too large (%lu)", length));
net->error=1;
net->last_errno=ER_NET_PACKET_TOO_LARGE;
net->error= 1;
net->report_error= 1;
net->last_errno= ER_NET_PACKET_TOO_LARGE;
return 1;
}
pkt_length = (length+IO_SIZE-1) & ~(IO_SIZE-1);
......@@ -152,9 +154,10 @@ static my_bool net_realloc(NET *net, ulong length)
NET_HEADER_SIZE + COMP_HEADER_SIZE,
MYF(MY_WME))))
{
net->error=1;
net->error= 1;
net->report_error= 1;
#ifdef MYSQL_SERVER
net->last_errno=ER_OUT_OF_RESOURCES;
net->last_errno= ER_OUT_OF_RESOURCES;
#endif
return 1;
}
......@@ -348,10 +351,12 @@ net_real_write(NET *net,const char *packet,ulong len)
COMP_HEADER_SIZE, MYF(MY_WME))))
{
#ifdef MYSQL_SERVER
net->last_errno=ER_OUT_OF_RESOURCES;
net->error=2;
net->last_errno= ER_OUT_OF_RESOURCES;
net->error= 2;
//TODO is it needed to set this variable if we have no socket
net->report_error= 1;
#endif
net->reading_or_writing=0;
net->reading_or_writing= 0;
DBUG_RETURN(1);
}
memcpy(b+header_length,packet,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",
my_progname,vio_errno(net->vio));
#endif /* EXTRA_DEBUG */
net->error=2; /* Close socket */
net->error= 2; /* Close socket */
net->report_error= 1;
goto end;
}
}
......@@ -428,7 +434,8 @@ net_real_write(NET *net,const char *packet,ulong len)
continue;
}
#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
net->last_errno= (interrupted ? ER_NET_WRITE_INTERRUPTED :
ER_NET_ERROR_ON_WRITE);
......@@ -562,9 +569,10 @@ my_real_read(NET *net, ulong *complen)
my_progname,vio_errno(net->vio));
#endif /* EXTRA_DEBUG */
len= packet_error;
net->error=2; /* Close socket */
net->error= 2; /* Close socket */
net->report_error= 1;
#ifdef MYSQL_SERVER
net->last_errno=ER_NET_FCNTL_ERROR;
net->last_errno= ER_NET_FCNTL_ERROR;
#endif
goto end;
}
......@@ -593,7 +601,8 @@ my_real_read(NET *net, ulong *complen)
#endif
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;
net->error=2; /* Close socket */
net->error= 2; /* Close socket */
net->report_error= 1;
#ifdef MYSQL_SERVER
net->last_errno= (interrupted ? ER_NET_READ_INTERRUPTED :
ER_NET_READ_ERROR);
......@@ -622,6 +631,7 @@ my_real_read(NET *net, ulong *complen)
#endif
}
len= packet_error;
net->report_error= 1;
#ifdef MYSQL_SERVER
net->last_errno=ER_NET_PACKETS_OUT_OF_ORDER;
#endif
......@@ -794,7 +804,8 @@ my_net_read(NET *net)
if (my_uncompress((byte*) net->buff + net->where_b, &packet_len,
&complen))
{
net->error=2; /* caller will close socket */
net->error= 2; /* caller will close socket */
net->report_error= 1;
#ifdef MYSQL_SERVER
net->last_errno=ER_NET_UNCOMPRESS_ERROR;
#endif
......
......@@ -1711,7 +1711,8 @@ Field *find_field_in_table(THD *thd,TABLE *table,const char *name,uint length,
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;
const char *db=item->db_name;
......@@ -1748,7 +1749,7 @@ find_field_in_tables(THD *thd,Item_field *item,TABLE_LIST *tables)
}
if (found)
return found;
if (!found_table)
if (!found_table && report_error)
{
char buff[NAME_LEN*2+1];
if (db)
......@@ -1760,8 +1761,9 @@ find_field_in_tables(THD *thd,Item_field *item,TABLE_LIST *tables)
thd->where);
}
else
my_printf_error(ER_BAD_FIELD_ERROR,ER(ER_BAD_FIELD_ERROR),MYF(0),
item->full_name(),thd->where);
if (report_error)
my_printf_error(ER_BAD_FIELD_ERROR,ER(ER_BAD_FIELD_ERROR),MYF(0),
item->full_name(),thd->where);
return (Field*) 0;
}
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)
{
if (!thd->where) // Returns first found
break;
my_printf_error(ER_NON_UNIQ_ERROR,ER(ER_NON_UNIQ_ERROR),MYF(0),
name,thd->where);
if (report_error)
my_printf_error(ER_NON_UNIQ_ERROR,ER(ER_NON_UNIQ_ERROR),MYF(0),
name,thd->where);
return (Field*) 0;
}
found=field;
......@@ -1787,13 +1790,14 @@ find_field_in_tables(THD *thd,Item_field *item,TABLE_LIST *tables)
}
if (found)
return found;
my_printf_error(ER_BAD_FIELD_ERROR,ER(ER_BAD_FIELD_ERROR),
MYF(0),item->full_name(),thd->where);
if (report_error)
my_printf_error(ER_BAD_FIELD_ERROR, ER(ER_BAD_FIELD_ERROR),
MYF(0), item->full_name(), thd->where);
return (Field*) 0;
}
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);
Item **found=0,*item;
......@@ -1841,9 +1845,9 @@ find_item_in_list(Item *find,List<Item> &items)
break;
}
}
if (!found && current_thd->where)
my_printf_error(ER_BAD_FIELD_ERROR,ER(ER_BAD_FIELD_ERROR),MYF(0),
find->full_name(),current_thd->where);
if (!found && report_error)
my_printf_error(ER_BAD_FIELD_ERROR, ER(ER_BAD_FIELD_ERROR), MYF(0),
find->full_name(), current_thd->where);
return found;
}
......@@ -2303,8 +2307,8 @@ bool remove_table_from_cache(THD *thd, const char *db, const char *table_name,
int setup_ftfuncs(THD *thd)
{
List_iterator<Item_func_match> li(thd->lex.select->ftfunc_list),
lj(thd->lex.select->ftfunc_list);
List_iterator<Item_func_match> li(*(thd->lex.select->ftfunc_list)),
lj(*(thd->lex.select->ftfunc_list));
Item_func_match *ftf, *ftf2;
while ((ftf=li++))
......@@ -2324,9 +2328,9 @@ int setup_ftfuncs(THD *thd)
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;
DBUG_PRINT("info",("Performing FULLTEXT search"));
thd->proc_info="FULLTEXT initialization";
......
......@@ -407,13 +407,19 @@ bool select_send::send_data(List<Item> &items)
if (item->send(thd, packet))
{
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);
}
}
thd->sent_row_count++;
bool error=my_net_write(&thd->net,(char*) packet->ptr(),packet->length());
DBUG_RETURN(error);
if (!thd->net.report_error)
{
DBUG_RETURN(my_net_write(&thd->net,
(char*) packet->ptr(),
packet->length()));
}
else
DBUG_RETURN(1);
}
bool select_send::send_eof()
......@@ -423,8 +429,13 @@ bool select_send::send_eof()
{
mysql_unlock_tables(thd, thd->lock); thd->lock=0;
}
::send_eof(&thd->net);
return 0;
if (!thd->net.report_error)
{
::send_eof(&thd->net);
return 0;
}
else
return 1;
}
......@@ -460,7 +471,7 @@ select_export::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
option);
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;
}
/* Create the file world readable */
......@@ -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) my_close(file,MYF(0));
file= -1;
......@@ -660,9 +671,7 @@ bool select_export::send_eof()
int error=test(end_io_cache(&cache));
if (my_close(file,MYF(MY_WME)))
error=1;
if (error)
::send_error(&thd->net);
else
if (!error)
::send_ok(&thd->net,row_count);
file= -1;
return error;
......@@ -735,7 +744,7 @@ bool select_dump::send_data(List<Item> &items)
}
if (row_count++ > 1)
{
my_error(ER_TOO_MANY_ROWS,MYF(0));
my_error(ER_TOO_MANY_ROWS, MYF(0));
goto err;
}
while ((item=li++))
......@@ -760,7 +769,7 @@ 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) my_close(file,MYF(0));
(void) my_delete(path,MYF(0)); // Delete file on error
......@@ -772,9 +781,7 @@ bool select_dump::send_eof()
int error=test(end_io_cache(&cache));
if (my_close(file,MYF(MY_WME)))
error=1;
if (error)
::send_error(&thd->net);
else
if (!error)
::send_ok(&thd->net,row_count);
file= -1;
return error;
......@@ -789,8 +796,9 @@ bool select_singleval_subselect::send_data(List<Item> &items)
{
DBUG_ENTER("select_singleval_subselect::send_data");
Item_singleval_subselect *it= (Item_singleval_subselect *)item;
if (it->assigned){
my_printf_error(ER_SUBSELECT_NO_1_ROW, ER(ER_SUBSELECT_NO_1_ROW), MYF(0));
if (it->assigned()){
thd->fatal_error= 1;
my_message(ER_SUBSELECT_NO_1_ROW, ER(ER_SUBSELECT_NO_1_ROW), MYF(0));
DBUG_RETURN(1);
}
if (unit->offset_limit_cnt)
......@@ -816,7 +824,7 @@ bool select_singleval_subselect::send_data(List<Item> &items)
it->int_value= val_item->val_int();
it->res_type= val_item->result_type();
}
it->assigned= 1;
it->assigned(1);
DBUG_RETURN(0);
}
......@@ -830,7 +838,7 @@ bool select_exists_subselect::send_data(List<Item> &items)
DBUG_RETURN(0);
}
it->value= 1;
it->assigned= 1;
it->assigned(1);
DBUG_RETURN(0);
}
......@@ -453,7 +453,7 @@ public:
bool query_error, bootstrap, cleanup_done;
bool safe_to_cache_query;
bool volatile killed;
bool prepare_command;
bool prepare_command;
ulong param_count,current_param_number;
Error<mysql_st_error> err_list;
Error<mysql_st_error> warn_list;
......@@ -621,7 +621,7 @@ public:
virtual void initialize_tables (JOIN *join=0) {}
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 void abort() {}
......
......@@ -99,7 +99,7 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
(ORDER*) sl->group_list.first,
sl->having, (ORDER*) NULL,
sl->options | thd->options | SELECT_NO_UNLOCK,
derived_result, unit);
derived_result, unit, 0);
if (!res)
{
// 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)
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);
table->file->extra(HA_EXTRA_NO_CACHE);
table->file->activate_all_index(thd);
......@@ -1357,6 +1358,7 @@ bool select_insert::send_eof()
if (error)
{
table->file->print_error(error,MYF(0));
//TODO error should be sent at the query processing end
::send_error(&thd->net);
return 1;
}
......
......@@ -146,7 +146,8 @@ LEX *lex_start(THD *thd, uchar *buf,uint length)
lex->length=0;
lex->select->in_sum_expr=0;
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->yacc_yyss=lex->yacc_yyvs=0;
lex->ignore_space=test(thd->sql_mode & MODE_IGNORE_SPACE);
......@@ -918,6 +919,8 @@ void st_select_lex_unit::init_query()
global_parameters= this;
select_limit_cnt= HA_POS_ERROR;
offset_limit_cnt= 0;
optimized= 0;
item= 0;
}
void st_select_lex::init_query()
......@@ -941,9 +944,11 @@ void st_select_lex::init_select()
expr_list.empty();
interval_list.empty();
use_index.empty();
ftfunc_list.empty();
ftfunc_list_alloc.empty();
ftfunc_list= &ftfunc_list_alloc;
linkage= UNSPECIFIED_TYPE;
depended= having_fix_field= 0;
}
/*
......
......@@ -216,7 +216,22 @@ private:
*/
class st_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 {
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:
/*
Pointer to 'last' select or pointer to unit where stored
......@@ -225,12 +240,21 @@ public:
st_select_lex_node *global_parameters;
/* LIMIT clause runtime counters */
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();
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* first_select() { return (st_select_lex*) slave; }
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);
private:
bool create_total_list_n_last_return(THD *thd, st_lex *lex,
......@@ -241,7 +265,6 @@ typedef class st_select_lex_unit SELECT_LEX_UNIT;
/*
SELECT_LEX - store information of parsed SELECT_LEX statment
*/
class JOIN;
class st_select_lex: public st_select_lex_node {
public:
char *db, *db1, *table1, *db2, *table2; /* For outer join using .. */
......@@ -252,7 +275,12 @@ public:
List<Item> item_list; /* list of fields & expressions */
List<String> interval_list, use_index, *use_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 */
uint in_sum_expr;
bool create_refs,
......
......@@ -665,7 +665,7 @@ pthread_handler_decl(handle_one_connection,arg)
if (thd->user_connect)
decrease_user_connections(thd->user_connect);
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)
sql_print_error(ER(ER_NEW_ABORTING_CONNECTION),
......@@ -1169,6 +1169,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
break;
}
case COM_PING:
DBUG_PRINT("info", ("query: PING"));
thread_safe_increment(com_other,&LOCK_thread_count);
send_ok(net); // Tell client we are alive
break;
......@@ -1257,6 +1258,7 @@ mysql_execute_command(void)
SELECT_LEX_UNIT *unit= &lex->unit;
DBUG_ENTER("mysql_execute_command");
thd->net.report_error= 0;
if (thd->slave_thread)
{
/*
......@@ -1864,7 +1866,7 @@ mysql_execute_command(void)
(ORDER *)NULL,
select_lex->options | thd->options |
SELECT_NO_JOIN_CACHE,
result, unit);
result, unit, 0);
delete result;
}
else
......@@ -2029,13 +2031,13 @@ mysql_execute_command(void)
lex->lock_option,
table_count)))
{
res=mysql_select(thd,tables,select_lex->item_list,
select_lex->where,
(ORDER *)NULL,(ORDER *)NULL,(Item *)NULL,
(ORDER *)NULL,
select_lex->options | thd->options |
SELECT_NO_JOIN_CACHE,
result, unit);
res= mysql_select(thd,tables,select_lex->item_list,
select_lex->where,
(ORDER *)NULL,(ORDER *)NULL,(Item *)NULL,
(ORDER *)NULL,
select_lex->options | thd->options |
SELECT_NO_JOIN_CACHE,
result, unit, 0);
delete result;
}
else
......
......@@ -178,9 +178,14 @@ int handle_select(THD *thd, LEX *lex, select_result *result)
select_lex->having,
(ORDER*) lex->proc_list.first,
select_lex->options | thd->options,
result, &(lex->unit));
result, &(lex->unit), 0);
if (res && result)
result->abort();
if (res || thd->net.report_error)
{
send_error(&thd->net, 0, MYF(0));
res= 1;
}
delete result;
return res;
}
......@@ -198,9 +203,10 @@ int handle_select(THD *thd, LEX *lex, select_result *result)
*/
int
JOIN::prepare(TABLE_LIST *tables_init,
COND *conds_init, ORDER *order_init, ORDER *group_init,
Item *having_init,
ORDER *proc_param_init, SELECT_LEX *select, SELECT_LEX_UNIT *unit)
COND *conds_init, ORDER *order_init, ORDER *group_init,
Item *having_init,
ORDER *proc_param_init, SELECT_LEX *select,
SELECT_LEX_UNIT *unit, bool fake_select_lex)
{
DBUG_ENTER("JOIN::prepare");
......@@ -211,7 +217,8 @@ JOIN::prepare(TABLE_LIST *tables_init,
proc_param= proc_param_init;
tables_list= tables_init;
select_lex= select;
select->join= this;
if (!fake_select_lex)
select->join= this;
union_part= (unit->first_select()->next_select() != 0);
/* Check that all tables, fields, conds and order are ok */
......@@ -231,7 +238,7 @@ JOIN::prepare(TABLE_LIST *tables_init,
select_lex->having_fix_field= 1;
bool having_fix_rc= having->fix_fields(thd, tables_list, &having);
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 */
if (having->with_sum_func)
having->split_sum_func(all_fields);
......@@ -538,7 +545,7 @@ JOIN::optimize()
make_join_readinfo(this,
(select_options & (SELECT_DESCRIBE |
SELECT_NO_JOIN_CACHE)) |
(thd->lex.select->ftfunc_list.elements ?
(thd->lex.select->ftfunc_list->elements ?
SELECT_NO_JOIN_CACHE : 0));
/* Need to tell Innobase that to play it safe, it should fetch all
......@@ -650,16 +657,16 @@ JOIN::exec()
result->send_fields(fields_list,1);
if (!having || having->val_int())
{
if (do_send_rows && result->send_data(fields_list))
{
result->send_error(0,NullS); /* purecov: inspected */
error=1;
}
if (do_send_rows && result->send_data(fields_list))
{
result->send_error(0,NullS); /* purecov: inspected */
error= 1;
}
else
error=(int) result->send_eof();
}
else
error=(int) result->send_eof();
error=(int) result->send_eof();
}
delete procedure;
DBUG_VOID_RETURN;
......@@ -995,8 +1002,9 @@ JOIN::cleanup(THD *thd)
int
mysql_select(THD *thd, TABLE_LIST *tables, List<Item> &fields, COND *conds,
ORDER *order, ORDER *group,Item *having, ORDER *proc_param,
ulong select_options, select_result *result, SELECT_LEX_UNIT *unit)
ORDER *order, ORDER *group,Item *having, ORDER *proc_param,
ulong select_options, select_result *result,
SELECT_LEX_UNIT *unit, bool fake_select_lex)
{
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,
thd->used_tables=0; // Updated by setup_fields
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);
}
......@@ -1026,7 +1034,7 @@ err:
thd->limit_found_rows = join->send_records;
thd->examined_row_count = join->examined_rows;
thd->proc_info="end";
int error= join->cleanup(thd);
int error= (fake_select_lex?0:join->cleanup(thd)) || thd->net.report_error;
delete join;
DBUG_RETURN(error);
}
......@@ -1760,7 +1768,7 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab,
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);
}
......@@ -4329,7 +4337,7 @@ do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure)
VOID(table->file->extra(HA_EXTRA_WRITE_CACHE));
empty_record(table);
}
join->tmp_table=table; /* Save for easy recursion */
join->tmp_table= table; /* Save for easy recursion */
join->fields= fields;
/* Set up select_end */
......@@ -4379,20 +4387,14 @@ do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure)
}
else
{
error=sub_select(join,join_tab,0);
error= sub_select(join,join_tab,0);
if (error >= 0)
error=sub_select(join,join_tab,1);
error= sub_select(join,join_tab,1);
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)
{
join->result->send_error(0,NullS); /* purecov: inspected */
error=1; // Error sent
}
else
if (error >= 0)
{
error=0;
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,
order->in_field_list=1;
return 0;
}
const char *save_where=thd->where;
thd->where=0; // No error if not found
Item **item=find_item_in_list(*order->item,fields);
thd->where=save_where;
Item **item=find_item_in_list(*order->item, fields, 0);
if (item)
{
order->item=item; // use it
......@@ -6546,17 +6545,15 @@ setup_new_fields(THD *thd,TABLE_LIST *tables,List<Item> &fields,
DBUG_ENTER("setup_new_fields");
thd->set_query_id=1; // Not really needed, but...
thd->where=0; // Don't give error
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 */
else
{
thd->where="procedure list";
if ((*new_field->item)->fix_fields(thd, tables, new_field->item))
DBUG_RETURN(1); /* purecov: inspected */
thd->where=0;
all_fields.push_front(*new_field->item);
new_field->item=all_fields.head_ref();
}
......
......@@ -209,6 +209,7 @@ class JOIN :public Sql_alloc{
send_records(0), found_records(0), examined_rows(0),
thd(thd),
sum_funcs(0),
procedure(0),
having(0),
select_options(select_options),
result(result),
......@@ -235,7 +236,8 @@ class JOIN :public Sql_alloc{
int prepare(TABLE_LIST *tables,
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 global_optimize();
int reinit();
......
This diff is collapsed.
......@@ -642,6 +642,8 @@ bool multi_update::send_data(List<Item> &values)
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 ... */
::send_error(&thd->net,errcode,err);
......@@ -766,6 +768,7 @@ bool multi_update::send_eof()
if (error == -1)
error = 0;
thd->proc_info="end";
//TODO error should be sent at the query processing end
if (error)
send_error(error,"An error occured in multi-table update");
......
......@@ -1773,10 +1773,10 @@ simple_expr:
| singleval_subselect { $$= $1; }
| '{' ident expr '}' { $$= $3; }
| 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))); }
| 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))); }
| BINARY expr %prec NEG { $$= new Item_func_binary($2); }
| CAST_SYM '(' expr AS cast_type ')' { $$= create_func_cast($3, $5); }
......@@ -4009,7 +4009,8 @@ singleval_subselect:
singleval_subselect_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:
......@@ -4022,7 +4023,8 @@ exists_subselect:
exists_subselect_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:
......
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