summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorbell@sanja.is.com.ua <>2003-07-03 02:30:52 +0300
committerbell@sanja.is.com.ua <>2003-07-03 02:30:52 +0300
commit28207ede0222a6b1ceff6f01b3f5bfccb7f73e42 (patch)
treebaf496555ea973850414a91a38ffbb81729b0bc6 /sql
parent2ae8a00b2a0e4bc11fb70f0161be34f1573a2f55 (diff)
downloadmariadb-git-28207ede0222a6b1ceff6f01b3f5bfccb7f73e42.tar.gz
(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)
Diffstat (limited to 'sql')
-rw-r--r--sql/item.cc6
-rw-r--r--sql/item_subselect.cc13
-rw-r--r--sql/item_sum.cc6
-rw-r--r--sql/sql_delete.cc2
-rw-r--r--sql/sql_derived.cc2
-rw-r--r--sql/sql_lex.cc142
-rw-r--r--sql/sql_lex.h112
-rw-r--r--sql/sql_parse.cc34
-rw-r--r--sql/sql_select.cc5
-rw-r--r--sql/sql_union.cc24
-rw-r--r--sql/sql_yacc.yy103
11 files changed, 222 insertions, 227 deletions
diff --git a/sql/item.cc b/sql/item.cc
index 4a04dc93a54..62f7823d1e3 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -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,
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index f29ac3b3c9c..d295e5c8261 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -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)
{
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index 67dffb35724..43534276759 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -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;
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index ebb09b99df7..876c4f9e670 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -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);
}
diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc
index 0f8b9b96455..92e37f95f0e 100644
--- a/sql/sql_derived.cc
+++ b/sql/sql_derived.cc
@@ -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");
/*
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 9b372f6eeda..8e3d6df0540 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -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,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
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=
- s->get_table_list();
- tbl;
- tbl= tbl->next)
- tbl->shared= 1;
- }
+ s->master_unit()->dependent= 1;
+ //Tables will be reopened many times
+ for (TABLE_LIST *tbl=
+ 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; }
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
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index a48aa5721e4..adf452376a7 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -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;
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 5070466007e..915bed8ae9c 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -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,17 +3536,32 @@ 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->include_down(lex->current_select);
unit->link_next= 0;
unit->link_prev= 0;
unit->return_to= lex->current_select;
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);
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index ca0f673954e..38c8cffdd22 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -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);
}
}
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index 79e1e9843a8..7c9e6f0a24e 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -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
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 659744ce677..23ce607040d 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -1835,7 +1835,7 @@ table_to_table:
table_ident TO_SYM table_ident
{
LEX *lex=Lex;
- SELECT_LEX_NODE *sl= lex->current_select;
+ SELECT_LEX *sl= lex->current_select;
if (!sl->add_table_to_list(lex->thd, $1,NULL,TL_OPTION_UPDATING,
TL_IGNORE) ||
!sl->add_table_to_list(lex->thd, $3,NULL,TL_OPTION_UPDATING,
@@ -1871,7 +1871,7 @@ preload_keys:
;
preload_keys_spec:
- keys_or_index { Select->select_lex()->interval_list.empty(); }
+ keys_or_index { Select->interval_list.empty(); }
preload_key_list_or_empty
{
LEX *lex=Lex;
@@ -1907,7 +1907,7 @@ select_init:
'(' SELECT_SYM select_part2 ')'
{
LEX *lex= Lex;
- SELECT_LEX * sel= lex->current_select->select_lex();
+ SELECT_LEX * sel= lex->current_select;
if (sel->set_braces(1))
{
send_error(lex->thd, ER_SYNTAX_ERROR);
@@ -1921,14 +1921,14 @@ select_init:
}
/* select in braces, can't contain global parameters */
sel->master_unit()->global_parameters=
- sel->master_unit();
+ sel->master_unit()->fake_select_lex;
} union_opt;
select_init2:
select_part2
{
LEX *lex= Lex;
- SELECT_LEX * sel= lex->current_select->select_lex();
+ SELECT_LEX * sel= lex->current_select;
if (lex->current_select->set_braces(0))
{
send_error(lex->thd, ER_SYNTAX_ERROR);
@@ -1947,7 +1947,7 @@ select_init2:
select_part2:
{
LEX *lex=Lex;
- SELECT_LEX * sel= lex->current_select->select_lex();
+ SELECT_LEX * sel= lex->current_select;
if (lex->current_select == &lex->select_lex)
lex->lock_option= TL_READ; /* Only for global SELECT */
if (sel->linkage != UNION_TYPE)
@@ -2038,7 +2038,7 @@ select_item_list:
THD *thd= YYTHD;
if (add_item_to_list(thd, new Item_field(NULL, NULL, "*")))
YYABORT;
- (thd->lex.current_select->select_lex()->with_wild)++;
+ (thd->lex.current_select->with_wild)++;
};
@@ -2668,9 +2668,9 @@ sum_expr:
| COUNT_SYM '(' in_sum_expr ')'
{ $$=new Item_sum_count($3); }
| COUNT_SYM '(' DISTINCT
- { Select->select_lex()->in_sum_expr++; }
+ { Select->in_sum_expr++; }
expr_list
- { Select->select_lex()->in_sum_expr--; }
+ { Select->in_sum_expr--; }
')'
{ $$=new Item_sum_count_distinct(* $5); }
| GROUP_UNIQUE_USERS '(' text_literal ',' NUM ',' NUM ',' in_sum_expr ')'
@@ -2726,7 +2726,7 @@ in_sum_expr:
}
expr
{
- Select->select_lex()->in_sum_expr--;
+ Select->in_sum_expr--;
$$= $3;
};
@@ -2780,13 +2780,13 @@ when_list:
when_list2:
expr THEN_SYM expr
{
- SELECT_LEX_NODE *sel=Select;
+ SELECT_LEX *sel=Select;
sel->when_list.head()->push_back($1);
sel->when_list.head()->push_back($3);
}
| when_list2 WHEN_SYM expr THEN_SYM expr
{
- SELECT_LEX_NODE *sel=Select;
+ SELECT_LEX *sel=Select;
sel->when_list.head()->push_back($3);
sel->when_list.head()->push_back($5);
};
@@ -2803,7 +2803,7 @@ join_table_list:
| join_table_list normal_join join_table_list
USING
{
- SELECT_LEX *sel= Select->select_lex();
+ SELECT_LEX *sel= Select;
sel->db1=$1->db; sel->table1=$1->alias;
sel->db2=$3->db; sel->table2=$3->alias;
}
@@ -2814,7 +2814,7 @@ join_table_list:
{ add_join_on($5,$7); $5->outer_join|=JOIN_TYPE_LEFT; $$=$5; }
| join_table_list LEFT opt_outer JOIN_SYM join_table_list
{
- SELECT_LEX *sel= Select->select_lex();
+ SELECT_LEX *sel= Select;
sel->db1=$1->db; sel->table1=$1->alias;
sel->db2=$5->db; sel->table2=$5->alias;
}
@@ -2830,7 +2830,7 @@ join_table_list:
{ add_join_on($1,$7); $1->outer_join|=JOIN_TYPE_RIGHT; $$=$5; }
| join_table_list RIGHT opt_outer JOIN_SYM join_table_list
{
- SELECT_LEX *sel= Select->select_lex();
+ SELECT_LEX *sel= Select;
sel->db1=$1->db; sel->table1=$1->alias;
sel->db2=$5->db; sel->table2=$5->alias;
}
@@ -2853,14 +2853,14 @@ normal_join:
join_table:
{
- SELECT_LEX *sel= Select->select_lex();
+ SELECT_LEX *sel= Select;
sel->use_index_ptr=sel->ignore_index_ptr=0;
sel->table_join_options= 0;
}
table_ident opt_table_alias opt_key_definition
{
LEX *lex= Lex;
- SELECT_LEX_NODE *sel= lex->current_select;
+ SELECT_LEX *sel= lex->current_select;
if (!($$= sel->add_table_to_list(lex->thd, $2, $3,
sel->get_table_join_options(),
lex->lock_option,
@@ -2910,28 +2910,28 @@ opt_key_definition:
/* empty */ {}
| USE_SYM key_usage_list
{
- SELECT_LEX *sel= Select->select_lex();
+ SELECT_LEX *sel= Select;
sel->use_index= *$2;
sel->use_index_ptr= &sel->use_index;
}
| FORCE_SYM key_usage_list
{
- SELECT_LEX *sel= Select->select_lex();
+ SELECT_LEX *sel= Select;
sel->use_index= *$2;
sel->use_index_ptr= &sel->use_index;
sel->table_join_options|= TL_OPTION_FORCE_INDEX;
}
| IGNORE_SYM key_usage_list
{
- SELECT_LEX *sel= Select->select_lex();
+ SELECT_LEX *sel= Select;
sel->ignore_index= *$2;
sel->ignore_index_ptr= &sel->ignore_index;
};
key_usage_list:
- key_or_index { Select->select_lex()->interval_list.empty(); }
+ key_or_index { Select->interval_list.empty(); }
'(' key_list_or_empty ')'
- { $$= &Select->select_lex()->interval_list; }
+ { $$= &Select->interval_list; }
;
key_list_or_empty:
@@ -2941,22 +2941,22 @@ key_list_or_empty:
key_usage_list2:
key_usage_list2 ',' ident
- { Select->select_lex()->
+ { Select->
interval_list.push_back(new String((const char*) $3.str, $3.length,
system_charset_info)); }
| ident
- { Select->select_lex()->
+ { Select->
interval_list.push_back(new String((const char*) $1.str, $1.length,
system_charset_info)); }
| PRIMARY_SYM
- { Select->select_lex()->
+ { Select->
interval_list.push_back(new String("PRIMARY", 7,
system_charset_info)); };
using_list:
ident
{
- SELECT_LEX *sel= Select->select_lex();
+ SELECT_LEX *sel= Select;
if (!($$= new Item_func_eq(new Item_field(sel->db1, sel->table1,
$1.str),
new Item_field(sel->db2, sel->table2,
@@ -2965,7 +2965,7 @@ using_list:
}
| using_list ',' ident
{
- SELECT_LEX *sel= Select->select_lex();
+ SELECT_LEX *sel= Select;
if (!($$= new Item_cond_and(new Item_func_eq(new Item_field(sel->db1,sel->table1,$3.str), new Item_field(sel->db2,sel->table2,$3.str)), $1)))
YYABORT;
};
@@ -3001,10 +3001,10 @@ opt_all:
;
where_clause:
- /* empty */ { Select->select_lex()->where= 0; }
+ /* empty */ { Select->where= 0; }
| WHERE expr
{
- Select->select_lex()->where= $2;
+ Select->where= $2;
if ($2)
$2->top_level_item();
}
@@ -3014,11 +3014,11 @@ having_clause:
/* empty */
| HAVING
{
- Select->select_lex()->parsing_place= SELECT_LEX_NODE::IN_HAVING;
+ Select->parsing_place= SELECT_LEX_NODE::IN_HAVING;
}
expr
{
- SELECT_LEX *sel= Select->select_lex();
+ SELECT_LEX *sel= Select;
sel->having= $3;
sel->parsing_place= SELECT_LEX_NODE::NO_MATTER;
if ($3)
@@ -3056,7 +3056,7 @@ olap_opt:
"global union parameters");
YYABORT;
}
- lex->current_select->select_lex()->olap= CUBE_TYPE;
+ lex->current_select->olap= CUBE_TYPE;
net_printf(lex->thd, ER_NOT_SUPPORTED_YET, "CUBE");
YYABORT; /* To be deleted in 5.1 */
}
@@ -3069,7 +3069,7 @@ olap_opt:
"global union parameters");
YYABORT;
}
- lex->current_select->select_lex()->olap= ROLLUP_TYPE;
+ lex->current_select->olap= ROLLUP_TYPE;
}
;
@@ -3086,7 +3086,7 @@ order_clause:
{
LEX *lex=Lex;
if (lex->current_select->linkage != GLOBAL_OPTIONS_TYPE &&
- lex->current_select->select_lex()->olap !=
+ lex->current_select->olap !=
UNSPECIFIED_OLAP_TYPE)
{
net_printf(lex->thd, ER_WRONG_USAGE,
@@ -3111,7 +3111,7 @@ order_dir:
opt_limit_clause_init:
/* empty */
{
- SELECT_LEX_NODE *sel= Select;
+ SELECT_LEX *sel= Select;
sel->offset_limit= 0L;
sel->select_limit= Lex->thd->variables.select_limit;
}
@@ -3130,19 +3130,19 @@ limit_clause:
limit_options:
ULONG_NUM
{
- SELECT_LEX_NODE *sel= Select;
+ SELECT_LEX *sel= Select;
sel->select_limit= $1;
sel->offset_limit= 0L;
}
| ULONG_NUM ',' ULONG_NUM
{
- SELECT_LEX_NODE *sel= Select;
+ SELECT_LEX *sel= Select;
sel->select_limit= $3;
sel->offset_limit= $1;
}
| ULONG_NUM OFFSET_SYM ULONG_NUM
{
- SELECT_LEX_NODE *sel= Select;
+ SELECT_LEX *sel= Select;
sel->select_limit= $1;
sel->offset_limit= $3;
}
@@ -4117,14 +4117,14 @@ table_wild:
ident '.' '*'
{
$$ = new Item_field(NullS,$1.str,"*");
- Lex->current_select->select_lex()->with_wild++;
+ Lex->current_select->with_wild++;
}
| ident '.' ident '.' '*'
{
$$ = new Item_field((YYTHD->client_capabilities &
CLIENT_NO_SCHEMA ? NullS : $1.str),
$3.str,"*");
- Lex->current_select->select_lex()->with_wild++;
+ Lex->current_select->with_wild++;
}
;
@@ -4134,7 +4134,7 @@ order_ident:
simple_ident:
ident
{
- SELECT_LEX_NODE *sel=Select;
+ SELECT_LEX *sel=Select;
$$= (sel->parsing_place != SELECT_LEX_NODE::IN_HAVING ||
sel->get_in_sum_expr() > 0) ?
(Item*) new Item_field(NullS,NullS,$1.str) :
@@ -4144,7 +4144,7 @@ simple_ident:
{
THD *thd= YYTHD;
LEX *lex= &thd->lex;
- SELECT_LEX_NODE *sel= lex->current_select;
+ SELECT_LEX *sel= lex->current_select;
if (sel->no_table_names_allowed)
{
my_printf_error(ER_TABLENAME_NOT_ALLOWED_HERE,
@@ -4160,7 +4160,7 @@ simple_ident:
{
THD *thd= YYTHD;
LEX *lex= &thd->lex;
- SELECT_LEX_NODE *sel= lex->current_select;
+ SELECT_LEX *sel= lex->current_select;
if (sel->no_table_names_allowed)
{
my_printf_error(ER_TABLENAME_NOT_ALLOWED_HERE,
@@ -4176,7 +4176,7 @@ simple_ident:
{
THD *thd= YYTHD;
LEX *lex= &thd->lex;
- SELECT_LEX_NODE *sel= lex->current_select;
+ SELECT_LEX *sel= lex->current_select;
if (sel->no_table_names_allowed)
{
my_printf_error(ER_TABLENAME_NOT_ALLOWED_HERE,
@@ -4858,7 +4858,7 @@ opt_table:
'*'
{
LEX *lex= Lex;
- lex->current_select->select_lex()->db= lex->thd->db;
+ lex->current_select->db= lex->thd->db;
if (lex->grant == GLOBAL_ACLS)
lex->grant = DB_ACLS & ~GRANT_ACL;
else if (lex->columns.elements)
@@ -4870,7 +4870,7 @@ opt_table:
| ident '.' '*'
{
LEX *lex= Lex;
- lex->current_select->select_lex()->db = $1.str;
+ lex->current_select->db = $1.str;
if (lex->grant == GLOBAL_ACLS)
lex->grant = DB_ACLS & ~GRANT_ACL;
else if (lex->columns.elements)
@@ -4882,7 +4882,7 @@ opt_table:
| '*' '.' '*'
{
LEX *lex= Lex;
- lex->current_select->select_lex()->db = NULL;
+ lex->current_select->db = NULL;
if (lex->grant == GLOBAL_ACLS)
lex->grant= GLOBAL_ACLS & ~GRANT_ACL;
else if (lex->columns.elements)
@@ -5077,11 +5077,12 @@ optional_order_or_limit:
THD *thd= YYTHD;
LEX *lex= &thd->lex;
DBUG_ASSERT(lex->current_select->linkage != GLOBAL_OPTIONS_TYPE);
- SELECT_LEX *sel= lex->current_select->select_lex();
+ SELECT_LEX *sel= lex->current_select;
SELECT_LEX_UNIT *unit= sel->master_unit();
- unit->global_parameters= unit;
- unit->no_table_names_allowed= 1;
- lex->current_select= unit;
+ SELECT_LEX *fake= unit->fake_select_lex;
+ unit->global_parameters= fake;
+ fake->no_table_names_allowed= 1;
+ lex->current_select= fake;
thd->where= "global ORDER clause";
}
order_or_limit