summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorunknown <bell@sanja.is.com.ua>2002-09-03 10:06:10 +0300
committerunknown <bell@sanja.is.com.ua>2002-09-03 10:06:10 +0300
commit5e1b47fb1344398d982f7f9eb3f3d1cc5a998ce6 (patch)
tree47d958e5060fcfc773f2874d7abccdd221a738cf /sql
parentd5f1d3ef19c56a3d2ecf8d92be67d84b4d1cf50e (diff)
parentc0c822d4c3ecafda17c6776f91ed642d159dca8a (diff)
downloadmariadb-git-5e1b47fb1344398d982f7f9eb3f3d1cc5a998ce6.tar.gz
merged
sql/item.cc: Auto merged sql/item_cmpfunc.cc: Auto merged sql/item_subselect.h: Auto merged sql/mysql_priv.h: Auto merged sql/mysqld.cc: Auto merged sql/sql_base.cc: Auto merged sql/sql_lex.h: Auto merged sql/sql_parse.cc: Auto merged sql/sql_select.cc: Auto merged sql/sql_select.h: Auto merged sql/sql_yacc.yy: Auto merged
Diffstat (limited to 'sql')
-rw-r--r--sql/item.cc25
-rw-r--r--sql/item_cmpfunc.cc2
-rw-r--r--sql/item_subselect.cc220
-rw-r--r--sql/item_subselect.h123
-rw-r--r--sql/mysql_priv.h7
-rw-r--r--sql/mysqld.cc3
-rw-r--r--sql/net_pkg.cc5
-rw-r--r--sql/net_serv.cc37
-rw-r--r--sql/sql_base.cc36
-rw-r--r--sql/sql_class.cc48
-rw-r--r--sql/sql_class.h4
-rw-r--r--sql/sql_derived.cc2
-rw-r--r--sql/sql_insert.cc2
-rw-r--r--sql/sql_lex.cc9
-rw-r--r--sql/sql_lex.h32
-rw-r--r--sql/sql_parse.cc20
-rw-r--r--sql/sql_select.cc69
-rw-r--r--sql/sql_select.h4
-rw-r--r--sql/sql_union.cc312
-rw-r--r--sql/sql_update.cc3
-rw-r--r--sql/sql_yacc.yy10
21 files changed, 620 insertions, 353 deletions
diff --git a/sql/item.cc b/sql/item.cc
index f717b78f4bf..86ddbc0b6e0 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -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;
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 084688f7d3d..bc723801aba 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -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;
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index b0a94f0b8e6..29034549367 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -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;
+}
diff --git a/sql/item_subselect.h b/sql/item_subselect.h
index 88ea01f9c68..0d8495d3ae8 100644
--- a/sql/item_subselect.h
+++ b/sql/item_subselect.h
@@ -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();
+};
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 9fff4880573..d3901770230 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -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);
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 59630644e5a..99099ff1bac 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -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);
diff --git a/sql/net_pkg.cc b/sql/net_pkg.cc
index fa3abc68bfa..5551e2b19bc 100644
--- a/sql/net_pkg.cc
+++ b/sql/net_pkg.cc
@@ -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;
}
diff --git a/sql/net_serv.cc b/sql/net_serv.cc
index 0d6e548a873..abda5a3c275 100644
--- a/sql/net_serv.cc
+++ b/sql/net_serv.cc
@@ -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
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 080a521cc91..a15cb23fbee 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -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";
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 9922eacdec1..b84bcf1df72 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -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);
}
diff --git a/sql/sql_class.h b/sql/sql_class.h
index a6b7e45ab03..82241f0ff1f 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -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() {}
diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc
index fb40a85fd91..cde120f3774 100644
--- a/sql/sql_derived.cc
+++ b/sql/sql_derived.cc
@@ -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
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index c3aeca1fff8..ea949e9eb99 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -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;
}
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 9ae5cdeeb15..7e6e2524400 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -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;
+
}
/*
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index af80b175cd3..b75826663ca 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -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,
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index fef022ff513..9977eaad0ff 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -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
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 4e7dbd96127..d071743aec4 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -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();
}
diff --git a/sql/sql_select.h b/sql/sql_select.h
index f651f069c13..495dd7f7ab7 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -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();
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index 0eea10e068a..e8ee3582135 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -24,31 +24,103 @@
#include "mysql_priv.h"
#include "sql_select.h"
+int mysql_union(THD *thd, LEX *lex, select_result *result)
+{
+ DBUG_ENTER("mysql_union");
+ SELECT_LEX_UNIT *unit= &lex->unit;
+ int res= 0;
+ if (!(res= unit->prepare(thd, result)))
+ res= unit->exec();
+ res|= unit->cleanup();
+ DBUG_RETURN(res);
+}
+
+
+/***************************************************************************
+** store records in temporary table for UNION
+***************************************************************************/
+
+select_union::select_union(TABLE *table_par)
+ :table(table_par)
+{
+ bzero((char*) &info,sizeof(info));
+ /*
+ We can always use DUP_IGNORE because the temporary table will only
+ contain a unique key if we are using not using UNION ALL
+ */
+ info.handle_duplicates= DUP_IGNORE;
+}
+
+select_union::~select_union()
+{
+}
+
+
+int select_union::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
+{
+ unit= u;
+ if (save_time_stamp && list.elements != table->fields)
+ {
+ my_message(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT,
+ ER(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT),MYF(0));
+ return -1;
+ }
+ return 0;
+}
+
+bool select_union::send_data(List<Item> &values)
+{
+ if (unit->offset_limit_cnt)
+ { // using limit offset,count
+ unit->offset_limit_cnt--;
+ return 0;
+ }
+ fill_record(table->field,values);
+ if ((write_record(table,&info)))
+ {
+ if (create_myisam_from_heap(table, tmp_table_param, info.errorno, 0))
+ return 1;
+ }
+ return 0;
+}
+
+bool select_union::send_eof()
+{
+ return 0;
+}
-int mysql_union(THD *thd, LEX *lex,select_result *result)
+bool select_union::flush()
{
- SELECT_LEX *sl;
- SELECT_LEX_UNIT *unit= &(lex->unit);
- List<Item> item_list;
- TABLE *table;
- int describe=(lex->select_lex.options & SELECT_DESCRIBE) ? 1 : 0;
- int res;
- bool found_rows_for_union=false;
- TABLE_LIST result_table_list;
+ int error;
+ if ((error=table->file->extra(HA_EXTRA_NO_CACHE)))
+ {
+ table->file->print_error(error,MYF(0));
+ ::send_error(&thd->net);
+ return 1;
+ }
+ return 0;
+}
+
+typedef JOIN * JOIN_P;
+int st_select_lex_unit::prepare(THD *thd, select_result *result)
+{
+ describe=(first_select()->options & SELECT_DESCRIBE) ? 1 : 0;
+ res= 0;
+ found_rows_for_union= false;
TMP_TABLE_PARAM tmp_table_param;
- select_union *union_result;
- DBUG_ENTER("mysql_union");
- st_select_lex_node * global;
+ DBUG_ENTER("st_select_lex_unit::prepare");
+ this->thd= thd;
+ this->result= result;
/* Global option */
- if (((void*)(global= unit->global_parameters)) == ((void*)unit))
+ if (((void*)(global_parameters)) == ((void*)this))
{
- found_rows_for_union = lex->select_lex.options & OPTION_FOUND_ROWS &&
- !describe && global->select_limit;
+ found_rows_for_union = first_select()->options & OPTION_FOUND_ROWS &&
+ !describe && global_parameters->select_limit;
if (found_rows_for_union)
- lex->select_lex.options ^= OPTION_FOUND_ROWS;
+ first_select()->options ^= OPTION_FOUND_ROWS;
}
-
+ item_list.empty();
if (describe)
{
Item *item;
@@ -70,8 +142,8 @@ int mysql_union(THD *thd, LEX *lex,select_result *result)
else
{
Item *item;
- List_iterator<Item> it(lex->select_lex.item_list);
- TABLE_LIST *first_table= (TABLE_LIST*) lex->select_lex.table_list.first;
+ List_iterator<Item> it(first_select()->item_list);
+ TABLE_LIST *first_table= (TABLE_LIST*) first_select()->table_list.first;
/* Create a list of items that will be in the result set */
while ((item= it++))
@@ -84,11 +156,12 @@ int mysql_union(THD *thd, LEX *lex,select_result *result)
bzero((char*) &tmp_table_param,sizeof(tmp_table_param));
tmp_table_param.field_count=item_list.elements;
if (!(table= create_tmp_table(thd, &tmp_table_param, item_list,
- (ORDER*) 0, !describe & !lex->union_option,
+ (ORDER*) 0, !describe &
+ !thd->lex.union_option,
1, 0,
- (lex->select_lex.options | thd->options |
+ (first_select()->options | thd->options |
TMP_TABLE_ALL_COLUMNS),
- unit)))
+ this)))
DBUG_RETURN(-1);
table->file->extra(HA_EXTRA_WRITE_CACHE);
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
@@ -98,46 +171,82 @@ int mysql_union(THD *thd, LEX *lex,select_result *result)
result_table_list.table=table;
if (!(union_result=new select_union(table)))
- {
- res= -1;
- goto exit;
- }
+ DBUG_RETURN(-1);
+
union_result->save_time_stamp=!describe;
union_result->tmp_table_param=&tmp_table_param;
- for (sl= &lex->select_lex; sl; sl= sl->next_select())
+
+ // prepare selects
+ joins.empty();
+ for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select())
{
- lex->select=sl;
- unit->offset_limit_cnt= sl->offset_limit;
- unit->select_limit_cnt= sl->select_limit+sl->offset_limit;
- if (unit->select_limit_cnt < sl->select_limit)
- unit->select_limit_cnt= HA_POS_ERROR; // no limit
- if (unit->select_limit_cnt == HA_POS_ERROR)
+ JOIN *join= new JOIN(thd, sl->item_list,
+ sl->options | thd->options | SELECT_NO_UNLOCK |
+ ((describe) ? SELECT_DESCRIBE : 0),
+ union_result);
+ joins.push_back(new JOIN_P(join));
+ thd->lex.select=sl;
+ offset_limit_cnt= sl->offset_limit;
+ select_limit_cnt= sl->select_limit+sl->offset_limit;
+ if (select_limit_cnt < sl->select_limit)
+ select_limit_cnt= HA_POS_ERROR; // no limit
+ if (select_limit_cnt == HA_POS_ERROR)
sl->options&= ~OPTION_FOUND_ROWS;
- res= mysql_select(thd,
- (TABLE_LIST*) sl->table_list.first,
- sl->item_list,
- sl->where,
- (sl->braces) ?
- (ORDER *)sl->order_list.first : (ORDER *) 0,
- (ORDER*) sl->group_list.first,
- sl->having,
- (ORDER*) NULL,
- sl->options | thd->options |
- SELECT_NO_UNLOCK | ((describe) ? SELECT_DESCRIBE : 0),
- union_result, unit);
- if (res)
- goto exit;
+ res= join->prepare((TABLE_LIST*) sl->table_list.first,
+ sl->where,
+ (sl->braces) ?
+ (ORDER *)sl->order_list.first : (ORDER *) 0,
+ (ORDER*) sl->group_list.first,
+ sl->having,
+ (ORDER*) NULL,
+ sl, this, 0);
+ if (res | thd->fatal_error)
+ DBUG_RETURN(res | thd->fatal_error);
}
+ DBUG_RETURN(res | thd->fatal_error);
+}
+
+int st_select_lex_unit::exec()
+{
+ DBUG_ENTER("st_select_lex_unit::exec");
+ if(depended || !item || !item->assigned())
+ {
+ if (optimized && item && item->assigned())
+ item->assigned(0); // We will reinit & rexecute unit
+
+ for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select())
+ {
+ thd->lex.select=sl;
+ offset_limit_cnt= sl->offset_limit;
+ select_limit_cnt= sl->select_limit+sl->offset_limit;
+ if (select_limit_cnt < sl->select_limit)
+ select_limit_cnt= HA_POS_ERROR; // no limit
+ if (select_limit_cnt == HA_POS_ERROR)
+ sl->options&= ~OPTION_FOUND_ROWS;
+
+ if (!optimized)
+ sl->join->optimize();
+ else
+ sl->join->reinit();
+
+ sl->join->exec();
+ res= sl->join->error;
+
+ if (res)
+ DBUG_RETURN(res);
+ }
+ optimized= 1;
+ }
+
if (union_result->flush())
{
res= 1; // Error is already sent
- goto exit;
+ DBUG_RETURN(res);
}
- delete union_result;
/* Send result to 'result' */
- lex->select = &lex->select_lex;
+ thd->lex.select = first_select();
res =-1;
{
/* Create a list of fields in the temporary table */
@@ -147,7 +256,9 @@ int mysql_union(THD *thd, LEX *lex,select_result *result)
List<Item_func_match> ftfunc_list;
ftfunc_list.empty();
#else
- thd->lex.select_lex.ftfunc_list.empty();
+ List<Item_func_match> empty_list;
+ empty_list.empty();
+ thd->lex.select_lex.ftfunc_list= &empty_list;
#endif
for (field=table->field ; *field ; field++)
@@ -157,92 +268,45 @@ int mysql_union(THD *thd, LEX *lex,select_result *result)
}
if (!thd->fatal_error) // Check if EOM
{
- st_select_lex_node * global= unit->global_parameters;
- unit->offset_limit_cnt= global->offset_limit;
- unit->select_limit_cnt= global->select_limit+global->offset_limit;
- if (unit->select_limit_cnt < global->select_limit)
- unit->select_limit_cnt= HA_POS_ERROR; // no limit
- if (unit->select_limit_cnt == HA_POS_ERROR)
+ offset_limit_cnt= global_parameters->offset_limit;
+ select_limit_cnt= global_parameters->select_limit+
+ global_parameters->offset_limit;
+ if (select_limit_cnt < global_parameters->select_limit)
+ select_limit_cnt= HA_POS_ERROR; // no limit
+ if (select_limit_cnt == HA_POS_ERROR)
thd->options&= ~OPTION_FOUND_ROWS;
if (describe)
- unit->select_limit_cnt= HA_POS_ERROR; // no limit
+ select_limit_cnt= HA_POS_ERROR; // no limit
res= mysql_select(thd,&result_table_list,
item_list, NULL,
- (describe) ? 0 : (ORDER*)global->order_list.first,
+ (describe) ?
+ 0:
+ (ORDER*)global_parameters->order_list.first,
(ORDER*) NULL, NULL, (ORDER*) NULL,
- thd->options, result, unit);
+ thd->options, result, this, 1);
if (found_rows_for_union && !res)
thd->limit_found_rows = (ulonglong)table->file->records;
}
}
-
-exit:
- free_tmp_table(thd,table);
+ thd->lex.select_lex.ftfunc_list= &thd->lex.select_lex.ftfunc_list_alloc;
DBUG_RETURN(res);
}
-
-/***************************************************************************
-** store records in temporary table for UNION
-***************************************************************************/
-
-select_union::select_union(TABLE *table_par)
- :table(table_par)
+int st_select_lex_unit::cleanup()
{
- bzero((char*) &info,sizeof(info));
- /*
- We can always use DUP_IGNORE because the temporary table will only
- contain a unique key if we are using not using UNION ALL
- */
- info.handle_duplicates= DUP_IGNORE;
-}
-
-select_union::~select_union()
-{
-}
-
-
-int select_union::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
-{
- unit= u;
- if (save_time_stamp && list.elements != table->fields)
- {
- my_message(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT,
- ER(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT),MYF(0));
- return -1;
- }
- return 0;
-}
-
-bool select_union::send_data(List<Item> &values)
-{
- if (unit->offset_limit_cnt)
- { // using limit offset,count
- unit->offset_limit_cnt--;
- return 0;
- }
- fill_record(table->field,values);
- if ((write_record(table,&info)))
- {
- if (create_myisam_from_heap(table, tmp_table_param, info.errorno, 0))
- return 1;
- }
- return 0;
-}
-
-bool select_union::send_eof()
-{
- return 0;
-}
-
-bool select_union::flush()
-{
- int error;
- if ((error=table->file->extra(HA_EXTRA_NO_CACHE)))
+ DBUG_ENTER("st_select_lex_unit::cleanup");
+ delete union_result;
+ free_tmp_table(thd,table);
+ table= 0; // Safety
+
+ List_iterator<JOIN*> j(joins);
+ JOIN** join;
+ while ((join= j++))
{
- table->file->print_error(error,MYF(0));
- ::send_error(&thd->net);
- return 1;
+ (*join)->cleanup(thd);
+ delete *join;
+ delete join;
}
- return 0;
+ joins.empty();
+ DBUG_RETURN(0);
}
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index 51453f955e8..9ea8f725947 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -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");
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 01894bfb7ad..e9eb5f67b0d 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -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: