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