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

(SCRUM)

It looks like samll revolution in SELECT_LEX tree, but it was only natural way to solve problem with name resolution of external fields inside subselect which belongs to global order of union
also it have following advantages:
 - removed mess with current_select type conversion
   - type checking/converting
   - a lot of virtual methods
 - fake select for union execution allocated only once (it was allocated for every subselect with union executing)

changes:
fixed bug with outer fields name resolution of subqueries which belong to global ORDER BY clause
remuved select_lex() function, now thd->lex.current_select always have type SELECT_LEX
new SELECT_LEX (fake_select_lex) will be allocated in case of UNION for using in UNION processing
fake_select_lex allocated for union hold global ORDER BY & LIMIT clauses and have linkage equal to GLOBAL_OPTIONS_TYPE 
new description of SELECT_LEX tree

(SCRUM)
parent 2ae8a00b
......@@ -23,7 +23,7 @@
#include <m_ctype.h>
#include "my_dir.h"
static void mark_as_dependent(SELECT_LEX *last, SELECT_LEX_NODE *current,
static void mark_as_dependent(SELECT_LEX *last, SELECT_LEX *current,
Item_ident *item);
/*****************************************************************************
......@@ -809,7 +809,7 @@ bool Item_ref_null_helper::get_date(TIME *ltime, bool fuzzydate)
item - item which should be marked
*/
static void mark_as_dependent(SELECT_LEX *last, SELECT_LEX_NODE *current,
static void mark_as_dependent(SELECT_LEX *last, SELECT_LEX *current,
Item_ident *item)
{
// store pointer on SELECT_LEX from wich item is dependent
......@@ -1413,7 +1413,7 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
if (((*ref)->with_sum_func && name &&
(depended_from ||
!(thd->lex.current_select->linkage != GLOBAL_OPTIONS_TYPE &&
thd->lex.current_select->select_lex()->having_fix_field))) ||
thd->lex.current_select->having_fix_field))) ||
!(*ref)->fixed)
{
my_error(ER_ILLEGAL_REFERENCE, MYF(0), name,
......
......@@ -336,8 +336,8 @@ Item_exists_subselect::Item_exists_subselect(THD *thd,
bool Item_in_subselect::test_limit(SELECT_LEX_UNIT *unit)
{
if (unit->global_parameters == unit &&
unit->global_parameters->test_limit())
if (unit->fake_select_lex &&
unit->fake_select_lex->test_limit())
return(1);
SELECT_LEX *sl= unit->first_select();
......@@ -495,7 +495,8 @@ Item_in_subselect::single_value_transformer(JOIN *join,
SELECT_LEX_UNIT *unit= select_lex->master_unit();
substitution= optimizer= new Item_in_optimizer(left_expr, this);
SELECT_LEX_NODE *current= thd->lex.current_select, *up;
SELECT_LEX *current= thd->lex.current_select, *up;
thd->lex.current_select= up= current->return_after_parsing();
//optimizer never use Item **ref => we can pass 0 as parameter
if (!optimizer || optimizer->fix_left(thd, up->get_table_list(), 0))
......@@ -658,7 +659,7 @@ Item_in_subselect::row_value_transformer(JOIN *join,
SELECT_LEX_UNIT *unit= select_lex->master_unit();
substitution= optimizer= new Item_in_optimizer(left_expr, this);
SELECT_LEX_NODE *current= thd->lex.current_select, *up;
SELECT_LEX *current= thd->lex.current_select, *up;
thd->lex.current_select= up= current->return_after_parsing();
//optimizer never use Item **ref => we can pass 0 as parameter
if (!optimizer || optimizer->fix_left(thd, up->get_table_list(), 0))
......@@ -771,7 +772,7 @@ int subselect_single_select_engine::prepare()
if (prepared)
return 0;
prepared= 1;
SELECT_LEX_NODE *save_select= thd->lex.current_select;
SELECT_LEX *save_select= thd->lex.current_select;
thd->lex.current_select= select_lex;
if (join->prepare(&select_lex->ref_pointer_array,
(TABLE_LIST*) select_lex->table_list.first,
......@@ -876,7 +877,7 @@ int subselect_single_select_engine::exec()
{
DBUG_ENTER("subselect_single_select_engine::exec");
char const *save_where= join->thd->where;
SELECT_LEX_NODE *save_select= join->thd->lex.current_select;
SELECT_LEX *save_select= join->thd->lex.current_select;
join->thd->lex.current_select= select_lex;
if (!optimized)
{
......
......@@ -1114,7 +1114,7 @@ void Item_sum_count_distinct::make_unique()
bool Item_sum_count_distinct::setup(THD *thd)
{
List<Item> list;
SELECT_LEX *select_lex= current_lex->current_select->select_lex();
SELECT_LEX *select_lex= current_lex->current_select;
if (select_lex->linkage == GLOBAL_OPTIONS_TYPE)
return 1;
......@@ -1607,7 +1607,7 @@ Item_func_group_concat::Item_func_group_concat(bool is_distinct,
original= 0;
quick_group= 0;
mark_as_sum_func();
SELECT_LEX *select_lex= current_lex->current_select->select_lex();
SELECT_LEX *select_lex= current_lex->current_select;
order= 0;
arg_show_fields= arg_count_field= is_select->elements;
......@@ -1786,7 +1786,7 @@ Item_func_group_concat::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
bool Item_func_group_concat::setup(THD *thd)
{
List<Item> list;
SELECT_LEX *select_lex= current_lex->current_select->select_lex();
SELECT_LEX *select_lex= current_lex->current_select;
if (select_lex->linkage == GLOBAL_OPTIONS_TYPE)
return 1;
......
......@@ -304,7 +304,7 @@ multi_delete::initialize_tables(JOIN *join)
table->file->ref_length,
MEM_STRIP_BUF_SIZE);
}
init_ftfuncs(thd, thd->lex.current_select->select_lex(), 1);
init_ftfuncs(thd, thd->lex.current_select, 1);
DBUG_RETURN(thd->is_fatal_error != 0);
}
......
......@@ -74,7 +74,7 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit,
bool is_union= select_cursor->next_select() &&
select_cursor->next_select()->linkage == UNION_TYPE;
bool is_subsel= select_cursor->first_inner_unit() ? 1: 0;
SELECT_LEX_NODE *save_current_select= lex->current_select;
SELECT_LEX *save_current_select= lex->current_select;
DBUG_ENTER("mysql_derived");
/*
......
......@@ -966,27 +966,17 @@ void st_select_lex_node::init_query()
options= 0;
linkage= UNSPECIFIED_TYPE;
no_table_names_allowed= uncacheable= dependent= 0;
ref_pointer_array= 0;
cond_count= 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;
select_items= 0;
with_sum_func= 0;
parsing_place= SELECT_LEX_NODE::NO_MATTER;
}
void st_select_lex_unit::init_query()
{
st_select_lex_node::init_query();
linkage= GLOBAL_OPTIONS_TYPE;
global_parameters= this;
global_parameters= first_select();
select_limit_cnt= HA_POS_ERROR;
offset_limit_cnt= 0;
union_option= 0;
......@@ -994,6 +984,7 @@ void st_select_lex_unit::init_query()
item= 0;
union_result= 0;
table= 0;
fake_select_lex= 0;
}
void st_select_lex::init_query()
......@@ -1005,7 +996,8 @@ void st_select_lex::init_query()
where= 0;
olap= UNSPECIFIED_OLAP_TYPE;
insert_select= having_fix_field= 0;
with_wild= 0;
cond_count= with_wild= 0;
ref_pointer_array= 0;
}
void st_select_lex::init_select()
......@@ -1027,6 +1019,14 @@ void st_select_lex::init_select()
ftfunc_list_alloc.empty();
ftfunc_list= &ftfunc_list_alloc;
linkage= UNSPECIFIED_TYPE;
order_list.elements= 0;
order_list.first= 0;
order_list.next= (byte**) &order_list.first;
select_limit= HA_POS_ERROR;
offset_limit= 0;
select_items= 0;
with_sum_func= 0;
parsing_place= SELECT_LEX_NODE::NO_MATTER;
}
/*
......@@ -1044,6 +1044,23 @@ void st_select_lex_node::include_down(st_select_lex_node *upper)
slave= 0;
}
/*
include on level down (but do not link)
SYNOPSYS
st_select_lex_node::include_standalone()
upper - reference on node underr which this node should be included
ref - references on reference on this node
*/
void st_select_lex_node::include_standalone(st_select_lex_node *upper,
st_select_lex_node **ref)
{
next= 0;
prev= ref;
master= upper;
slave= 0;
}
/* include neighbour (on same level) */
void st_select_lex_node::include_neighbour(st_select_lex_node *before)
{
......@@ -1125,33 +1142,6 @@ void st_select_lex_unit::exclude_level()
(*prev)= next;
}
st_select_lex* st_select_lex_node::select_lex()
{
DBUG_ENTER("st_select_lex_node::select_lex (never should be called)");
DBUG_ASSERT(0);
DBUG_RETURN(0);
}
bool st_select_lex_node::add_item_to_list(THD *thd, Item *item)
{
return 1;
}
bool st_select_lex_node::add_group_to_list(THD *thd, Item *item, bool asc)
{
return 1;
}
bool st_select_lex_node::add_order_to_list(THD *thd, Item *item, bool asc)
{
return add_to_list(thd, order_list, item, asc);
}
bool st_select_lex_node::add_ftfunc_to_list(Item_func_match *func)
{
return 1;
}
/*
st_select_lex_node::mark_as_dependent mark all st_select_lex struct from
this to 'last' as dependent
......@@ -1165,23 +1155,19 @@ bool st_select_lex_node::add_ftfunc_to_list(Item_func_match *func)
*/
void st_select_lex_node::mark_as_dependent(SELECT_LEX *last)
void st_select_lex::mark_as_dependent(SELECT_LEX *last)
{
/*
Mark all selects from resolved to 1 before select where was
found table as depended (of select where was found table)
*/
for (SELECT_LEX_NODE *s= this;
for (SELECT_LEX *s= this;
s &&s != last;
s= s->outer_select())
if ( !s->dependent )
{
// Select is dependent of outer select
s->dependent= 1;
if (s->linkage != GLOBAL_OPTIONS_TYPE)
{
//s is st_select_lex*
s->master_unit()->dependent= 1;
//Tables will be reopened many times
for (TABLE_LIST *tbl=
......@@ -1190,7 +1176,6 @@ void st_select_lex_node::mark_as_dependent(SELECT_LEX *last)
tbl= tbl->next)
tbl->shared= 1;
}
}
}
bool st_select_lex_node::set_braces(bool value) { return 1; }
......@@ -1200,15 +1185,6 @@ TABLE_LIST* st_select_lex_node::get_table_list() { return 0; }
List<Item>* st_select_lex_node::get_item_list() { return 0; }
List<String>* st_select_lex_node::get_use_index() { return 0; }
List<String>* st_select_lex_node::get_ignore_index() { return 0; }
TABLE_LIST *st_select_lex_node::add_table_to_list(THD *thd, Table_ident *table,
LEX_STRING *alias,
ulong table_join_options,
thr_lock_type flags,
List<String> *use_index,
List<String> *ignore_index)
{
return 0;
}
ulong st_select_lex_node::get_table_join_options()
{
......@@ -1218,7 +1194,7 @@ ulong st_select_lex_node::get_table_join_options()
/*
prohibit using LIMIT clause
*/
bool st_select_lex_node::test_limit()
bool st_select_lex::test_limit()
{
if (select_limit != HA_POS_ERROR)
{
......@@ -1293,22 +1269,39 @@ bool st_select_lex_unit::create_total_list_n_last_return(THD *thd, st_lex *lex,
TABLE_LIST *slave_list_first=0, **slave_list_last= &slave_list_first;
TABLE_LIST **new_table_list= *result, *aux;
SELECT_LEX *sl= (SELECT_LEX*)slave;
for (; sl; sl= sl->next_select())
/*
iterate all inner selects + fake_select (if exists),
fake_select->next_select() always is 0
*/
for (;
sl;
sl= (sl->next_select() ?
sl->next_select() :
(sl == fake_select_lex ?
0 :
fake_select_lex)))
{
// check usage of ORDER BY in union
if (sl->order_list.first && sl->next_select() && !sl->braces)
if (sl->order_list.first && sl->next_select() && !sl->braces &&
sl->linkage != GLOBAL_OPTIONS_TYPE)
{
net_printf(thd,ER_WRONG_USAGE,"UNION","ORDER BY");
return 1;
}
if (sl->linkage == DERIVED_TABLE_TYPE && !check_derived)
continue;
goto end;
for (SELECT_LEX_UNIT *inner= sl->first_inner_unit();
inner;
inner= inner->next_unit())
{
if (inner->create_total_list_n_last_return(thd, lex,
&slave_list_last, 0))
return 1;
}
if ((aux= (TABLE_LIST*) sl->table_list.first))
{
TABLE_LIST *next;
......@@ -1342,6 +1335,7 @@ bool st_select_lex_unit::create_total_list_n_last_return(THD *thd, st_lex *lex,
}
}
}
end:
if (slave_list_first)
{
*new_table_list= slave_list_first;
......@@ -1361,9 +1355,9 @@ st_select_lex* st_select_lex_unit::outer_select()
return (st_select_lex*) master;
}
st_select_lex* st_select_lex::select_lex()
bool st_select_lex::add_order_to_list(THD *thd, Item *item, bool asc)
{
return this;
return add_to_list(thd, order_list, item, asc);
}
bool st_select_lex::add_item_to_list(THD *thd, Item *item)
......@@ -1433,18 +1427,6 @@ ulong st_select_lex::get_table_join_options()
return table_join_options;
}
st_select_lex::st_select_lex(struct st_lex *lex)
:fake_select(0)
{
select_number= ++lex->thd->select_number;
init_query();
init_select();
include_neighbour(lex->current_select);
include_global((st_select_lex_node**)&lex->all_selects_list);
lex->current_select= this;
}
/*
There are st_select_lex::add_table_to_list &
st_select_lex::set_lock_for_tables in sql_parse.cc
......
......@@ -118,6 +118,12 @@ enum olap_type
subselects or derived tables) for ordinary select_lex
- list of all select_lex (for group operation like correcting list of opened
tables)
- if unit contain several selects (union) then it have special
select_lex called fake_select_lex. It used for storing global parameters
and executing union. subqueries of global ORDER BY clause will be
attached to this fake_select_lex, which will allow them correctly
resolve fields of 'upper' union and other more outer selects.
for example for following query:
select *
......@@ -138,6 +144,7 @@ enum olap_type
main unit
fake0
select1 select2 select3
|^^ |^
s||| ||master
......@@ -146,7 +153,8 @@ enum olap_type
v|||master slave ||
e||+-------------------------+ ||
V| neighbor | V|
unit 1.1<==================>unit1.2 unit2.1
unit1.1<+==================>unit1.2 unit2.1
fake1.1 fake2.1
select1.1.1 select 1.1.2 select1.2.1 select2.1.1 select2.1.2
|^
||
......@@ -158,13 +166,14 @@ enum olap_type
relation in main unit will be following:
main unit
|^^^
||||
|||+------------------------------+
||+--------------+ |
slave||master | |
V| neighbor | neighbor |
select1<========>select2<========>select3
|^^^^|fake_select_lex
|||||+--------------------------------------------+
||||+--------------------------------------------+|
|||+------------------------------+ ||
||+--------------+ | ||
slave||master | | ||
V| neighbor | neighbor | master|V
select1<========>select2<========>select3 fake0
list of all select_lex will be following (as it will be constructed by
parser):
......@@ -199,17 +208,6 @@ public:
ulong options;
enum sub_select_type linkage;
SQL_LIST order_list; /* ORDER clause */
List<List_item> expr_list;
List<List_item> when_list; /* WHEN clause (expression) */
ha_rows select_limit, offset_limit; /* LIMIT clause parameters */
// Arrays of pointers to top elements of all_fields list
Item **ref_pointer_array;
uint select_items; /* number of items in select_list */
uint cond_count; /* number of arguments of and/or/xor in where/having */
enum_parsing_place parsing_place; /* where we are parsing expression */
bool with_sum_func; /* sum function indicator */
bool dependent; /* dependent from outer select subselect */
bool uncacheable; /* result of this query can't be cached */
bool no_table_names_allowed; /* used for global order by */
......@@ -226,18 +224,13 @@ public:
virtual void init_select();
void include_down(st_select_lex_node *upper);
void include_neighbour(st_select_lex_node *before);
void include_standalone(st_select_lex_node *sel, st_select_lex_node **ref);
void include_global(st_select_lex_node **plink);
void exclude();
virtual st_select_lex* select_lex();
virtual bool add_item_to_list(THD *thd, Item *item);
bool add_order_to_list(THD *thd, Item *item, bool asc);
virtual bool add_group_to_list(THD *thd, Item *item, bool asc);
virtual bool add_ftfunc_to_list(Item_func_match *func);
virtual st_select_lex_unit* master_unit()= 0;
virtual st_select_lex* outer_select()= 0;
virtual st_select_lex_node* return_after_parsing()= 0;
virtual st_select_lex* return_after_parsing()= 0;
virtual bool set_braces(bool value);
virtual bool inc_in_sum_expr();
......@@ -247,16 +240,7 @@ public:
virtual List<String>* get_use_index();
virtual List<String>* get_ignore_index();
virtual ulong get_table_join_options();
virtual TABLE_LIST *add_table_to_list(THD *thd, Table_ident *table,
LEX_STRING *alias,
ulong table_options,
thr_lock_type flags= TL_UNLOCK,
List<String> *use_index= 0,
List<String> *ignore_index= 0);
virtual void set_lock_for_tables(thr_lock_type lock_type) {}
void mark_as_dependent(st_select_lex *last);
bool test_limit();
friend class st_select_lex_unit;
friend bool mysql_new_select(struct st_lex *lex, bool move_down);
......@@ -293,14 +277,17 @@ public:
Pointer to 'last' select or pointer to unit where stored
global parameters for union
*/
st_select_lex_node *global_parameters;
st_select_lex *global_parameters;
//node on wich we should return current_select pointer after parsing subquery
st_select_lex_node *return_to;
st_select_lex *return_to;
/* LIMIT clause runtime counters */
ha_rows select_limit_cnt, offset_limit_cnt;
/* not NULL if union used in subselect, point to subselect item */
Item_subselect *item;
/* thread handler */
THD *thd;
/* fake SELECT_LEX for union processing */
st_select_lex *fake_select_lex;
uint union_option;
......@@ -312,11 +299,10 @@ public:
st_select_lex* first_select() { return (st_select_lex*) slave; }
st_select_lex* first_select_in_union()
{
return (slave && slave->linkage == GLOBAL_OPTIONS_TYPE) ?
(st_select_lex*) slave->next : (st_select_lex*) slave;
return (st_select_lex*) slave;
}
st_select_lex_unit* next_unit() { return (st_select_lex_unit*) next; }
st_select_lex_node* return_after_parsing() { return return_to; }
st_select_lex* return_after_parsing() { return return_to; }
void exclude_level();
/* UNION methods */
......@@ -354,6 +340,19 @@ public:
List<Item_func_match> ftfunc_list_alloc;
JOIN *join; /* after JOIN::prepare it is pointer to corresponding JOIN */
const char *type; /* type of select for EXPLAIN */
SQL_LIST order_list; /* ORDER clause */
List<List_item> expr_list;
List<List_item> when_list; /* WHEN clause (expression) */
ha_rows select_limit, offset_limit; /* LIMIT clause parameters */
// Arrays of pointers to top elements of all_fields list
Item **ref_pointer_array;
uint select_items; /* number of items in select_list */
uint cond_count; /* number of arguments of and/or/xor in where/having */
enum_parsing_place parsing_place; /* where we are parsing expression */
bool with_sum_func; /* sum function indicator */
ulong table_join_options;
uint in_sum_expr;
uint select_number; /* number of select (used for EXPLAIN) */
......@@ -369,8 +368,6 @@ public:
before passing to handle_select)
*/
bool insert_select;
/* TRUE for fake select, which used in UNION processing */
bool fake_select;
void init_query();
void init_select();
......@@ -389,31 +386,33 @@ public:
{
return &link_next;
}
st_select_lex_node* return_after_parsing()
st_select_lex* return_after_parsing()
{
return master_unit()->return_after_parsing();
}
void mark_as_dependent(st_select_lex *last);
bool set_braces(bool value);
bool inc_in_sum_expr();
uint get_in_sum_expr();
st_select_lex* select_lex();
bool add_item_to_list(THD *thd, Item *item);
bool add_group_to_list(THD *thd, Item *item, bool asc);
bool add_ftfunc_to_list(Item_func_match *func);
TABLE_LIST* get_table_list();
List<Item>* get_item_list();
List<String>* get_use_index();
List<String>* get_ignore_index();
ulong get_table_join_options();
bool add_order_to_list(THD *thd, Item *item, bool asc);
TABLE_LIST* add_table_to_list(THD *thd, Table_ident *table,
LEX_STRING *alias,
ulong table_options,
thr_lock_type flags= TL_UNLOCK,
List<String> *use_index= 0,
List<String> *ignore_index= 0);
TABLE_LIST* get_table_list();
List<Item>* get_item_list();
List<String>* get_use_index();
List<String>* get_ignore_index();
ulong get_table_join_options();
void set_lock_for_tables(thr_lock_type lock_type);
inline void init_order()
{
......@@ -422,15 +421,14 @@ public:
order_list.next= (byte**) &order_list.first;
}
bool test_limit();
friend void mysql_init_query(THD *thd);
st_select_lex(struct st_lex *lex);
st_select_lex() :fake_select(0) {}
void make_empty_select(st_select_lex *last_select)
st_select_lex() {}
void make_empty_select()
{
select_number=INT_MAX;
init_query();
init_select();
include_neighbour(last_select);
}
};
typedef class st_select_lex SELECT_LEX;
......@@ -445,7 +443,7 @@ typedef struct st_lex
SELECT_LEX_UNIT unit; /* most upper unit */
SELECT_LEX select_lex; /* first SELECT_LEX */
/* current SELECT_LEX in parsing */
SELECT_LEX_NODE *current_select;
SELECT_LEX *current_select;
/* list of all SELECT_LEX */
SELECT_LEX *all_selects_list;
uchar *ptr,*tok_start,*tok_end,*end_of_query;
......@@ -517,7 +515,7 @@ typedef struct st_lex
but we should merk all subselects as uncacheable from current till
most upper
*/
SELECT_LEX_NODE *sl;
SELECT_LEX *sl;
SELECT_LEX_UNIT *un;
for (sl= current_select, un= sl->master_unit();
un != &unit;
......
......@@ -3474,10 +3474,10 @@ mysql_init_query(THD *thd)
lex->select_lex.init_query();
lex->value_list.empty();
lex->param_list.empty();
lex->unit.next= lex->unit.master= lex->unit.return_to=
lex->unit.link_next= 0;
lex->unit.next= lex->unit.master=
lex->unit.link_next= lex->unit.return_to=0;
lex->unit.prev= lex->unit.link_prev= 0;
lex->unit.global_parameters= lex->unit.slave= lex->current_select=
lex->unit.slave= lex->unit.global_parameters= lex->current_select=
lex->all_selects_list= &lex->select_lex;
lex->select_lex.master= &lex->unit;
lex->select_lex.prev= &lex->unit.slave;
......@@ -3506,10 +3506,9 @@ mysql_init_query(THD *thd)
void
mysql_init_select(LEX *lex)
{
SELECT_LEX *select_lex= lex->current_select->select_lex();
SELECT_LEX *select_lex= lex->current_select;
select_lex->init_select();
select_lex->master_unit()->select_limit= select_lex->select_limit=
lex->thd->variables.select_limit;
select_lex->select_limit= lex->thd->variables.select_limit;
if (select_lex == &lex->select_lex)
{
lex->exchange= 0;
......@@ -3537,9 +3536,6 @@ mysql_new_select(LEX *lex, bool move_down)
unit->init_query();
unit->init_select();
unit->thd= lex->thd;
if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE)
unit->include_neighbour(lex->current_select);
else
unit->include_down(lex->current_select);
unit->link_next= 0;
unit->link_prev= 0;
......@@ -3547,7 +3543,25 @@ mysql_new_select(LEX *lex, bool move_down)
select_lex->include_down(unit);
}
else
{
select_lex->include_neighbour(lex->current_select);
SELECT_LEX_UNIT *unit= select_lex->master_unit();
SELECT_LEX *fake= unit->fake_select_lex;
if (!fake)
{
/*
as far as we included SELECT_LEX for UNION unit should have
fake SELECT_LEX for UNION processing
*/
fake= unit->fake_select_lex= new SELECT_LEX();
fake->include_standalone(unit,
(SELECT_LEX_NODE**)&unit->fake_select_lex);
fake->select_number= INT_MAX;
fake->make_empty_select();
fake->linkage= GLOBAL_OPTIONS_TYPE;
fake->select_limit= lex->thd->variables.select_limit;
}
}
select_lex->master_unit()->global_parameters= select_lex;
select_lex->include_global((st_select_lex_node**)&lex->all_selects_list);
......
......@@ -318,7 +318,7 @@ JOIN::prepare(Item ***rref_pointer_array,
{
Item_subselect *subselect;
if ((subselect= select_lex->master_unit()->item) &&
!select_lex->fake_select)
select_lex->linkage != GLOBAL_OPTIONS_TYPE)
{
Item_subselect::trans_res res;
if ((res= subselect->select_transformer(this)) !=
......@@ -5713,7 +5713,8 @@ end_send(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
else
{
join->do_send_rows= 0;
join->unit->select_limit= HA_POS_ERROR;
if (join->unit->fake_select_lex)
join->unit->fake_select_lex->select_limit= HA_POS_ERROR;
DBUG_RETURN(0);
}
}
......
......@@ -115,7 +115,7 @@ bool select_union::flush()
int st_select_lex_unit::prepare(THD *thd, select_result *sel_result,
bool tables_and_fields_initied)
{
SELECT_LEX_NODE *lex_select_save= thd->lex.current_select;
SELECT_LEX *lex_select_save= thd->lex.current_select;
SELECT_LEX *select_cursor;
DBUG_ENTER("st_select_lex_unit::prepare");
......@@ -241,7 +241,7 @@ err:
int st_select_lex_unit::exec()
{
int do_print_slow= 0;
SELECT_LEX_NODE *lex_select_save= thd->lex.current_select;
SELECT_LEX *lex_select_save= thd->lex.current_select;
SELECT_LEX *select_cursor=first_select_in_union();
DBUG_ENTER("st_select_lex_unit::exec");
......@@ -318,8 +318,7 @@ int st_select_lex_unit::exec()
/* Send result to 'result' */
// to correct ORDER BY reference resolving
thd->lex.current_select= select_cursor;
res= -1;
{
List<Item_func_match> empty_list;
......@@ -327,8 +326,7 @@ int st_select_lex_unit::exec()
if (!thd->is_fatal_error) // Check if EOM
{
SELECT_LEX *fake_select = new SELECT_LEX(&thd->lex);
fake_select->fake_select= 1;
thd->lex.current_select= fake_select_lex;
offset_limit_cnt= (select_cursor->braces ?
global_parameters->offset_limit : 0);
select_limit_cnt= (select_cursor->braces ?
......@@ -338,19 +336,19 @@ int st_select_lex_unit::exec()
select_limit_cnt= HA_POS_ERROR; // no limit
if (select_limit_cnt == HA_POS_ERROR)
thd->options&= ~OPTION_FOUND_ROWS;
fake_select->ftfunc_list= &empty_list;
fake_select->table_list.link_in_list((byte *)&result_table_list,
(byte **)&result_table_list.next);
res= mysql_select(thd, &ref_pointer_array, &result_table_list,
fake_select_lex->ftfunc_list= &empty_list;
fake_select_lex->table_list.link_in_list((byte *)&result_table_list,
(byte **)
&result_table_list.next);
res= mysql_select(thd, &fake_select_lex->ref_pointer_array,
&result_table_list,
0, item_list, NULL,
global_parameters->order_list.elements,
(ORDER*)global_parameters->order_list.first,
(ORDER*) NULL, NULL, (ORDER*) NULL,
thd->options, result, this, fake_select, 0);
thd->options, result, this, fake_select_lex, 0);
if (found_rows_for_union && !res)
thd->limit_found_rows = (ulonglong)table->file->records;
fake_select->exclude();
delete fake_select;
/*
Mark for slow query log if any of the union parts didn't use
indexes efficiently
......
This diff is collapsed.
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