Commit f0503007 authored by unknown's avatar unknown

merge


mysql-test/r/derived.result:
  Auto merged
mysql-test/t/derived.test:
  Auto merged
sql/sql_yacc.yy:
  mergin: new code contain this bug fixing
parents 779b7a2a 6ff06df2
...@@ -88,7 +88,6 @@ explain (select a,b from t1 limit 2) union all (select a,b from t2 order by a l ...@@ -88,7 +88,6 @@ explain (select a,b from t1 limit 2) union all (select a,b from t2 order by a l
table type possible_keys key key_len ref rows Extra table type possible_keys key key_len ref rows Extra
t1 ALL NULL NULL NULL NULL 4 t1 ALL NULL NULL NULL NULL 4
t2 ALL NULL NULL NULL NULL 4 Using filesort t2 ALL NULL NULL NULL NULL 4 Using filesort
t1 ALL NULL NULL NULL NULL 4
(select sql_calc_found_rows a,b from t1 limit 2) union all (select a,b from t2 order by a) limit 2; (select sql_calc_found_rows a,b from t1 limit 2) union all (select a,b from t2 order by a) limit 2;
a b a b
1 a 1 a
......
...@@ -940,6 +940,7 @@ bool Item_sum_count_distinct::fix_fields(THD *thd,TABLE_LIST *tables) ...@@ -940,6 +940,7 @@ bool Item_sum_count_distinct::fix_fields(THD *thd,TABLE_LIST *tables)
bool Item_sum_count_distinct::setup(THD *thd) bool Item_sum_count_distinct::setup(THD *thd)
{ {
List<Item> list; List<Item> list;
SELECT_LEX *select_lex= current_lex->select;
/* Create a table with an unique key over all parameters */ /* Create a table with an unique key over all parameters */
for (uint i=0; i < arg_count ; i++) for (uint i=0; i < arg_count ; i++)
{ {
...@@ -961,9 +962,10 @@ bool Item_sum_count_distinct::setup(THD *thd) ...@@ -961,9 +962,10 @@ bool Item_sum_count_distinct::setup(THD *thd)
free_tmp_table(thd, table); free_tmp_table(thd, table);
tmp_table_param->cleanup(); tmp_table_param->cleanup();
} }
if (!(table=create_tmp_table(thd, tmp_table_param, list, (ORDER*) 0, 1, if (!(table= create_tmp_table(thd, tmp_table_param, list, (ORDER*) 0, 1,
0, 0, 0, 0,
current_lex->select->options | thd->options))) select_lex->options | thd->options,
(SELECT_LEX_UNIT*) select_lex->master)))
return 1; return 1;
table->file->extra(HA_EXTRA_NO_ROWS); // Don't update rows table->file->extra(HA_EXTRA_NO_ROWS); // Don't update rows
table->no_rows=1; table->no_rows=1;
......
...@@ -291,7 +291,7 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list); ...@@ -291,7 +291,7 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list);
bool mysql_change_db(THD *thd,const char *name); bool mysql_change_db(THD *thd,const char *name);
void mysql_parse(THD *thd,char *inBuf,uint length); void mysql_parse(THD *thd,char *inBuf,uint length);
void mysql_init_select(LEX *lex); void mysql_init_select(LEX *lex);
bool mysql_new_select(LEX *lex); bool mysql_new_select(LEX *lex, bool move_down);
void mysql_init_multi_delete(LEX *lex); void mysql_init_multi_delete(LEX *lex);
void init_max_user_conn(void); void init_max_user_conn(void);
void free_max_user_conn(void); void free_max_user_conn(void);
...@@ -359,9 +359,10 @@ int setup_order(THD *thd,TABLE_LIST *tables, List<Item> &fields, ...@@ -359,9 +359,10 @@ int setup_order(THD *thd,TABLE_LIST *tables, List<Item> &fields,
int handle_select(THD *thd, LEX *lex, select_result *result); int handle_select(THD *thd, LEX *lex, select_result *result);
int mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &list,COND *conds, int mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &list,COND *conds,
ORDER *order, ORDER *group,Item *having,ORDER *proc_param, ORDER *order, ORDER *group,Item *having,ORDER *proc_param,
ulong select_type,select_result *result); ulong select_type,select_result *result,
int mysql_union(THD *thd,LEX *lex,select_result *result); SELECT_LEX_UNIT *unit);
int mysql_derived(THD *thd,LEX *lex,SELECT_LEX *s, TABLE_LIST *t); 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, Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
Item_result_field ***copy_func, Field **from_field, Item_result_field ***copy_func, Field **from_field,
bool group,bool modify_item); bool group,bool modify_item);
......
...@@ -389,9 +389,9 @@ bool select_send::send_data(List<Item> &items) ...@@ -389,9 +389,9 @@ bool select_send::send_data(List<Item> &items)
String *packet= &thd->packet; String *packet= &thd->packet;
DBUG_ENTER("send_data"); DBUG_ENTER("send_data");
if (thd->offset_limit) if (unit->offset_limit_cnt)
{ // using limit offset,count { // using limit offset,count
thd->offset_limit--; unit->offset_limit_cnt--;
DBUG_RETURN(0); DBUG_RETURN(0);
} }
packet->length(0); // Reset packet packet->length(0); // Reset packet
...@@ -439,11 +439,12 @@ select_export::~select_export() ...@@ -439,11 +439,12 @@ select_export::~select_export()
} }
int int
select_export::prepare(List<Item> &list) select_export::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
{ {
char path[FN_REFLEN]; char path[FN_REFLEN];
uint option=4; uint option=4;
bool blob_flag=0; bool blob_flag=0;
unit= u;
#ifdef DONT_ALLOW_FULL_LOAD_DATA_PATHS #ifdef DONT_ALLOW_FULL_LOAD_DATA_PATHS
option|=1; // Force use of db directory option|=1; // Force use of db directory
#endif #endif
...@@ -510,9 +511,9 @@ bool select_export::send_data(List<Item> &items) ...@@ -510,9 +511,9 @@ bool select_export::send_data(List<Item> &items)
String tmp(buff,sizeof(buff)),*res; String tmp(buff,sizeof(buff)),*res;
tmp.length(0); tmp.length(0);
if (thd->offset_limit) if (unit->offset_limit_cnt)
{ // using limit offset,count { // using limit offset,count
thd->offset_limit--; unit->offset_limit_cnt--;
DBUG_RETURN(0); DBUG_RETURN(0);
} }
row_count++; row_count++;
...@@ -678,9 +679,11 @@ select_dump::~select_dump() ...@@ -678,9 +679,11 @@ select_dump::~select_dump()
} }
int int
select_dump::prepare(List<Item> &list __attribute__((unused))) select_dump::prepare(List<Item> &list __attribute__((unused)),
SELECT_LEX_UNIT *u)
{ {
uint option=4; uint option=4;
unit= u;
#ifdef DONT_ALLOW_FULL_LOAD_DATA_PATHS #ifdef DONT_ALLOW_FULL_LOAD_DATA_PATHS
option|=1; // Force use of db directory option|=1; // Force use of db directory
#endif #endif
...@@ -719,9 +722,9 @@ bool select_dump::send_data(List<Item> &items) ...@@ -719,9 +722,9 @@ bool select_dump::send_data(List<Item> &items)
Item *item; Item *item;
DBUG_ENTER("send_data"); DBUG_ENTER("send_data");
if (thd->offset_limit) if (unit->offset_limit_cnt)
{ // using limit offset,count { // using limit offset,count
thd->offset_limit--; unit->offset_limit_cnt--;
DBUG_RETURN(0); DBUG_RETURN(0);
} }
if (row_count++ > 1) if (row_count++ > 1)
......
...@@ -382,7 +382,7 @@ class THD :public ilink { ...@@ -382,7 +382,7 @@ class THD :public ilink {
#endif #endif
ulonglong next_insert_id,last_insert_id,current_insert_id, ulonglong next_insert_id,last_insert_id,current_insert_id,
limit_found_rows; limit_found_rows;
ha_rows select_limit,offset_limit,default_select_limit,cuted_fields, ha_rows default_select_limit,cuted_fields,
max_join_size, sent_row_count, examined_row_count; max_join_size, sent_row_count, examined_row_count;
table_map used_tables; table_map used_tables;
UC *user_connect; UC *user_connect;
...@@ -551,10 +551,15 @@ void send_error(NET *net,uint sql_errno=0, const char *err=0); ...@@ -551,10 +551,15 @@ void send_error(NET *net,uint sql_errno=0, const char *err=0);
class select_result :public Sql_alloc { class select_result :public Sql_alloc {
protected: protected:
THD *thd; THD *thd;
SELECT_LEX_UNIT *unit;
public: public:
select_result(); select_result();
virtual ~select_result() {}; virtual ~select_result() {};
virtual int prepare(List<Item> &list) { return 0; } virtual int prepare(List<Item> &list, SELECT_LEX_UNIT *u)
{
unit= u;
return 0;
}
virtual bool send_fields(List<Item> &list,uint flag)=0; virtual bool send_fields(List<Item> &list,uint flag)=0;
virtual bool send_data(List<Item> &items)=0; virtual bool send_data(List<Item> &items)=0;
virtual void initialize_tables (JOIN *join=0) {} virtual void initialize_tables (JOIN *join=0) {}
...@@ -587,7 +592,7 @@ class select_export :public select_result { ...@@ -587,7 +592,7 @@ class select_export :public select_result {
public: public:
select_export(sql_exchange *ex) :exchange(ex),file(-1),row_count(0L) {} select_export(sql_exchange *ex) :exchange(ex),file(-1),row_count(0L) {}
~select_export(); ~select_export();
int prepare(List<Item> &list); int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
bool send_fields(List<Item> &list, bool send_fields(List<Item> &list,
uint flag) { return 0; } uint flag) { return 0; }
bool send_data(List<Item> &items); bool send_data(List<Item> &items);
...@@ -606,7 +611,7 @@ class select_dump :public select_result { ...@@ -606,7 +611,7 @@ class select_dump :public select_result {
select_dump(sql_exchange *ex) :exchange(ex),file(-1),row_count(0L) select_dump(sql_exchange *ex) :exchange(ex),file(-1),row_count(0L)
{ path[0]=0; } { path[0]=0; }
~select_dump(); ~select_dump();
int prepare(List<Item> &list); int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
bool send_fields(List<Item> &list, bool send_fields(List<Item> &list,
uint flag) { return 0; } uint flag) { return 0; }
bool send_data(List<Item> &items); bool send_data(List<Item> &items);
...@@ -629,7 +634,7 @@ class select_insert :public select_result { ...@@ -629,7 +634,7 @@ class select_insert :public select_result {
info.handle_duplicates=duplic; info.handle_duplicates=duplic;
} }
~select_insert(); ~select_insert();
int prepare(List<Item> &list); int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
bool send_fields(List<Item> &list, uint flag) bool send_fields(List<Item> &list, uint flag)
{ return 0; } { return 0; }
bool send_data(List<Item> &items); bool send_data(List<Item> &items);
...@@ -658,7 +663,7 @@ class select_create: public select_insert { ...@@ -658,7 +663,7 @@ class select_create: public select_insert {
create_info(create_info_par), create_info(create_info_par),
lock(0) lock(0)
{} {}
int prepare(List<Item> &list); int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
bool send_data(List<Item> &values); bool send_data(List<Item> &values);
bool send_eof(); bool send_eof();
void abort(); void abort();
...@@ -672,7 +677,7 @@ class select_union :public select_result { ...@@ -672,7 +677,7 @@ class select_union :public select_result {
select_union(TABLE *table_par); select_union(TABLE *table_par);
~select_union(); ~select_union();
int prepare(List<Item> &list); int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
bool send_fields(List<Item> &list, uint flag) bool send_fields(List<Item> &list, uint flag)
{ return 0; } { return 0; }
bool send_data(List<Item> &items); bool send_data(List<Item> &items);
...@@ -706,19 +711,28 @@ class Table_ident :public Sql_alloc { ...@@ -706,19 +711,28 @@ class Table_ident :public Sql_alloc {
public: public:
LEX_STRING db; LEX_STRING db;
LEX_STRING table; LEX_STRING table;
SELECT_LEX *sel; SELECT_LEX_UNIT *sel;
inline Table_ident(LEX_STRING db_arg,LEX_STRING table_arg,bool force) inline Table_ident(LEX_STRING db_arg, LEX_STRING table_arg, bool force)
:table(table_arg), sel((SELECT_LEX *)0) :table(table_arg), sel((SELECT_LEX_UNIT *)0)
{ {
if (!force && (current_thd->client_capabilities & CLIENT_NO_SCHEMA)) if (!force && (current_thd->client_capabilities & CLIENT_NO_SCHEMA))
db.str=0; db.str=0;
else else
db= db_arg; db= db_arg;
} }
inline Table_ident(LEX_STRING table_arg) :table(table_arg), sel((SELECT_LEX *)0) {db.str=0;} inline Table_ident(LEX_STRING table_arg)
inline Table_ident(SELECT_LEX *s) : sel(s) {db.str=0; table.str=(char *)""; table.length=0;} :table(table_arg), sel((SELECT_LEX_UNIT *)0)
{
db.str=0;
}
inline Table_ident(SELECT_LEX_UNIT *s) : sel(s)
{
db.str=0; table.str=(char *)""; table.length=0;
}
inline void change_db(char *db_name) inline void change_db(char *db_name)
{ db.str= db_name; db.length=(uint) strlen(db_name); } {
db.str= db_name; db.length= (uint) strlen(db_name);
}
}; };
// this is needed for user_vars hash // this is needed for user_vars hash
...@@ -778,7 +792,7 @@ class Unique :public Sql_alloc ...@@ -778,7 +792,7 @@ class Unique :public Sql_alloc
multi_delete(THD *thd, TABLE_LIST *dt, thr_lock_type lock_option_arg, multi_delete(THD *thd, TABLE_LIST *dt, thr_lock_type lock_option_arg,
uint num_of_tables); uint num_of_tables);
~multi_delete(); ~multi_delete();
int prepare(List<Item> &list); int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
bool send_fields(List<Item> &list, bool send_fields(List<Item> &list,
uint flag) { return 0; } uint flag) { return 0; }
bool send_data(List<Item> &items); bool send_data(List<Item> &items);
...@@ -807,7 +821,7 @@ class Unique :public Sql_alloc ...@@ -807,7 +821,7 @@ class Unique :public Sql_alloc
enum enum_duplicates handle_duplicates, enum enum_duplicates handle_duplicates,
thr_lock_type lock_option_arg, uint num); thr_lock_type lock_option_arg, uint num);
~multi_update(); ~multi_update();
int prepare(List<Item> &list); int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
bool send_fields(List<Item> &list, bool send_fields(List<Item> &list,
uint flag) { return 0; } uint flag) { return 0; }
bool send_data(List<Item> &items); bool send_data(List<Item> &items);
......
...@@ -232,9 +232,10 @@ multi_delete::multi_delete(THD *thd_arg, TABLE_LIST *dt, ...@@ -232,9 +232,10 @@ multi_delete::multi_delete(THD *thd_arg, TABLE_LIST *dt,
int int
multi_delete::prepare(List<Item> &values) multi_delete::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
{ {
DBUG_ENTER("multi_delete::prepare"); DBUG_ENTER("multi_delete::prepare");
unit= u;
do_delete = true; do_delete = true;
thd->proc_info="deleting from main table"; thd->proc_info="deleting from main table";
......
...@@ -28,21 +28,25 @@ ...@@ -28,21 +28,25 @@
static const char *any_db="*any*"; // Special symbol for check_access static const char *any_db="*any*"; // Special symbol for check_access
int mysql_derived(THD *thd, LEX *lex,SELECT_LEX *s, TABLE_LIST *t) int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
{ {
SELECT_LEX *sl=s; /*
TODO: make derived tables with union inside (now only 1 SELECT may be
procesed)
*/
SELECT_LEX *sl= (SELECT_LEX*)unit->slave;
List<Item> item_list; List<Item> item_list;
TABLE *table; TABLE *table;
int res; int res;
select_union *derived_result; select_union *derived_result;
TABLE_LIST *tables=(TABLE_LIST *)sl->table_list.first; TABLE_LIST *tables= (TABLE_LIST *)sl->table_list.first;
TMP_TABLE_PARAM tmp_table_param; TMP_TABLE_PARAM tmp_table_param;
DBUG_ENTER("mysql_derived"); DBUG_ENTER("mysql_derived");
if (tables) if (tables)
res=check_table_access(thd,SELECT_ACL, tables); res= check_table_access(thd,SELECT_ACL, tables);
else else
res=check_access(thd, SELECT_ACL, any_db); res= check_access(thd, SELECT_ACL, any_db);
if (res) if (res)
DBUG_RETURN(-1); DBUG_RETURN(-1);
...@@ -52,7 +56,7 @@ int mysql_derived(THD *thd, LEX *lex,SELECT_LEX *s, TABLE_LIST *t) ...@@ -52,7 +56,7 @@ int mysql_derived(THD *thd, LEX *lex,SELECT_LEX *s, TABLE_LIST *t)
{ {
if (cursor->derived) if (cursor->derived)
{ {
res=mysql_derived(thd,lex,(SELECT_LEX *)cursor->derived,cursor); res=mysql_derived(thd, lex, (SELECT_LEX_UNIT *)cursor->derived, cursor);
if (res) DBUG_RETURN(res); if (res) DBUG_RETURN(res);
} }
} }
...@@ -71,9 +75,11 @@ int mysql_derived(THD *thd, LEX *lex,SELECT_LEX *s, TABLE_LIST *t) ...@@ -71,9 +75,11 @@ int mysql_derived(THD *thd, LEX *lex,SELECT_LEX *s, TABLE_LIST *t)
} }
bzero((char*) &tmp_table_param,sizeof(tmp_table_param)); bzero((char*) &tmp_table_param,sizeof(tmp_table_param));
tmp_table_param.field_count=item_list.elements; tmp_table_param.field_count=item_list.elements;
if (!(table=create_tmp_table(thd, &tmp_table_param, sl->item_list, if (!(table= create_tmp_table(thd, &tmp_table_param, sl->item_list,
(ORDER*) 0, 0, 1, 0, (ORDER*) 0, 0, 1, 0,
(sl->options | thd->options | TMP_TABLE_ALL_COLUMNS)))) (sl->options | thd->options |
TMP_TABLE_ALL_COLUMNS),
unit)))
{ {
res=-1; res=-1;
goto exit; goto exit;
...@@ -81,11 +87,11 @@ int mysql_derived(THD *thd, LEX *lex,SELECT_LEX *s, TABLE_LIST *t) ...@@ -81,11 +87,11 @@ int mysql_derived(THD *thd, LEX *lex,SELECT_LEX *s, TABLE_LIST *t)
if ((derived_result=new select_union(table))) if ((derived_result=new select_union(table)))
{ {
thd->offset_limit=sl->offset_limit; unit->offset_limit_cnt= sl->offset_limit;
thd->select_limit=sl->select_limit+sl->offset_limit; unit->select_limit_cnt= sl->select_limit+sl->offset_limit;
if (thd->select_limit < sl->select_limit) if (unit->select_limit_cnt < sl->select_limit)
thd->select_limit= HA_POS_ERROR; unit->select_limit_cnt= HA_POS_ERROR;
if (thd->select_limit == HA_POS_ERROR) if (unit->select_limit_cnt == HA_POS_ERROR)
sl->options&= ~OPTION_FOUND_ROWS; sl->options&= ~OPTION_FOUND_ROWS;
res=mysql_select(thd, tables, sl->item_list, res=mysql_select(thd, tables, sl->item_list,
...@@ -93,7 +99,7 @@ int mysql_derived(THD *thd, LEX *lex,SELECT_LEX *s, TABLE_LIST *t) ...@@ -93,7 +99,7 @@ int mysql_derived(THD *thd, LEX *lex,SELECT_LEX *s, TABLE_LIST *t)
(ORDER*) sl->group_list.first, (ORDER*) sl->group_list.first,
sl->having, (ORDER*) NULL, sl->having, (ORDER*) NULL,
sl->options | thd->options | SELECT_NO_UNLOCK, sl->options | thd->options | SELECT_NO_UNLOCK,
derived_result); derived_result, unit);
if (!res) if (!res)
{ {
// Here we entirely fix both TABLE_LIST and list of SELECT's as there were no derived tables // Here we entirely fix both TABLE_LIST and list of SELECT's as there were no derived tables
...@@ -103,9 +109,8 @@ int mysql_derived(THD *thd, LEX *lex,SELECT_LEX *s, TABLE_LIST *t) ...@@ -103,9 +109,8 @@ int mysql_derived(THD *thd, LEX *lex,SELECT_LEX *s, TABLE_LIST *t)
{ {
t->real_name=table->real_name; t->real_name=table->real_name;
t->table=table; t->table=table;
sl->prev->next=sl->next; sl->exclude();
t->derived=(SELECT_LEX *)0; // just in case ... t->derived=(SELECT_LEX *)0; // just in case ...
if (!sl->next) lex->last_select = sl;
} }
} }
delete derived_result; delete derived_result;
......
...@@ -1266,10 +1266,11 @@ bool delayed_insert::handle_inserts(void) ...@@ -1266,10 +1266,11 @@ bool delayed_insert::handle_inserts(void)
***************************************************************************/ ***************************************************************************/
int int
select_insert::prepare(List<Item> &values) select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
{ {
DBUG_ENTER("select_insert::prepare"); DBUG_ENTER("select_insert::prepare");
unit= u;
save_time_stamp=table->time_stamp; save_time_stamp=table->time_stamp;
if (check_insert_fields(thd,table,*fields,values,1)) if (check_insert_fields(thd,table,*fields,values,1))
DBUG_RETURN(1); DBUG_RETURN(1);
...@@ -1302,9 +1303,9 @@ select_insert::~select_insert() ...@@ -1302,9 +1303,9 @@ select_insert::~select_insert()
bool select_insert::send_data(List<Item> &values) bool select_insert::send_data(List<Item> &values)
{ {
if (thd->offset_limit) if (unit->offset_limit_cnt)
{ // using limit offset,count { // using limit offset,count
thd->offset_limit--; unit->offset_limit_cnt--;
return 0; return 0;
} }
if (fields->elements) if (fields->elements)
...@@ -1380,10 +1381,11 @@ bool select_insert::send_eof() ...@@ -1380,10 +1381,11 @@ bool select_insert::send_eof()
***************************************************************************/ ***************************************************************************/
int int
select_create::prepare(List<Item> &values) select_create::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
{ {
DBUG_ENTER("select_create::prepare"); DBUG_ENTER("select_create::prepare");
unit= u;
table=create_table_from_items(thd, create_info, db, name, table=create_table_from_items(thd, create_info, db, name,
extra_fields, keys, &values, &lock); extra_fields, keys, &values, &lock);
if (!table) if (!table)
...@@ -1413,9 +1415,9 @@ select_create::prepare(List<Item> &values) ...@@ -1413,9 +1415,9 @@ select_create::prepare(List<Item> &values)
bool select_create::send_data(List<Item> &values) bool select_create::send_data(List<Item> &values)
{ {
if (thd->offset_limit) if (unit->offset_limit_cnt)
{ // using limit offset,count { // using limit offset,count
thd->offset_limit--; unit->offset_limit_cnt--;
return 0; return 0;
} }
fill_record(field,values); fill_record(field,values);
......
...@@ -879,3 +879,120 @@ int yylex(void *arg) ...@@ -879,3 +879,120 @@ int yylex(void *arg)
} }
} }
} }
/*
st_select_lex structures initialisations
*/
void st_select_lex_node::init_query()
{
next= master= slave= link_next= 0;
prev= link_prev= 0;
}
void st_select_lex_node::init_select()
{
order_list.elements= 0;
order_list.first= 0;
order_list.next= (byte**) &order_list.first;
select_limit= HA_POS_ERROR;
offset_limit= 0;
}
void st_select_lex_unit::init_query()
{
st_select_lex_node::init_query();
global_parameters= this;
select_limit_cnt= HA_POS_ERROR;
offset_limit_cnt= 0;
}
void st_select_lex::init_query()
{
st_select_lex_node::init_query();
table_list.elements= 0;
table_list.first= 0;
table_list.next= (byte**) &table_list.first;
item_list.empty();
}
void st_select_lex::init_select()
{
st_select_lex_node::init_select();
group_list.elements= 0;
group_list.first= 0;
group_list.next= (byte**) &group_list.first;
options= 0;
where= having= 0;
when_list.empty();
expr_list.empty();
interval_list.empty();
use_index.empty();
ftfunc_list.empty();
linkage=UNSPECIFIED_TYPE;
}
/*
st_select_lex structures linking
*/
/* include on level down */
void st_select_lex_node::include_down(st_select_lex_node *upper)
{
if ((next= upper->slave))
next->prev= &next;
prev= &upper->slave;
upper->slave= this;
master= upper;
}
/* include neighbour (on same level) */
void st_select_lex_node::include_neighbour(st_select_lex_node *before)
{
if ((next= before->next))
next->prev= &next;
prev= &before->next;
before->next= this;
master= before->master;
}
/* including in global SELECT_LEX list */
void st_select_lex_node::include_global(st_select_lex_node **plink)
{
if ((link_next= *plink))
link_next->link_prev= &link_next;
link_prev= plink;
*plink= this;
}
//excluding from global list (internal function)
void st_select_lex_node::fast_exclude()
{
if(link_prev)
{
if ((*link_prev= link_next))
link_next->link_prev= link_prev;
// Remove slave structure
for (; slave; slave= slave->next)
slave->fast_exclude();
}
}
/*
excluding select_lex structure (except first (first select can't be
deleted, because it is most upper select))
*/
void st_select_lex_node::exclude()
{
//exclude from global list
fast_exclude();
//exclude from other structures
if ((*prev= next))
next->prev= prev;
/*
We do not need following statements, because prev pointer of first
list element point to master->slave
if (master->slave == this)
master->slave= next;
*/
}
...@@ -103,28 +103,143 @@ typedef struct st_lex_master_info ...@@ -103,28 +103,143 @@ typedef struct st_lex_master_info
} LEX_MASTER_INFO; } LEX_MASTER_INFO;
enum sub_select_type {UNSPECIFIED_TYPE,UNION_TYPE, INTERSECT_TYPE, EXCEPT_TYPE, NOT_A_SELECT, DERIVED_TABLE_TYPE}; enum sub_select_type {UNSPECIFIED_TYPE,UNION_TYPE, INTERSECT_TYPE,
EXCEPT_TYPE, GLOBAL_OPTIONS_TYPE, DERIVED_TABLE_TYPE};
/* The state of the lex parsing for selects */ /*
The state of the lex parsing for selects
All select describing structures linked with following pointers:
- list of neighbors (next/prev) (prev of first element point to slave
pointer of upper structure)
- one level units for unit (union) structure
- member of one union(unit) for ordinary select_lex
- pointer to master
- outer select_lex for unit (union)
- unit structure for ordinary select_lex
- pointer to slave
- first list element of select_lex belonged to this unit for unit
- first unit in list of units that belong to this select_lex (as
subselects or derived tables) for ordinary select_lex
- list of all select_lex (for group operation like correcting list of opened
tables)
for example for following query:
typedef struct st_select_lex { select *
from table1
where table1.field IN (select * from table1_1_1 union
select * from table1_1_2)
union
select *
from table2
where table2.field=(select (select f1 from table2_1_1_1_1
where table2_1_1_1_1.f2=table2_1_1.f3)
from table2_1_1
where table2_1_1.f1=table2.f2)
union
select * from table3;
we will have following structure:
main unit
select1 select2 select3
|^^ |^
s||| ||master
l||| |+---------------------------------+
a||| +---------------------------------+|
v|||master slave ||
e||+-------------------------+ ||
V| neighbor | V|
unit 1.1<==================>unit1.2 unit2.1
select1.1.1 select 1.1.2 select1.2.1 select2.1.1 select2.1.2
|^
||
V|
unit2.1.1.1
select2.1.1.1.1
relation in main unit will be following:
main unit
|^^^
||||
|||+------------------------------+
||+--------------+ |
slave||master | |
V| neighbor | neighbor |
select1<========>select2<========>select3
list of all select_lex will be following (as it will be constructed by
parser):
select1->select2->select3->select2.1.1->select 2.1.2->select2.1.1.1.1-+
|
+---------------------------------------------------------------------+
|
+->select1.1.1->select1.1.2
*/
/*
Base class for st_select_lex (SELECT_LEX) &
st_select_lex_unit (SELECT_LEX_UNIT)
*/
struct st_select_lex_node {
enum sub_select_type linkage; enum sub_select_type linkage;
char *db,*db1,*table1,*db2,*table2; /* For outer join using .. */ st_select_lex_node *next, **prev, /* neighbor list */
Item *where,*having; *master, *slave, /* vertical links */
ha_rows select_limit,offset_limit; *link_next, **link_prev; /* list of whole SELECT_LEX */
SQL_LIST order_list; /* ORDER clause */
ha_rows select_limit, offset_limit; /* LIMIT clause parameters */
void init_query();
void init_select();
void include_down(st_select_lex_node *upper);
void include_neighbour(st_select_lex_node *before);
void include_global(st_select_lex_node **plink);
void exclude();
private:
void fast_exclude();
};
/*
SELECT_LEX_UNIT - unit of selects (UNION, INTERSECT, ...) group
SELECT_LEXs
*/
struct st_select_lex_unit: public st_select_lex_node {
/*
Pointer to 'last' select or pointer to unit where stored
global parameters for union
*/
st_select_lex_node *global_parameters;
/* LIMIT clause runtime counters */
ha_rows select_limit_cnt, offset_limit_cnt;
void init_query();
};
typedef struct st_select_lex_unit SELECT_LEX_UNIT;
/*
SELECT_LEX - store information of parsed SELECT_LEX statment
*/
struct st_select_lex: public st_select_lex_node {
char *db, *db1, *table1, *db2, *table2; /* For outer join using .. */
Item *where, *having; /* WHERE & HAVING clauses */
ulong options; ulong options;
List<List_item> expr_list; List<List_item> expr_list;
List<List_item> when_list; List<List_item> when_list; /* WHEN clause */
SQL_LIST order_list,table_list,group_list; SQL_LIST table_list, group_list; /* FROM & GROUP BY clauses */
List<Item> item_list; List<Item> item_list; /* list of fields & expressions */
List<String> interval_list,use_index, *use_index_ptr, List<String> interval_list, use_index, *use_index_ptr,
ignore_index, *ignore_index_ptr; ignore_index, *ignore_index_ptr;
List<Item_func_match> ftfunc_list; List<Item_func_match> ftfunc_list;
uint in_sum_expr, sort_default; uint in_sum_expr, sort_default;
bool create_refs, braces; bool create_refs,
st_select_lex *next, *prev; braces; /* SELECT ... UNION (SELECT ... ) <- this braces */
} SELECT_LEX; void init_query();
void init_select();
};
typedef struct st_select_lex SELECT_LEX;
class Set_option :public Sql_alloc { class Set_option :public Sql_alloc {
public: public:
...@@ -137,13 +252,15 @@ class Set_option :public Sql_alloc { ...@@ -137,13 +252,15 @@ class Set_option :public Sql_alloc {
:name(par_name), item(par_item), name_length(length), type(par_type) {} :name(par_name), item(par_item), name_length(length), type(par_type) {}
}; };
/* The state of the lex parsing. This is saved in the THD struct */ /* The state of the lex parsing. This is saved in the THD struct */
typedef struct st_lex { typedef struct st_lex {
uint yylineno,yytoklen; /* Simulate lex */ uint yylineno,yytoklen; /* Simulate lex */
LEX_YYSTYPE yylval; LEX_YYSTYPE yylval;
SELECT_LEX select_lex, *select, *last_select; SELECT_LEX_UNIT unit; /* most upper unit */
SELECT_LEX select_lex, /* first SELECT_LEX */
/* current SELECT_LEX in parsing */
*select;
uchar *ptr,*tok_start,*tok_end,*end_of_query; uchar *ptr,*tok_start,*tok_end,*end_of_query;
char *length,*dec,*change,*name; char *length,*dec,*change,*name;
char *backup_dir; /* For RESTORE/BACKUP */ char *backup_dir; /* For RESTORE/BACKUP */
......
...@@ -1203,11 +1203,12 @@ bool dispatch_command(enum enum_server_command command, THD *thd, ...@@ -1203,11 +1203,12 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
void void
mysql_execute_command(void) mysql_execute_command(void)
{ {
int res=0; int res= 0;
THD *thd=current_thd; THD *thd= current_thd;
LEX *lex= &thd->lex; LEX *lex= &thd->lex;
TABLE_LIST *tables=(TABLE_LIST*) lex->select_lex.table_list.first; TABLE_LIST *tables= (TABLE_LIST*) lex->select_lex.table_list.first;
SELECT_LEX *select_lex = lex->select; SELECT_LEX *select_lex= lex->select;
SELECT_LEX_UNIT *unit= &lex->unit;
DBUG_ENTER("mysql_execute_command"); DBUG_ENTER("mysql_execute_command");
if (thd->slave_thread) if (thd->slave_thread)
...@@ -1240,8 +1241,10 @@ mysql_execute_command(void) ...@@ -1240,8 +1241,10 @@ mysql_execute_command(void)
{ {
for (TABLE_LIST *cursor= tables; for (TABLE_LIST *cursor= tables;
cursor; cursor;
cursor=cursor->next) cursor= cursor->next)
if (cursor->derived && mysql_derived(thd,lex,(SELECT_LEX *)cursor->derived,cursor)) if (cursor->derived && mysql_derived(thd, lex,
(SELECT_LEX_UNIT *)cursor->derived,
cursor))
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
if ((lex->select_lex.next && create_total_list(thd,lex,&tables)) || if ((lex->select_lex.next && create_total_list(thd,lex,&tables)) ||
...@@ -1272,11 +1275,11 @@ mysql_execute_command(void) ...@@ -1272,11 +1275,11 @@ mysql_execute_command(void)
break; // Error message is given break; // Error message is given
} }
thd->offset_limit=select_lex->offset_limit; unit->offset_limit_cnt =select_lex->offset_limit;
thd->select_limit=select_lex->select_limit+select_lex->offset_limit; unit->select_limit_cnt =select_lex->select_limit+select_lex->offset_limit;
if (thd->select_limit < select_lex->select_limit) if (unit->select_limit_cnt < select_lex->select_limit)
thd->select_limit= HA_POS_ERROR; // no limit unit->select_limit_cnt= HA_POS_ERROR; // no limit
if (thd->select_limit == HA_POS_ERROR) if (unit->select_limit_cnt == HA_POS_ERROR)
select_lex->options&= ~OPTION_FOUND_ROWS; select_lex->options&= ~OPTION_FOUND_ROWS;
if (lex->exchange) if (lex->exchange)
...@@ -1501,10 +1504,11 @@ mysql_execute_command(void) ...@@ -1501,10 +1504,11 @@ mysql_execute_command(void)
for (table = tables->next ; table ; table=table->next) for (table = tables->next ; table ; table=table->next)
table->lock_type= lex->lock_option; table->lock_type= lex->lock_option;
} }
thd->offset_limit=select_lex->offset_limit; unit->offset_limit_cnt= select_lex->offset_limit;
thd->select_limit=select_lex->select_limit+select_lex->offset_limit; unit->select_limit_cnt= select_lex->select_limit+
if (thd->select_limit < select_lex->select_limit) select_lex->offset_limit;
thd->select_limit= HA_POS_ERROR; // No limit if (unit->select_limit_cnt < select_lex->select_limit)
unit->select_limit_cnt= HA_POS_ERROR; // No limit
/* Skip first table, which is the table we are creating */ /* Skip first table, which is the table we are creating */
lex->select_lex.table_list.first= lex->select_lex.table_list.first=
...@@ -1786,13 +1790,13 @@ mysql_execute_command(void) ...@@ -1786,13 +1790,13 @@ mysql_execute_command(void)
while ((item=value_list++)) while ((item=value_list++))
total_list.push_back(item); total_list.push_back(item);
res=mysql_select(thd,tables,total_list, res= mysql_select(thd, tables, total_list,
select_lex->where, select_lex->where,
(ORDER *)NULL,(ORDER *)NULL,(Item *)NULL, (ORDER *)NULL, (ORDER *)NULL, (Item *)NULL,
(ORDER *)NULL, (ORDER *)NULL,
select_lex->options | thd->options | select_lex->options | thd->options |
SELECT_NO_JOIN_CACHE, SELECT_NO_JOIN_CACHE,
result); result, unit);
delete result; delete result;
} }
else else
...@@ -1842,10 +1846,10 @@ mysql_execute_command(void) ...@@ -1842,10 +1846,10 @@ mysql_execute_command(void)
} }
select_result *result; select_result *result;
thd->offset_limit=select_lex->offset_limit; unit->offset_limit_cnt= select_lex->offset_limit;
thd->select_limit=select_lex->select_limit+select_lex->offset_limit; unit->select_limit_cnt= select_lex->select_limit+select_lex->offset_limit;
if (thd->select_limit < select_lex->select_limit) if (unit->select_limit_cnt < select_lex->select_limit)
thd->select_limit= HA_POS_ERROR; // No limit unit->select_limit_cnt= HA_POS_ERROR; // No limit
if (check_dup(tables->db, tables->real_name, tables->next)) if (check_dup(tables->db, tables->real_name, tables->next))
{ {
...@@ -1961,7 +1965,7 @@ mysql_execute_command(void) ...@@ -1961,7 +1965,7 @@ mysql_execute_command(void)
(ORDER *)NULL, (ORDER *)NULL,
select_lex->options | thd->options | select_lex->options | thd->options |
SELECT_NO_JOIN_CACHE, SELECT_NO_JOIN_CACHE,
result); result, unit);
delete result; delete result;
} }
else else
...@@ -2664,18 +2668,21 @@ static void ...@@ -2664,18 +2668,21 @@ static void
mysql_init_query(THD *thd) mysql_init_query(THD *thd)
{ {
DBUG_ENTER("mysql_init_query"); DBUG_ENTER("mysql_init_query");
thd->lex.select_lex.item_list.empty(); thd->lex.unit.init_query();
thd->lex.unit.init_select();
thd->lex.select_lex.init_query();
thd->lex.unit.slave= &thd->lex.select_lex;
thd->lex.unit.select_limit= thd->default_select_limit; //Global limit
thd->lex.select_lex.master= &thd->lex.unit;
thd->lex.select_lex.prev= &thd->lex.unit.slave;
thd->lex.value_list.empty(); thd->lex.value_list.empty();
thd->lex.select_lex.table_list.elements=0; thd->free_list= 0;
thd->free_list=0; thd->lex.union_option=0; thd->lex.union_option= 0;
thd->lex.select = thd->lex.last_select = &thd->lex.select_lex; thd->lex.select= &thd->lex.select_lex;
thd->lex.select_lex.table_list.first=0; thd->fatal_error= 0; // Safety
thd->lex.select_lex.table_list.next= (byte**) &thd->lex.select_lex.table_list.first; thd->last_insert_id_used= thd->query_start_used= thd->insert_id_used=0;
thd->lex.select_lex.next=0; thd->sent_row_count= thd->examined_row_count= 0;
thd->fatal_error=0; // Safety thd->safe_to_cache_query= 1;
thd->last_insert_id_used=thd->query_start_used=thd->insert_id_used=0;
thd->sent_row_count=thd->examined_row_count=0;
thd->safe_to_cache_query=1;
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
...@@ -2683,53 +2690,53 @@ void ...@@ -2683,53 +2690,53 @@ void
mysql_init_select(LEX *lex) mysql_init_select(LEX *lex)
{ {
SELECT_LEX *select_lex = lex->select; SELECT_LEX *select_lex = lex->select;
select_lex->where=select_lex->having=0; select_lex->init_select();
select_lex->select_limit=lex->thd->default_select_limit; select_lex->select_limit=lex->thd->default_select_limit;
select_lex->offset_limit=0; select_lex->offset_limit=0;
select_lex->options=0;
select_lex->linkage=UNSPECIFIED_TYPE;
lex->exchange = 0; lex->exchange = 0;
lex->proc_list.first=0; lex->proc_list.first=0;
select_lex->order_list.elements=select_lex->group_list.elements=0;
select_lex->order_list.first=0;
select_lex->order_list.next= (byte**) &select_lex->order_list.first;
select_lex->group_list.first=0;
select_lex->group_list.next= (byte**) &select_lex->group_list.first;
select_lex->next = select_lex->prev = (SELECT_LEX *)NULL;
} }
bool bool
mysql_new_select(LEX *lex) mysql_new_select(LEX *lex, bool move_down)
{ {
SELECT_LEX *select_lex = (SELECT_LEX *) lex->thd->calloc(sizeof(SELECT_LEX)); SELECT_LEX *select_lex = (SELECT_LEX *) lex->thd->calloc(sizeof(SELECT_LEX));
if (!select_lex) if (!select_lex)
return 1; return 1;
lex->select=lex->last_select; select_lex->init_query();
lex->select->next=select_lex; select_lex->init_select();
lex->select=lex->last_select=select_lex; if (move_down)
select_lex->table_list.next= (byte**) &select_lex->table_list.first; {
select_lex->item_list.empty(); /* first select_lex of subselect or derived table */
select_lex->when_list.empty(); SELECT_LEX_UNIT *unit=
select_lex->expr_list.empty(); (SELECT_LEX_UNIT *) lex->thd->calloc(sizeof(SELECT_LEX_UNIT));
select_lex->interval_list.empty(); if (!unit)
select_lex->use_index.empty(); return 1;
select_lex->ftfunc_list.empty(); unit->init_query();
unit->init_select();
unit->include_down(lex->select);
select_lex->include_down(unit);
}
else
select_lex->include_neighbour(lex->select);
((SELECT_LEX_UNIT*)select_lex->master)->global_parameters= select_lex;
select_lex->include_global(&lex->select->link_next);
lex->select= select_lex;
return 0; return 0;
} }
void mysql_init_multi_delete(LEX *lex) void mysql_init_multi_delete(LEX *lex)
{ {
lex->sql_command = SQLCOM_DELETE_MULTI; lex->sql_command= SQLCOM_DELETE_MULTI;
mysql_init_select(lex); mysql_init_select(lex);
lex->select->select_limit=HA_POS_ERROR; lex->select->select_limit= HA_POS_ERROR;
lex->auxilliary_table_list=lex->select_lex.table_list; lex->auxilliary_table_list= lex->select_lex.table_list;
lex->select->table_list.elements=0; lex->select->init_query();
lex->select->table_list.first=0;
lex->select->table_list.next= (byte**) &(lex->select->table_list.first);
} }
void void
mysql_parse(THD *thd,char *inBuf,uint length) mysql_parse(THD *thd, char *inBuf, uint length)
{ {
DBUG_ENTER("mysql_parse"); DBUG_ENTER("mysql_parse");
...@@ -3159,7 +3166,7 @@ TABLE_LIST *add_table_to_list(Table_ident *table, LEX_STRING *alias, ...@@ -3159,7 +3166,7 @@ TABLE_LIST *add_table_to_list(Table_ident *table, LEX_STRING *alias,
ptr->real_name_length=table->table.length; ptr->real_name_length=table->table.length;
ptr->lock_type=flags; ptr->lock_type=flags;
ptr->updating=updating; ptr->updating=updating;
ptr->derived=(SELECT_LEX *)table->sel; ptr->derived= (SELECT_LEX_UNIT *) table->sel;
if (use_index) if (use_index)
ptr->use_index=(List<String> *) thd->memdup((gptr) use_index, ptr->use_index=(List<String> *) thd->memdup((gptr) use_index,
sizeof(*use_index)); sizeof(*use_index));
...@@ -3204,8 +3211,8 @@ static bool create_total_list(THD *thd, LEX *lex, TABLE_LIST **result) ...@@ -3204,8 +3211,8 @@ static bool create_total_list(THD *thd, LEX *lex, TABLE_LIST **result)
SELECT_LEX *sl; SELECT_LEX *sl;
TABLE_LIST **new_table_list= result, *aux; TABLE_LIST **new_table_list= result, *aux;
*new_table_list=0; // end result list *new_table_list= 0; // end result list
for (sl= &lex->select_lex; sl; sl=sl->next) for (sl= &lex->select_lex; sl; sl= (SELECT_LEX *) sl->next)
{ {
if (sl->order_list.first && sl->next && !sl->braces) if (sl->order_list.first && sl->next && !sl->braces)
{ {
......
This diff is collapsed.
...@@ -173,6 +173,8 @@ class JOIN { ...@@ -173,6 +173,8 @@ class JOIN {
select_result *result; select_result *result;
TMP_TABLE_PARAM tmp_table_param; TMP_TABLE_PARAM tmp_table_param;
MYSQL_LOCK *lock; MYSQL_LOCK *lock;
// unit structure (with global parameters) for this select
SELECT_LEX_UNIT *unit;
}; };
...@@ -187,7 +189,8 @@ void TEST_join(JOIN *join); ...@@ -187,7 +189,8 @@ void TEST_join(JOIN *join);
bool store_val_in_field(Field *field,Item *val); bool store_val_in_field(Field *field,Item *val);
TABLE *create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, TABLE *create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
ORDER *group, bool distinct, bool save_sum_fields, ORDER *group, bool distinct, bool save_sum_fields,
bool allow_distinct_limit, ulong select_options); bool allow_distinct_limit, ulong select_options,
SELECT_LEX_UNIT *unit);
void free_tmp_table(THD *thd, TABLE *entry); void free_tmp_table(THD *thd, TABLE *entry);
void count_field_types(TMP_TABLE_PARAM *param, List<Item> &fields, void count_field_types(TMP_TABLE_PARAM *param, List<Item> &fields,
bool reset_with_sum_func); bool reset_with_sum_func);
......
...@@ -27,8 +27,8 @@ ...@@ -27,8 +27,8 @@
int mysql_union(THD *thd, LEX *lex,select_result *result) int mysql_union(THD *thd, LEX *lex,select_result *result)
{ {
SELECT_LEX *sl, *last_sl, *lex_sl; SELECT_LEX *sl;
ORDER *order; SELECT_LEX_UNIT *unit= &(lex->unit);
List<Item> item_list; List<Item> item_list;
TABLE *table; TABLE *table;
int describe=(lex->select_lex.options & SELECT_DESCRIBE) ? 1 : 0; int describe=(lex->select_lex.options & SELECT_DESCRIBE) ? 1 : 0;
...@@ -39,12 +39,12 @@ int mysql_union(THD *thd, LEX *lex,select_result *result) ...@@ -39,12 +39,12 @@ int mysql_union(THD *thd, LEX *lex,select_result *result)
TMP_TABLE_PARAM tmp_table_param; TMP_TABLE_PARAM tmp_table_param;
select_union *union_result; select_union *union_result;
DBUG_ENTER("mysql_union"); DBUG_ENTER("mysql_union");
st_select_lex_node * global;
/* Fix tables 'to-be-unioned-from' list to point at opened tables */ /* Fix tables 'to-be-unioned-from' list to point at opened tables */
last_sl= &lex->select_lex; for (sl= &lex->select_lex;
for (sl= last_sl; sl;
sl && sl->linkage != NOT_A_SELECT; sl= (SELECT_LEX *) sl->next)
last_sl=sl, sl=sl->next)
{ {
for (TABLE_LIST *cursor= (TABLE_LIST *)sl->table_list.first; for (TABLE_LIST *cursor= (TABLE_LIST *)sl->table_list.first;
cursor; cursor;
...@@ -52,31 +52,13 @@ int mysql_union(THD *thd, LEX *lex,select_result *result) ...@@ -52,31 +52,13 @@ int mysql_union(THD *thd, LEX *lex,select_result *result)
cursor->table= ((TABLE_LIST*) cursor->table)->table; cursor->table= ((TABLE_LIST*) cursor->table)->table;
} }
/* last_sel now points at the last select where the ORDER BY is stored */ /* Global option */
if (sl) if (((void*)(global= unit->global_parameters)) == ((void*)unit))
{ {
/* found_rows_for_union = lex->select_lex.options & OPTION_FOUND_ROWS &&
The found SL is an extra SELECT_LEX argument that contains !describe && global->select_limit;
the ORDER BY and LIMIT parameter for the whole UNION
*/
lex_sl= sl;
order= (ORDER *) lex_sl->order_list.first;
found_rows_for_union = lex->select_lex.options & OPTION_FOUND_ROWS && !describe && sl->select_limit;
if (found_rows_for_union) if (found_rows_for_union)
lex->select_lex.options ^= OPTION_FOUND_ROWS; lex->select_lex.options ^= OPTION_FOUND_ROWS;
// This is done to eliminate unnecessary slowing down of the first query
if (!order || !describe)
last_sl->next=0; // Remove this extra element
}
else if (!last_sl->braces)
{
lex_sl= last_sl; // ORDER BY is here
order= (ORDER *) lex_sl->order_list.first;
}
else
{
lex_sl=0;
order=0;
} }
if (describe) if (describe)
...@@ -113,11 +95,12 @@ int mysql_union(THD *thd, LEX *lex,select_result *result) ...@@ -113,11 +95,12 @@ int mysql_union(THD *thd, LEX *lex,select_result *result)
bzero((char*) &tmp_table_param,sizeof(tmp_table_param)); bzero((char*) &tmp_table_param,sizeof(tmp_table_param));
tmp_table_param.field_count=item_list.elements; tmp_table_param.field_count=item_list.elements;
if (!(table=create_tmp_table(thd, &tmp_table_param, item_list, if (!(table= create_tmp_table(thd, &tmp_table_param, item_list,
(ORDER*) 0, !describe & !lex->union_option, (ORDER*) 0, !describe & !lex->union_option,
1, 0, 1, 0,
(lex->select_lex.options | thd->options | (lex->select_lex.options | thd->options |
TMP_TABLE_ALL_COLUMNS)))) TMP_TABLE_ALL_COLUMNS),
unit)))
DBUG_RETURN(-1); DBUG_RETURN(-1);
table->file->extra(HA_EXTRA_WRITE_CACHE); table->file->extra(HA_EXTRA_WRITE_CACHE);
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY); table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
...@@ -133,25 +116,29 @@ int mysql_union(THD *thd, LEX *lex,select_result *result) ...@@ -133,25 +116,29 @@ int mysql_union(THD *thd, LEX *lex,select_result *result)
} }
union_result->save_time_stamp=!describe; union_result->save_time_stamp=!describe;
for (sl= &lex->select_lex; sl; sl=sl->next) for (sl= &lex->select_lex; sl; sl= (SELECT_LEX*) sl->next)
{ {
lex->select=sl; lex->select=sl;
thd->offset_limit=sl->offset_limit; unit->offset_limit_cnt= sl->offset_limit;
thd->select_limit=sl->select_limit+sl->offset_limit; unit->select_limit_cnt= sl->select_limit+sl->offset_limit;
if (thd->select_limit < sl->select_limit) if (unit->select_limit_cnt < sl->select_limit)
thd->select_limit= HA_POS_ERROR; // no limit unit->select_limit_cnt= HA_POS_ERROR; // no limit
if (thd->select_limit == HA_POS_ERROR) if (unit->select_limit_cnt == HA_POS_ERROR)
sl->options&= ~OPTION_FOUND_ROWS; sl->options&= ~OPTION_FOUND_ROWS;
res=mysql_select(thd, (describe && sl->linkage==NOT_A_SELECT) ? first_table : (TABLE_LIST*) sl->table_list.first, res= mysql_select(thd,
sl->item_list, (describe && sl->linkage==GLOBAL_OPTIONS_TYPE) ?
sl->where, first_table : (TABLE_LIST*) sl->table_list.first,
(sl->braces) ? (ORDER *)sl->order_list.first : (ORDER *) 0, sl->item_list,
(ORDER*) sl->group_list.first, sl->where,
sl->having, (sl->braces) ?
(ORDER*) NULL, (ORDER *)sl->order_list.first : (ORDER *) 0,
sl->options | thd->options | SELECT_NO_UNLOCK | ((describe) ? SELECT_DESCRIBE : 0), (ORDER*) sl->group_list.first,
union_result); sl->having,
(ORDER*) NULL,
sl->options | thd->options |
SELECT_NO_UNLOCK | ((describe) ? SELECT_DESCRIBE : 0),
union_result, unit);
if (res) if (res)
goto exit; goto exit;
} }
...@@ -183,26 +170,20 @@ int mysql_union(THD *thd, LEX *lex,select_result *result) ...@@ -183,26 +170,20 @@ int mysql_union(THD *thd, LEX *lex,select_result *result)
} }
if (!thd->fatal_error) // Check if EOM if (!thd->fatal_error) // Check if EOM
{ {
if (lex_sl) st_select_lex_node * global= unit->global_parameters;
{ unit->offset_limit_cnt= global->offset_limit;
thd->offset_limit=lex_sl->offset_limit; unit->select_limit_cnt= global->select_limit+global->offset_limit;
thd->select_limit=lex_sl->select_limit+lex_sl->offset_limit; if (unit->select_limit_cnt < global->select_limit)
if (thd->select_limit < lex_sl->select_limit) unit->select_limit_cnt= HA_POS_ERROR; // no limit
thd->select_limit= HA_POS_ERROR; // no limit if (unit->select_limit_cnt == HA_POS_ERROR)
if (thd->select_limit == HA_POS_ERROR) thd->options&= ~OPTION_FOUND_ROWS;
thd->options&= ~OPTION_FOUND_ROWS;
}
else
{
thd->offset_limit= 0;
thd->select_limit= thd->default_select_limit;
}
if (describe) if (describe)
thd->select_limit= HA_POS_ERROR; // no limit unit->select_limit_cnt= HA_POS_ERROR; // no limit
res=mysql_select(thd,&result_table_list, res= mysql_select(thd,&result_table_list,
item_list, NULL, (describe) ? 0 : order, item_list, NULL,
(ORDER*) NULL, NULL, (ORDER*) NULL, (describe) ? 0 : (ORDER*)global->order_list.first,
thd->options, result); (ORDER*) NULL, NULL, (ORDER*) NULL,
thd->options, result, unit);
if (found_rows_for_union && !res) if (found_rows_for_union && !res)
thd->limit_found_rows = (ulonglong)table->file->records; thd->limit_found_rows = (ulonglong)table->file->records;
} }
...@@ -226,7 +207,7 @@ select_union::select_union(TABLE *table_par) ...@@ -226,7 +207,7 @@ select_union::select_union(TABLE *table_par)
We can always use DUP_IGNORE because the temporary table will only We can always use DUP_IGNORE because the temporary table will only
contain a unique key if we are using not using UNION ALL contain a unique key if we are using not using UNION ALL
*/ */
info.handle_duplicates=DUP_IGNORE; info.handle_duplicates= DUP_IGNORE;
} }
select_union::~select_union() select_union::~select_union()
...@@ -234,8 +215,9 @@ select_union::~select_union() ...@@ -234,8 +215,9 @@ select_union::~select_union()
} }
int select_union::prepare(List<Item> &list) int select_union::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
{ {
unit= u;
if (save_time_stamp && list.elements != table->fields) if (save_time_stamp && list.elements != table->fields)
{ {
my_message(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT, my_message(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT,
...@@ -247,9 +229,9 @@ int select_union::prepare(List<Item> &list) ...@@ -247,9 +229,9 @@ int select_union::prepare(List<Item> &list)
bool select_union::send_data(List<Item> &values) bool select_union::send_data(List<Item> &values)
{ {
if (thd->offset_limit) if (unit->offset_limit_cnt)
{ // using limit offset,count { // using limit offset,count
thd->offset_limit--; unit->offset_limit_cnt--;
return 0; return 0;
} }
fill_record(table->field,values); fill_record(table->field,values);
......
...@@ -379,9 +379,10 @@ multi_update::multi_update(THD *thd_arg, TABLE_LIST *ut, List<Item> &fs, ...@@ -379,9 +379,10 @@ multi_update::multi_update(THD *thd_arg, TABLE_LIST *ut, List<Item> &fs,
} }
int int
multi_update::prepare(List<Item> &values) multi_update::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
{ {
DBUG_ENTER("multi_update::prepare"); DBUG_ENTER("multi_update::prepare");
unit= u;
do_update = true; do_update = true;
thd->count_cuted_fields=1; thd->count_cuted_fields=1;
thd->cuted_fields=0L; thd->cuted_fields=0L;
...@@ -466,15 +467,19 @@ multi_update::prepare(List<Item> &values) ...@@ -466,15 +467,19 @@ multi_update::prepare(List<Item> &values)
} }
if (counter) if (counter)
{ {
Field_string offset(table_ref->table->file->ref_length,false,"offset",table_ref->table,true); Field_string offset(table_ref->table->file->ref_length, false,
"offset", table_ref->table, true);
temp_fields->push_front(new Item_field(((Field *)&offset))); temp_fields->push_front(new Item_field(((Field *)&offset)));
// Here I make tmp tables // Here I make tmp tables
int cnt=counter-1; int cnt=counter-1;
TMP_TABLE_PARAM tmp_table_param; TMP_TABLE_PARAM tmp_table_param;
bzero((char*) &tmp_table_param,sizeof(tmp_table_param)); bzero((char*) &tmp_table_param,sizeof(tmp_table_param));
tmp_table_param.field_count=temp_fields->elements; tmp_table_param.field_count=temp_fields->elements;
if (!(tmp_tables[cnt]=create_tmp_table(thd, &tmp_table_param, *temp_fields, if (!(tmp_tables[cnt]=create_tmp_table(thd, &tmp_table_param,
(ORDER*) 0, 1, 0, 0, TMP_TABLE_ALL_COLUMNS))) *temp_fields,
(ORDER*) 0, 1, 0, 0,
TMP_TABLE_ALL_COLUMNS,
unit)))
{ {
error = 1; // A proper error message is due here error = 1; // A proper error message is due here
DBUG_RETURN(1); DBUG_RETURN(1);
......
...@@ -1449,7 +1449,14 @@ select: ...@@ -1449,7 +1449,14 @@ select:
select_init: select_init:
SELECT_SYM select_part2 { Select->braces=false; } union SELECT_SYM select_part2 { Select->braces=false; } union
| |
'(' SELECT_SYM select_part2 ')' { Select->braces=true;} union_opt '(' SELECT_SYM select_part2 ')'
{
SELECT_LEX * sel=Select;
sel->braces=true;
/* select in braces, can't contain global parameters */
((SELECT_LEX_UNIT*)sel->master)->global_parameters=
sel->master;
} union_opt
select_part2: select_part2:
...@@ -2155,23 +2162,22 @@ join_table: ...@@ -2155,23 +2162,22 @@ join_table:
| '(' SELECT_SYM select_part3 ')' opt_table_alias | '(' SELECT_SYM select_part3 ')' opt_table_alias
{ {
LEX *lex=Lex; LEX *lex=Lex;
SELECT_LEX *select_to_execute= lex->select; SELECT_LEX_UNIT *unit= (SELECT_LEX_UNIT*) lex->select->master;
lex->select=lex->select->prev; lex->select= (SELECT_LEX*) unit->master;
if (!($$=add_table_to_list(new Table_ident(select_to_execute), if (!($$= add_table_to_list(new Table_ident(unit),
$5,0,TL_UNLOCK))) $5,0,TL_UNLOCK)))
YYABORT; YYABORT;
} }
select_part3: select_part3:
{ {
LEX *lex=Lex; LEX *lex= Lex;
lex->derived_tables=true; lex->derived_tables= true;
SELECT_LEX *tmp=lex->select; if (lex->select->linkage == GLOBAL_OPTIONS_TYPE ||
if (lex->select->linkage == NOT_A_SELECT || mysql_new_select(lex)) mysql_new_select(lex, 1))
YYABORT; YYABORT;
mysql_init_select(lex); mysql_init_select(lex);
lex->select->linkage=DERIVED_TABLE_TYPE; lex->select->linkage= DERIVED_TABLE_TYPE;
lex->select->prev=tmp;
} }
select_options select_item_list select_intoto select_options select_item_list select_intoto
...@@ -3811,7 +3817,8 @@ union_list: ...@@ -3811,7 +3817,8 @@ union_list:
net_printf(&lex->thd->net, ER_WRONG_USAGE,"UNION","INTO"); net_printf(&lex->thd->net, ER_WRONG_USAGE,"UNION","INTO");
YYABORT; YYABORT;
} }
if (lex->select->linkage == NOT_A_SELECT || mysql_new_select(lex)) if (lex->select->linkage == GLOBAL_OPTIONS_TYPE ||
mysql_new_select(lex, 0))
YYABORT; YYABORT;
lex->select->linkage=UNION_TYPE; lex->select->linkage=UNION_TYPE;
} }
...@@ -3826,10 +3833,15 @@ optional_order_or_limit: ...@@ -3826,10 +3833,15 @@ optional_order_or_limit:
| |
{ {
LEX *lex=Lex; LEX *lex=Lex;
if (!lex->select->braces || mysql_new_select(lex)) if (!lex->select->braces)
YYABORT; YYABORT;
mysql_init_select(lex); ((SELECT_LEX_UNIT*)lex->select->master)->global_parameters=
lex->select->linkage=NOT_A_SELECT; lex->select->master;
/*
Following type conversion looks like hack, but all that need SELECT_LEX
fields always check linkage type.
*/
lex->select= (SELECT_LEX*)lex->select->master;
lex->select->select_limit=lex->thd->default_select_limit; lex->select->select_limit=lex->thd->default_select_limit;
} }
opt_order_clause limit_clause opt_order_clause limit_clause
......
...@@ -139,18 +139,18 @@ typedef struct st_table_list { ...@@ -139,18 +139,18 @@ typedef struct st_table_list {
struct st_table_list *next; struct st_table_list *next;
char *db,*name,*real_name; char *db,*name,*real_name;
uint32 db_length, real_name_length; uint32 db_length, real_name_length;
Item *on_expr; /* Used with outer join */ Item *on_expr; /* Used with outer join */
struct st_table_list *natural_join; /* natural join on this table*/ struct st_table_list *natural_join; /* natural join on this table*/
/* ... join ... USE INDEX ... IGNORE INDEX */ /* ... join ... USE INDEX ... IGNORE INDEX */
List<String> *use_index,*ignore_index; List<String> *use_index, *ignore_index;
TABLE *table; TABLE *table;
GRANT_INFO grant; GRANT_INFO grant;
thr_lock_type lock_type; thr_lock_type lock_type;
uint outer_join; /* Which join type */ uint outer_join; /* Which join type */
bool straight; /* optimize with prev table */ bool straight; /* optimize with prev table */
bool updating; /* for replicate-do/ignore table */ bool updating; /* for replicate-do/ignore table */
bool shared; /* Used twice in union */ bool shared; /* Used twice in union */
void *derived; void *derived; /* SELECT_LEX_UNIT of derived table */
} TABLE_LIST; } TABLE_LIST;
typedef struct st_changed_table_list { typedef struct st_changed_table_list {
......
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