summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorOleksandr Byelkin <sanja@mariadb.com>2018-05-22 19:08:39 +0200
committerOleksandr Byelkin <sanja@mariadb.com>2018-07-04 19:13:55 +0200
commitde745ecf29721795710910a19bd0ea3389da804c (patch)
treed5beaf48411123b9212a024480e495f1774c633c /sql
parent1b981b9edb419e2ac3be1d6e007192a827504185 (diff)
downloadmariadb-git-de745ecf29721795710910a19bd0ea3389da804c.tar.gz
MDEV-11953: support of brackets in UNION/EXCEPT/INTERSECT operations
Diffstat (limited to 'sql')
-rw-r--r--sql/events.cc9
-rw-r--r--sql/item.cc16
-rw-r--r--sql/item.h9
-rw-r--r--sql/item_create.cc7
-rw-r--r--sql/item_func.cc6
-rw-r--r--sql/item_subselect.cc26
-rw-r--r--sql/item_sum.cc3
-rw-r--r--sql/log_event.cc7
-rw-r--r--sql/opt_range.cc2
-rw-r--r--sql/opt_subselect.cc1
-rw-r--r--sql/opt_table_elimination.cc4
-rw-r--r--sql/set_var.cc2
-rw-r--r--sql/sp_head.cc3
-rw-r--r--sql/sp_head.h3
-rw-r--r--sql/sp_rcontext.cc14
-rw-r--r--sql/sql_admin.cc18
-rw-r--r--sql/sql_alter.cc4
-rw-r--r--sql/sql_base.cc8
-rw-r--r--sql/sql_base.h6
-rw-r--r--sql/sql_cache.cc8
-rw-r--r--sql/sql_class.h3
-rw-r--r--sql/sql_cte.cc24
-rw-r--r--sql/sql_cte.h26
-rw-r--r--sql/sql_delete.cc32
-rw-r--r--sql/sql_derived.cc3
-rw-r--r--sql/sql_do.cc2
-rw-r--r--sql/sql_error.cc2
-rw-r--r--sql/sql_help.cc11
-rw-r--r--sql/sql_insert.cc40
-rw-r--r--sql/sql_lex.cc1498
-rw-r--r--sql/sql_lex.h365
-rw-r--r--sql/sql_load.cc9
-rw-r--r--sql/sql_parse.cc109
-rw-r--r--sql/sql_partition.cc3
-rw-r--r--sql/sql_partition_admin.cc4
-rw-r--r--sql/sql_prepare.cc50
-rw-r--r--sql/sql_priv.h9
-rw-r--r--sql/sql_profile.cc4
-rw-r--r--sql/sql_select.cc86
-rw-r--r--sql/sql_sequence.cc4
-rw-r--r--sql/sql_show.cc31
-rw-r--r--sql/sql_table.cc6
-rw-r--r--sql/sql_truncate.cc2
-rw-r--r--sql/sql_tvc.cc8
-rw-r--r--sql/sql_union.cc6
-rw-r--r--sql/sql_update.cc30
-rw-r--r--sql/sql_view.cc46
-rw-r--r--sql/sql_yacc.yy2091
-rw-r--r--sql/sql_yacc_ora.yy1991
-rw-r--r--sql/structs.h37
-rw-r--r--sql/table.cc34
-rw-r--r--sql/wsrep_mysqld.cc4
52 files changed, 3957 insertions, 2769 deletions
diff --git a/sql/events.cc b/sql/events.cc
index c13582e634c..af020d5240e 100644
--- a/sql/events.cc
+++ b/sql/events.cc
@@ -824,12 +824,13 @@ Events::fill_schema_events(THD *thd, TABLE_LIST *tables, COND * /* cond */)
*/
if (thd->lex->sql_command == SQLCOM_SHOW_EVENTS)
{
- DBUG_ASSERT(thd->lex->select_lex.db.str);
- if (!is_infoschema_db(&thd->lex->select_lex.db) && // There is no events in I_S
- check_access(thd, EVENT_ACL, thd->lex->select_lex.db.str,
+ DBUG_ASSERT(thd->lex->first_select_lex()->db.str);
+ if (!is_infoschema_db(&thd->lex->first_select_lex()->db) && // There is no events in I_S
+ check_access(thd, EVENT_ACL, thd->lex->first_select_lex()->db.str,
NULL, NULL, 0, 0))
DBUG_RETURN(1);
- db= normalize_db_name(thd->lex->select_lex.db.str, db_tmp, sizeof(db_tmp));
+ db= normalize_db_name(thd->lex->first_select_lex()->db.str,
+ db_tmp, sizeof(db_tmp));
}
ret= db_repository->fill_schema_events(thd, tables, db);
diff --git a/sql/item.cc b/sql/item.cc
index 878b4c91439..df11b9ce562 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -746,7 +746,8 @@ Item_ident::Item_ident(THD *thd, TABLE_LIST *view_arg,
:Item_result_field(thd), orig_db_name(NullS),
orig_table_name(view_arg->table_name.str),
orig_field_name(*field_name_arg),
- context(&view_arg->view->select_lex.context),
+ /* TODO: suspicious use of first_select_lex */
+ context(&view_arg->view->first_select_lex()->context),
db_name(NullS), table_name(view_arg->alias.str),
field_name(*field_name_arg),
alias_name_used(FALSE), cached_field_index(NO_CACHED_FIELD_INDEX),
@@ -2896,7 +2897,7 @@ bool Item_sp::execute(THD *thd, bool *null_value, Item **args, uint arg_count)
if (unlikely(execute_impl(thd, args, arg_count)))
{
*null_value= 1;
- context->process_error(thd);
+ process_error(thd);
if (thd->killed)
thd->send_kill_message();
return true;
@@ -2929,7 +2930,7 @@ Item_sp::execute_impl(THD *thd, Item **args, uint arg_count)
DBUG_ENTER("Item_sp::execute_impl");
- if (context->security_ctx)
+ if (context && context->security_ctx)
{
/* Set view definer security context */
thd->security_ctx= context->security_ctx;
@@ -3108,7 +3109,10 @@ Item_field::Item_field(THD *thd, Field *f)
have_privileges(0), any_privileges(0)
{
set_field(f);
-
+ /*
+ field_name and table_name should not point to garbage
+ if this item is to be reused
+ */
orig_table_name= table_name;
orig_field_name= field_name;
with_field= 1;
@@ -5731,7 +5735,7 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference)
Name_resolution_context *outer_context= 0;
SELECT_LEX *select= 0;
/* Currently derived tables cannot be correlated */
- if (current_sel->master_unit()->first_select()->linkage !=
+ if (current_sel->master_unit()->first_select()->get_linkage() !=
DERIVED_TABLE_TYPE)
outer_context= context->outer_context;
@@ -8287,7 +8291,7 @@ bool Item_ref::fix_fields(THD *thd, Item **reference)
if (!((*ref)->type() == REF_ITEM &&
((Item_ref *)(*ref))->ref_type() == OUTER_REF) &&
(((*ref)->with_sum_func() && name.str &&
- !(current_sel->linkage != GLOBAL_OPTIONS_TYPE &&
+ !(current_sel->get_linkage() != GLOBAL_OPTIONS_TYPE &&
current_sel->having_fix_field)) ||
!(*ref)->is_fixed()))
{
diff --git a/sql/item.h b/sql/item.h
index 29e5b6455cc..4fce15af83d 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -5011,8 +5011,10 @@ struct st_sp_security_context;
class Item_sp
{
-public:
+protected:
+ // Can be NULL in some non-SELECT queries
Name_resolution_context *context;
+public:
sp_name *m_name;
sp_head *m_sp;
TABLE *dummy_table;
@@ -5034,6 +5036,11 @@ public:
bool execute_impl(THD *thd, Item **args, uint arg_count);
bool init_result_field(THD *thd, uint max_length, uint maybe_null,
bool *null_value, LEX_CSTRING *name);
+ void process_error(THD *thd)
+ {
+ if (context)
+ context->process_error(thd);
+ }
};
class Item_ref :public Item_ident,
diff --git a/sql/item_create.cc b/sql/item_create.cc
index ab91e378be3..904896770c7 100644
--- a/sql/item_create.cc
+++ b/sql/item_create.cc
@@ -3487,12 +3487,11 @@ Create_sp_func::create_with_db(THD *thd, LEX_CSTRING *db, LEX_CSTRING *name,
sph->add_used_routine(lex, thd, qname);
if (pkgname.m_name.length)
sp_handler_package_body.add_used_routine(lex, thd, &pkgname);
+ Name_resolution_context *ctx= lex->current_context();
if (arg_count > 0)
- func= new (thd->mem_root) Item_func_sp(thd, lex->current_context(),
- qname, sph, *item_list);
+ func= new (thd->mem_root) Item_func_sp(thd, ctx, qname, sph, *item_list);
else
- func= new (thd->mem_root) Item_func_sp(thd, lex->current_context(),
- qname, sph);
+ func= new (thd->mem_root) Item_func_sp(thd, ctx, qname, sph);
lex->safe_to_cache_query= 0;
return func;
diff --git a/sql/item_func.cc b/sql/item_func.cc
index d904af7c56b..931e621529e 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -6472,7 +6472,7 @@ Item_func_sp::fix_fields(THD *thd, Item **ref)
(thd->lex->sql_command == SQLCOM_CREATE_VIEW))
{
Security_context *save_security_ctx= thd->security_ctx;
- if (context->security_ctx)
+ if (context && context->security_ctx)
thd->security_ctx= context->security_ctx;
/*
@@ -6487,7 +6487,7 @@ Item_func_sp::fix_fields(THD *thd, Item **ref)
if (res)
{
- context->process_error(thd);
+ process_error(thd);
DBUG_RETURN(res);
}
}
@@ -6504,7 +6504,7 @@ Item_func_sp::fix_fields(THD *thd, Item **ref)
if (!(m_sp= sp))
{
my_missing_function_error(m_name->m_name, ErrConvDQName(m_name).ptr());
- context->process_error(thd);
+ process_error(thd);
DBUG_RETURN(TRUE);
}
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index 9b513ac9795..7af5472d408 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -85,6 +85,9 @@ void Item_subselect::init(st_select_lex *select_lex,
DBUG_ENTER("Item_subselect::init");
DBUG_PRINT("enter", ("select_lex: %p this: %p",
select_lex, this));
+
+ select_lex->parent_lex->relink_hack(select_lex);
+
unit= select_lex->master_unit();
if (unit->item)
@@ -123,14 +126,7 @@ void Item_subselect::init(st_select_lex *select_lex,
else
engine= new subselect_single_select_engine(select_lex, result, this);
}
- {
- SELECT_LEX *upper= unit->outer_select();
- if (upper->parsing_place == IN_HAVING)
- upper->subquery_in_having= 1;
- /* The subquery is an expression cache candidate */
- upper->expr_cache_may_be_used[upper->parsing_place]= TRUE;
- }
- DBUG_PRINT("info", ("engine: %p", engine));
+ DBUG_PRINT("info", ("engine: 0x%lx", (ulong)engine));
DBUG_VOID_RETURN;
}
@@ -220,7 +216,8 @@ Item_subselect::~Item_subselect()
if (own_engine)
delete engine;
else
- engine->cleanup();
+ if (engine) // can be empty in case of EOM
+ engine->cleanup();
engine= NULL;
DBUG_VOID_RETURN;
}
@@ -244,6 +241,14 @@ bool Item_subselect::fix_fields(THD *thd_param, Item **ref)
DBUG_ASSERT(unit->thd == thd);
+ {
+ SELECT_LEX *upper= unit->outer_select();
+ if (upper->parsing_place == IN_HAVING)
+ upper->subquery_in_having= 1;
+ /* The subquery is an expression cache candidate */
+ upper->expr_cache_may_be_used[upper->parsing_place]= TRUE;
+ }
+
status_var_increment(thd_param->status_var.feature_subquery);
DBUG_ASSERT(fixed == 0);
@@ -1407,6 +1412,8 @@ Item_exists_subselect::Item_exists_subselect(THD *thd,
emb_on_expr_nest(NULL), optimizer(0), exists_transformed(0)
{
DBUG_ENTER("Item_exists_subselect::Item_exists_subselect");
+
+
init(select_lex, new (thd->mem_root) select_exists_subselect(thd, this));
max_columns= UINT_MAX;
null_value= FALSE; //can't be NULL
@@ -1449,6 +1456,7 @@ Item_in_subselect::Item_in_subselect(THD *thd, Item * left_exp,
{
DBUG_ENTER("Item_in_subselect::Item_in_subselect");
DBUG_PRINT("info", ("in_strategy: %u", (uint)in_strategy));
+
left_expr_orig= left_expr= left_exp;
/* prepare to possible disassembling the item in convert_subq_to_sj() */
if (left_exp->type() == Item::ROW_ITEM)
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index 3e26e70ee6e..6de33d22c63 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -1288,7 +1288,7 @@ Item_sum_sp::fix_fields(THD *thd, Item **ref)
if (!m_sp)
{
my_missing_function_error(m_name->m_name, ErrConvDQName(m_name).ptr());
- context->process_error(thd);
+ process_error(thd);
return TRUE;
}
@@ -4009,6 +4009,7 @@ bool Item_func_group_concat::setup(THD *thd)
if (!ref_pointer_array)
DBUG_RETURN(TRUE);
memcpy(ref_pointer_array, args, arg_count * sizeof(Item*));
+ DBUG_ASSERT(context);
if (setup_order(thd, Ref_ptr_array(ref_pointer_array, n_elems),
context->table_list, list, all_fields, *order))
DBUG_RETURN(TRUE);
diff --git a/sql/log_event.cc b/sql/log_event.cc
index c550adea26b..fcaa7672bf6 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -4390,7 +4390,7 @@ Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg, size_t que
have to use the transactional cache to ensure we don't
calculate any checksum for the CREATE part.
*/
- trx_cache= (lex->select_lex.item_list.elements &&
+ trx_cache= (lex->first_select_lex()->item_list.elements &&
thd->is_current_stmt_binlog_format_row()) ||
(thd->variables.option_bits & OPTION_GTID_BEGIN);
use_cache= (lex->tmp_table() &&
@@ -7382,8 +7382,9 @@ int Load_log_event::do_apply_event(NET* net, rpl_group_info *rgi,
ex.skip_lines = skip_lines;
List<Item> field_list;
- thd->lex->select_lex.context.resolve_in_table_list_only(&tables);
- set_fields(tables.db.str, field_list, &thd->lex->select_lex.context);
+ thd->lex->first_select_lex()->context.resolve_in_table_list_only(&tables);
+ set_fields(tables.db.str,
+ field_list, &thd->lex->first_select_lex()->context);
thd->variables.pseudo_thread_id= thread_id;
if (net)
{
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 6879eb6bdcf..d49ee33aafc 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -4543,7 +4543,7 @@ double get_sweep_read_cost(const PARAM *param, ha_rows records)
if (max_cost != DBL_MAX && (busy_blocks+index_reads_cost) >= n_blocks)
return 1;
*/
- JOIN *join= param->thd->lex->select_lex.join;
+ JOIN *join= param->thd->lex->first_select_lex()->join;
if (!join || join->table_count == 1)
{
/* No join, assume reading is done in one 'sweep' */
diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc
index ba57d9d3ca4..efc38e5fe66 100644
--- a/sql/opt_subselect.cc
+++ b/sql/opt_subselect.cc
@@ -518,6 +518,7 @@ bool is_materialization_applicable(THD *thd, Item_in_subselect *in_subs,
if (optimizer_flag(thd, OPTIMIZER_SWITCH_MATERIALIZATION) && // 0
!child_select->is_part_of_union() && // 1
parent_unit->first_select()->leaf_tables.elements && // 2
+ child_select->outer_select() &&
child_select->outer_select()->leaf_tables.elements && // 2A
subquery_types_allow_materialization(in_subs) &&
(in_subs->is_top_level_item() || //3
diff --git a/sql/opt_table_elimination.cc b/sql/opt_table_elimination.cc
index 4b22aeaf871..74d1e775c43 100644
--- a/sql/opt_table_elimination.cc
+++ b/sql/opt_table_elimination.cc
@@ -617,7 +617,7 @@ void eliminate_tables(JOIN *join)
we should also take into account tables mentioned in "val".
*/
if (join->thd->lex->sql_command == SQLCOM_INSERT_SELECT &&
- join->select_lex == &thd->lex->select_lex)
+ join->select_lex == thd->lex->first_select_lex())
{
List_iterator<Item> val_it(thd->lex->value_list);
while ((item= val_it++))
@@ -640,7 +640,7 @@ void eliminate_tables(JOIN *join)
used_tables |= (*(cur_list->item))->used_tables();
}
- if (join->select_lex == &thd->lex->select_lex)
+ if (join->select_lex == thd->lex->first_select_lex())
{
/* Multi-table UPDATE: don't eliminate tables referred from SET statement */
diff --git a/sql/set_var.cc b/sql/set_var.cc
index 8ab892068b3..de9bda3d067 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -742,7 +742,7 @@ int sql_set_variables(THD *thd, List<set_var_base> *var_list, bool free)
err:
if (free)
- free_underlaid_joins(thd, &thd->lex->select_lex);
+ free_underlaid_joins(thd, thd->lex->first_select_lex());
DBUG_RETURN(error);
}
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index 0d5e1abfdf2..98db8699967 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -290,7 +290,7 @@ sp_get_flags_for_command(LEX *lex)
- EXPLAIN DELETE ...
- ANALYZE DELETE ...
*/
- if (lex->select_lex.item_list.is_empty() &&
+ if (lex->first_select_lex()->item_list.is_empty() &&
!lex->describe && !lex->analyze_stmt)
flags= 0;
else
@@ -2264,6 +2264,7 @@ sp_head::execute_procedure(THD *thd, List<Item> *args)
if (!err_status)
{
err_status= execute(thd, TRUE);
+ DBUG_PRINT("info", ("execute returned %d", (int) err_status));
}
if (save_log_general)
diff --git a/sql/sp_head.h b/sql/sp_head.h
index 3ec8bba1b50..8db6ecac9e7 100644
--- a/sql/sp_head.h
+++ b/sql/sp_head.h
@@ -589,7 +589,8 @@ public:
if (!oldlex)
DBUG_RETURN(false); // Nothing to restore
LEX *sublex= thd->lex;
- if (thd->restore_from_local_lex_to_old_lex(oldlex))// This restores thd->lex
+ // This restores thd->lex and thd->stmt_lex
+ if (thd->restore_from_local_lex_to_old_lex(oldlex))
DBUG_RETURN(true);
if (!sublex->sp_lex_in_use)
{
diff --git a/sql/sp_rcontext.cc b/sql/sp_rcontext.cc
index 24777abe1c3..a31631e33ef 100644
--- a/sql/sp_rcontext.cc
+++ b/sql/sp_rcontext.cc
@@ -228,9 +228,10 @@ bool Qualified_column_ident::resolve_type_ref(THD *thd, Column_definition *def)
// Make %TYPE variables see temporary tables that shadow permanent tables
thd->temporary_tables= open_tables_state_backup.temporary_tables;
- if ((table_list= lex.select_lex.add_table_to_list(thd, this, NULL, 0,
- TL_READ_NO_INSERT,
- MDL_SHARED_READ)) &&
+ if ((table_list=
+ lex.first_select_lex()->add_table_to_list(thd, this, NULL, 0,
+ TL_READ_NO_INSERT,
+ MDL_SHARED_READ)) &&
!check_table_access(thd, SELECT_ACL, table_list, TRUE, UINT_MAX, FALSE) &&
!open_tables_only_view_structure(thd, table_list,
thd->mdl_context.has_locks()))
@@ -286,9 +287,10 @@ bool Table_ident::resolve_table_rowtype_ref(THD *thd,
// Make %ROWTYPE variables see temporary tables that shadow permanent tables
thd->temporary_tables= open_tables_state_backup.temporary_tables;
- if ((table_list= lex.select_lex.add_table_to_list(thd, this, NULL, 0,
- TL_READ_NO_INSERT,
- MDL_SHARED_READ)) &&
+ if ((table_list=
+ lex.first_select_lex()->add_table_to_list(thd, this, NULL, 0,
+ TL_READ_NO_INSERT,
+ MDL_SHARED_READ)) &&
!check_table_access(thd, SELECT_ACL, table_list, TRUE, UINT_MAX, FALSE) &&
!open_tables_only_view_structure(thd, table_list,
thd->mdl_context.has_locks()))
diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc
index 21bb086f013..9f92af61eec 100644
--- a/sql/sql_admin.cc
+++ b/sql/sql_admin.cc
@@ -306,7 +306,7 @@ static bool open_only_one_table(THD* thd, TABLE_LIST* table,
bool is_view_operator_func)
{
LEX *lex= thd->lex;
- SELECT_LEX *select= &lex->select_lex;
+ SELECT_LEX *select= lex->first_select_lex();
TABLE_LIST *save_next_global, *save_next_local;
bool open_error;
save_next_global= table->next_global;
@@ -1301,7 +1301,7 @@ bool mysql_preload_keys(THD* thd, TABLE_LIST* tables)
bool Sql_cmd_analyze_table::execute(THD *thd)
{
LEX *m_lex= thd->lex;
- TABLE_LIST *first_table= m_lex->select_lex.table_list.first;
+ TABLE_LIST *first_table= m_lex->first_select_lex()->table_list.first;
bool res= TRUE;
thr_lock_type lock_type = TL_READ_NO_INSERT;
DBUG_ENTER("Sql_cmd_analyze_table::execute");
@@ -1321,7 +1321,7 @@ bool Sql_cmd_analyze_table::execute(THD *thd)
*/
res= write_bin_log(thd, TRUE, thd->query(), thd->query_length());
}
- m_lex->select_lex.table_list.first= first_table;
+ m_lex->first_select_lex()->table_list.first= first_table;
m_lex->query_tables= first_table;
error:
@@ -1332,7 +1332,7 @@ error:
bool Sql_cmd_check_table::execute(THD *thd)
{
LEX *m_lex= thd->lex;
- TABLE_LIST *first_table= m_lex->select_lex.table_list.first;
+ TABLE_LIST *first_table= m_lex->first_select_lex()->table_list.first;
thr_lock_type lock_type = TL_READ_NO_INSERT;
bool res= TRUE;
DBUG_ENTER("Sql_cmd_check_table::execute");
@@ -1345,7 +1345,7 @@ bool Sql_cmd_check_table::execute(THD *thd)
lock_type, 0, 0, HA_OPEN_FOR_REPAIR, 0,
&handler::ha_check, &view_check);
- m_lex->select_lex.table_list.first= first_table;
+ m_lex->first_select_lex()->table_list.first= first_table;
m_lex->query_tables= first_table;
error:
@@ -1356,7 +1356,7 @@ error:
bool Sql_cmd_optimize_table::execute(THD *thd)
{
LEX *m_lex= thd->lex;
- TABLE_LIST *first_table= m_lex->select_lex.table_list.first;
+ TABLE_LIST *first_table= m_lex->first_select_lex()->table_list.first;
bool res= TRUE;
DBUG_ENTER("Sql_cmd_optimize_table::execute");
@@ -1378,7 +1378,7 @@ bool Sql_cmd_optimize_table::execute(THD *thd)
*/
res= write_bin_log(thd, TRUE, thd->query(), thd->query_length());
}
- m_lex->select_lex.table_list.first= first_table;
+ m_lex->first_select_lex()->table_list.first= first_table;
m_lex->query_tables= first_table;
error:
@@ -1389,7 +1389,7 @@ error:
bool Sql_cmd_repair_table::execute(THD *thd)
{
LEX *m_lex= thd->lex;
- TABLE_LIST *first_table= m_lex->select_lex.table_list.first;
+ TABLE_LIST *first_table= m_lex->first_select_lex()->table_list.first;
bool res= TRUE;
DBUG_ENTER("Sql_cmd_repair_table::execute");
@@ -1413,7 +1413,7 @@ bool Sql_cmd_repair_table::execute(THD *thd)
*/
res= write_bin_log(thd, TRUE, thd->query(), thd->query_length());
}
- m_lex->select_lex.table_list.first= first_table;
+ m_lex->first_select_lex()->table_list.first= first_table;
m_lex->query_tables= first_table;
error:
diff --git a/sql/sql_alter.cc b/sql/sql_alter.cc
index a96b0a5a32b..700b4699430 100644
--- a/sql/sql_alter.cc
+++ b/sql/sql_alter.cc
@@ -356,7 +356,7 @@ bool Sql_cmd_alter_table::execute(THD *thd)
{
LEX *lex= thd->lex;
/* first SELECT_LEX (have special meaning for many of non-SELECTcommands) */
- SELECT_LEX *select_lex= &lex->select_lex;
+ SELECT_LEX *select_lex= lex->first_select_lex();
/* first table of first SELECT_LEX */
TABLE_LIST *first_table= (TABLE_LIST*) select_lex->table_list.first;
/*
@@ -506,7 +506,7 @@ error:
bool Sql_cmd_discard_import_tablespace::execute(THD *thd)
{
/* first SELECT_LEX (have special meaning for many of non-SELECTcommands) */
- SELECT_LEX *select_lex= &thd->lex->select_lex;
+ SELECT_LEX *select_lex= thd->lex->first_select_lex();
/* first table of first SELECT_LEX */
TABLE_LIST *table_list= (TABLE_LIST*) select_lex->table_list.first;
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 6aafdcd7a71..9540b0a706f 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -7462,7 +7462,7 @@ bool setup_tables(THD *thd, Name_resolution_context *context,
TABLE_LIST *first_select_table= (select_insert ?
tables->next_local:
0);
- SELECT_LEX *select_lex= select_insert ? &thd->lex->select_lex :
+ SELECT_LEX *select_lex= select_insert ? thd->lex->first_select_lex() :
thd->lex->current_select;
if (select_lex->first_cond_optimization)
{
@@ -7490,7 +7490,7 @@ bool setup_tables(THD *thd, Name_resolution_context *context,
{
/* new counting for SELECT of INSERT ... SELECT command */
first_select_table= 0;
- thd->lex->select_lex.insert_tables= tablenr;
+ thd->lex->first_select_lex()->insert_tables= tablenr;
tablenr= 0;
}
if(table_list->jtbm_subselect)
@@ -8037,7 +8037,7 @@ int setup_conds(THD *thd, TABLE_LIST *tables, List<TABLE_LIST> &leaves,
from subquery of VIEW, because tables of subquery belongs to VIEW
(see condition before prepare_check_option() call)
*/
- bool it_is_update= (select_lex == &thd->lex->select_lex) &&
+ bool it_is_update= (select_lex == thd->lex->first_select_lex()) &&
thd->lex->which_check_option_applicable();
bool save_is_item_list_lookup= select_lex->is_item_list_lookup;
TABLE_LIST *derived= select_lex->master_unit()->derived;
@@ -8053,7 +8053,7 @@ int setup_conds(THD *thd, TABLE_LIST *tables, List<TABLE_LIST> &leaves,
for (table= tables; table; table= table->next_local)
{
- if (select_lex == &thd->lex->select_lex &&
+ if (select_lex == thd->lex->first_select_lex() &&
select_lex->first_cond_optimization &&
table->merged_for_insert &&
table->prepare_where(thd, conds, FALSE))
diff --git a/sql/sql_base.h b/sql/sql_base.h
index 01892c0b938..86c4627ecff 100644
--- a/sql/sql_base.h
+++ b/sql/sql_base.h
@@ -366,10 +366,12 @@ inline bool setup_fields_with_no_wrap(THD *thd, Ref_ptr_array ref_pointer_array,
bool allow_sum_func)
{
bool res;
- thd->lex->select_lex.no_wrap_view_item= TRUE;
+ SELECT_LEX *first= thd->lex->first_select_lex();
+ DBUG_ASSERT(thd->lex->current_select == first);
+ first->no_wrap_view_item= TRUE;
res= setup_fields(thd, ref_pointer_array, item, column_usage,
sum_func_list, NULL, allow_sum_func);
- thd->lex->select_lex.no_wrap_view_item= FALSE;
+ first->no_wrap_view_item= FALSE;
return res;
}
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc
index aa4c77d0939..76b2d6db247 100644
--- a/sql/sql_cache.cc
+++ b/sql/sql_cache.cc
@@ -4147,13 +4147,13 @@ Query_cache::is_cacheable(THD *thd, LEX *lex,
if (thd->lex->safe_to_cache_query &&
(thd->variables.query_cache_type == 1 ||
- (thd->variables.query_cache_type == 2 && (lex->select_lex.options &
- OPTION_TO_QUERY_CACHE))) &&
+ (thd->variables.query_cache_type == 2 &&
+ (lex->first_select_lex()->options & OPTION_TO_QUERY_CACHE))) &&
qc_is_able_to_intercept_result(thd))
{
DBUG_PRINT("qcache", ("options: %lx %lx type: %u",
(long) OPTION_TO_QUERY_CACHE,
- (long) lex->select_lex.options,
+ (long) lex->first_select_lex()->options,
(int) thd->variables.query_cache_type));
if (!(table_count= process_and_count_tables(thd, tables_used,
@@ -4174,7 +4174,7 @@ Query_cache::is_cacheable(THD *thd, LEX *lex,
("not interesting query: %d or not cacheable, options %lx %lx type: %u net->vio present: %u",
(int) lex->sql_command,
(long) OPTION_TO_QUERY_CACHE,
- (long) lex->select_lex.options,
+ (long) lex->first_select_lex()->options,
(int) thd->variables.query_cache_type,
(uint) MY_TEST(qc_is_able_to_intercept_result(thd))));
DBUG_RETURN(0);
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 359d5f93a1f..7f3be3353fb 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -6319,7 +6319,8 @@ public:
inline bool add_item_to_list(THD *thd, Item *item)
{
- return thd->lex->current_select->add_item_to_list(thd, item);
+ bool res= thd->lex->current_select->add_item_to_list(thd, item);
+ return res;
}
inline bool add_value_to_list(THD *thd, Item *value)
diff --git a/sql/sql_cte.cc b/sql/sql_cte.cc
index 693ea9f0c5b..a518f991892 100644
--- a/sql/sql_cte.cc
+++ b/sql/sql_cte.cc
@@ -55,6 +55,14 @@ bool With_clause::add_with_element(With_element *elem)
}
+void st_select_lex_unit::set_with_clause(With_clause *with_cl)
+{
+ with_clause= with_cl;
+ if (with_clause)
+ with_clause->set_owner(this);
+}
+
+
/**
@brief
Check dependencies between tables defined in a list of with clauses
@@ -682,7 +690,7 @@ void With_element::move_anchors_ahead()
{
st_select_lex *next_sl;
st_select_lex *new_pos= spec->first_select();
- new_pos->linkage= UNION_TYPE;
+ new_pos->set_linkage(UNION_TYPE);
for (st_select_lex *sl= new_pos; sl; sl= next_sl)
{
next_sl= sl->next_select();
@@ -691,9 +699,9 @@ void With_element::move_anchors_ahead()
sl->move_node(new_pos);
if (new_pos == spec->first_select())
{
- enum sub_select_type type= new_pos->linkage;
- new_pos->linkage= sl->linkage;
- sl->linkage= type;
+ enum sub_select_type type= new_pos->get_linkage();
+ new_pos->set_linkage(sl->get_linkage());
+ sl->set_linkage(type);
new_pos->with_all_modifier= sl->with_all_modifier;
sl->with_all_modifier= false;
}
@@ -834,9 +842,8 @@ st_select_lex_unit *With_element::clone_parsed_spec(THD *thd,
goto err;
lex_start(thd);
lex->stmt_lex= old_lex;
- with_select= &lex->select_lex;
- with_select->select_number= ++thd->lex->stmt_lex->current_select_number;
parse_status= parse_sql(thd, &parser_state, 0);
+ with_select= lex->first_select_lex();
if (parse_status)
goto err;
@@ -987,7 +994,7 @@ bool With_element::prepare_unreferenced(THD *thd)
rename_columns_of_derived_unit(thd, spec) ||
check_duplicate_names(thd, first_sl->item_list, 1)))
rc= true;
-
+
thd->lex->context_analysis_only&= ~CONTEXT_ANALYSIS_ONLY_DERIVED;
return rc;
}
@@ -1098,7 +1105,8 @@ bool TABLE_LIST::set_as_with_table(THD *thd, With_element *with_elem)
if(!(derived= with_elem->clone_parsed_spec(thd, this)))
return true;
}
- derived->first_select()->linkage= DERIVED_TABLE_TYPE;
+ derived->first_select()->set_linkage(DERIVED_TABLE_TYPE);
+ select_lex->add_statistics(derived);
with_elem->inc_references();
return false;
}
diff --git a/sql/sql_cte.h b/sql/sql_cte.h
index 16b473f0665..4a194b2a38f 100644
--- a/sql/sql_cte.h
+++ b/sql/sql_cte.h
@@ -279,8 +279,7 @@ private:
*/
With_clause *next_with_clause;
/* Set to true if dependencies between with elements have been checked */
- bool dependencies_are_checked;
-
+ bool dependencies_are_checked;
/*
The bitmap of all recursive with elements whose specifications
are not complied with restrictions imposed by the SQL standards
@@ -304,9 +303,8 @@ public:
bool with_recursive;
With_clause(bool recursive_fl, With_clause *emb_with_clause)
- : owner(NULL),
- embedding_with_clause(emb_with_clause), next_with_clause(NULL),
- dependencies_are_checked(false), unrestricted(0),
+ : owner(NULL), embedding_with_clause(emb_with_clause),
+ next_with_clause(NULL), dependencies_are_checked(false), unrestricted(0),
with_prepared_anchor(0), cleaned(0), stabilized(0),
with_recursive(recursive_fl)
{ }
@@ -320,8 +318,12 @@ public:
last_next= &this->next_with_clause;
}
+ st_select_lex_unit *get_owner() { return owner; }
+
void set_owner(st_select_lex_unit *unit) { owner= unit; }
+ void attach_to(st_select_lex *select_lex);
+
With_clause *pop() { return embedding_with_clause; }
bool check_dependencies();
@@ -354,7 +356,6 @@ bool With_element::is_unrestricted()
}
inline
-
bool With_element::is_with_prepared_anchor()
{
return owner->with_prepared_anchor & get_elem_map();
@@ -436,11 +437,14 @@ void With_element::prepare_for_next_iteration()
inline
-void st_select_lex_unit::set_with_clause(With_clause *with_cl)
-{
- with_clause= with_cl;
- if (with_clause)
- with_clause->set_owner(this);
+void With_clause::attach_to(st_select_lex *select_lex)
+{
+ for (With_element *with_elem= with_list.first;
+ with_elem;
+ with_elem= with_elem->next)
+ {
+ select_lex->register_unit(with_elem->spec, NULL);
+ }
}
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index 096d5b15af1..80ee4a22419 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -290,7 +290,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
bool has_triggers;
ORDER *order= (ORDER *) ((order_list && order_list->elements) ?
order_list->first : NULL);
- SELECT_LEX *select_lex= &thd->lex->select_lex;
+ SELECT_LEX *select_lex= thd->lex->first_select_lex();
killed_state killed_status= NOT_KILLED;
THD::enum_binlog_query_type query_type= THD::ROW_QUERY_TYPE;
bool binlog_is_row;
@@ -348,7 +348,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
DBUG_RETURN(TRUE);
}
table->map=1;
- query_plan.select_lex= &thd->lex->select_lex;
+ query_plan.select_lex= thd->lex->first_select_lex();
query_plan.table= table;
query_plan.updating_a_view= MY_TEST(table_list->view);
@@ -380,7 +380,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
setup_order(thd, select_lex->ref_pointer_array, &tables,
fields, all_fields, order))
{
- free_underlaid_joins(thd, &thd->lex->select_lex);
+ free_underlaid_joins(thd, thd->lex->first_select_lex());
DBUG_RETURN(TRUE);
}
}
@@ -927,14 +927,16 @@ int mysql_prepare_delete(THD *thd, TABLE_LIST *table_list,
bool *delete_while_scanning)
{
Item *fake_conds= 0;
- SELECT_LEX *select_lex= &thd->lex->select_lex;
+ SELECT_LEX *select_lex= thd->lex->first_select_lex();
DBUG_ENTER("mysql_prepare_delete");
List<Item> all_fields;
*delete_while_scanning= true;
thd->lex->allow_sum_func= 0;
- if (setup_tables_and_check_access(thd, &thd->lex->select_lex.context,
- &thd->lex->select_lex.top_join_list,
+ if (setup_tables_and_check_access(thd,
+ &thd->lex->first_select_lex()->context,
+ &thd->lex->first_select_lex()->
+ top_join_list,
table_list,
select_lex->leaf_tables, FALSE,
DELETE_ACL, SELECT_ACL, TRUE))
@@ -1017,21 +1019,23 @@ int mysql_multi_delete_prepare(THD *thd)
lex->query_tables also point on local list of DELETE SELECT_LEX
*/
- if (setup_tables_and_check_access(thd, &thd->lex->select_lex.context,
- &thd->lex->select_lex.top_join_list,
+ if (setup_tables_and_check_access(thd,
+ &thd->lex->first_select_lex()->context,
+ &thd->lex->first_select_lex()->
+ top_join_list,
lex->query_tables,
- lex->select_lex.leaf_tables, FALSE,
- DELETE_ACL, SELECT_ACL, FALSE))
+ lex->first_select_lex()->leaf_tables,
+ FALSE, DELETE_ACL, SELECT_ACL, FALSE))
DBUG_RETURN(TRUE);
- if (lex->select_lex.handle_derived(thd->lex, DT_MERGE))
+ if (lex->first_select_lex()->handle_derived(thd->lex, DT_MERGE))
DBUG_RETURN(TRUE);
/*
Multi-delete can't be constructed over-union => we always have
single SELECT on top and have to check underlying SELECTs of it
*/
- lex->select_lex.exclude_from_table_unique_test= TRUE;
+ lex->first_select_lex()->exclude_from_table_unique_test= TRUE;
/* Fix tables-to-be-deleted-from list to point at opened tables */
for (target_tbl= (TABLE_LIST*) aux_tables;
target_tbl;
@@ -1073,8 +1077,8 @@ int mysql_multi_delete_prepare(THD *thd)
Reset the exclude flag to false so it doesn't interfare
with further calls to unique_table
*/
- lex->select_lex.exclude_from_table_unique_test= FALSE;
-
+ lex->first_select_lex()->exclude_from_table_unique_test= FALSE;
+
if (lex->save_prep_leaf_tables())
DBUG_RETURN(TRUE);
diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc
index 39630293c20..d65969d2160 100644
--- a/sql/sql_derived.cc
+++ b/sql/sql_derived.cc
@@ -99,7 +99,8 @@ mysql_handle_derived(LEX *lex, uint phases)
processed normally.
*/
if (phases == DT_MERGE_FOR_INSERT &&
- cursor && cursor->top_table()->select_lex != &lex->select_lex)
+ cursor && (cursor->top_table()->select_lex !=
+ lex->first_select_lex()))
continue;
for (;
cursor && !res;
diff --git a/sql/sql_do.cc b/sql/sql_do.cc
index 2a4e43ab78a..1652b313909 100644
--- a/sql/sql_do.cc
+++ b/sql/sql_do.cc
@@ -33,7 +33,7 @@ bool mysql_do(THD *thd, List<Item> &values)
DBUG_RETURN(TRUE);
while ((value = li++))
(void) value->is_null();
- free_underlaid_joins(thd, &thd->lex->select_lex);
+ free_underlaid_joins(thd, thd->lex->first_select_lex());
if (unlikely(thd->is_error()))
{
diff --git a/sql/sql_error.cc b/sql/sql_error.cc
index d6f5b99eef6..8d639f9271d 100644
--- a/sql/sql_error.cc
+++ b/sql/sql_error.cc
@@ -781,7 +781,7 @@ bool mysqld_show_warnings(THD *thd, ulong levels_to_show)
List<Item> field_list;
MEM_ROOT *mem_root= thd->mem_root;
const Sql_condition *err;
- SELECT_LEX *sel= &thd->lex->select_lex;
+ SELECT_LEX *sel= thd->lex->first_select_lex();
SELECT_LEX_UNIT *unit= &thd->lex->unit;
ulonglong idx= 0;
Protocol *protocol=thd->protocol;
diff --git a/sql/sql_help.cc b/sql/sql_help.cc
index aa9f3fedd6d..95bc6ade366 100644
--- a/sql/sql_help.cc
+++ b/sql/sql_help.cc
@@ -87,7 +87,7 @@ enum enum_used_fields
static bool init_fields(THD *thd, TABLE_LIST *tables,
struct st_find_field *find_fields, uint count)
{
- Name_resolution_context *context= &thd->lex->select_lex.context;
+ Name_resolution_context *context= &thd->lex->first_select_lex()->context;
DBUG_ENTER("init_fields");
context->resolve_in_table_list_only(tables);
for (; count-- ; find_fields++)
@@ -719,10 +719,11 @@ static bool mysqld_help_internal(THD *thd, const char *mask)
Init tables and fields to be usable from items
tables do not contain VIEWs => we can pass 0 as conds
*/
- thd->lex->select_lex.context.table_list=
- thd->lex->select_lex.context.first_name_resolution_table= &tables[0];
- if (setup_tables(thd, &thd->lex->select_lex.context,
- &thd->lex->select_lex.top_join_list,
+ thd->lex->first_select_lex()->context.table_list=
+ thd->lex->first_select_lex()->context.first_name_resolution_table=
+ &tables[0];
+ if (setup_tables(thd, &thd->lex->first_select_lex()->context,
+ &thd->lex->first_select_lex()->top_join_list,
tables, leaves, FALSE, FALSE))
goto error;
memcpy((char*) used_fields, (char*) init_used_fields, sizeof(used_fields));
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index e3c53e59d21..51acf10a98a 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -241,7 +241,7 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list,
}
else
{ // Part field list
- SELECT_LEX *select_lex= &thd->lex->select_lex;
+ SELECT_LEX *select_lex= thd->lex->first_select_lex();
Name_resolution_context *context= &select_lex->context;
Name_resolution_context_state ctx_state;
int res;
@@ -273,7 +273,7 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list,
/* Restore the current context. */
ctx_state.restore_state(context, table_list);
- thd->lex->select_lex.no_wrap_view_item= FALSE;
+ thd->lex->first_select_lex()->no_wrap_view_item= FALSE;
if (res)
DBUG_RETURN(-1);
@@ -657,7 +657,7 @@ static void save_insert_query_plan(THD* thd, TABLE_LIST *table_list)
bool skip= MY_TEST(table_list->view);
/* Save subquery children */
- for (SELECT_LEX_UNIT *unit= thd->lex->select_lex.first_inner_unit();
+ for (SELECT_LEX_UNIT *unit= thd->lex->first_select_lex()->first_inner_unit();
unit;
unit= unit->next_unit())
{
@@ -777,7 +777,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
/* mysql_prepare_insert sets table_list->table if it was not set */
table= table_list->table;
- context= &thd->lex->select_lex.context;
+ context= &thd->lex->first_select_lex()->context;
/*
These three asserts test the hypothesis that the resetting of the name
resolution context below is not necessary at all since the list of local
@@ -1070,7 +1070,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
} while (bulk_parameters_iterations(thd));
values_loop_end:
- free_underlaid_joins(thd, &thd->lex->select_lex);
+ free_underlaid_joins(thd, thd->lex->first_select_lex());
joins_freed= TRUE;
/*
@@ -1259,7 +1259,7 @@ abort:
table->file->ha_release_auto_increment();
if (!joins_freed)
- free_underlaid_joins(thd, &thd->lex->select_lex);
+ free_underlaid_joins(thd, thd->lex->first_select_lex());
thd->abort_on_warning= 0;
DBUG_RETURN(retval);
}
@@ -1289,7 +1289,7 @@ abort:
static bool check_view_insertability(THD * thd, TABLE_LIST *view)
{
- uint num= view->view->select_lex.item_list.elements;
+ uint num= view->view->first_select_lex()->item_list.elements;
TABLE *table= view->table;
Field_translator *trans_start= view->field_translation,
*trans_end= trans_start + num;
@@ -1389,10 +1389,12 @@ static bool mysql_prepare_insert_check_table(THD *thd, TABLE_LIST *table_list,
than INSERT.
*/
- if (setup_tables_and_check_access(thd, &thd->lex->select_lex.context,
- &thd->lex->select_lex.top_join_list,
+ if (setup_tables_and_check_access(thd,
+ &thd->lex->first_select_lex()->context,
+ &thd->lex->first_select_lex()->
+ top_join_list,
table_list,
- thd->lex->select_lex.leaf_tables,
+ thd->lex->first_select_lex()->leaf_tables,
select_insert, INSERT_ACL, SELECT_ACL,
TRUE))
DBUG_RETURN(TRUE);
@@ -1400,7 +1402,7 @@ static bool mysql_prepare_insert_check_table(THD *thd, TABLE_LIST *table_list,
if (insert_into_view && !fields.elements)
{
thd->lex->empty_field_list_on_rset= 1;
- if (!thd->lex->select_lex.leaf_tables.head()->table ||
+ if (!thd->lex->first_select_lex()->leaf_tables.head()->table ||
table_list->is_multitable())
{
my_error(ER_VIEW_NO_INSERT_FIELD_LIST, MYF(0),
@@ -1474,7 +1476,7 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list,
enum_duplicates duplic, COND **where,
bool select_insert)
{
- SELECT_LEX *select_lex= &thd->lex->select_lex;
+ SELECT_LEX *select_lex= thd->lex->first_select_lex();
Name_resolution_context *context= &select_lex->context;
Name_resolution_context_state ctx_state;
bool insert_into_view= (table_list->view != 0);
@@ -3516,7 +3518,7 @@ bool Delayed_insert::handle_inserts(void)
bool mysql_insert_select_prepare(THD *thd)
{
LEX *lex= thd->lex;
- SELECT_LEX *select_lex= &lex->select_lex;
+ SELECT_LEX *select_lex= lex->first_select_lex();
DBUG_ENTER("mysql_insert_select_prepare");
@@ -3605,7 +3607,7 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
select, LEX::current_select should point to the first select while
we are fixing fields from insert list.
*/
- lex->current_select= &lex->select_lex;
+ lex->current_select= lex->first_select_lex();
res= (setup_fields(thd, Ref_ptr_array(),
values, MARK_COLUMNS_READ, 0, NULL, 0) ||
@@ -3622,7 +3624,7 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
if (info.handle_duplicates == DUP_UPDATE && !res)
{
- Name_resolution_context *context= &lex->select_lex.context;
+ Name_resolution_context *context= &lex->first_select_lex()->context;
Name_resolution_context_state ctx_state;
/* Save the state of the current name resolution context. */
@@ -3632,7 +3634,7 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
table_list->next_local= 0;
context->resolve_in_table_list_only(table_list);
- lex->select_lex.no_wrap_view_item= TRUE;
+ lex->first_select_lex()->no_wrap_view_item= TRUE;
res= res ||
check_update_fields(thd, context->table_list,
*info.update_fields, *info.update_values,
@@ -3643,15 +3645,15 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
*/
true,
&map);
- lex->select_lex.no_wrap_view_item= FALSE;
+ lex->first_select_lex()->no_wrap_view_item= FALSE;
/*
When we are not using GROUP BY and there are no ungrouped aggregate functions
we can refer to other tables in the ON DUPLICATE KEY part.
We use next_name_resolution_table descructively, so check it first (views?)
*/
DBUG_ASSERT (!table_list->next_name_resolution_table);
- if (lex->select_lex.group_list.elements == 0 &&
- !lex->select_lex.with_sum_func)
+ if (lex->first_select_lex()->group_list.elements == 0 &&
+ !lex->first_select_lex()->with_sum_func)
/*
We must make a single context out of the two separate name resolution contexts :
the INSERT table and the tables in the SELECT part of INSERT ... SELECT.
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index ec38baa219a..fa8155507f8 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -174,7 +174,7 @@ init_lex_with_single_table(THD *thd, TABLE *table, LEX *lex)
{
TABLE_LIST *table_list;
Table_ident *table_ident;
- SELECT_LEX *select_lex= &lex->select_lex;
+ SELECT_LEX *select_lex= lex->first_select_lex();
Name_resolution_context *context= &select_lex->context;
/*
We will call the parser to create a part_info struct based on the
@@ -635,6 +635,30 @@ void Lex_input_stream::reduce_digest_token(uint token_left, uint token_right)
}
}
+/**
+ lex starting operations for builtin select collected together
+*/
+
+void SELECT_LEX::lex_start(LEX *plex)
+{
+ SELECT_LEX_UNIT *unit= &plex->unit;
+ /* 'parent_lex' is used in init_query() so it must be before it. */
+ parent_lex= plex;
+ init_query();
+ master= unit;
+ prev= &unit->slave;
+ link_next= slave= next= 0;
+ link_prev= (st_select_lex_node**)&(plex->all_selects_list);
+ DBUG_ASSERT(!group_list_ptrs);
+ select_number= 1;
+ in_sum_expr=0;
+ ftfunc_list_alloc.empty();
+ ftfunc_list= &ftfunc_list_alloc;
+ group_list.empty();
+ order_list.empty();
+ gorder_list.empty();
+}
+
void lex_start(THD *thd)
{
DBUG_ENTER("lex_start");
@@ -659,17 +683,18 @@ void LEX::start(THD *thd_arg)
DBUG_ASSERT(!explain);
+ builtin_select.lex_start(this);
+ lex_options= 0;
context_stack.empty();
+ //empty select_stack
+ select_stack_top= 0;
unit.init_query();
- current_select_number= 1;
- select_lex.linkage= UNSPECIFIED_TYPE;
- /* 'parent_lex' is used in init_query() so it must be before it. */
- select_lex.parent_lex= this;
- select_lex.init_query();
+ current_select_number= 0;
curr_with_clause= 0;
with_clauses_list= 0;
with_clauses_list_last_next= &with_clauses_list;
create_view= NULL;
+ field_list.empty();
value_list.empty();
update_list.empty();
set_var_list.empty();
@@ -683,17 +708,8 @@ void LEX::start(THD *thd_arg)
auxiliary_table_list.empty();
unit.next= unit.master= unit.link_next= unit.return_to= 0;
unit.prev= unit.link_prev= 0;
- unit.slave= current_select= all_selects_list= &select_lex;
- select_lex.master= &unit;
- select_lex.prev= &unit.slave;
- select_lex.link_next= select_lex.slave= select_lex.next= 0;
- select_lex.link_prev= (st_select_lex_node**)&(all_selects_list);
- select_lex.options= 0;
- select_lex.sql_cache= SELECT_LEX::SQL_CACHE_UNSPECIFIED;
- select_lex.init_order();
- select_lex.group_list.empty();
- if (select_lex.group_list_ptrs)
- select_lex.group_list_ptrs->clear();
+ unit.slave= current_select= all_selects_list= &builtin_select;
+ sql_cache= LEX::SQL_CACHE_UNSPECIFIED;
describe= 0;
analyze_stmt= 0;
explain_json= false;
@@ -703,14 +719,7 @@ void LEX::start(THD *thd_arg)
safe_to_cache_query= 1;
parsing_options.reset();
empty_field_list_on_rset= 0;
- select_lex.select_number= 1;
part_info= 0;
- select_lex.in_sum_expr=0;
- select_lex.ftfunc_list_alloc.empty();
- select_lex.ftfunc_list= &select_lex.ftfunc_list_alloc;
- select_lex.group_list.empty();
- select_lex.order_list.empty();
- select_lex.gorder_list.empty();
m_sql_cmd= NULL;
duplicates= DUP_ERROR;
ignore= 0;
@@ -722,6 +731,8 @@ void LEX::start(THD *thd_arg)
query_tables= 0;
reset_query_tables_list(FALSE);
expr_allows_subselect= TRUE;
+ selects_allow_into= FALSE;
+ selects_allow_procedure= FALSE;
use_only_table_context= FALSE;
parse_vcol_expr= FALSE;
check_exists= FALSE;
@@ -731,8 +742,8 @@ void LEX::start(THD *thd_arg)
name= null_clex_str;
event_parse_data= NULL;
profile_options= PROFILE_NONE;
- nest_level=0 ;
- select_lex.nest_level_base= &unit;
+ nest_level= 0;
+ builtin_select.nest_level_base= &unit;
allow_sum_func= 0;
in_sum_func= NULL;
@@ -756,6 +767,13 @@ void LEX::start(THD *thd_arg)
vers_conditions.empty();
is_lex_started= TRUE;
+
+ next_is_main= FALSE;
+ next_is_down= FALSE;
+
+ wild= 0;
+ exchange= 0;
+
DBUG_VOID_RETURN;
}
@@ -1272,7 +1290,8 @@ int ORAlex(YYSTYPE *yylval, THD *thd)
int Lex_input_stream::lex_token(YYSTYPE *yylval, THD *thd)
{
int token;
-
+ const int left_paren= (int) '(';
+
if (lookahead_token >= 0)
{
/*
@@ -1289,6 +1308,8 @@ int Lex_input_stream::lex_token(YYSTYPE *yylval, THD *thd)
token= lex_one_token(yylval, thd);
add_digest_token(token, yylval);
+ SELECT_LEX *curr_sel= thd->lex->current_select;
+
switch(token) {
case WITH:
/*
@@ -1337,8 +1358,16 @@ int Lex_input_stream::lex_token(YYSTYPE *yylval, THD *thd)
}
break;
case VALUES:
- if (thd->lex->current_select->parsing_place == IN_UPDATE_ON_DUP_KEY ||
- thd->lex->current_select->parsing_place == IN_PART_FUNC)
+ if (curr_sel &&
+ (curr_sel->parsing_place == BEFORE_OPT_LIST ||
+ curr_sel->parsing_place == AFTER_LIST))
+ {
+ curr_sel->parsing_place= NO_MATTER;
+ break;
+ }
+ if (curr_sel &&
+ (curr_sel->parsing_place == IN_UPDATE_ON_DUP_KEY ||
+ curr_sel->parsing_place == IN_PART_FUNC))
return VALUE_SYM;
token= lex_one_token(yylval, thd);
add_digest_token(token, yylval);
@@ -1352,6 +1381,43 @@ int Lex_input_stream::lex_token(YYSTYPE *yylval, THD *thd)
lookahead_token= token;
return VALUES;
}
+ case VALUE_SYM:
+ if (curr_sel &&
+ (curr_sel->parsing_place == BEFORE_OPT_LIST ||
+ curr_sel->parsing_place == AFTER_LIST))
+ {
+ curr_sel->parsing_place= NO_MATTER;
+ return VALUES;
+ }
+ break;
+ case PARTITION_SYM:
+ case SELECT_SYM:
+ case UNION_SYM:
+ if (curr_sel &&
+ (curr_sel->parsing_place == BEFORE_OPT_LIST ||
+ curr_sel->parsing_place == AFTER_LIST))
+ {
+ curr_sel->parsing_place= NO_MATTER;
+ }
+ break;
+ case left_paren:
+ if (!curr_sel ||
+ curr_sel->parsing_place != BEFORE_OPT_LIST)
+ return token;
+ token= lex_one_token(yylval, thd);
+ add_digest_token(token, yylval);
+ lookahead_yylval= yylval;
+ yylval= NULL;
+ lookahead_token= token;
+ curr_sel->parsing_place= NO_MATTER;
+ if (token == LIKE)
+ return LEFT_PAREN_LIKE;
+ if (token == WITH)
+ return LEFT_PAREN_WITH;
+ if (token != left_paren && token != SELECT_SYM)
+ return LEFT_PAREN_ALT;
+ else
+ return left_paren;
break;
default:
break;
@@ -1688,7 +1754,7 @@ int Lex_input_stream::lex_one_token(YYSTYPE *yylval, THD *thd)
return(TEXT_STRING);
}
case MY_LEX_COMMENT: // Comment
- lex->select_lex.options|= OPTION_FOUND_COMMENT;
+ lex->lex_options|= OPTION_LEX_FOUND_COMMENT;
while ((c= yyGet()) != '\n' && c) ;
yyUnget(); // Safety against eof
state= MY_LEX_START; // Try again
@@ -1699,7 +1765,7 @@ int Lex_input_stream::lex_one_token(YYSTYPE *yylval, THD *thd)
state= MY_LEX_CHAR; // Probable division
break;
}
- lex->select_lex.options|= OPTION_FOUND_COMMENT;
+ lex->lex_options|= OPTION_LEX_FOUND_COMMENT;
/* Reject '/' '*', since we might need to turn off the echo */
yyUnget();
@@ -2207,8 +2273,8 @@ void trim_whitespace(CHARSET_INFO *cs, LEX_CSTRING *str, size_t * prefix_length)
void st_select_lex_node::init_query_common()
{
options= 0;
- sql_cache= SQL_CACHE_UNSPECIFIED;
- linkage= UNSPECIFIED_TYPE;
+ set_linkage(UNSPECIFIED_TYPE);
+ distinct= TRUE;
no_table_names_allowed= 0;
uncacheable= 0;
}
@@ -2216,7 +2282,7 @@ void st_select_lex_node::init_query_common()
void st_select_lex_unit::init_query()
{
init_query_common();
- linkage= GLOBAL_OPTIONS_TYPE;
+ set_linkage(GLOBAL_OPTIONS_TYPE);
select_limit_cnt= HA_POS_ERROR;
offset_limit_cnt= 0;
union_distinct= 0;
@@ -2258,16 +2324,6 @@ void st_select_lex::init_query()
having_fix_field_for_pushed_cond= 0;
context.select_lex= this;
context.init();
- /*
- Add the name resolution context of the current (sub)query to the
- stack of contexts for the whole query.
- TODO:
- push_context may return an error if there is no memory for a new
- element in the stack, however this method has no return value,
- thus push_context should be moved to a place where query
- initialization is checked for failure.
- */
- parent_lex->push_context(&context, parent_lex->thd->mem_root);
cond_count= between_count= with_wild= 0;
max_equal_elems= 0;
ref_pointer_array.reset();
@@ -2313,16 +2369,14 @@ void st_select_lex::init_select()
table_join_options= 0;
in_sum_expr= with_wild= 0;
options= 0;
- sql_cache= SQL_CACHE_UNSPECIFIED;
ftfunc_list_alloc.empty();
inner_sum_func_list= 0;
ftfunc_list= &ftfunc_list_alloc;
- order_list.elements= 0;
- order_list.first= 0;
- order_list.next= &order_list.first;
+ order_list.empty();
/* Set limit and offset to default values */
select_limit= 0; /* denotes the default limit = HA_POS_ERROR */
offset_limit= 0; /* denotes the default offset = 0 */
+ is_set_query_expr_tail= false;
with_sum_func= 0;
with_all_modifier= 0;
is_correlated= 0;
@@ -2384,6 +2438,23 @@ void st_select_lex_node::add_slave(st_select_lex_node *slave_arg)
}
}
+void st_select_lex_node::link_chain_down(st_select_lex_node *first)
+{
+ st_select_lex_node *last_node;
+ st_select_lex_node *node= first;
+ do
+ {
+ last_node= node;
+ node->master= this;
+ node= node->next;
+ } while (node);
+ if ((last_node->next= slave))
+ {
+ slave->prev= &last_node->next;
+ }
+ first->prev= &slave;
+ slave= first;
+}
/*
include on level down (but do not link)
@@ -2433,7 +2504,7 @@ void st_select_lex_node::fast_exclude()
// Remove slave structure
for (; slave; slave= slave->next)
slave->fast_exclude();
-
+
}
@@ -3102,6 +3173,7 @@ LEX::LEX()
gtid_domain_static_buffer,
initial_gtid_domain_buffer_size,
initial_gtid_domain_buffer_size, 0);
+ unit.slave= &builtin_select;
}
@@ -3128,12 +3200,12 @@ bool LEX::can_be_merged()
// TODO: do not forget implement case when select_lex.table_list.elements==0
/* find non VIEW subqueries/unions */
- bool selects_allow_merge= (select_lex.next_select() == 0 &&
- !(select_lex.uncacheable &
+ bool selects_allow_merge= (first_select_lex()->next_select() == 0 &&
+ !(first_select_lex()->uncacheable &
UNCACHEABLE_RAND));
if (selects_allow_merge)
{
- for (SELECT_LEX_UNIT *tmp_unit= select_lex.first_inner_unit();
+ for (SELECT_LEX_UNIT *tmp_unit= first_select_lex()->first_inner_unit();
tmp_unit;
tmp_unit= tmp_unit->next_unit())
{
@@ -3150,12 +3222,12 @@ bool LEX::can_be_merged()
}
return (selects_allow_merge &&
- select_lex.group_list.elements == 0 &&
- select_lex.having == 0 &&
- select_lex.with_sum_func == 0 &&
- select_lex.table_list.elements >= 1 &&
- !(select_lex.options & SELECT_DISTINCT) &&
- select_lex.select_limit == 0);
+ first_select_lex()->group_list.elements == 0 &&
+ first_select_lex()->having == 0 &&
+ first_select_lex()->with_sum_func == 0 &&
+ first_select_lex()->table_list.elements >= 1 &&
+ !(first_select_lex()->options & SELECT_DISTINCT) &&
+ first_select_lex()->select_limit == 0);
}
@@ -3508,7 +3580,7 @@ void LEX::set_trg_event_type_for_tables()
Do not iterate over sub-selects, only the tables in the outermost
SELECT_LEX can be modified, if any.
*/
- TABLE_LIST *tables= select_lex.get_table_list();
+ TABLE_LIST *tables= first_select_lex()->get_table_list();
while (tables)
{
@@ -3564,12 +3636,13 @@ TABLE_LIST *LEX::unlink_first_table(bool *link_to_local)
/*
and from local list if it is not empty
*/
- if ((*link_to_local= MY_TEST(select_lex.table_list.first)))
+ if ((*link_to_local= MY_TEST(first_select_lex()->table_list.first)))
{
- select_lex.context.table_list=
- select_lex.context.first_name_resolution_table= first->next_local;
- select_lex.table_list.first= first->next_local;
- select_lex.table_list.elements--; //safety
+ first_select_lex()->context.table_list=
+ first_select_lex()->context.first_name_resolution_table=
+ first->next_local;
+ first_select_lex()->table_list.first= first->next_local;
+ first_select_lex()->table_list.elements--; //safety
first->next_local= 0;
/*
Ensure that the global list has the same first table as the local
@@ -3600,7 +3673,7 @@ TABLE_LIST *LEX::unlink_first_table(bool *link_to_local)
void LEX::first_lists_tables_same()
{
- TABLE_LIST *first_table= select_lex.table_list.first;
+ TABLE_LIST *first_table= first_select_lex()->table_list.first;
if (query_tables != first_table && first_table != 0)
{
TABLE_LIST *next;
@@ -3625,6 +3698,23 @@ void LEX::first_lists_tables_same()
}
}
+void LEX::fix_first_select_number()
+{
+ SELECT_LEX *first= first_select_lex();
+ if (first && first->select_number != 1)
+ {
+ uint num= first->select_number;
+ for (SELECT_LEX *sel= all_selects_list;
+ sel;
+ sel= sel->next_select_in_list())
+ {
+ if (sel->select_number < num)
+ sel->select_number++;
+ }
+ first->select_number= 1;
+ }
+}
+
/*
Link table back that was unlinked with unlink_first_table()
@@ -3650,10 +3740,10 @@ void LEX::link_first_table_back(TABLE_LIST *first,
if (link_to_local)
{
- first->next_local= select_lex.table_list.first;
- select_lex.context.table_list= first;
- select_lex.table_list.first= first;
- select_lex.table_list.elements++; //safety
+ first->next_local= first_select_lex()->table_list.first;
+ first_select_lex()->context.table_list= first;
+ first_select_lex()->table_list.first= first;
+ first_select_lex()->table_list.elements++; //safety
}
}
}
@@ -3682,19 +3772,19 @@ void LEX::cleanup_after_one_table_open()
NOTE: all units will be connected to thd->lex->select_lex, because we
have not UNION on most upper level.
*/
- if (all_selects_list != &select_lex)
+ if (all_selects_list != first_select_lex())
{
derived_tables= 0;
- select_lex.exclude_from_table_unique_test= false;
+ first_select_lex()->exclude_from_table_unique_test= false;
/* cleunup underlying units (units of VIEW) */
- for (SELECT_LEX_UNIT *un= select_lex.first_inner_unit();
+ for (SELECT_LEX_UNIT *un= first_select_lex()->first_inner_unit();
un;
un= un->next_unit())
un->cleanup();
/* reduce all selects list to default state */
- all_selects_list= &select_lex;
+ all_selects_list= first_select_lex();
/* remove underlying units (units of VIEW) subtree */
- select_lex.cut_subtree();
+ first_select_lex()->cut_subtree();
}
}
@@ -4558,7 +4648,7 @@ void st_select_lex::set_explain_type(bool on_the_fly)
using_materialization= TRUE;
}
- if (&master_unit()->thd->lex->select_lex == this)
+ if (master_unit()->thd->lex->first_select_lex() == this)
{
type= is_primary ? "PRIMARY" : "SIMPLE";
}
@@ -4753,8 +4843,8 @@ bool LEX::save_prep_leaf_tables()
Query_arena *arena= thd->stmt_arena, backup;
arena= thd->activate_stmt_arena_if_needed(&backup);
//It is used for DETETE/UPDATE so top level has only one SELECT
- DBUG_ASSERT(select_lex.next_select() == NULL);
- bool res= select_lex.save_prep_leaf_tables(thd);
+ DBUG_ASSERT(first_select_lex()->next_select() == NULL);
+ bool res= first_select_lex()->save_prep_leaf_tables(thd);
if (arena)
thd->restore_active_arena(arena, &backup);
@@ -5085,8 +5175,13 @@ bool LEX::is_partition_management() const
SELECT_LEX *LEX::exclude_last_select()
{
- DBUG_ENTER("SELECT_LEX::exclude_last_select");
- SELECT_LEX *exclude= current_select;
+ return exclude_not_first_select(current_select);
+}
+
+SELECT_LEX *LEX::exclude_not_first_select(SELECT_LEX *exclude)
+{
+ DBUG_ENTER("LEX::exclude_not_first_select");
+ DBUG_PRINT("enter", ("exclude %p #%u", exclude, exclude->select_number));
SELECT_LEX_UNIT *unit= exclude->master_unit();
SELECT_LEX *sl;
DBUG_ASSERT(unit->first_select() != exclude);
@@ -5097,89 +5192,255 @@ SELECT_LEX *LEX::exclude_last_select()
DBUG_PRINT("info", ("excl: %p unit: %p prev: %p", exclude, unit, sl));
if (!sl)
DBUG_RETURN(NULL);
- DBUG_ASSERT(exclude->next_select() == NULL);
- exclude->exclude_from_tree();
+ DBUG_ASSERT(&sl->next == exclude->prev);
+
+ exclude->prev= NULL;
+
current_select= sl;
DBUG_RETURN(exclude);
}
-/**
- Put given (new) SELECT_LEX level below after currect (last) SELECT
+SELECT_LEX_UNIT *LEX::alloc_unit()
+{
+ SELECT_LEX_UNIT *unit;
+ DBUG_ENTER("LEX::alloc_unit");
+ if (!(unit= new (thd->mem_root) SELECT_LEX_UNIT()))
+ DBUG_RETURN(NULL);
- LAST SELECT -> DUMMY SELECT
- |
- V
- NEW UNIT
- |
- V
- NEW SELECT
+ unit->init_query();
+ /* TODO: reentrant problem */
+ unit->thd= thd;
+ unit->link_next= 0;
+ unit->link_prev= 0;
+ /* TODO: remove return_to */
+ unit->return_to= NULL;
+ DBUG_RETURN(unit);
+}
- SELECT (*LAST*) ... FROM (SELECT (*NEW*) ... )
- @param nselect Select to put one level below
+SELECT_LEX *LEX::alloc_select(bool select)
+{
+ SELECT_LEX *select_lex;
+ DBUG_ENTER("LEX::alloc_select");
+ if (!(select_lex= new (thd->mem_root) SELECT_LEX()))
+ DBUG_RETURN(NULL);
+ DBUG_PRINT("info", ("Allocate select: %p #%u statement lex: %p",
+ select_lex, thd->lex->stmt_lex->current_select_number,
+ thd->lex->stmt_lex));
+ /*
+ TODO: move following init to constructor when we get rid of builtin
+ select
+ */
+ select_lex->select_number= ++thd->lex->stmt_lex->current_select_number;
+ select_lex->parent_lex= this; /* Used in init_query. */
+ select_lex->init_query();
+ if (select)
+ select_lex->init_select();
+ select_lex->nest_level_base= &this->unit;
+ select_lex->include_global((st_select_lex_node**)&all_selects_list);
+ select_lex->context.resolve_in_select_list= TRUE;
+ DBUG_RETURN(select_lex);
+}
- @retval TRUE Error
- @retval FALSE OK
-*/
+SELECT_LEX_UNIT *
+LEX::create_unit(SELECT_LEX *first_sel)
+{
+ SELECT_LEX_UNIT *unit;
+ DBUG_ENTER("LEX::create_unit");
+
+ if (!(unit= alloc_unit()))
+ DBUG_RETURN(NULL);
+
+ unit->register_select_chain(first_sel);
+ if (first_sel->next_select())
+ {
+ unit->reset_distinct();
+ DBUG_ASSERT(!unit->fake_select_lex);
+ if (unit->add_fake_select_lex(thd))
+ DBUG_RETURN(NULL);
+ }
+ DBUG_RETURN(unit);
+}
-bool LEX::add_unit_in_brackets(SELECT_LEX *nselect)
+SELECT_LEX_UNIT *
+SELECT_LEX::attach_selects_chain(SELECT_LEX *first_sel,
+ Name_resolution_context *context)
{
- DBUG_ENTER("LEX::add_unit_in_brackets");
- bool distinct= nselect->master_unit()->union_distinct == nselect;
- bool rc= add_select_to_union_list(distinct, nselect->linkage, 0);
- if (rc)
- DBUG_RETURN(TRUE);
- SELECT_LEX* dummy_select= current_select;
- dummy_select->automatic_brackets= TRUE;
- dummy_select->linkage= nselect->linkage;
+ SELECT_LEX_UNIT *unit;
+ DBUG_ENTER("SELECT_LEX::attach_select_chain");
+
+ if (!(unit= parent_lex->alloc_unit()))
+ DBUG_RETURN(NULL);
+
+ unit->register_select_chain(first_sel);
+ register_unit(unit, context);
+ if (first_sel->next_select())
+ {
+ unit->reset_distinct();
+ DBUG_ASSERT(!unit->fake_select_lex);
+ if (unit->add_fake_select_lex(parent_lex->thd))
+ DBUG_RETURN(NULL);
+ }
+
+ DBUG_RETURN(unit);
+}
+
+SELECT_LEX *
+LEX::wrap_unit_into_derived(SELECT_LEX_UNIT *unit)
+{
+ SELECT_LEX *wrapping_sel;
+ Table_ident *ti;
+ DBUG_ENTER("LEX::wrap_unit_into_derived");
+
+ if (!(wrapping_sel= alloc_select(TRUE)))
+ DBUG_RETURN(NULL);
+ Name_resolution_context *context= &wrapping_sel->context;
+ context->init();
+ wrapping_sel->automatic_brackets= FALSE;
+
+ wrapping_sel->register_unit(unit, context);
/* stuff dummy SELECT * FROM (...) */
+
+ if (push_select(wrapping_sel)) // for Items & TABLE_LIST
+ DBUG_RETURN(NULL);
+
+ /* add SELECT list*/
+ {
+ Item *item= new (thd->mem_root)
+ Item_field(thd, context, NULL, NULL, &star_clex_str);
+ if (item == NULL)
+ goto err;
+ if (add_item_to_list(thd, item))
+ goto err;
+ (wrapping_sel->with_wild)++;
+ }
+
+ unit->first_select()->set_linkage(DERIVED_TABLE_TYPE);
+
+ ti= new (thd->mem_root) Table_ident(unit);
+ if (ti == NULL)
+ goto err;
+ {
+ TABLE_LIST *table_list;
+ LEX_CSTRING alias;
+ if (wrapping_sel->make_unique_derived_name(thd, &alias))
+ goto err;
+
+ if (!(table_list= wrapping_sel->add_table_to_list(thd, ti, &alias,
+ 0, TL_READ,
+ MDL_SHARED_READ)))
+ goto err;
+
+ context->resolve_in_table_list_only(table_list);
+ wrapping_sel->add_joined_table(table_list);
+ }
+
+ pop_select();
+
+ derived_tables|= DERIVED_SUBQUERY;
+
+ DBUG_RETURN(wrapping_sel);
+
+err:
+ pop_select();
+ DBUG_RETURN(NULL);
+}
+
+SELECT_LEX *LEX::wrap_select_chain_into_derived(SELECT_LEX *sel)
+{
+ SELECT_LEX *dummy_select;
+ SELECT_LEX_UNIT *unit;
+ Table_ident *ti;
+ DBUG_ENTER("LEX::wrap_select_chain_into_derived");
+
+ if (!(dummy_select= alloc_select(TRUE)))
+ DBUG_RETURN(NULL);
Name_resolution_context *context= &dummy_select->context;
- context->init();
+ dummy_select->automatic_brackets= FALSE;
+
+ if (!(unit= dummy_select->attach_selects_chain(sel, context)))
+ DBUG_RETURN(NULL);
+
+ /* stuff dummy SELECT * FROM (...) */
+
+ if (push_select(dummy_select)) // for Items & TABLE_LIST
+ DBUG_RETURN(NULL);
/* add SELECT list*/
- Item *item= new (thd->mem_root)
- Item_field(thd, context, NULL, NULL, &star_clex_str);
- if (unlikely(item == NULL))
- DBUG_RETURN(TRUE);
- if (unlikely(add_item_to_list(thd, item)))
- DBUG_RETURN(TRUE);
- (dummy_select->with_wild)++;
+ {
+ Item *item= new (thd->mem_root)
+ Item_field(thd, context, NULL, NULL, &star_clex_str);
+ if (item == NULL)
+ goto err;
+ if (add_item_to_list(thd, item))
+ goto err;
+ (dummy_select->with_wild)++;
+ }
- rc= mysql_new_select(this, 1, nselect);
- nselect->linkage= DERIVED_TABLE_TYPE;
- DBUG_ASSERT(nselect->outer_select() == dummy_select);
+ sel->set_linkage(DERIVED_TABLE_TYPE);
- current_select= dummy_select;
- current_select->nest_level--;
+ ti= new (thd->mem_root) Table_ident(unit);
+ if (ti == NULL)
+ goto err;
+ {
+ TABLE_LIST *table_list;
+ LEX_CSTRING alias;
+ if (dummy_select->make_unique_derived_name(thd, &alias))
+ goto err;
- SELECT_LEX_UNIT *unit= nselect->master_unit();
- Table_ident *ti= new (thd->mem_root) Table_ident(unit);
- if (unlikely(ti == NULL))
- DBUG_RETURN(TRUE);
- char buff[10];
- LEX_CSTRING alias;
- alias.length= my_snprintf(buff, sizeof(buff),
- "__%u", dummy_select->select_number);
- alias.str= thd->strmake(buff, alias.length);
- if (unlikely(!alias.str))
- DBUG_RETURN(TRUE);
+ if (!(table_list= dummy_select->add_table_to_list(thd, ti, &alias,
+ 0, TL_READ,
+ MDL_SHARED_READ)))
+ goto err;
- TABLE_LIST *table_list;
- if (unlikely(!(table_list=
- dummy_select->add_table_to_list(thd, ti, &alias,
- 0, TL_READ,
- MDL_SHARED_READ))))
- DBUG_RETURN(TRUE);
- context->resolve_in_table_list_only(table_list);
- dummy_select->add_joined_table(table_list);
+ context->resolve_in_table_list_only(table_list);
+ dummy_select->add_joined_table(table_list);
+ }
+
+ pop_select();
derived_tables|= DERIVED_SUBQUERY;
- current_select= nselect;
- current_select->nest_level++;
- DBUG_RETURN(rc);
+ DBUG_RETURN(dummy_select);
+
+err:
+ pop_select();
+ DBUG_RETURN(NULL);
+}
+
+bool LEX::push_context(Name_resolution_context *context)
+{
+ DBUG_ENTER("LEX::push_context");
+ DBUG_PRINT("info", ("Context: %p Select: %p (%d)",
+ context, context->select_lex,
+ (context->select_lex ?
+ context->select_lex->select_number:
+ 0)));
+ bool res= context_stack.push_front(context, thd->mem_root);
+ DBUG_RETURN(res);
+}
+
+
+SELECT_LEX *LEX::create_priority_nest(SELECT_LEX *first_in_nest)
+{
+ DBUG_ENTER("LEX::create_priority_nest");
+ DBUG_ASSERT(first_in_nest->first_nested);
+ enum sub_select_type wr_unit_type= first_in_nest->get_linkage();
+ bool wr_distinct= first_in_nest->distinct;
+ SELECT_LEX *attach_to= first_in_nest->first_nested;
+ attach_to->cut_next();
+ SELECT_LEX *wrapper= wrap_select_chain_into_derived(first_in_nest);
+ if (wrapper)
+ {
+ first_in_nest->first_nested= NULL;
+ wrapper->set_linkage_and_distinct(wr_unit_type, wr_distinct);
+ wrapper->first_nested= attach_to->first_nested;
+ wrapper->set_master_unit(attach_to->master_unit());
+ attach_to->link_neighbour(wrapper);
+ }
+ DBUG_RETURN(wrapper);
}
@@ -5194,7 +5455,7 @@ bool LEX::add_unit_in_brackets(SELECT_LEX *nselect)
void LEX::check_automatic_up(enum sub_select_type type)
{
if (type != INTERSECT_TYPE &&
- current_select->linkage == INTERSECT_TYPE &&
+ current_select->get_linkage() == INTERSECT_TYPE &&
current_select->outer_select() &&
current_select->outer_select()->automatic_brackets)
{
@@ -5644,10 +5905,17 @@ bool LEX::sp_for_loop_implicit_cursor_statement(THD *thd,
bounds->m_index->sp_lex_in_use= true;
sphead->reset_lex(thd, bounds->m_index);
DBUG_ASSERT(thd->lex != this);
- if (unlikely(!(item=
- new (thd->mem_root) Item_field(thd,
- thd->lex->current_context(),
- NullS, NullS, &name))))
+ /*
+ We pass NULL as Name_resolution_context here.
+ It's OK, fix_fields() will not be called for this Item_field created.
+ Item_field is only needed for LEX::sp_for_loop_cursor_declarations()
+ and is used to transfer the loop index variable name, "rec" in this example:
+ FOR rec IN (SELECT * FROM t1)
+ DO
+ SELECT rec.a, rec.b;
+ END FOR;
+ */
+ if (!(item= new (thd->mem_root) Item_field(thd, NULL, NullS, NullS, &name)))
return true;
bounds->m_index->set_item_and_free_list(item, NULL);
if (thd->lex->sphead->restore_lex(thd))
@@ -5754,10 +6022,22 @@ bool LEX::sp_for_loop_intrange_declarations(THD *thd, Lex_for_loop_st *loop,
const LEX_CSTRING *index,
const Lex_for_loop_bounds_st &bounds)
{
- if (unlikely(!(loop->m_index=
- bounds.m_index->
- sp_add_for_loop_variable(thd, index,
- bounds.m_index->get_item()))))
+ Item *item;
+ if ((item= bounds.m_index->get_item())->type() == Item::FIELD_ITEM)
+ {
+ // We're here is the lower bound is unknown identifier
+ my_error(ER_SP_UNDECLARED_VAR, MYF(0), item->full_name());
+ return true;
+ }
+ if ((item= bounds.m_upper_bound->get_item())->type() == Item::FIELD_ITEM)
+ {
+ // We're here is the upper bound is unknown identifier
+ my_error(ER_SP_UNDECLARED_VAR, MYF(0), item->full_name());
+ return true;
+ }
+ if (!(loop->m_index=
+ bounds.m_index->sp_add_for_loop_variable(thd, index,
+ bounds.m_index->get_item())))
return true;
if (unlikely(!(loop->m_upper_bound=
bounds.m_upper_bound->
@@ -6670,7 +6950,6 @@ Item_param *LEX::add_placeholder(THD *thd, const LEX_CSTRING *name,
my_error(ER_VIEW_SELECT_VARIABLE, MYF(0));
return NULL;
}
-
Query_fragment pos(thd, sphead, start, end);
Item_param *item= new (thd->mem_root) Item_param(thd, name,
pos.pos(), pos.length());
@@ -6701,6 +6980,38 @@ bool LEX::add_resignal_statement(THD *thd, const sp_condition_value *v)
}
+/*
+ Make an Item when an identifier is found in the FOR loop bounds:
+ FOR rec IN cursor
+ FOR var IN var1 .. xxx
+ FOR var IN row1.field1 .. xxx
+ When we parse the first expression after the "IN" keyword,
+ we don't know yet if it's a cursor name, or a scalar SP variable name,
+ or a field of a ROW SP variable. Here we create Item_field to remember
+ the fully qualified name. Later sp_for_loop_cursor_declarations()
+ detects how to treat this name properly.
+*/
+Item *LEX::create_item_for_loop_bound(THD *thd,
+ const LEX_CSTRING *a,
+ const LEX_CSTRING *b,
+ const LEX_CSTRING *c)
+{
+ /*
+ Pass NULL as the name resolution context.
+ This is OK, fix_fields() won't be called for this Item_field.
+ */
+ return new (thd->mem_root) Item_field(thd, NULL, a->str, b->str, c);
+}
+
+
+bool LEX::check_expr_allows_fields_or_error(THD *thd, const char *name) const
+{
+ if (select_stack_top > 0)
+ return false; // OK, fields are allowed
+ my_error(ER_BAD_FIELD_ERROR, MYF(0), name, thd->where);
+ return true; // Error, fields are not allowed
+}
+
Item *LEX::create_item_ident_nospvar(THD *thd,
const Lex_ident_sys_st *a,
const Lex_ident_sys_st *b)
@@ -6723,12 +7034,11 @@ Item *LEX::create_item_ident_nospvar(THD *thd,
my_error(ER_TABLENAME_NOT_ALLOWED_HERE, MYF(0), a->str, thd->where);
return NULL;
}
- if ((current_select->parsing_place != IN_HAVING) ||
- (current_select->get_in_sum_expr() > 0))
- return new (thd->mem_root) Item_field(thd, current_context(),
- NullS, a->str, b);
- return new (thd->mem_root) Item_ref(thd, current_context(),
- NullS, a->str, b);
+
+ if (current_select->parsing_place == FOR_LOOP_BOUND)
+ return create_item_for_loop_bound(thd, &null_clex_str, a, b);
+
+ return create_item_ident_field(thd, NullS, a->str, b);
}
@@ -6940,12 +7250,11 @@ Item *LEX::create_item_ident(THD *thd,
my_error(ER_TABLENAME_NOT_ALLOWED_HERE, MYF(0), b->str, thd->where);
return NULL;
}
- if (current_select->parsing_place != IN_HAVING ||
- current_select->get_in_sum_expr() > 0)
- return new (thd->mem_root) Item_field(thd, current_context(),
- schema, b->str, c);
- return new (thd->mem_root) Item_ref(thd, current_context(),
- schema, b->str, c);
+
+ if (current_select->parsing_place == FOR_LOOP_BOUND)
+ return create_item_for_loop_bound(thd, &null_clex_str, b, c);
+
+ return create_item_ident_field(thd, schema, b->str, c);
}
@@ -7031,15 +7340,20 @@ bool LEX::set_user_variable(THD *thd, const LEX_CSTRING *name, Item *val)
}
-Item *LEX::create_item_ident_nosp(THD *thd, Lex_ident_sys_st *name)
+Item *LEX::create_item_ident_field(THD *thd, const char *db,
+ const char *table,
+ const Lex_ident_sys_st *name)
{
+ if (check_expr_allows_fields_or_error(thd, name->str))
+ return NULL;
+
if (current_select->parsing_place != IN_HAVING ||
current_select->get_in_sum_expr() > 0)
return new (thd->mem_root) Item_field(thd, current_context(),
- NullS, NullS, name);
+ db, table, name);
return new (thd->mem_root) Item_ref(thd, current_context(),
- NullS, NullS, name);
+ db, table, name);
}
@@ -7089,6 +7403,11 @@ Item *LEX::create_item_ident_sp(THD *thd, Lex_ident_sys_st *name,
if (lex_string_eq(name, STRING_WITH_LEN("SQLERRM")))
return new (thd->mem_root) Item_func_sqlerrm(thd);
}
+
+ if (current_select->parsing_place == FOR_LOOP_BOUND)
+ return create_item_for_loop_bound(thd, &null_clex_str, &null_clex_str,
+ name);
+
return create_item_ident_nosp(thd, name);
}
@@ -7552,6 +7871,140 @@ Item *st_select_lex::build_cond_for_grouping_fields(THD *thd, Item *cond,
}
+bool st_select_lex::set_nest_level(int new_nest_level)
+{
+ DBUG_ENTER("st_select_lex::set_nest_level");
+ DBUG_PRINT("enter", ("select #%d %p nest level: %d",
+ select_number, this, new_nest_level));
+ if (new_nest_level > (int) MAX_SELECT_NESTING)
+ {
+ my_error(ER_TOO_HIGH_LEVEL_OF_NESTING_FOR_SELECT, MYF(0));
+ DBUG_RETURN(TRUE);
+ }
+ nest_level= new_nest_level;
+ new_nest_level++;
+ for (SELECT_LEX_UNIT *u= first_inner_unit(); u; u= u->next_unit())
+ {
+ if (u->set_nest_level(new_nest_level))
+ DBUG_RETURN(TRUE);
+ }
+ DBUG_RETURN(FALSE);
+}
+
+bool st_select_lex_unit::set_nest_level(int new_nest_level)
+{
+ DBUG_ENTER("st_select_lex_unit::set_nest_level");
+ for(SELECT_LEX *sl= first_select(); sl; sl= sl->next_select())
+ {
+ if (sl->set_nest_level(new_nest_level))
+ DBUG_RETURN(TRUE);
+ }
+ if (fake_select_lex &&
+ fake_select_lex->set_nest_level(new_nest_level))
+ DBUG_RETURN(TRUE);
+ DBUG_RETURN(FALSE);
+}
+
+
+bool st_select_lex::check_parameters(SELECT_LEX *main_select)
+{
+ DBUG_ENTER("st_select_lex::check_parameters");
+ DBUG_PRINT("enter", ("select #%d %p nest level: %d",
+ select_number, this, nest_level));
+
+
+ if ((options & OPTION_PROCEDURE_CLAUSE) &&
+ (!parent_lex->selects_allow_procedure ||
+ next_select() != NULL ||
+ this != master_unit()->first_select() ||
+ nest_level != 0))
+ {
+ my_error(ER_CANT_USE_OPTION_HERE, MYF(0), "PROCEDURE");
+ DBUG_RETURN(TRUE);
+ }
+
+ if ((options & SELECT_HIGH_PRIORITY) && this != main_select)
+ {
+ my_error(ER_CANT_USE_OPTION_HERE, MYF(0), "HIGH_PRIORITY");
+ DBUG_RETURN(TRUE);
+ }
+ if ((options & OPTION_BUFFER_RESULT) && this != main_select)
+ {
+ my_error(ER_CANT_USE_OPTION_HERE, MYF(0), "SQL_BUFFER_RESULT");
+ DBUG_RETURN(TRUE);
+ }
+ if ((options & OPTION_FOUND_ROWS) && this != main_select)
+ {
+ my_error(ER_CANT_USE_OPTION_HERE, MYF(0), "SQL_CALC_FOUND_ROWS");
+ DBUG_RETURN(TRUE);
+ }
+ if (options & OPTION_NO_QUERY_CACHE)
+ {
+ /*
+ Allow this flag only on the first top-level SELECT statement, if
+ SQL_CACHE wasn't specified.
+ */
+ if (this != main_select)
+ {
+ my_error(ER_CANT_USE_OPTION_HERE, MYF(0), "SQL_NO_CACHE");
+ DBUG_RETURN(TRUE);
+ }
+ if (parent_lex->sql_cache == LEX::SQL_CACHE)
+ {
+ my_error(ER_WRONG_USAGE, MYF(0), "SQL_CACHE", "SQL_NO_CACHE");
+ DBUG_RETURN(TRUE);
+ }
+ parent_lex->safe_to_cache_query=0;
+ parent_lex->sql_cache= LEX::SQL_NO_CACHE;
+ }
+ if (options & OPTION_TO_QUERY_CACHE)
+ {
+ /*
+ Allow this flag only on the first top-level SELECT statement, if
+ SQL_NO_CACHE wasn't specified.
+ */
+ if (this != main_select)
+ {
+ my_error(ER_CANT_USE_OPTION_HERE, MYF(0), "SQL_CACHE");
+ DBUG_RETURN(TRUE);
+ }
+ if (parent_lex->sql_cache == LEX::SQL_NO_CACHE)
+ {
+ my_error(ER_WRONG_USAGE, MYF(0), "SQL_NO_CACHE", "SQL_CACHE");
+ DBUG_RETURN(TRUE);
+ }
+ parent_lex->safe_to_cache_query=1;
+ parent_lex->sql_cache= LEX::SQL_CACHE;
+ }
+
+ for (SELECT_LEX_UNIT *u= first_inner_unit(); u; u= u->next_unit())
+ {
+ if (u->check_parameters(main_select))
+ DBUG_RETURN(TRUE);
+ }
+ DBUG_RETURN(FALSE);
+}
+
+
+bool st_select_lex_unit::check_parameters(SELECT_LEX *main_select)
+{
+ for(SELECT_LEX *sl= first_select(); sl; sl= sl->next_select())
+ {
+ if (sl->check_parameters(main_select))
+ return TRUE;
+ }
+ return fake_select_lex && fake_select_lex->check_parameters(main_select);
+}
+
+
+bool LEX::check_main_unit_semantics()
+{
+ if (unit.set_nest_level(0) ||
+ unit.check_parameters(first_select_lex()))
+ return TRUE;
+ return FALSE;
+}
+
int set_statement_var_if_exists(THD *thd, const char *var_name,
size_t var_name_length, ulonglong value)
{
@@ -7606,10 +8059,10 @@ bool LEX::create_or_alter_view_finalize(THD *thd, Table_ident *table_ident)
{
sql_command= SQLCOM_CREATE_VIEW;
/* first table in list is target VIEW name */
- if (unlikely(!select_lex.add_table_to_list(thd, table_ident, NULL,
+ if (!first_select_lex()->add_table_to_list(thd, table_ident, NULL,
TL_OPTION_UPDATING,
TL_IGNORE,
- MDL_EXCLUSIVE)))
+ MDL_EXCLUSIVE))
return true;
query_tables->open_strategy= TABLE_LIST::OPEN_STUB;
return false;
@@ -8025,6 +8478,7 @@ void st_select_lex::pushdown_cond_into_where_clause(THD *thd, Item *cond,
*remaining_cond= cond;
}
+
Item *LEX::make_item_func_call_generic(THD *thd, Lex_ident_cli_st *cdb,
Lex_ident_cli_st *cname, List<Item> *args)
{
@@ -8291,9 +8745,717 @@ bool LEX::tvc_finalize_derived()
thd->parse_error();
return true;
}
- if (current_select->linkage == GLOBAL_OPTIONS_TYPE ||
+ if (current_select->get_linkage() == GLOBAL_OPTIONS_TYPE ||
unlikely(mysql_new_select(this, 1, NULL)))
return true;
- current_select->linkage= DERIVED_TABLE_TYPE;
+ current_select->set_linkage(DERIVED_TABLE_TYPE);
return tvc_finalize();
}
+
+
+void st_select_lex_unit::reset_distinct()
+{
+ union_distinct= NULL;
+ for(SELECT_LEX *sl= first_select()->next_select();
+ sl;
+ sl= sl->next_select())
+ {
+ if (sl->distinct)
+ {
+ union_distinct= sl;
+ return;
+ }
+ }
+}
+
+
+void st_select_lex_unit::fix_distinct(st_select_lex_unit *new_unit)
+{
+ if (union_distinct)
+ {
+ if (this != union_distinct->master_unit())
+ {
+ DBUG_ASSERT(new_unit == union_distinct->master_unit());
+ new_unit->union_distinct= union_distinct;
+ reset_distinct();
+ }
+ else
+ new_unit->reset_distinct();
+ }
+}
+
+
+void st_select_lex_unit::register_select_chain(SELECT_LEX *first_sel)
+{
+ DBUG_ASSERT(first_sel != 0);
+ slave= first_sel;
+ first_sel->prev= &slave;
+ for(SELECT_LEX *sel=first_sel; sel; sel= sel->next_select())
+ {
+ sel->master= (st_select_lex_node *)this;
+ uncacheable|= sel->uncacheable;
+ }
+}
+
+
+void st_select_lex::register_unit(SELECT_LEX_UNIT *unit,
+ Name_resolution_context *outer_context)
+{
+ if ((unit->next= slave))
+ slave->prev= &unit->next;
+ unit->prev= &slave;
+ slave= unit;
+ unit->master= this;
+ uncacheable|= unit->uncacheable;
+
+ for(SELECT_LEX *sel= unit->first_select();sel; sel= sel->next_select())
+ {
+ sel->context.outer_context= outer_context;
+ }
+}
+
+
+void st_select_lex::add_statistics(SELECT_LEX_UNIT *unit)
+{
+ for (;
+ unit;
+ unit= unit->next_unit())
+ for(SELECT_LEX *child= unit->first_select();
+ child;
+ child= child->next_select())
+ {
+ /*
+ A subselect can add fields to an outer select.
+ Reserve space for them.
+ */
+ select_n_where_fields+= child->select_n_where_fields;
+ /*
+ Aggregate functions in having clause may add fields
+ to an outer select. Count them also.
+ */
+ select_n_having_items+= child->select_n_having_items;
+ }
+}
+
+
+bool LEX::main_select_push()
+{
+ DBUG_ENTER("LEX::main_select_push");
+ current_select_number= 1;
+ builtin_select.select_number= 1;
+ if (push_select(&builtin_select))
+ DBUG_RETURN(TRUE);
+ DBUG_RETURN(FALSE);
+}
+
+void Lex_select_lock::set_to(SELECT_LEX *sel)
+{
+ if (defined_lock)
+ {
+ if (sel->master_unit() &&
+ sel == sel->master_unit()->fake_select_lex)
+ sel->master_unit()->set_lock_to_the_last_select(*this);
+ else
+ {
+ sel->parent_lex->safe_to_cache_query= 0;
+ if (update_lock)
+ {
+ sel->lock_type= TL_WRITE;
+ sel->set_lock_for_tables(TL_WRITE);
+ }
+ else
+ {
+ sel->lock_type= TL_READ_WITH_SHARED_LOCKS;
+ sel->set_lock_for_tables(TL_READ_WITH_SHARED_LOCKS);
+ }
+ }
+ }
+}
+
+bool Lex_order_limit_lock::set_to(SELECT_LEX *sel)
+{
+ /*TODO: lock */
+ //if (lock.defined_lock && sel == sel->master_unit()->fake_select_lex)
+ // return TRUE;
+ if (lock.defined_timeout)
+ {
+ THD *thd= sel->parent_lex->thd;
+ if (set_statement_var_if_exists(thd,
+ C_STRING_WITH_LEN("lock_wait_timeout"),
+ lock.timeout) ||
+ set_statement_var_if_exists(thd,
+ C_STRING_WITH_LEN("innodb_lock_wait_timeout"),
+ lock.timeout))
+ return TRUE;
+ }
+ lock.set_to(sel);
+ sel->explicit_limit= limit.explicit_limit;
+ sel->select_limit= limit.select_limit;
+ sel->offset_limit= limit.offset_limit;
+ if (order_list)
+ {
+ if (sel->get_linkage() != GLOBAL_OPTIONS_TYPE &&
+ sel->olap != UNSPECIFIED_OLAP_TYPE &&
+ (sel->get_linkage() != UNION_TYPE || sel->braces))
+ {
+ my_error(ER_WRONG_USAGE, MYF(0),
+ "CUBE/ROLLUP", "ORDER BY");
+ return TRUE;
+ }
+ sel->order_list= *(order_list);
+ }
+ sel->is_set_query_expr_tail= true;
+ return FALSE;
+}
+
+
+static void change_item_list_context(List<Item> *list,
+ Name_resolution_context *context)
+{
+ List_iterator_fast<Item> it (*list);
+ Item *item;
+ while((item= it++))
+ {
+ item->walk(&Item::change_context_processor, FALSE, (void *)context);
+ }
+}
+
+
+bool LEX::insert_select_hack(SELECT_LEX *sel)
+{
+ DBUG_ENTER("LEX::insert_select_hack");
+
+ DBUG_ASSERT(first_select_lex() == &builtin_select);
+ DBUG_ASSERT(sel != NULL);
+
+ DBUG_ASSERT(builtin_select.first_inner_unit() == NULL);
+
+ if (builtin_select.link_prev)
+ {
+ if ((*builtin_select.link_prev= builtin_select.link_next))
+ ((st_select_lex *)builtin_select.link_next)->link_prev=
+ builtin_select.link_prev;
+ builtin_select.link_prev= NULL; // indicator of removal
+ }
+
+ set_main_unit(sel->master_unit());
+
+ DBUG_ASSERT(builtin_select.table_list.elements == 1);
+ TABLE_LIST *insert_table= builtin_select.table_list.first;
+
+ if (!(insert_table->next_local= sel->table_list.first))
+ {
+ sel->table_list.next= &insert_table->next_local;
+ }
+ sel->table_list.first= insert_table;
+ sel->table_list.elements++;
+ insert_table->select_lex= sel;
+
+ sel->context.first_name_resolution_table= insert_table;
+ builtin_select.context= sel->context;
+ change_item_list_context(&field_list, &sel->context);
+
+ if (sel->tvc && !sel->next_select() &&
+ (sql_command == SQLCOM_INSERT_SELECT ||
+ sql_command == SQLCOM_REPLACE_SELECT))
+ {
+ DBUG_PRINT("info", ("'Usual' INSERT detected"));
+ many_values= sel->tvc->lists_of_values;
+ sel->options= sel->tvc->select_options;
+ sel->tvc= NULL;
+ if (sql_command == SQLCOM_INSERT_SELECT)
+ sql_command= SQLCOM_INSERT;
+ else
+ sql_command= SQLCOM_REPLACE;
+ }
+
+
+ for (SELECT_LEX *sel= all_selects_list;
+ sel;
+ sel= sel->next_select_in_list())
+ {
+ if (sel->select_number != 1)
+ sel->select_number--;
+ };
+
+ DBUG_RETURN(FALSE);
+}
+
+
+/*
+ Create an Item_singlerow_subselect for a query expression.
+*/
+Item *LEX::create_item_query_expression(THD *thd,
+ const char *tok_start,
+ st_select_lex_unit *unit)
+{
+ if (!expr_allows_subselect || sql_command == SQLCOM_PURGE)
+ {
+ thd->parse_error(ER_SYNTAX_ERROR, tok_start);
+ return NULL;
+ }
+
+ // Add the subtree of subquery to the current SELECT_LEX
+ SELECT_LEX *curr_sel= select_stack_head();
+ DBUG_ASSERT(current_select == curr_sel);
+ if (!curr_sel)
+ curr_sel= &builtin_select;
+ curr_sel->register_unit(unit, &curr_sel->context);
+ curr_sel->add_statistics(unit);
+
+ return new (thd->mem_root)
+ Item_singlerow_subselect(thd, unit->first_select());
+}
+
+
+/**
+ Process unit parsed in brackets
+*/
+
+bool LEX::parsed_unit_in_brackets(SELECT_LEX_UNIT *unit)
+{
+ SELECT_LEX *first_in_nest= unit->pre_last_parse->next_select()->first_nested;
+ if (first_in_nest->first_nested != first_in_nest)
+ {
+ /* There is a priority jump starting from first_in_nest */
+ if (create_priority_nest(first_in_nest) == NULL)
+ return true;
+ }
+ push_select(unit->fake_select_lex);
+ return false;
+}
+
+
+/**
+ Process tail of unit parsed in brackets
+*/
+SELECT_LEX *LEX::parsed_unit_in_brackets_tail(SELECT_LEX_UNIT *unit,
+ Lex_order_limit_lock * l)
+{
+ pop_select();
+ if (l)
+ {
+ (l)->set_to(unit->fake_select_lex);
+ }
+ return unit->first_select();
+}
+
+
+/**
+ Process select parsed in brackets
+*/
+
+SELECT_LEX *LEX::parsed_select(SELECT_LEX *sel, Lex_order_limit_lock * l)
+{
+ pop_select();
+ if (l)
+ {
+ if (sel->next_select())
+ {
+ SELECT_LEX_UNIT *unit= sel->master_unit();
+ if (!unit)
+ unit= create_unit(sel);
+ if (!unit)
+ return NULL;
+ if (!unit->fake_select_lex->is_set_query_expr_tail)
+ l->set_to(unit->fake_select_lex);
+ else
+ {
+ sel= wrap_unit_into_derived(unit);
+ if (!sel)
+ return NULL;
+ l->set_to(sel);
+ }
+ }
+ else if (!sel->is_set_query_expr_tail)
+ {
+ l->set_to(sel);
+ }
+ else
+ {
+ SELECT_LEX_UNIT *unit= create_unit(sel);
+ if (!unit)
+ return NULL;
+ sel= wrap_unit_into_derived(unit);
+ if (!sel)
+ return NULL;
+ l->set_to(sel);
+ }
+ }
+ return sel;
+}
+
+
+/**
+ Process select parsed in brackets
+*/
+
+SELECT_LEX *LEX::parsed_select_in_brackets(SELECT_LEX *sel,
+ Lex_order_limit_lock * l)
+{
+ sel->braces= TRUE;
+ return parsed_select(sel, l);
+}
+
+
+SELECT_LEX_UNIT *LEX::parsed_select_expr_start(SELECT_LEX *s1, SELECT_LEX *s2,
+ enum sub_select_type unit_type,
+ bool distinct)
+{
+ SELECT_LEX_UNIT *res;
+ SELECT_LEX *sel1;
+ SELECT_LEX *sel2;
+ if (!s1->next_select())
+ sel1= s1;
+ else
+ {
+ sel1= wrap_unit_into_derived(s1->master_unit());
+ if (!sel1)
+ return NULL;
+ }
+ if (!s2->next_select())
+ sel2= s2;
+ else
+ {
+ sel2= wrap_unit_into_derived(s2->master_unit());
+ if (!sel2)
+ return NULL;
+ }
+ sel1->link_neighbour(sel2);
+ sel2->set_linkage_and_distinct(unit_type, distinct);
+ sel2->first_nested= sel1->first_nested= sel1;
+ res= create_unit(sel1);
+ if (res == NULL)
+ return NULL;
+ res->pre_last_parse= sel1;
+ return res;
+}
+
+
+SELECT_LEX_UNIT *LEX::parsed_select_expr_cont(SELECT_LEX_UNIT *unit,
+ SELECT_LEX *s2,
+ enum sub_select_type unit_type,
+ bool distinct, bool oracle)
+{
+ SELECT_LEX *sel1;
+ if (!s2->next_select())
+ sel1= s2;
+ else
+ {
+ sel1= wrap_unit_into_derived(s2->master_unit());
+ if (!sel1)
+ return NULL;
+ }
+ SELECT_LEX *last= unit->pre_last_parse->next_select();
+
+ int cmp= oracle? 0 : cmp_unit_op(unit_type, last->get_linkage());
+ if (cmp == 0)
+ {
+ sel1->first_nested= last->first_nested;
+ }
+ else if (cmp > 0)
+ {
+ last->first_nested= unit->pre_last_parse;
+ sel1->first_nested= last;
+ }
+ else /* cmp < 0 */
+ {
+ SELECT_LEX *first_in_nest= last->first_nested;
+ if (first_in_nest->first_nested != first_in_nest)
+ {
+ /* There is a priority jump starting from first_in_nest */
+ if ((last= create_priority_nest(first_in_nest)) == NULL)
+ return NULL;
+ }
+ sel1->first_nested= last->first_nested;
+ }
+ last->link_neighbour(sel1);
+ sel1->set_master_unit(unit);
+ sel1->set_linkage_and_distinct(unit_type, distinct);
+ unit->pre_last_parse= last;
+ return unit;
+}
+
+/**
+ Process parsed select in body
+*/
+
+SELECT_LEX_UNIT *LEX::parsed_body_select(SELECT_LEX *sel,
+ Lex_order_limit_lock * l)
+{
+ if (!(sel= parsed_select(sel, l)))
+ return NULL;
+
+ SELECT_LEX_UNIT *res= create_unit(sel);
+ return res;
+}
+
+/**
+ Process parsed unit in body
+*/
+
+bool LEX::parsed_body_unit(SELECT_LEX_UNIT *unit)
+{
+ SELECT_LEX *first_in_nest=
+ unit->pre_last_parse->next_select()->first_nested;
+ if (first_in_nest->first_nested != first_in_nest)
+ {
+ /* There is a priority jump starting from first_in_nest */
+ if (create_priority_nest(first_in_nest) == NULL)
+ return true;
+ }
+ push_select(unit->fake_select_lex);
+ return false;
+}
+
+/**
+ Process parsed tail of unit in body
+
+ TODO: make processing for double tail case
+*/
+
+SELECT_LEX_UNIT *LEX::parsed_body_unit_tail(SELECT_LEX_UNIT *unit,
+ Lex_order_limit_lock * l)
+{
+ pop_select();
+ if (l)
+ {
+ (l)->set_to(unit->fake_select_lex);
+ }
+ return unit;
+}
+
+/**
+ Process subselect parsing
+*/
+
+SELECT_LEX *LEX::parsed_subselect(SELECT_LEX_UNIT *unit, char *place)
+{
+ if (!expr_allows_subselect ||
+ sql_command == (int)SQLCOM_PURGE)
+ {
+ thd->parse_error(ER_SYNTAX_ERROR, place);
+ return NULL;
+ }
+
+ // Add the subtree of subquery to the current SELECT_LEX
+ SELECT_LEX *curr_sel= select_stack_head();
+ DBUG_ASSERT(current_select == curr_sel);
+ if (curr_sel)
+ {
+ curr_sel->register_unit(unit, &curr_sel->context);
+ curr_sel->add_statistics(unit);
+ }
+
+ return unit->first_select();
+}
+
+
+/**
+ Process INSERT-like select
+*/
+
+bool LEX::parsed_insert_select(SELECT_LEX *first_select)
+{
+ if (sql_command == SQLCOM_INSERT ||
+ sql_command == SQLCOM_REPLACE)
+ {
+ if (sql_command == SQLCOM_INSERT)
+ sql_command= SQLCOM_INSERT_SELECT;
+ else
+ sql_command= SQLCOM_REPLACE_SELECT;
+ }
+ insert_select_hack(first_select);
+ if (check_main_unit_semantics())
+ return true;
+
+ // fix "main" select
+ SELECT_LEX *blt= pop_select();
+ DBUG_ASSERT(blt == &builtin_select);
+ push_select(first_select);
+ return false;
+}
+
+
+bool LEX::parsed_TVC_start()
+{
+ SELECT_LEX *sel;
+ many_values.empty();
+ insert_list= 0;
+ if (!(sel= alloc_select(TRUE)) ||
+ push_select(sel))
+ return true;
+ sel->init_select();
+ sel->braces= FALSE; // just initialisation
+ return false;
+}
+
+
+SELECT_LEX *LEX::parsed_TVC_end()
+{
+
+ SELECT_LEX *res= pop_select(); // above TVC select
+ if (!(res->tvc=
+ new (thd->mem_root) table_value_constr(many_values,
+ res,
+ res->options)))
+ return NULL;
+ many_values.empty();
+ return res;
+}
+
+
+TABLE_LIST *LEX::parsed_derived_select(SELECT_LEX *sel, int for_system_time,
+ LEX_CSTRING *alias)
+{
+ TABLE_LIST *res;
+ derived_tables|= DERIVED_SUBQUERY;
+ sel->set_linkage(DERIVED_TABLE_TYPE);
+ sel->braces= FALSE;
+ // Add the subtree of subquery to the current SELECT_LEX
+ SELECT_LEX *curr_sel= select_stack_head();
+ DBUG_ASSERT(current_select == curr_sel);
+ SELECT_LEX_UNIT *unit= sel->master_unit();
+ if (!unit)
+ {
+ unit= create_unit(sel);
+ if (!unit)
+ return NULL;
+ }
+ curr_sel->register_unit(unit, &curr_sel->context);
+ curr_sel->add_statistics(unit);
+
+ Table_ident *ti= new (thd->mem_root) Table_ident(unit);
+ if (ti == NULL)
+ return NULL;
+ if (!(res= curr_sel->add_table_to_list(thd, ti, alias, 0,
+ TL_READ, MDL_SHARED_READ)))
+ return NULL;
+ if (for_system_time)
+ {
+ res->vers_conditions= vers_conditions;
+ }
+ return res;
+}
+
+TABLE_LIST *LEX::parsed_derived_unit(SELECT_LEX_UNIT *unit,
+ int for_system_time,
+ LEX_CSTRING *alias)
+{
+ TABLE_LIST *res;
+ derived_tables|= DERIVED_SUBQUERY;
+ unit->first_select()->set_linkage(DERIVED_TABLE_TYPE);
+
+ // Add the subtree of subquery to the current SELECT_LEX
+ SELECT_LEX *curr_sel= select_stack_head();
+ DBUG_ASSERT(current_select == curr_sel);
+ curr_sel->register_unit(unit, &curr_sel->context);
+ curr_sel->add_statistics(unit);
+
+ Table_ident *ti= new (thd->mem_root) Table_ident(unit);
+ if (ti == NULL)
+ return NULL;
+ if (!(res= curr_sel->add_table_to_list(thd, ti, alias, 0,
+ TL_READ, MDL_SHARED_READ)))
+ return NULL;
+ if (for_system_time)
+ {
+ res->vers_conditions= vers_conditions;
+ }
+ return res;
+}
+
+bool LEX::parsed_create_view(SELECT_LEX_UNIT *unit, int check)
+{
+ SQL_I_List<TABLE_LIST> *save= &first_select_lex()->table_list;
+ set_main_unit(unit);
+ if (check_main_unit_semantics())
+ return true;
+ first_select_lex()->table_list.push_front(save);
+ current_select= first_select_lex();
+ size_t len= thd->m_parser_state->m_lip.get_cpp_ptr() -
+ create_view->select.str;
+ void *create_view_select= thd->memdup(create_view->select.str, len);
+ create_view->select.length= len;
+ create_view->select.str= (char *) create_view_select;
+ size_t not_used;
+ trim_whitespace(thd->charset(),
+ &create_view->select, &not_used);
+ create_view->check= check;
+ parsing_options.allows_variable= TRUE;
+ return false;
+}
+
+bool LEX::select_finalize(st_select_lex_unit *expr)
+{
+ sql_command= SQLCOM_SELECT;
+ selects_allow_into= TRUE;
+ selects_allow_procedure= TRUE;
+ set_main_unit(expr);
+ return check_main_unit_semantics();
+}
+
+
+/*
+ "IN" and "EXISTS" subselect can appear in two statement types:
+
+ 1. Statements that can have table columns, such as SELECT, DELETE, UPDATE
+ 2. Statements that cannot have table columns, e.g:
+ RETURN ((1) IN (SELECT * FROM t1))
+ IF ((1) IN (SELECT * FROM t1))
+
+ Statements of the first type call master_select_push() in the beginning.
+ In such case everything is properly linked.
+
+ Statements of the second type do not call mastr_select_push().
+ Here we catch the second case and relink thd->lex->builtin_select and
+ select_lex to properly point to each other.
+
+ QQ: Shouldn't subselects of other type also call relink_hack()?
+ QQ: Can we do it at constructor time instead?
+*/
+
+void LEX::relink_hack(st_select_lex *select_lex)
+{
+ if (!select_stack_top) // Statements of the second type
+ {
+ if (!select_lex->get_master()->get_master())
+ ((st_select_lex *) select_lex->get_master())->
+ set_master(&builtin_select);
+ if (!builtin_select.get_slave())
+ builtin_select.set_slave(select_lex->get_master());
+ }
+}
+
+
+
+bool SELECT_LEX_UNIT::set_lock_to_the_last_select(Lex_select_lock l)
+{
+ if (l.defined_lock)
+ {
+ SELECT_LEX *sel= first_select();
+ while (sel->next_select())
+ sel= sel->next_select();
+ if (sel->braces)
+ {
+ my_error(ER_WRONG_USAGE, MYF(0), "lock options",
+ "End SELECT expression");
+ return TRUE;
+ }
+ l.set_to(sel);
+ }
+ return FALSE;
+}
+
+/**
+ Generate unique name for generated derived table for this SELECT
+*/
+
+bool SELECT_LEX::make_unique_derived_name(THD *thd, LEX_CSTRING *alias)
+{
+ // uint32 digits + two underscores + trailing '\0'
+ char buff[MAX_INT_WIDTH + 2 + 1];
+ alias->length= my_snprintf(buff, sizeof(buff), "__%u", select_number);
+ alias->str= thd->strmake(buff, alias->length);
+ return !alias->str;
+}
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 5cc46aa8615..f3e26e5b8ac 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -162,6 +162,23 @@ public:
};
+/**
+ ORDER BY ... LIMIT parameters;
+*/
+class Lex_order_limit_lock: public Sql_alloc
+{
+public:
+ SQL_I_List<st_order> *order_list; /* ORDER clause */
+ Lex_select_lock lock;
+ Lex_select_limit limit;
+
+ Lex_order_limit_lock() :order_list(NULL)
+ {}
+
+ bool set_to(st_select_lex *sel);
+};
+
+
enum sub_select_type
{
UNSPECIFIED_TYPE,
@@ -169,6 +186,14 @@ enum sub_select_type
UNION_TYPE, INTERSECT_TYPE, EXCEPT_TYPE,
GLOBAL_OPTIONS_TYPE, DERIVED_TABLE_TYPE, OLAP_TYPE
};
+
+inline int cmp_unit_op(enum sub_select_type op1, enum sub_select_type op2)
+{
+ DBUG_ASSERT(op1 >= UNION_TYPE && op1 <= EXCEPT_TYPE);
+ DBUG_ASSERT(op2 >= UNION_TYPE && op2 <= EXCEPT_TYPE);
+ return (op1 == INTERSECT_TYPE ? 1 : 0) - (op2 == INTERSECT_TYPE ? 1 : 0);
+}
+
enum unit_common_op {OP_MIX, OP_UNION, OP_INTERSECT, OP_EXCEPT};
enum enum_view_suid
@@ -287,7 +312,8 @@ struct LEX_TYPE
This is not within #ifdef because we want "EXPLAIN PARTITIONS ..." to produce
additional "partitions" column even if partitioning is not compiled in.
*/
-#define DESCRIBE_PARTITIONS 4
+#define DESCRIBE_PARTITIONS 4
+#define DESCRIBE_EXTENDED2 8
#ifdef MYSQL_SERVER
@@ -526,7 +552,7 @@ public:
unit is container of either
- One SELECT
- UNION of selects
- select_lex and unit are both inherited form select_lex_node
+ select_lex and unit are both inherited form st_select_lex_node
neighbors are two select_lex or units on the same level
All select describing structures linked with following pointers:
@@ -651,13 +677,6 @@ public:
ulonglong options;
/*
- In sql_cache we store SQL_CACHE flag as specified by user to be
- able to restore SELECT statement from internal structures.
- */
- enum e_sql_cache { SQL_CACHE_UNSPECIFIED, SQL_NO_CACHE, SQL_CACHE };
- e_sql_cache sql_cache;
-
- /*
result of this query can't be cached, bit field, can be :
UNCACHEABLE_DEPENDENT_GENERATED
UNCACHEABLE_DEPENDENT_INJECTED
@@ -667,11 +686,15 @@ public:
UNCACHEABLE_PREPARE
*/
uint8 uncacheable;
+private:
enum sub_select_type linkage;
+public:
bool is_linkage_set() const
{
return linkage == UNION_TYPE || linkage == INTERSECT_TYPE || linkage == EXCEPT_TYPE;
}
+ enum sub_select_type get_linkage() { return linkage; }
+ bool distinct;
bool no_table_names_allowed; /* used for global order by */
static void *operator new(size_t size, MEM_ROOT *mem_root) throw ()
@@ -689,13 +712,33 @@ public:
}
inline st_select_lex_node* get_master() { return master; }
+ inline st_select_lex_node* get_slave() { return slave; }
void include_down(st_select_lex_node *upper);
void add_slave(st_select_lex_node *slave_arg);
void include_neighbour(st_select_lex_node *before);
+ void link_chain_down(st_select_lex_node *first);
+ void link_neighbour(st_select_lex_node *neighbour)
+ {
+ DBUG_ASSERT(next == NULL);
+ DBUG_ASSERT(neighbour != NULL);
+ next= neighbour;
+ neighbour->prev= &next;
+ }
+ void cut_next() { next= NULL; }
void include_standalone(st_select_lex_node *sel, st_select_lex_node **ref);
void include_global(st_select_lex_node **plink);
void exclude();
void exclude_from_tree();
+ void exclude_from_global()
+ {
+ if (!link_prev)
+ return;
+ if (((*link_prev)= link_next))
+ link_next->link_prev= link_prev;
+ link_next= NULL;
+ link_prev= NULL;
+ }
+
void set_slave(st_select_lex_node *slave_arg) { slave= slave_arg; }
void move_node(st_select_lex_node *where_to_move)
@@ -711,6 +754,22 @@ public:
st_select_lex_node *insert_chain_before(st_select_lex_node **ptr_pos_to_insert,
st_select_lex_node *end_chain_node);
void move_as_slave(st_select_lex_node *new_master);
+ void set_linkage(enum sub_select_type l)
+ {
+ DBUG_ENTER("st_select_lex_node::set_linkage");
+ DBUG_PRINT("info", ("node: %p linkage: %d->%d", this, linkage, l));
+ linkage= l;
+ DBUG_VOID_RETURN;
+ }
+ /*
+ This method created for reiniting LEX in mysql_admin_table() and can be
+ used only if you are going remove all SELECT_LEX & units except belonger
+ to LEX (LEX::unit & LEX::select, for other purposes there are
+ SELECT_LEX_UNIT::exclude_level & SELECT_LEX_UNIT::exclude_tree.
+
+ It is also used in parsing to detach builtin select.
+ */
+ void cut_subtree() { slave= 0; }
friend class st_select_lex_unit;
friend bool mysql_new_select(LEX *lex, bool move_down, SELECT_LEX *sel);
friend bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table,
@@ -720,6 +779,8 @@ public:
friend bool mysql_derived_merge(THD *thd, LEX *lex,
TABLE_LIST *orig_table_list);
friend bool TABLE_LIST::init_derived(THD *thd, bool init_view);
+
+ friend class st_select_lex;
private:
void fast_exclude();
};
@@ -765,9 +826,9 @@ public:
{
}
-
TABLE *table; /* temporary table using for appending UNION results */
select_result *result;
+ st_select_lex *pre_last_parse;
bool prepared, // prepare phase already performed for UNION (unit)
optimized, // optimize phase already performed for UNION (unit)
optimized_2,
@@ -854,7 +915,7 @@ public:
{
return reinterpret_cast<st_select_lex*>(slave);
}
- inline void set_with_clause(With_clause *with_cl);
+ void set_with_clause(With_clause *with_cl);
st_select_lex_unit* next_unit()
{
return reinterpret_cast<st_select_lex_unit*>(next);
@@ -897,6 +958,18 @@ public:
int save_union_explain(Explain_query *output);
int save_union_explain_part2(Explain_query *output);
unit_common_op common_op();
+
+ void reset_distinct();
+ void fix_distinct(st_select_lex_unit *new_unit);
+
+ void register_select_chain(SELECT_LEX *first_sel);
+
+ bool set_nest_level(int new_nest_level);
+ bool check_parameters(SELECT_LEX *main_select);
+
+ bool set_lock_to_the_last_select(Lex_select_lock l);
+
+ friend class st_select_lex;
};
typedef class st_select_lex_unit SELECT_LEX_UNIT;
@@ -923,6 +996,23 @@ public:
class st_select_lex: public st_select_lex_node
{
public:
+ /*
+ Currently the field first_nested is used only by parser.
+ It containa either a reference to the first select
+ of the nest of selects to which 'this' belongs to, or
+ in the case of priority jump it contains a reference to
+ the select to which the priority nest has to be attached to.
+ If there is no priority jump then the first select of the
+ nest contains the reference to itself in first_nested.
+ Example:
+ select1 union select2 intersect select
+ Here we have a priority jump at select2.
+ So select2->first_nested points to select1,
+ while select3->first_nested points to select2 and
+ select1->first_nested points to select1.
+ */
+ st_select_lex *first_nested;
+
Name_resolution_context context;
LEX_CSTRING db;
Item *where, *having; /* WHERE & HAVING clauses */
@@ -1018,6 +1108,7 @@ public:
SQL_I_List<ORDER> order_list; /* ORDER clause */
SQL_I_List<ORDER> gorder_list;
Item *select_limit, *offset_limit; /* LIMIT clause parameters */
+ bool is_set_query_expr_tail;
/// Array of pointers to top elements of all_fields list
Ref_ptr_array ref_pointer_array;
@@ -1159,6 +1250,14 @@ public:
void init_query();
void init_select();
st_select_lex_unit* master_unit() { return (st_select_lex_unit*) master; }
+ inline void set_master_unit(st_select_lex_unit *master_unit)
+ {
+ master= (st_select_lex_node *)master_unit;
+ }
+ void set_master(st_select_lex *master_arg)
+ {
+ master= master_arg;
+ }
st_select_lex_unit* first_inner_unit()
{
return (st_select_lex_unit*) slave;
@@ -1210,12 +1309,6 @@ public:
List<Item>* get_item_list();
ulong get_table_join_options();
void set_lock_for_tables(thr_lock_type lock_type);
- inline void init_order()
- {
- order_list.elements= 0;
- order_list.first= 0;
- order_list.next= &order_list.first;
- }
/*
This method created for reiniting LEX in mysql_admin_table() and can be
used only if you are going remove all SELECT_LEX & units except belonger
@@ -1395,6 +1488,35 @@ public:
DBUG_ASSERT(this != sel);
select_n_where_fields+= sel->select_n_where_fields;
}
+ inline void set_linkage_and_distinct(enum sub_select_type l, bool d)
+ {
+ DBUG_ENTER("SELECT_LEX::set_linkage_and_distinct");
+ DBUG_PRINT("info", ("select: %p distinct %d", this, d));
+ set_linkage(l);
+ DBUG_ASSERT(l == UNION_TYPE ||
+ l == INTERSECT_TYPE ||
+ l == EXCEPT_TYPE);
+ if (d && master_unit() && master_unit()->union_distinct != this)
+ master_unit()->union_distinct= this;
+ distinct= d;
+ with_all_modifier= !distinct;
+ DBUG_VOID_RETURN;
+ }
+ bool set_nest_level(int new_nest_level);
+ bool check_parameters(SELECT_LEX *main_select);
+ void mark_select()
+ {
+ DBUG_ENTER("st_select_lex::mark_select()");
+ DBUG_PRINT("info", ("Select #%d", select_number));
+ DBUG_VOID_RETURN;
+ }
+ void register_unit(SELECT_LEX_UNIT *unit,
+ Name_resolution_context *outer_context);
+ SELECT_LEX_UNIT *attach_selects_chain(SELECT_LEX *sel,
+ Name_resolution_context *context);
+ void add_statistics(SELECT_LEX_UNIT *unit);
+ bool make_unique_derived_name(THD *thd, LEX_CSTRING *alias);
+ void lex_start(LEX *plex);
};
typedef class st_select_lex SELECT_LEX;
@@ -2794,8 +2916,13 @@ class Query_arena_memroot;
struct LEX: public Query_tables_list
{
SELECT_LEX_UNIT unit; /* most upper unit */
- SELECT_LEX select_lex; /* first SELECT_LEX */
+ inline SELECT_LEX *first_select_lex() {return unit.first_select();}
+
+private:
+ SELECT_LEX builtin_select;
/* current SELECT_LEX in parsing */
+
+public:
SELECT_LEX *current_select;
/* list of all SELECT_LEX */
SELECT_LEX *all_selects_list;
@@ -2892,6 +3019,12 @@ private:
bool sp_for_loop_condition(THD *thd, const Lex_for_loop_st &loop);
bool sp_for_loop_increment(THD *thd, const Lex_for_loop_st &loop);
+ /*
+ Check if Item_field and Item_ref are allowed in the current statement.
+ @retval false OK (fields are allowed)
+ @retval true ERROR (fields are not allowed). Error is raised.
+ */
+ bool check_expr_allows_fields_or_error(THD *thd, const char *name) const;
public:
void parse_error(uint err_number= ER_SYNTAX_ERROR);
inline bool is_arena_for_set_stmt() {return arena_for_set_stmt != 0;}
@@ -2919,6 +3052,8 @@ public:
required a local context, the parser pops the top-most context.
*/
List<Name_resolution_context> context_stack;
+ SELECT_LEX *select_stack[MAX_SELECT_NESTING];
+ uint select_stack_top;
SQL_I_List<ORDER> proc_list;
SQL_I_List<TABLE_LIST> auxiliary_table_list, save_list;
@@ -2958,6 +3093,8 @@ public:
syntax error back.
*/
bool expr_allows_subselect;
+ bool selects_allow_into;
+ bool selects_allow_procedure;
/*
A special command "PARSE_VCOL_EXPR" is defined for the parser
to translate a defining expression of a virtual column into an
@@ -3012,7 +3149,17 @@ public:
enum enum_yes_no_unknown tx_chain, tx_release;
bool safe_to_cache_query;
bool subqueries, ignore;
+ bool next_is_main; // use "main" SELECT_LEX for nrxt allocation;
+ bool next_is_down; // use "main" SELECT_LEX for nrxt allocation;
st_parsing_options parsing_options;
+ uint8 lex_options; // see OPTION_LEX_*
+ /*
+ In sql_cache we store SQL_CACHE flag as specified by user to be
+ able to restore SELECT statement from internal structures.
+ */
+ enum e_sql_cache { SQL_CACHE_UNSPECIFIED, SQL_NO_CACHE, SQL_CACHE };
+ e_sql_cache sql_cache;
+
Alter_info alter_info;
/*
For CREATE TABLE statement last element of table list which is not
@@ -3211,20 +3358,24 @@ public:
SELECT_LEX *sl;
SELECT_LEX_UNIT *un;
for (sl= current_select, un= sl->master_unit();
- un != &unit;
- sl= sl->outer_select(), un= sl->master_unit())
+ un && un != &unit;
+ sl= sl->outer_select(), un= (sl ? sl->master_unit() : NULL))
{
- sl->uncacheable|= cause;
- un->uncacheable|= cause;
+ sl->uncacheable|= cause;
+ un->uncacheable|= cause;
}
- select_lex.uncacheable|= cause;
+ if (sl)
+ sl->uncacheable|= cause;
}
+ if (first_select_lex())
+ first_select_lex()->uncacheable|= cause;
}
void set_trg_event_type_for_tables();
TABLE_LIST *unlink_first_table(bool *link_to_local);
void link_first_table_back(TABLE_LIST *first, bool link_to_local);
void first_lists_tables_same();
+ void fix_first_select_number();
bool can_be_merged();
bool can_use_merged();
@@ -3262,14 +3413,83 @@ public:
void cleanup_after_one_table_open();
- bool push_context(Name_resolution_context *context, MEM_ROOT *mem_root)
+ bool push_context(Name_resolution_context *context);
+
+ void pop_context()
{
- return context_stack.push_front(context, mem_root);
+ DBUG_ENTER("LEX::pop_context");
+ Name_resolution_context *context= context_stack.pop();
+ DBUG_PRINT("info", ("Pop context %p Select: %p (%d)",
+ context, context->select_lex,
+ (context->select_lex ?
+ context->select_lex->select_number:
+ 0)));
+ DBUG_VOID_RETURN;
}
- void pop_context()
+ SELECT_LEX *select_stack_head()
{
- context_stack.pop();
+ if (likely(select_stack_top))
+ return select_stack[select_stack_top - 1];
+ return NULL;
+ }
+
+ bool push_select(SELECT_LEX *select_lex)
+ {
+ DBUG_ENTER("LEX::push_select");
+ DBUG_PRINT("info", ("Top Select was %p (%d) depth: %u pushed: %p (%d)",
+ select_stack_head(),
+ select_stack_top,
+ (select_stack_top ?
+ select_stack_head()->select_number :
+ 0),
+ select_lex, select_lex->select_number));
+ if (unlikely(select_stack_top == MAX_SELECT_NESTING))
+ {
+ my_error(ER_TOO_HIGH_LEVEL_OF_NESTING_FOR_SELECT, MYF(0));
+ DBUG_RETURN(TRUE);
+ }
+ if (push_context(&select_lex->context))
+ DBUG_RETURN(TRUE);
+ select_stack[select_stack_top++]= select_lex;
+ current_select= select_lex;
+ DBUG_RETURN(FALSE);
+ }
+
+ SELECT_LEX *pop_select()
+ {
+ DBUG_ENTER("LEX::pop_select");
+ SELECT_LEX *select_lex;
+ if (likely(select_stack_top))
+ select_lex= select_stack[--select_stack_top];
+ else
+ select_lex= 0;
+ DBUG_PRINT("info", ("Top Select is %p (%d) depth: %u poped: %p (%d)",
+ select_stack_head(),
+ select_stack_top,
+ (select_stack_top ?
+ select_stack_head()->select_number :
+ 0),
+ select_lex,
+ (select_lex ? select_lex->select_number : 0)));
+ DBUG_ASSERT(select_lex);
+
+ pop_context();
+
+ if (unlikely(!select_stack_top))
+ {
+ current_select= NULL;
+ DBUG_PRINT("info", ("Top Select is empty"));
+ }
+ else
+ current_select= select_stack[select_stack_top - 1];
+
+ DBUG_RETURN(select_lex);
+ }
+
+ SELECT_LEX *current_select_or_default()
+ {
+ return current_select ? current_select : &builtin_select;
}
bool copy_db_to(LEX_CSTRING *to);
@@ -3278,6 +3498,7 @@ public:
{
return context_stack.head();
}
+
/*
Restore the LEX and THD in case of a parse error.
*/
@@ -3306,9 +3527,8 @@ public:
on its top. So select_lex (as the first added) will be at the tail
of the list.
*/
- if (&select_lex == all_selects_list && !sroutines.records)
+ if (first_select_lex() == all_selects_list && !sroutines.records)
{
- DBUG_ASSERT(!all_selects_list->next_select_in_list());
return TRUE;
}
return FALSE;
@@ -3347,9 +3567,6 @@ public:
int case_stmt_action_expr(Item* expr);
int case_stmt_action_when(Item *when, bool simple);
int case_stmt_action_then();
- bool add_select_to_union_list(bool is_union_distinct,
- enum sub_select_type type,
- bool is_top_level);
bool setup_select_in_parentheses();
bool set_trigger_new_row(const LEX_CSTRING *name, Item *val);
bool set_trigger_field(const LEX_CSTRING *name1, const LEX_CSTRING *name2,
@@ -3474,7 +3691,12 @@ public:
return create_item_qualified_asterisk(thd, &a, &b);
}
- Item *create_item_ident_nosp(THD *thd, Lex_ident_sys_st *name);
+ Item *create_item_ident_field(THD *thd, const char *db, const char *table,
+ const Lex_ident_sys_st *name);
+ Item *create_item_ident_nosp(THD *thd, Lex_ident_sys_st *name)
+ {
+ return create_item_ident_field(thd, NullS, NullS, name);
+ }
Item *create_item_ident_sp(THD *thd, Lex_ident_sys_st *name,
const char *start, const char *end);
Item *create_item_ident(THD *thd, Lex_ident_cli_st *cname)
@@ -3612,6 +3834,10 @@ public:
const Lex_ident_cli_st *var_name,
const Lex_ident_cli_st *field_name);
+ Item *create_item_query_expression(THD *thd,
+ const char *tok_start,
+ st_select_lex_unit *unit);
+
Item *make_item_func_replace(THD *thd, Item *org, Item *find, Item *replace);
Item *make_item_func_substr(THD *thd, Item *a, Item *b, Item *c);
Item *make_item_func_substr(THD *thd, Item *a, Item *b);
@@ -3806,6 +4032,17 @@ public:
sp_for_loop_intrange_finalize(thd, loop);
}
bool sp_for_loop_outer_block_finalize(THD *thd, const Lex_for_loop_st &loop);
+
+ /*
+ Make an Item when an identifier is found in the FOR loop bounds:
+ FOR rec IN cursor
+ FOR rec IN var1 .. var2
+ FOR rec IN row1.field1 .. xxx
+ */
+ Item *create_item_for_loop_bound(THD *thd,
+ const LEX_CSTRING *a,
+ const LEX_CSTRING *b,
+ const LEX_CSTRING *c);
/* End of FOR LOOP methods */
bool add_signal_statement(THD *thd, const class sp_condition_value *value);
@@ -3928,7 +4165,7 @@ public:
bool if_exists() const { return create_info.if_exists(); }
SELECT_LEX *exclude_last_select();
- bool add_unit_in_brackets(SELECT_LEX *nselect);
+ SELECT_LEX *exclude_not_first_select(SELECT_LEX *exclude);
void check_automatic_up(enum sub_select_type type);
bool create_or_alter_view_finalize(THD *thd, Table_ident *table_ident);
bool add_alter_view(THD *thd, uint16 algorithm, enum_view_suid suid,
@@ -3936,7 +4173,6 @@ public:
bool add_create_view(THD *thd, DDL_options_st ddl,
uint16 algorithm, enum_view_suid suid,
Table_ident *table_ident);
-
bool add_grant_command(THD *thd, enum_sql_command sql_command_arg,
stored_procedure_type type_arg);
@@ -3955,7 +4191,7 @@ public:
*/
bool check_simple_select(const LEX_CSTRING *option)
{
- if (current_select != &select_lex)
+ if (current_select != &builtin_select)
{
char command[80];
strmake(command, option->str, MY_MIN(option->length, sizeof(command)-1));
@@ -3973,6 +4209,63 @@ public:
}
bool tvc_finalize();
bool tvc_finalize_derived();
+
+ bool make_select_in_brackets(SELECT_LEX* dummy_select,
+ SELECT_LEX *nselect, bool automatic);
+
+ SELECT_LEX_UNIT *alloc_unit();
+ SELECT_LEX *alloc_select(bool is_select);
+ SELECT_LEX_UNIT *create_unit(SELECT_LEX*);
+ SELECT_LEX *wrap_unit_into_derived(SELECT_LEX_UNIT *unit);
+ SELECT_LEX *wrap_select_chain_into_derived(SELECT_LEX *sel);
+ bool main_select_push();
+ bool insert_select_hack(SELECT_LEX *sel);
+ SELECT_LEX *create_priority_nest(SELECT_LEX *first_in_nest);
+
+ void set_main_unit(st_select_lex_unit *u)
+ {
+ unit.options= u->options;
+ unit.uncacheable= u->uncacheable;
+ unit.register_select_chain(u->first_select());
+ unit.first_select()->options|= builtin_select.options;
+ unit.fake_select_lex= u->fake_select_lex;
+ unit.union_distinct= u->union_distinct;
+ unit.set_with_clause(u->with_clause);
+ builtin_select.exclude_from_global();
+ }
+ bool check_main_unit_semantics();
+
+ // reaction on different parsed parts (bodies are in sql_yacc.yy)
+ bool parsed_unit_in_brackets(SELECT_LEX_UNIT *unit);
+ SELECT_LEX *parsed_select(SELECT_LEX *sel, Lex_order_limit_lock * l);
+ SELECT_LEX *parsed_unit_in_brackets_tail(SELECT_LEX_UNIT *unit,
+ Lex_order_limit_lock * l);
+ SELECT_LEX *parsed_select_in_brackets(SELECT_LEX *sel,
+ Lex_order_limit_lock * l);
+ SELECT_LEX_UNIT *parsed_select_expr_start(SELECT_LEX *s1, SELECT_LEX *s2,
+ enum sub_select_type unit_type,
+ bool distinct);
+ SELECT_LEX_UNIT *parsed_select_expr_cont(SELECT_LEX_UNIT *unit,
+ SELECT_LEX *s2,
+ enum sub_select_type unit_type,
+ bool distinct, bool oracle);
+ SELECT_LEX_UNIT *parsed_body_select(SELECT_LEX *sel,
+ Lex_order_limit_lock * l);
+ bool parsed_body_unit(SELECT_LEX_UNIT *unit);
+ SELECT_LEX_UNIT *parsed_body_unit_tail(SELECT_LEX_UNIT *unit,
+ Lex_order_limit_lock * l);
+ SELECT_LEX *parsed_subselect(SELECT_LEX_UNIT *unit, char *place);
+ bool parsed_insert_select(SELECT_LEX *firs_select);
+ bool parsed_TVC_start();
+ SELECT_LEX *parsed_TVC_end();
+ TABLE_LIST *parsed_derived_select(SELECT_LEX *sel, int for_system_time,
+ LEX_CSTRING *alias);
+ TABLE_LIST *parsed_derived_unit(SELECT_LEX_UNIT *unit,
+ int for_system_time,
+ LEX_CSTRING *alias);
+ bool parsed_create_view(SELECT_LEX_UNIT *unit, int check);
+ bool select_finalize(st_select_lex_unit *expr);
+ void relink_hack(st_select_lex *select_lex);
};
diff --git a/sql/sql_load.cc b/sql/sql_load.cc
index ddb5029c78a..dd6e723c953 100644
--- a/sql/sql_load.cc
+++ b/sql/sql_load.cc
@@ -390,10 +390,13 @@ int mysql_load(THD *thd, const sql_exchange *ex, TABLE_LIST *table_list,
if (mysql_handle_single_derived(thd->lex, table_list, DT_MERGE_FOR_INSERT) ||
mysql_handle_single_derived(thd->lex, table_list, DT_PREPARE))
DBUG_RETURN(TRUE);
- if (setup_tables_and_check_access(thd, &thd->lex->select_lex.context,
- &thd->lex->select_lex.top_join_list,
+ if (setup_tables_and_check_access(thd,
+ &thd->lex->first_select_lex()->context,
+ &thd->lex->first_select_lex()->
+ top_join_list,
table_list,
- thd->lex->select_lex.leaf_tables, FALSE,
+ thd->lex->first_select_lex()->leaf_tables,
+ FALSE,
INSERT_ACL | UPDATE_ACL,
INSERT_ACL | UPDATE_ACL, FALSE))
DBUG_RETURN(-1);
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index e981ed6d3f1..0509fdbfb4e 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -2005,10 +2005,10 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
Init TABLE_LIST members necessary when the undelrying
table is view.
*/
- table_list.select_lex= &(thd->lex->select_lex);
+ table_list.select_lex= thd->lex->first_select_lex();
thd->lex->
- select_lex.table_list.link_in_list(&table_list,
- &table_list.next_local);
+ first_select_lex()->table_list.link_in_list(&table_list,
+ &table_list.next_local);
thd->lex->add_to_query_tables(&table_list);
if (is_infoschema_db(&table_list.db))
@@ -2571,23 +2571,24 @@ int prepare_schema_table(THD *thd, LEX *lex, Table_ident *table_ident,
DBUG_RETURN(1);
#else
{
- if (lex->select_lex.db.str == NULL &&
- lex->copy_db_to(&lex->select_lex.db))
+ if (lex->first_select_lex()->db.str == NULL &&
+ lex->copy_db_to(&lex->first_select_lex()->db))
{
DBUG_RETURN(1);
}
schema_select_lex= new (thd->mem_root) SELECT_LEX();
schema_select_lex->table_list.first= NULL;
if (lower_case_table_names == 1)
- lex->select_lex.db.str= thd->strdup(lex->select_lex.db.str);
- schema_select_lex->db= lex->select_lex.db;
+ lex->first_select_lex()->db.str=
+ thd->strdup(lex->first_select_lex()->db.str);
+ schema_select_lex->db= lex->first_select_lex()->db;
/*
check_db_name() may change db.str if lower_case_table_names == 1,
but that's ok as the db is allocted above in this case.
*/
- if (check_db_name((LEX_STRING*) &lex->select_lex.db))
+ if (check_db_name((LEX_STRING*) &lex->first_select_lex()->db))
{
- my_error(ER_WRONG_DB_NAME, MYF(0), lex->select_lex.db.str);
+ my_error(ER_WRONG_DB_NAME, MYF(0), lex->first_select_lex()->db.str);
DBUG_RETURN(1);
}
break;
@@ -2626,7 +2627,8 @@ int prepare_schema_table(THD *thd, LEX *lex, Table_ident *table_ident,
default:
break;
}
-
+ if (schema_select_lex)
+ schema_select_lex->set_master_unit(&lex->unit);
SELECT_LEX *select_lex= lex->current_select;
if (make_schema_select(thd, select_lex, get_schema_table(schema_table_idx)))
DBUG_RETURN(1);
@@ -3223,7 +3225,7 @@ mysql_execute_command(THD *thd)
int up_result= 0;
LEX *lex= thd->lex;
/* first SELECT_LEX (have special meaning for many of non-SELECTcommands) */
- SELECT_LEX *select_lex= &lex->select_lex;
+ SELECT_LEX *select_lex= lex->first_select_lex();
/* first table of first SELECT_LEX */
TABLE_LIST *first_table= select_lex->table_list.first;
/* list of all tables in query */
@@ -3262,6 +3264,7 @@ mysql_execute_command(THD *thd)
DBUG_ASSERT(first_table == all_tables && first_table != 0);
*/
lex->first_lists_tables_same();
+ lex->fix_first_select_number();
/* should be assigned after making first tables same */
all_tables= lex->query_tables;
/* set context for commands which do not use setup_tables */
@@ -7594,8 +7597,7 @@ void THD::reset_for_next_command(bool do_clear_error)
code is executed first.
*/
DBUG_ASSERT(lex == &main_lex);
- main_lex.stmt_lex= &main_lex; main_lex.current_select_number= 1;
- DBUG_PRINT("info", ("Lex and stmt_lex: %p", &main_lex));
+ main_lex.stmt_lex= &main_lex; main_lex.current_select_number= 0;
/*
Those two lines below are theoretically unneeded as
THD::cleanup_after_query() should take care of this already.
@@ -7681,11 +7683,7 @@ mysql_init_select(LEX *lex)
SELECT_LEX *select_lex= lex->current_select;
select_lex->init_select();
lex->wild= 0;
- if (select_lex == &lex->select_lex)
- {
- DBUG_ASSERT(lex->result == 0);
- lex->exchange= 0;
- }
+ lex->exchange= 0;
}
@@ -7706,6 +7704,7 @@ mysql_new_select(LEX *lex, bool move_down, SELECT_LEX *select_lex)
{
THD *thd= lex->thd;
bool new_select= select_lex == NULL;
+ int old_nest_level= lex->current_select->nest_level;
DBUG_ENTER("mysql_new_select");
if (new_select)
@@ -7717,27 +7716,19 @@ mysql_new_select(LEX *lex, bool move_down, SELECT_LEX *select_lex)
select_lex->init_query();
select_lex->init_select();
}
- lex->nest_level++;
- if (lex->nest_level > (int) MAX_SELECT_NESTING)
- {
- my_error(ER_TOO_HIGH_LEVEL_OF_NESTING_FOR_SELECT, MYF(0));
- DBUG_RETURN(1);
- }
- select_lex->nest_level= lex->nest_level;
select_lex->nest_level_base= &thd->lex->unit;
if (move_down)
{
+ lex->nest_level++;
+ if (select_lex->set_nest_level(old_nest_level + 1))
+ DBUG_RETURN(1);
SELECT_LEX_UNIT *unit;
lex->subqueries= TRUE;
/* first select_lex of subselect or derived table */
- if (!(unit= new (thd->mem_root) SELECT_LEX_UNIT()))
+ if (!(unit= lex->alloc_unit()))
DBUG_RETURN(1);
- unit->init_query();
- unit->thd= thd;
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);
/*
@@ -7771,15 +7762,13 @@ mysql_new_select(LEX *lex, bool move_down, SELECT_LEX *select_lex)
"SELECT ... PROCEDURE ANALYSE()");
DBUG_RETURN(TRUE);
}
- // SELECT 1 FROM t1 ORDER BY 1 UNION SELECT 1 FROM t1 -- not possible
- DBUG_ASSERT(!lex->current_select->order_list.first ||
- lex->current_select->braces);
- // SELECT 1 FROM t1 LIMIT 1 UNION SELECT 1 FROM t1; -- not possible
- DBUG_ASSERT(!lex->current_select->explicit_limit ||
- lex->current_select->braces);
+ SELECT_LEX_NODE *save_slave= select_lex->slave;
select_lex->include_neighbour(lex->current_select);
- SELECT_LEX_UNIT *unit= select_lex->master_unit();
+ select_lex->slave= save_slave;
+ SELECT_LEX_UNIT *unit= select_lex->master_unit();
+ if (select_lex->set_nest_level(old_nest_level))
+ DBUG_RETURN(1);
if (!unit->fake_select_lex && unit->add_fake_select_lex(lex->thd))
DBUG_RETURN(1);
select_lex->context.outer_context=
@@ -7835,9 +7824,10 @@ void mysql_init_multi_delete(LEX *lex)
{
lex->sql_command= SQLCOM_DELETE_MULTI;
mysql_init_select(lex);
- lex->select_lex.select_limit= 0;
+ lex->first_select_lex()->select_limit= 0;
lex->unit.select_limit_cnt= HA_POS_ERROR;
- lex->select_lex.table_list.save_and_clear(&lex->auxiliary_table_list);
+ lex->first_select_lex()->table_list.
+ save_and_clear(&lex->auxiliary_table_list);
lex->query_tables= 0;
lex->query_tables_last= &lex->query_tables;
}
@@ -8140,7 +8130,7 @@ bool mysql_test_parse_for_slave(THD *thd, char *rawbuf, uint length)
thd->reset_for_next_command();
if (!parse_sql(thd, & parser_state, NULL, true) &&
- all_tables_not_ok(thd, lex->select_lex.table_list.first))
+ all_tables_not_ok(thd, lex->first_select_lex()->table_list.first))
error= 1; /* Ignore question */
thd->end_statement();
}
@@ -8222,6 +8212,10 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
LEX_CSTRING alias_str;
LEX *lex= thd->lex;
DBUG_ENTER("add_table_to_list");
+ DBUG_PRINT("enter", ("Table '%s' (%p) Select %p (%u)",
+ (alias ? alias->str : table->table.str),
+ table,
+ this, select_number));
if (unlikely(!table))
DBUG_RETURN(0); // End of memory
@@ -8315,7 +8309,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
ptr->schema_table_name= ptr->table_name;
ptr->schema_table= schema_table;
}
- ptr->select_lex= lex->current_select;
+ ptr->select_lex= this;
/*
We can't cache internal temporary tables between prepares as the
table may be deleted before next exection.
@@ -8422,8 +8416,6 @@ bool st_select_lex::init_nested_join(THD *thd)
nested_join= ptr->nested_join=
((NESTED_JOIN*) ((uchar*) ptr + ALIGN_SIZE(sizeof(TABLE_LIST))));
- if (unlikely(join_list->push_front(ptr, thd->mem_root)))
- DBUG_RETURN(1);
ptr->embedding= embedding;
ptr->join_list= join_list;
ptr->alias.str="(nested_join)";
@@ -8531,7 +8523,6 @@ TABLE_LIST *st_select_lex::nest_last_join(THD *thd)
ptr->join_using_fields= prev_join_using;
}
}
- join_list->push_front(ptr, thd->mem_root);
nested_join->used_tables= nested_join->not_null_tables= (table_map) 0;
DBUG_RETURN(ptr);
}
@@ -8723,7 +8714,7 @@ void st_select_lex::set_lock_for_tables(thr_lock_type lock_type)
bool st_select_lex_unit::add_fake_select_lex(THD *thd_arg)
{
SELECT_LEX *first_sl= first_select();
- DBUG_ENTER("add_fake_select_lex");
+ DBUG_ENTER("st_select_lex_unit::add_fake_select_lex");
DBUG_ASSERT(!fake_select_lex);
if (!(fake_select_lex= new (thd_arg->mem_root) SELECT_LEX()))
@@ -8733,16 +8724,19 @@ bool st_select_lex_unit::add_fake_select_lex(THD *thd_arg)
fake_select_lex->select_number= INT_MAX;
fake_select_lex->parent_lex= thd_arg->lex; /* Used in init_query. */
fake_select_lex->make_empty_select();
- fake_select_lex->linkage= GLOBAL_OPTIONS_TYPE;
+ fake_select_lex->set_linkage(GLOBAL_OPTIONS_TYPE);
fake_select_lex->select_limit= 0;
+ fake_select_lex->no_table_names_allowed= 1;
+
fake_select_lex->context.outer_context=first_sl->context.outer_context;
/* allow item list resolving in fake select for ORDER BY */
fake_select_lex->context.resolve_in_select_list= TRUE;
fake_select_lex->context.select_lex= fake_select_lex;
fake_select_lex->nest_level_base= first_select()->nest_level_base;
- fake_select_lex->nest_level=first_select()->nest_level;
+ if (fake_select_lex->set_nest_level(first_select()->nest_level))
+ DBUG_RETURN(1);
if (!is_unit_op())
{
@@ -8755,7 +8749,7 @@ bool st_select_lex_unit::add_fake_select_lex(THD *thd_arg)
fake_select_lex->no_table_names_allowed= 1;
thd_arg->lex->current_select= fake_select_lex;
}
- thd_arg->lex->pop_context();
+ //thd_arg->lex->pop_context("add fake");
DBUG_RETURN(0);
}
@@ -8791,7 +8785,7 @@ push_new_name_resolution_context(THD *thd,
left_op->first_leaf_for_name_resolution();
on_context->last_name_resolution_table=
right_op->last_leaf_for_name_resolution();
- return thd->lex->push_context(on_context, thd->mem_root);
+ return thd->lex->push_context(on_context);
}
@@ -9220,7 +9214,7 @@ bool multi_update_precheck(THD *thd, TABLE_LIST *tables)
{
TABLE_LIST *table;
LEX *lex= thd->lex;
- SELECT_LEX *select_lex= &lex->select_lex;
+ SELECT_LEX *select_lex= lex->first_select_lex();
DBUG_ENTER("multi_update_precheck");
if (select_lex->item_list.elements != lex->value_list.elements)
@@ -9256,7 +9250,7 @@ bool multi_update_precheck(THD *thd, TABLE_LIST *tables)
/*
Is there tables of subqueries?
*/
- if (&lex->select_lex != lex->all_selects_list)
+ if (lex->first_select_lex() != lex->all_selects_list)
{
DBUG_PRINT("info",("Checking sub query list"));
for (table= tables; table; table= table->next_global)
@@ -9290,7 +9284,7 @@ bool multi_update_precheck(THD *thd, TABLE_LIST *tables)
bool multi_delete_precheck(THD *thd, TABLE_LIST *tables)
{
- SELECT_LEX *select_lex= &thd->lex->select_lex;
+ SELECT_LEX *select_lex= thd->lex->first_select_lex();
TABLE_LIST *aux_tables= thd->lex->auxiliary_table_list.first;
TABLE_LIST **save_query_tables_own_last= thd->lex->query_tables_own_last;
DBUG_ENTER("multi_delete_precheck");
@@ -9407,7 +9401,7 @@ static TABLE_LIST *multi_delete_table_match(LEX *lex, TABLE_LIST *tbl,
bool multi_delete_set_locks_and_link_aux_tables(LEX *lex)
{
- TABLE_LIST *tables= lex->select_lex.table_list.first;
+ TABLE_LIST *tables= lex->first_select_lex()->table_list.first;
TABLE_LIST *target_tbl;
DBUG_ENTER("multi_delete_set_locks_and_link_aux_tables");
@@ -9449,7 +9443,8 @@ bool multi_delete_set_locks_and_link_aux_tables(LEX *lex)
bool update_precheck(THD *thd, TABLE_LIST *tables)
{
DBUG_ENTER("update_precheck");
- if (thd->lex->select_lex.item_list.elements != thd->lex->value_list.elements)
+ if (thd->lex->first_select_lex()->item_list.elements !=
+ thd->lex->value_list.elements)
{
my_message(ER_WRONG_VALUE_COUNT, ER_THD(thd, ER_WRONG_VALUE_COUNT), MYF(0));
DBUG_RETURN(TRUE);
@@ -9540,7 +9535,7 @@ void create_table_set_open_action_and_adjust_tables(LEX *lex)
else
create_table->open_type= OT_BASE_ONLY;
- if (!lex->select_lex.item_list.elements)
+ if (!lex->first_select_lex()->item_list.elements)
{
/*
Avoid opening and locking target table for ordinary CREATE TABLE
@@ -9571,7 +9566,7 @@ bool create_table_precheck(THD *thd, TABLE_LIST *tables,
TABLE_LIST *create_table)
{
LEX *lex= thd->lex;
- SELECT_LEX *select_lex= &lex->select_lex;
+ SELECT_LEX *select_lex= lex->first_select_lex();
ulong want_priv;
bool error= TRUE; // Error message is given
DBUG_ENTER("create_table_precheck");
@@ -10083,6 +10078,8 @@ bool parse_sql(THD *thd, Parser_state *parser_state,
((thd->variables.sql_mode & MODE_ORACLE) ?
ORAparse(thd) :
MYSQLparse(thd)) != 0;
+ DBUG_ASSERT(opt_bootstrap | mysql_parse_status || thd->lex->select_stack_top == 0);
+ thd->lex->current_select= thd->lex->first_select_lex();
/*
Check that if MYSQLparse() failed either thd->is_error() is set, or an
diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc
index 54907c0edbc..3133b94fa5b 100644
--- a/sql/sql_partition.cc
+++ b/sql/sql_partition.cc
@@ -830,7 +830,8 @@ static bool fix_fields_part_func(THD *thd, Item* func_expr, TABLE *table,
goto end;
table->get_fields_in_item_tree= true;
- func_expr->walk(&Item::change_context_processor, 0, &lex.select_lex.context);
+ func_expr->walk(&Item::change_context_processor, 0,
+ &lex.first_select_lex()->context);
thd->where= "partition function";
/*
In execution we must avoid the use of thd->change_item_tree since
diff --git a/sql/sql_partition_admin.cc b/sql/sql_partition_admin.cc
index 99fe09d5afe..2cc3f247e95 100644
--- a/sql/sql_partition_admin.cc
+++ b/sql/sql_partition_admin.cc
@@ -51,7 +51,7 @@ bool Sql_cmd_alter_table_exchange_partition::execute(THD *thd)
/* Moved from mysql_execute_command */
LEX *lex= thd->lex;
/* first SELECT_LEX (have special meaning for many of non-SELECTcommands) */
- SELECT_LEX *select_lex= &lex->select_lex;
+ SELECT_LEX *select_lex= lex->first_select_lex();
/* first table of first SELECT_LEX */
TABLE_LIST *first_table= (TABLE_LIST*) select_lex->table_list.first;
/*
@@ -743,7 +743,7 @@ bool Sql_cmd_alter_table_truncate_partition::execute(THD *thd)
int error;
ha_partition *partition;
ulong timeout= thd->variables.lock_wait_timeout;
- TABLE_LIST *first_table= thd->lex->select_lex.table_list.first;
+ TABLE_LIST *first_table= thd->lex->first_select_lex()->table_list.first;
Alter_info *alter_info= &thd->lex->alter_info;
uint table_counter, i;
List<String> partition_names_list;
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 8d8047601d5..2419fd2d85e 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -1342,7 +1342,7 @@ static int mysql_test_update(Prepared_statement *stmt,
THD *thd= stmt->thd;
uint table_count= 0;
TABLE_LIST *update_source_table;
- SELECT_LEX *select= &stmt->lex->select_lex;
+ SELECT_LEX *select= stmt->lex->first_select_lex();
#ifndef NO_EMBEDDED_ACCESS_CHECKS
uint want_privilege;
#endif
@@ -1398,10 +1398,10 @@ static int mysql_test_update(Prepared_statement *stmt,
table_list->table->grant.want_privilege= want_privilege;
table_list->register_want_access(want_privilege);
#endif
- thd->lex->select_lex.no_wrap_view_item= TRUE;
+ thd->lex->first_select_lex()->no_wrap_view_item= TRUE;
res= setup_fields(thd, Ref_ptr_array(),
select->item_list, MARK_COLUMNS_READ, 0, NULL, 0);
- thd->lex->select_lex.no_wrap_view_item= FALSE;
+ thd->lex->first_select_lex()->no_wrap_view_item= FALSE;
if (res)
goto error;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
@@ -1466,10 +1466,10 @@ static bool mysql_test_delete(Prepared_statement *stmt,
goto error;
}
- DBUG_RETURN(mysql_prepare_delete(thd, table_list,
- lex->select_lex.with_wild,
- lex->select_lex.item_list,
- &lex->select_lex.where,
+ DBUG_RETURN(mysql_prepare_delete(thd, table_list,
+ lex->first_select_lex()->with_wild,
+ lex->first_select_lex()->item_list,
+ &lex->first_select_lex()->where,
&delete_while_scanning));
error:
DBUG_RETURN(TRUE);
@@ -1501,7 +1501,7 @@ static int mysql_test_select(Prepared_statement *stmt,
SELECT_LEX_UNIT *unit= &lex->unit;
DBUG_ENTER("mysql_test_select");
- lex->select_lex.context.resolve_in_select_list= TRUE;
+ lex->first_select_lex()->context.resolve_in_select_list= TRUE;
ulong privilege= lex->exchange ? SELECT_ACL | FILE_ACL : SELECT_ACL;
if (tables)
@@ -1535,7 +1535,7 @@ static int mysql_test_select(Prepared_statement *stmt,
if (!lex->describe && !thd->lex->analyze_stmt && !stmt->is_sql_prepare())
{
/* Make copy of item list, as change_columns may change it */
- List<Item> fields(lex->select_lex.item_list);
+ List<Item> fields(lex->first_select_lex()->item_list);
/* Change columns if a procedure like analyse() */
if (unit->last_procedure && unit->last_procedure->change_columns(thd, fields))
@@ -1692,7 +1692,7 @@ static bool select_like_stmt_test(Prepared_statement *stmt,
THD *thd= stmt->thd;
LEX *lex= stmt->lex;
- lex->select_lex.context.resolve_in_select_list= TRUE;
+ lex->first_select_lex()->context.resolve_in_select_list= TRUE;
if (specific_prepare && (*specific_prepare)(thd))
DBUG_RETURN(TRUE);
@@ -1760,7 +1760,7 @@ static bool mysql_test_create_table(Prepared_statement *stmt)
DBUG_ENTER("mysql_test_create_table");
THD *thd= stmt->thd;
LEX *lex= stmt->lex;
- SELECT_LEX *select_lex= &lex->select_lex;
+ SELECT_LEX *select_lex= lex->first_select_lex();
bool res= FALSE;
bool link_to_local;
TABLE_LIST *create_table= lex->query_tables;
@@ -2080,7 +2080,7 @@ static bool mysql_test_multidelete(Prepared_statement *stmt,
{
THD *thd= stmt->thd;
- thd->lex->current_select= &thd->lex->select_lex;
+ thd->lex->current_select= thd->lex->first_select_lex();
if (add_item_to_list(thd, new (thd->mem_root)
Item_null(thd)))
{
@@ -2119,13 +2119,14 @@ error:
static int mysql_insert_select_prepare_tester(THD *thd)
{
- SELECT_LEX *first_select= &thd->lex->select_lex;
+ SELECT_LEX *first_select= thd->lex->first_select_lex();
TABLE_LIST *second_table= first_select->table_list.first->next_local;
/* Skip first table, which is the table we are inserting in */
first_select->table_list.first= second_table;
- thd->lex->select_lex.context.table_list=
- thd->lex->select_lex.context.first_name_resolution_table= second_table;
+ thd->lex->first_select_lex()->context.table_list=
+ thd->lex->first_select_lex()->context.first_name_resolution_table=
+ second_table;
return mysql_insert_select_prepare(thd);
}
@@ -2160,7 +2161,7 @@ static bool mysql_test_insert_select(Prepared_statement *stmt,
return 1;
/* store it, because mysql_insert_select_prepare_tester change it */
- first_local_table= lex->select_lex.table_list.first;
+ first_local_table= lex->first_select_lex()->table_list.first;
DBUG_ASSERT(first_local_table != 0);
res=
@@ -2168,7 +2169,7 @@ static bool mysql_test_insert_select(Prepared_statement *stmt,
&mysql_insert_select_prepare_tester,
OPTION_SETUP_TABLES_DONE);
/* revert changes made by mysql_insert_select_prepare_tester */
- lex->select_lex.table_list.first= first_local_table;
+ lex->first_select_lex()->table_list.first= first_local_table;
return res;
}
@@ -2194,7 +2195,7 @@ static int mysql_test_handler_read(Prepared_statement *stmt,
SQL_HANDLER *ha_table;
DBUG_ENTER("mysql_test_handler_read");
- lex->select_lex.context.resolve_in_select_list= TRUE;
+ lex->first_select_lex()->context.resolve_in_select_list= TRUE;
/*
We don't have to test for permissions as this is already done during
@@ -2204,7 +2205,7 @@ static int mysql_test_handler_read(Prepared_statement *stmt,
lex->ident.str,
lex->insert_list,
lex->ha_rkey_mode,
- lex->select_lex.where)))
+ lex->first_select_lex()->where)))
DBUG_RETURN(1);
if (!stmt->is_sql_prepare())
@@ -2243,7 +2244,7 @@ static bool check_prepared_statement(Prepared_statement *stmt)
{
THD *thd= stmt->thd;
LEX *lex= stmt->lex;
- SELECT_LEX *select_lex= &lex->select_lex;
+ SELECT_LEX *select_lex= lex->first_select_lex();
TABLE_LIST *tables;
enum enum_sql_command sql_command= lex->sql_command;
int res= 0;
@@ -2252,10 +2253,11 @@ static bool check_prepared_statement(Prepared_statement *stmt)
sql_command, stmt->param_count));
lex->first_lists_tables_same();
+ lex->fix_first_select_number();
tables= lex->query_tables;
/* set context for commands which do not use setup_tables */
- lex->select_lex.context.resolve_in_table_list_only(select_lex->
+ lex->first_select_lex()->context.resolve_in_table_list_only(select_lex->
get_table_list());
/* Reset warning count for each query that uses tables */
@@ -3020,7 +3022,7 @@ void reinit_stmt_before_use(THD *thd, LEX *lex)
{
tables->reinit_before_use(thd);
}
- lex->current_select= &lex->select_lex;
+ lex->current_select= lex->first_select_lex();
if (lex->result)
@@ -4558,8 +4560,8 @@ bool Prepared_statement::validate_metadata(Prepared_statement *copy)
if (is_sql_prepare() || lex->describe)
return FALSE;
- if (lex->select_lex.item_list.elements !=
- copy->lex->select_lex.item_list.elements)
+ if (lex->first_select_lex()->item_list.elements !=
+ copy->lex->first_select_lex()->item_list.elements)
{
/** Column counts mismatch, update the client */
thd->server_status|= SERVER_STATUS_METADATA_CHANGED;
diff --git a/sql/sql_priv.h b/sql/sql_priv.h
index 4e82b6a5d3a..fa12b645041 100644
--- a/sql/sql_priv.h
+++ b/sql/sql_priv.h
@@ -183,7 +183,11 @@
#define OPTION_ALLOW_BATCH (1ULL << 36) // THD, intern (slave)
#define OPTION_SKIP_REPLICATION (1ULL << 37) // THD, user
#define OPTION_RPL_SKIP_PARALLEL (1ULL << 38)
-#define OPTION_FOUND_COMMENT (1ULL << 39) // SELECT, intern, parser
+#define OPTION_NO_QUERY_CACHE (1ULL << 39) // SELECT, user
+#define OPTION_PROCEDURE_CLAUSE (1ULL << 40) // Internal usage
+
+
+#define OPTION_LEX_FOUND_COMMENT (1ULL << 0) // intern, parser
/* The rest of the file is included in the server only */
#ifndef MYSQL_CLIENT
@@ -358,6 +362,9 @@ enum enum_parsing_place
IN_ORDER_BY,
IN_UPDATE_ON_DUP_KEY,
IN_PART_FUNC,
+ BEFORE_OPT_LIST,
+ AFTER_LIST,
+ FOR_LOOP_BOUND,
PARSING_PLACE_SIZE /* always should be the last */
};
diff --git a/sql/sql_profile.cc b/sql/sql_profile.cc
index 13f03fed5f3..6ca21aebb37 100644
--- a/sql/sql_profile.cc
+++ b/sql/sql_profile.cc
@@ -110,7 +110,7 @@ int make_profile_table_for_show(THD *thd, ST_SCHEMA_TABLE *schema_table)
};
ST_FIELD_INFO *field_info;
- Name_resolution_context *context= &thd->lex->select_lex.context;
+ Name_resolution_context *context= &thd->lex->first_select_lex()->context;
int i;
for (i= 0; schema_table->fields_info[i].field_name != NULL; i++)
@@ -402,7 +402,7 @@ bool PROFILING::show_profiles()
QUERY_PROFILE *prof;
List<Item> field_list;
MEM_ROOT *mem_root= thd->mem_root;
- SELECT_LEX *sel= &thd->lex->select_lex;
+ SELECT_LEX *sel= thd->lex->first_select_lex();
SELECT_LEX_UNIT *unit= &thd->lex->unit;
ha_rows idx= 0;
Protocol *protocol= thd->protocol;
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 536c14798d1..49bff77b547 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -351,7 +351,7 @@ bool handle_select(THD *thd, LEX *lex, select_result *result,
ulong setup_tables_done_option)
{
bool res;
- SELECT_LEX *select_lex = &lex->select_lex;
+ SELECT_LEX *select_lex= lex->first_select_lex();
DBUG_ENTER("handle_select");
MYSQL_SELECT_START(thd->query());
@@ -1393,6 +1393,7 @@ err:
bool JOIN::build_explain()
{
+ DBUG_ENTER("JOIN::build_explain");
create_explain_query_if_not_exists(thd->lex, thd->mem_root);
have_query_plan= QEP_AVAILABLE;
@@ -1410,8 +1411,7 @@ bool JOIN::build_explain()
thd->mem_root= old_mem_root;
DBUG_ASSERT(thd->free_list == old_free_list); // no Items were created
if (res)
- return 1;
-
+ DBUG_RETURN(1);
uint select_nr= select_lex->select_number;
JOIN_TAB *curr_tab= join_tab + exec_join_tab_cnt();
for (uint i= 0; i < aggr_tables; i++, curr_tab++)
@@ -1429,7 +1429,7 @@ bool JOIN::build_explain()
get_using_temporary_read_tracker();
}
}
- return 0;
+ DBUG_RETURN(0);
}
@@ -3791,6 +3791,15 @@ bool JOIN::save_explain_data(Explain_query *output, bool can_overwrite,
bool need_tmp_table, bool need_order,
bool distinct)
{
+ DBUG_ENTER("JOIN::save_explain_data");
+ DBUG_PRINT("enter", ("Save explain Select_lex: %u (%p) parent lex: %p stmt_lex: %p present select: %u (%p)",
+ select_lex->select_number, select_lex,
+ select_lex->parent_lex, thd->lex->stmt_lex,
+ (output->get_select(select_lex->select_number) ?
+ select_lex->select_number : 0),
+ (output->get_select(select_lex->select_number) ?
+ output->get_select(select_lex->select_number)
+ ->select_lex : NULL)));
/*
If there is SELECT in this statement with the same number it must be the
same SELECT
@@ -3817,8 +3826,9 @@ bool JOIN::save_explain_data(Explain_query *output, bool can_overwrite,
/* It's a degenerate join */
message= zero_result_cause ? zero_result_cause : "No tables used";
}
- return save_explain_data_intern(thd->lex->explain, need_tmp_table, need_order,
- distinct, message);
+ bool rc= save_explain_data_intern(thd->lex->explain, need_tmp_table,
+ need_order, distinct, message);
+ DBUG_RETURN(rc);
}
/*
@@ -3840,11 +3850,11 @@ bool JOIN::save_explain_data(Explain_query *output, bool can_overwrite,
{
if (!(join_tab[i].filesort->tracker=
new Filesort_tracker(thd->lex->analyze_stmt)))
- return 1;
+ DBUG_RETURN(1);
}
}
}
- return 0;
+ DBUG_RETURN(0);
}
@@ -4201,10 +4211,10 @@ mysql_select(THD *thd,
is it single SELECT in derived table, called in derived table
creation
*/
- if (select_lex->linkage != DERIVED_TABLE_TYPE ||
+ if (select_lex->get_linkage() != DERIVED_TABLE_TYPE ||
(select_options & SELECT_DESCRIBE))
{
- if (select_lex->linkage != GLOBAL_OPTIONS_TYPE)
+ if (select_lex->get_linkage() != GLOBAL_OPTIONS_TYPE)
{
/*
Original join tabs might be overwritten at first
@@ -12689,7 +12699,8 @@ void JOIN::join_free()
!(select_options & SELECT_NO_UNLOCK) &&
!select_lex->subquery_in_having &&
(select_lex == (thd->lex->unit.fake_select_lex ?
- thd->lex->unit.fake_select_lex : &thd->lex->select_lex)))
+ thd->lex->unit.fake_select_lex :
+ thd->lex->first_select_lex())))
{
/*
TODO: unlock tables even if the join isn't top level select in the
@@ -18443,7 +18454,7 @@ create_internal_tmp_table_from_heap(THD *thd, TABLE *table,
new_table.no_rows= table->no_rows;
if (create_internal_tmp_table(&new_table, table->key_info, start_recinfo,
recinfo,
- thd->lex->select_lex.options |
+ thd->lex->first_select_lex()->options |
thd->variables.option_bits))
goto err2;
if (open_tmp_table(&new_table))
@@ -24959,7 +24970,8 @@ bool JOIN_TAB::save_explain_data(Explain_table_access *eta,
*/
if (real_table->merged_for_insert)
{
- TABLE_LIST *view_child= real_table->view->select_lex.table_list.first;
+ TABLE_LIST *view_child=
+ real_table->view->first_select_lex()->table_list.first;
for (;view_child; view_child= view_child->next_local)
{
if (view_child->table == table)
@@ -25412,8 +25424,9 @@ int JOIN::save_explain_data_intern(Explain_query *output,
{
JOIN *join= this; /* Legacy: this code used to be a non-member function */
DBUG_ENTER("JOIN::save_explain_data_intern");
- DBUG_PRINT("info", ("Select %p, type %s, message %s",
- join->select_lex, join->select_lex->type,
+ DBUG_PRINT("info", ("Select %p (%u), type %s, message %s",
+ join->select_lex, join->select_lex->select_number,
+ join->select_lex->type,
message ? message : "NULL"));
DBUG_ASSERT(have_query_plan == QEP_AVAILABLE);
/* fake_select_lex is created/printed by Explain_union */
@@ -25439,7 +25452,7 @@ int JOIN::save_explain_data_intern(Explain_query *output,
explain->select_id= join->select_lex->select_number;
explain->select_type= join->select_lex->type;
- explain->linkage= select_lex->linkage;
+ explain->linkage= select_lex->get_linkage();
explain->using_temporary= need_tmp;
explain->using_filesort= need_order_arg;
/* Setting explain->message means that all other members are invalid */
@@ -25462,7 +25475,7 @@ int JOIN::save_explain_data_intern(Explain_query *output,
explain->select_id= select_lex->select_number;
explain->select_type= select_lex->type;
- explain->linkage= select_lex->linkage;
+ explain->linkage= select_lex->get_linkage();
explain->using_temporary= need_tmp;
explain->using_filesort= need_order_arg;
explain->message= "Storage engine handles GROUP BY";
@@ -25485,7 +25498,7 @@ int JOIN::save_explain_data_intern(Explain_query *output,
join->select_lex->set_explain_type(true);
xpl_sel->select_id= join->select_lex->select_number;
xpl_sel->select_type= join->select_lex->type;
- xpl_sel->linkage= select_lex->linkage;
+ xpl_sel->linkage= select_lex->get_linkage();
if (select_lex->master_unit()->derived)
xpl_sel->connection_type= Explain_node::EXPLAIN_NODE_DERIVED;
@@ -26068,6 +26081,18 @@ void st_select_lex::print(THD *thd, String *str, enum_query_type query_type)
{
str->append("/* select#");
str->append_ulonglong(select_number);
+ if (thd->lex->describe & DESCRIBE_EXTENDED2)
+ {
+ str->append("/");
+ str->append_ulonglong(nest_level);
+
+ if (master_unit()->fake_select_lex &&
+ master_unit()->first_select() == this)
+ {
+ str->append(" Filter Select: ");
+ master_unit()->fake_select_lex->print(thd, str, query_type);
+ }
+ }
str->append(" */ ");
}
@@ -26099,18 +26124,21 @@ void st_select_lex::print(THD *thd, String *str, enum_query_type query_type)
str->append(STRING_WITH_LEN("sql_buffer_result "));
if (options & OPTION_FOUND_ROWS)
str->append(STRING_WITH_LEN("sql_calc_found_rows "));
- switch (sql_cache)
+ if (this == parent_lex->first_select_lex())
{
- case SQL_NO_CACHE:
- str->append(STRING_WITH_LEN("sql_no_cache "));
- break;
- case SQL_CACHE:
- str->append(STRING_WITH_LEN("sql_cache "));
- break;
- case SQL_CACHE_UNSPECIFIED:
- break;
- default:
- DBUG_ASSERT(0);
+ switch (parent_lex->sql_cache)
+ {
+ case LEX::SQL_NO_CACHE:
+ str->append(STRING_WITH_LEN("sql_no_cache "));
+ break;
+ case LEX::SQL_CACHE:
+ str->append(STRING_WITH_LEN("sql_cache "));
+ break;
+ case LEX::SQL_CACHE_UNSPECIFIED:
+ break;
+ default:
+ DBUG_ASSERT(0);
+ }
}
//Item List
diff --git a/sql/sql_sequence.cc b/sql/sql_sequence.cc
index 21a8781087f..baaa4571c9e 100644
--- a/sql/sql_sequence.cc
+++ b/sql/sql_sequence.cc
@@ -220,8 +220,8 @@ bool check_sequence_fields(LEX *lex, List<Create_field> *fields)
err:
my_error(ER_SEQUENCE_INVALID_TABLE_STRUCTURE, MYF(0),
- lex->select_lex.table_list.first->db.str,
- lex->select_lex.table_list.first->table_name.str, reason);
+ lex->first_select_lex()->table_list.first->db.str,
+ lex->first_select_lex()->table_list.first->table_name.str, reason);
DBUG_RETURN(TRUE);
}
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 2484b5039ad..cffc62cd381 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -4143,8 +4143,9 @@ bool get_lookup_field_values(THD *thd, COND *cond, TABLE_LIST *tables,
case SQLCOM_SHOW_TABLE_STATUS:
case SQLCOM_SHOW_TRIGGERS:
case SQLCOM_SHOW_EVENTS:
- thd->make_lex_string(&lookup_field_values->db_value,
- lex->select_lex.db.str, lex->select_lex.db.length);
+ thd->make_lex_string(&lookup_field_values->db_value,
+ lex->first_select_lex()->db.str,
+ lex->first_select_lex()->db.length);
if (wild)
{
thd->make_lex_string(&lookup_field_values->table_value,
@@ -4537,10 +4538,10 @@ fill_schema_table_by_open(THD *thd, MEM_ROOT *mem_root,
temporary LEX. The latter is required to correctly open views and
produce table describing their structure.
*/
- if (make_table_list(thd, &lex->select_lex, &db_name, &table_name))
+ if (make_table_list(thd, lex->first_select_lex(), &db_name, &table_name))
goto end;
- table_list= lex->select_lex.table_list.first;
+ table_list= lex->first_select_lex()->table_list.first;
if (is_show_fields_or_keys)
{
@@ -6715,7 +6716,7 @@ static int get_schema_views_record(THD *thd, TABLE_LIST *tables,
& 'field_translation_end' are uninitialized is this
case.
*/
- List<Item> *fields= &tables->view->select_lex.item_list;
+ List<Item> *fields= &tables->view->first_select_lex()->item_list;
List_iterator<Item> it(*fields);
Item *item;
Item_field *field;
@@ -7694,9 +7695,9 @@ int fill_open_tables(THD *thd, TABLE_LIST *tables, COND *cond)
TABLE *table= tables->table;
CHARSET_INFO *cs= system_charset_info;
OPEN_TABLE_LIST *open_list;
- if (unlikely(!(open_list= list_open_tables(thd, thd->lex->select_lex.db.str,
- wild))) &&
- unlikely(thd->is_fatal_error))
+ if (!(open_list= list_open_tables(thd, thd->lex->first_select_lex()->db.str,
+ wild))
+ && thd->is_fatal_error)
DBUG_RETURN(1);
for (; open_list ; open_list=open_list->next)
@@ -8190,7 +8191,7 @@ TABLE *create_schema_table(THD *thd, TABLE_LIST *table_list)
tmp_table_param->table_charset= cs;
tmp_table_param->field_count= field_count;
tmp_table_param->schema_table= 1;
- SELECT_LEX *select_lex= thd->lex->current_select;
+ SELECT_LEX *select_lex= table_list->select_lex;
bool keep_row_order= is_show_command(thd);
if (!(table= create_tmp_table(thd, tmp_table_param,
field_list, (ORDER*) 0, 0, 0,
@@ -8227,7 +8228,7 @@ TABLE *create_schema_table(THD *thd, TABLE_LIST *table_list)
static int make_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
{
ST_FIELD_INFO *field_info= schema_table->fields_info;
- Name_resolution_context *context= &thd->lex->select_lex.context;
+ Name_resolution_context *context= &thd->lex->first_select_lex()->context;
for (; field_info->field_name; field_info++)
{
if (field_info->old_name)
@@ -8287,14 +8288,14 @@ int make_table_names_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
char tmp[128];
String buffer(tmp,sizeof(tmp), thd->charset());
LEX *lex= thd->lex;
- Name_resolution_context *context= &lex->select_lex.context;
+ Name_resolution_context *context= &lex->first_select_lex()->context;
ST_FIELD_INFO *field_info= &schema_table->fields_info[2];
LEX_CSTRING field_name= {field_info->field_name,
strlen(field_info->field_name) };
buffer.length(0);
buffer.append(field_info->old_name);
- buffer.append(&lex->select_lex.db);
+ buffer.append(&lex->first_select_lex()->db);
if (lex->wild && lex->wild->ptr())
{
buffer.append(STRING_WITH_LEN(" ("));
@@ -8327,7 +8328,7 @@ int make_columns_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
int fields_arr[]= {3, 15, 14, 6, 16, 5, 17, 18, 19, -1};
int *field_num= fields_arr;
ST_FIELD_INFO *field_info;
- Name_resolution_context *context= &thd->lex->select_lex.context;
+ Name_resolution_context *context= &thd->lex->first_select_lex()->context;
for (; *field_num >= 0; field_num++)
{
@@ -8358,7 +8359,7 @@ int make_character_sets_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
int fields_arr[]= {0, 2, 1, 3, -1};
int *field_num= fields_arr;
ST_FIELD_INFO *field_info;
- Name_resolution_context *context= &thd->lex->select_lex.context;
+ Name_resolution_context *context= &thd->lex->first_select_lex()->context;
for (; *field_num >= 0; field_num++)
{
@@ -8385,7 +8386,7 @@ int make_proc_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
int fields_arr[]= {2, 3, 4, 27, 24, 23, 22, 26, 28, 29, 30, -1};
int *field_num= fields_arr;
ST_FIELD_INFO *field_info;
- Name_resolution_context *context= &thd->lex->select_lex.context;
+ Name_resolution_context *context= &thd->lex->first_select_lex()->context;
for (; *field_num >= 0; field_num++)
{
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 04fd7bf6e32..2c36c552354 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -4890,7 +4890,7 @@ int create_table_impl(THD *thd,
/*
Restart statement transactions for the case of CREATE ... SELECT.
*/
- if (thd->lex->select_lex.item_list.elements &&
+ if (thd->lex->first_select_lex()->item_list.elements &&
restart_trans_for_tables(thd, thd->lex->query_tables))
goto err;
}
@@ -10291,8 +10291,8 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
Filesort_tracker dummy_tracker(false);
Filesort fsort(order, HA_POS_ERROR, true, NULL);
- if (thd->lex->select_lex.setup_ref_array(thd, order_num) ||
- setup_order(thd, thd->lex->select_lex.ref_pointer_array,
+ if (thd->lex->first_select_lex()->setup_ref_array(thd, order_num) ||
+ setup_order(thd, thd->lex->first_select_lex()->ref_pointer_array,
&tables, fields, all_fields, order))
goto err;
diff --git a/sql/sql_truncate.cc b/sql/sql_truncate.cc
index cf91d6d2189..d515aacd1d0 100644
--- a/sql/sql_truncate.cc
+++ b/sql/sql_truncate.cc
@@ -492,7 +492,7 @@ bool Sql_cmd_truncate_table::truncate_table(THD *thd, TABLE_LIST *table_ref)
bool Sql_cmd_truncate_table::execute(THD *thd)
{
bool res= TRUE;
- TABLE_LIST *table= thd->lex->select_lex.table_list.first;
+ TABLE_LIST *table= thd->lex->first_select_lex()->table_list.first;
DBUG_ENTER("Sql_cmd_truncate_table::execute");
if (check_one_table_access(thd, DROP_ACL, table))
diff --git a/sql/sql_tvc.cc b/sql/sql_tvc.cc
index f81fe173c7d..43edd2d506a 100644
--- a/sql/sql_tvc.cc
+++ b/sql/sql_tvc.cc
@@ -295,7 +295,7 @@ int table_value_constr::save_explain_data_intern(THD *thd,
explain->select_id= select_lex->select_number;
explain->select_type= select_lex->type;
- explain->linkage= select_lex->linkage;
+ explain->linkage= select_lex->get_linkage();
explain->using_temporary= false;
explain->using_filesort= false;
/* Setting explain->message means that all other members are invalid */
@@ -548,7 +548,7 @@ bool Item_subselect::wrap_tvc_in_derived_table(THD *thd,
Item *item;
SELECT_LEX *sq_select; // select for IN subquery;
sq_select= lex->current_select;
- sq_select->linkage= tvc_sl->linkage;
+ sq_select->set_linkage(tvc_sl->get_linkage());
sq_select->parsing_place= SELECT_LIST;
item= new (thd->mem_root) Item_field(thd, &sq_select->context,
NULL, NULL, &star_clex_str);
@@ -567,7 +567,7 @@ bool Item_subselect::wrap_tvc_in_derived_table(THD *thd,
goto err;
tvc_select= lex->current_select;
derived_unit= tvc_select->master_unit();
- tvc_select->linkage= DERIVED_TABLE_TYPE;
+ tvc_select->set_linkage(DERIVED_TABLE_TYPE);
lex->current_select= sq_select;
@@ -694,7 +694,7 @@ Item *Item_func_in::in_predicate_to_in_subs_transformer(THD *thd,
mysql_init_select(lex);
tvc_select= lex->current_select;
derived_unit= tvc_select->master_unit();
- tvc_select->linkage= DERIVED_TABLE_TYPE;
+ tvc_select->set_linkage(DERIVED_TABLE_TYPE);
/* Create TVC used in the transformation */
if (create_value_list_for_tvc(thd, &values))
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index 10c2e7ebcb2..be987b82cba 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -68,7 +68,7 @@ void select_unit::change_select()
curr_sel= current_select_number;
/* New SELECT processing starts */
DBUG_ASSERT(table->file->inited == 0);
- step= thd->lex->current_select->linkage;
+ step= thd->lex->current_select->get_linkage();
switch (step)
{
case INTERSECT_TYPE:
@@ -248,7 +248,7 @@ bool select_unit::send_eof()
{
if (step != INTERSECT_TYPE ||
(thd->lex->current_select->next_select() &&
- thd->lex->current_select->next_select()->linkage == INTERSECT_TYPE))
+ thd->lex->current_select->next_select()->get_linkage() == INTERSECT_TYPE))
{
/*
it is not INTESECT or next SELECT in the sequence is INTERSECT so no
@@ -1417,7 +1417,7 @@ bool st_select_lex_unit::exec()
union_result->change_select();
if (fake_select_lex)
{
- if (sl != &thd->lex->select_lex)
+ if (sl != thd->lex->first_select_lex())
fake_select_lex->uncacheable|= sl->uncacheable;
else
fake_select_lex->uncacheable= 0;
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index b56f7383837..97025de8a05 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -318,7 +318,7 @@ int mysql_update(THD *thd,
SQL_SELECT *select= NULL;
SORT_INFO *file_sort= 0;
READ_RECORD info;
- SELECT_LEX *select_lex= &thd->lex->select_lex;
+ SELECT_LEX *select_lex= thd->lex->first_select_lex();
ulonglong id;
List<Item> all_fields;
killed_state killed_status= NOT_KILLED;
@@ -375,7 +375,7 @@ int mysql_update(THD *thd,
table->covering_keys= table->s->keys_in_use;
table->quick_keys.clear_all();
- query_plan.select_lex= &thd->lex->select_lex;
+ query_plan.select_lex= thd->lex->first_select_lex();
query_plan.table= table;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
/* Force privilege re-checking for views after they have been opened. */
@@ -1243,7 +1243,7 @@ bool mysql_prepare_update(THD *thd, TABLE_LIST *table_list,
TABLE *table= table_list->table;
#endif
List<Item> all_fields;
- SELECT_LEX *select_lex= &thd->lex->select_lex;
+ SELECT_LEX *select_lex= thd->lex->first_select_lex();
DBUG_ENTER("mysql_prepare_update");
#ifndef NO_EMBEDDED_ACCESS_CHECKS
@@ -1520,7 +1520,7 @@ int mysql_multi_update_prepare(THD *thd)
LEX *lex= thd->lex;
TABLE_LIST *table_list= lex->query_tables;
TABLE_LIST *tl;
- List<Item> *fields= &lex->select_lex.item_list;
+ List<Item> *fields= &lex->first_select_lex()->item_list;
table_map tables_for_update;
bool update_view= 0;
/*
@@ -1562,14 +1562,15 @@ int mysql_multi_update_prepare(THD *thd)
if (mysql_handle_derived(lex, DT_PREPARE))
DBUG_RETURN(TRUE);
- if (setup_tables_and_check_access(thd, &lex->select_lex.context,
- &lex->select_lex.top_join_list,
+ if (setup_tables_and_check_access(thd,
+ &lex->first_select_lex()->context,
+ &lex->first_select_lex()->top_join_list,
table_list,
- lex->select_lex.leaf_tables, FALSE,
- UPDATE_ACL, SELECT_ACL, FALSE))
+ lex->first_select_lex()->leaf_tables,
+ FALSE, UPDATE_ACL, SELECT_ACL, FALSE))
DBUG_RETURN(TRUE);
- if (lex->select_lex.handle_derived(thd->lex, DT_MERGE))
+ if (lex->first_select_lex()->handle_derived(thd->lex, DT_MERGE))
DBUG_RETURN(TRUE);
if (setup_fields_with_no_wrap(thd, Ref_ptr_array(),
@@ -1592,13 +1593,14 @@ int mysql_multi_update_prepare(THD *thd)
thd->table_map_for_update= tables_for_update= get_table_map(fields);
- if (unsafe_key_update(lex->select_lex.leaf_tables, tables_for_update))
+ if (unsafe_key_update(lex->first_select_lex()->leaf_tables,
+ tables_for_update))
DBUG_RETURN(true);
/*
Setup timestamp handling and locking mode
*/
- List_iterator<TABLE_LIST> ti(lex->select_lex.leaf_tables);
+ List_iterator<TABLE_LIST> ti(lex->first_select_lex()->leaf_tables);
while ((tl= ti++))
{
TABLE *table= tl->table;
@@ -1691,7 +1693,7 @@ int mysql_multi_update_prepare(THD *thd)
Check that we are not using table that we are updating, but we should
skip all tables of UPDATE SELECT itself
*/
- lex->select_lex.exclude_from_table_unique_test= TRUE;
+ lex->first_select_lex()->exclude_from_table_unique_test= TRUE;
/* We only need SELECT privilege for columns in the values list */
ti.rewind();
while ((tl= ti++))
@@ -1713,7 +1715,7 @@ int mysql_multi_update_prepare(THD *thd)
Set exclude_from_table_unique_test value back to FALSE. It is needed for
further check in multi_update::prepare whether to use record cache.
*/
- lex->select_lex.exclude_from_table_unique_test= FALSE;
+ lex->first_select_lex()->exclude_from_table_unique_test= FALSE;
if (lex->save_prep_leaf_tables())
DBUG_RETURN(TRUE);
@@ -1742,7 +1744,7 @@ bool mysql_multi_update(THD *thd,
DBUG_ENTER("mysql_multi_update");
if (!(*result= new (thd->mem_root) multi_update(thd, table_list,
- &thd->lex->select_lex.leaf_tables,
+ &thd->lex->first_select_lex()->leaf_tables,
fields, values,
handle_duplicates, ignore)))
{
diff --git a/sql/sql_view.cc b/sql/sql_view.cc
index f262daad89d..f2fc4b6bf75 100644
--- a/sql/sql_view.cc
+++ b/sql/sql_view.cc
@@ -254,7 +254,7 @@ bool create_view_precheck(THD *thd, TABLE_LIST *tables, TABLE_LIST *view,
LEX *lex= thd->lex;
/* first table in list is target VIEW name => cut off it */
TABLE_LIST *tbl;
- SELECT_LEX *select_lex= &lex->select_lex;
+ SELECT_LEX *select_lex= lex->first_select_lex();
SELECT_LEX *sl;
bool res= TRUE;
DBUG_ENTER("create_view_precheck");
@@ -323,7 +323,6 @@ bool create_view_precheck(THD *thd, TABLE_LIST *tables, TABLE_LIST *view,
}
}
- if (&lex->select_lex != lex->all_selects_list)
{
/* check tables of subqueries */
for (tbl= tables; tbl; tbl= tbl->next_global)
@@ -399,7 +398,7 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views,
TABLE_LIST *view= lex->unlink_first_table(&link_to_local);
TABLE_LIST *tables= lex->query_tables;
TABLE_LIST *tbl;
- SELECT_LEX *select_lex= &lex->select_lex;
+ SELECT_LEX *select_lex= lex->first_select_lex();
SELECT_LEX *sl;
SELECT_LEX_UNIT *unit= &lex->unit;
bool res= FALSE;
@@ -995,7 +994,7 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view,
view->algorithm != VIEW_ALGORITHM_TMPTABLE)))
{
/* TODO: change here when we will support UNIONs */
- for (TABLE_LIST *tbl= lex->select_lex.table_list.first;
+ for (TABLE_LIST *tbl= lex->first_select_lex()->table_list.first;
tbl;
tbl= tbl->next_local)
{
@@ -1114,8 +1113,8 @@ loop_out:
UNION
*/
if (view->updatable_view &&
- !lex->select_lex.master_unit()->is_unit_op() &&
- !(lex->select_lex.table_list.first)->next_local &&
+ !lex->first_select_lex()->master_unit()->is_unit_op() &&
+ !(lex->first_select_lex()->table_list.first)->next_local &&
find_table_in_global_list(lex->query_tables->next_global,
&lex->query_tables->db,
&lex->query_tables->table_name))
@@ -1162,7 +1161,8 @@ err:
bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table,
bool open_view_no_parse)
{
- SELECT_LEX *end, *UNINIT_VAR(view_select);
+ SELECT_LEX_NODE *end;
+ SELECT_LEX *UNINIT_VAR(view_select);
LEX *old_lex, *lex;
Query_arena *arena, backup;
TABLE_LIST *top_view= table->top_table();
@@ -1361,8 +1361,6 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table,
lex_start(thd);
lex->stmt_lex= old_lex;
- view_select= &lex->select_lex;
- view_select->select_number= ++thd->lex->stmt_lex->current_select_number;
sql_mode_t saved_mode= thd->variables.sql_mode;
/* switch off modes which can prevent normal parsing of VIEW
@@ -1397,6 +1395,8 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table,
parse_status= parse_sql(thd, & parser_state, table->view_creation_ctx);
+ view_select= lex->first_select_lex();
+
/* Restore environment. */
if ((old_lex->sql_command == SQLCOM_SHOW_FIELDS) ||
@@ -1546,7 +1546,7 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table,
This may change in future, for example if we enable merging of
views with subqueries in select list.
*/
- view_main_select_tables= lex->select_lex.table_list.first;
+ view_main_select_tables= lex->first_select_lex()->table_list.first;
/*
Let us set proper lock type for tables of the view's main
@@ -1574,7 +1574,7 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table,
/* Fields in this view can be used in upper select in case of merge. */
if (table->select_lex)
- table->select_lex->add_where_field(&lex->select_lex);
+ table->select_lex->add_where_field(lex->first_select_lex());
}
/*
This method has a dependency on the proper lock type being set,
@@ -1596,8 +1596,8 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table,
old_lex->safe_to_cache_query= (old_lex->safe_to_cache_query &&
lex->safe_to_cache_query);
/* move SQL_CACHE to whole query */
- if (view_select->options & OPTION_TO_QUERY_CACHE)
- old_lex->select_lex.options|= OPTION_TO_QUERY_CACHE;
+ if (lex->first_select_lex()->options & OPTION_TO_QUERY_CACHE)
+ old_lex->first_select_lex()->options|= OPTION_TO_QUERY_CACHE;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (table->view_suid)
@@ -1679,9 +1679,10 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table,
tbl->grant.want_privilege= top_view->grant.orig_want_privilege;
/* prepare view context */
- lex->select_lex.context.resolve_in_table_list_only(view_main_select_tables);
- lex->select_lex.context.outer_context= 0;
- lex->select_lex.select_n_having_items+=
+ lex->first_select_lex()->
+ context.resolve_in_table_list_only(view_main_select_tables);
+ lex->first_select_lex()->context.outer_context= 0;
+ lex->first_select_lex()->select_n_having_items+=
table->select_lex->select_n_having_items;
table->where= view_select->where;
@@ -1692,12 +1693,13 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table,
*/
if (!table->select_lex->master_unit()->is_unit_op() &&
table->select_lex->order_list.elements == 0)
- table->select_lex->order_list.push_back(&lex->select_lex.order_list);
+ table->select_lex->order_list.
+ push_back(&lex->first_select_lex()->order_list);
else
{
if (old_lex->sql_command == SQLCOM_SELECT &&
(old_lex->describe & DESCRIBE_EXTENDED) &&
- lex->select_lex.order_list.elements &&
+ lex->first_select_lex()->order_list.elements &&
!table->select_lex->master_unit()->is_unit_op())
{
push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
@@ -1732,7 +1734,11 @@ ok:
lex->unit.include_down(table->select_lex);
lex->unit.slave= view_select; // fix include_down initialisation
/* global SELECT list linking */
- end= view_select; // primary SELECT_LEX is always last
+ /*
+ The primary SELECT_LEX is always last (because parsed first) if WITH not
+ used, otherwise it is good start point for last element finding
+ */
+ for (end= view_select; end->link_next; end= end->link_next);
end->link_next= old_lex->all_selects_list;
old_lex->all_selects_list->link_prev= &end->link_next;
old_lex->all_selects_list= lex->all_selects_list;
@@ -1917,7 +1923,7 @@ bool check_key_in_view(THD *thd, TABLE_LIST *view)
*/
if ((!view->view && !view->belong_to_view) ||
thd->lex->sql_command == SQLCOM_INSERT ||
- thd->lex->select_lex.select_limit == 0)
+ thd->lex->first_select_lex()->select_limit == 0)
DBUG_RETURN(FALSE); /* it is normal table or query without LIMIT */
table= view->table;
view= view->top_table();
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index dffc91ea465..c8eb1fce6c3 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -491,96 +491,6 @@ Item* handle_sql2003_note184_exception(THD *thd, Item* left, bool equal,
}
/**
- @brief Creates a new SELECT_LEX for a UNION branch.
-
- Sets up and initializes a SELECT_LEX structure for a query once the parser
- discovers a UNION token. The current SELECT_LEX is pushed on the stack and
- the new SELECT_LEX becomes the current one.
-
- @param lex The parser state.
-
- @param is_union_distinct True if the union preceding the new select
- statement uses UNION DISTINCT.
-
- @param is_top_level This should be @c TRUE if the newly created SELECT_LEX
- is a non-nested statement.
-
- @return <code>false</code> if successful, <code>true</code> if an error was
- reported. In the latter case parsing should stop.
- */
-bool LEX::add_select_to_union_list(bool is_union_distinct,
- enum sub_select_type type,
- bool is_top_level)
-{
- const char *type_name= (type == INTERSECT_TYPE ? "INTERSECT" :
- (type == EXCEPT_TYPE ? "EXCEPT" : "UNION"));
- /*
- Only the last SELECT can have INTO. Since the grammar won't allow INTO in
- a nested SELECT, we make this check only when creating a top-level SELECT.
- */
- if (is_top_level && result)
- {
- my_error(ER_WRONG_USAGE, MYF(0), type_name, "INTO");
- return TRUE;
- }
- if (current_select->order_list.first && !current_select->braces)
- {
- my_error(ER_WRONG_USAGE, MYF(0), type_name, "ORDER BY");
- return TRUE;
- }
-
- if (current_select->explicit_limit && !current_select->braces)
- {
- my_error(ER_WRONG_USAGE, MYF(0), type_name, "LIMIT");
- return TRUE;
- }
- if (current_select->linkage == GLOBAL_OPTIONS_TYPE)
- {
- thd->parse_error();
- return TRUE;
- }
- if (!is_union_distinct && (type == INTERSECT_TYPE || type == EXCEPT_TYPE))
- {
- my_error(ER_WRONG_USAGE, MYF(0), type_name, "ALL");
- return TRUE;
- }
- /*
- Priority implementation, but also trying to keep things as flat
- as possible */
- if (type == INTERSECT_TYPE &&
- (current_select->linkage != INTERSECT_TYPE &&
- current_select != current_select->master_unit()->first_select())
- && !(thd->variables.sql_mode & MODE_ORACLE))
- {
- /*
- This and previous SELECTs should go one level down because of
- priority
- */
- SELECT_LEX *prev= exclude_last_select();
- if (add_unit_in_brackets(prev))
- return TRUE;
- return add_select_to_union_list(is_union_distinct, type, 0);
- }
- else
- {
- check_automatic_up(type);
- }
- /* This counter shouldn't be incremented for UNION parts */
- nest_level--;
- if (mysql_new_select(this, 0, NULL))
- return TRUE;
- mysql_init_select(this);
- current_select->linkage= type;
- current_select->with_all_modifier= !is_union_distinct;
- if (is_union_distinct) /* UNION DISTINCT - remember position */
- current_select->master_unit()->union_distinct= current_select;
- else
- DBUG_ASSERT(type == UNION_TYPE);
- return FALSE;
-}
-
-
-/**
Create a separate LEX for each assignment if in SP.
If we are in SP we want have own LEX for each assignment.
@@ -621,6 +531,7 @@ void sp_create_assignment_lex(THD *thd, bool no_lookahead)
lex->sphead->m_tmp_query= lip->get_tok_end();
/* Inherit from outer lex. */
lex->option_type= old_lex->option_type;
+ lex->main_select_push();
}
}
@@ -680,6 +591,9 @@ bool sp_create_assignment_instr(THD *thd, bool no_lookahead)
if (sp->add_instr(i))
return true;
}
+ lex->pop_select();
+ if (Lex->check_main_unit_semantics())
+ return true;
enum_var_type inner_option_type= lex->option_type;
if (lex->sphead->restore_lex(thd))
return true;
@@ -767,6 +681,7 @@ Virtual_column_info *add_virtual_expression(THD *thd, Item *expr)
return v;
}
+
%}
%union {
int num;
@@ -796,6 +711,20 @@ Virtual_column_info *add_virtual_expression(THD *thd, Item *expr)
uint offset;
} sp_cursor_name_and_offset;
vers_history_point_t vers_history_point;
+ struct
+ {
+ enum sub_select_type unit_type;
+ bool distinct;
+ } unit_operation;
+ struct
+ {
+ SELECT_LEX *first;
+ SELECT_LEX *prev_last;
+ } select_list;
+ SQL_I_List<ORDER> *select_order;
+ Lex_select_lock select_lock;
+ Lex_select_limit select_limit;
+ Lex_order_limit_lock *order_limit_lock;
/* pointers */
Create_field *create_field;
@@ -841,6 +770,7 @@ Virtual_column_info *add_virtual_expression(THD *thd, Item *expr)
handlerton *db_type;
st_select_lex *select_lex;
+ st_select_lex_unit *select_lex_unit;
struct p_elem_val *p_elem_value;
class Window_frame *window_frame;
class Window_frame_bound *window_frame_bound;
@@ -849,7 +779,6 @@ Virtual_column_info *add_virtual_expression(THD *thd, Item *expr)
/* enums */
enum enum_view_suid view_suid;
- enum sub_select_type unit_type;
enum Condition_information_item::Name cond_info_item_name;
enum enum_diag_condition_item_name diag_condition_item_name;
enum Diagnostics_information::Which_area diag_area;
@@ -888,10 +817,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
%parse-param { THD *thd }
%lex-param { THD *thd }
/*
- Currently there are 62 shift/reduce conflicts.
+ Currently there are 58 shift/reduce conflicts.
We should not introduce new conflicts any more.
*/
-%expect 62
+%expect 58
/*
Comments for TOKENS.
@@ -1042,6 +971,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
%token LEADING /* SQL-2003-R */
%token LEAVE_SYM
%token LEFT /* SQL-2003-R */
+%token LEFT_PAREN_ALT /* INTERNAL */
+%token LEFT_PAREN_WITH /* INTERNAL */
+%token LEFT_PAREN_LIKE /* INTERNAL */
%token LEX_HOSTNAME
%token LIKE /* SQL-2003-R */
%token LIMIT
@@ -1784,7 +1716,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
NCHAR_STRING
%type <lex_str_ptr>
- opt_table_alias
+ opt_table_alias_clause
+ table_alias_clause
%type <ident_cli>
IDENT
@@ -1846,7 +1779,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
opt_temporary all_or_any opt_distinct opt_glimit_clause
opt_ignore_leaves fulltext_options union_option
opt_not
- select_derived_init transaction_access_mode_types
+ transaction_access_mode_types
opt_natural_language_mode opt_query_expansion
opt_ev_status opt_ev_on_completion ev_on_completion opt_ev_comment
ev_alter_on_schedule_completion opt_ev_rename_to opt_ev_sql_stmt
@@ -1966,11 +1899,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
join_table_list join_table
table_factor table_ref esc_table_ref
table_primary_ident table_primary_derived
- select_derived derived_table_list
- select_derived_union
- derived_simple_table
- derived_query_specification
- derived_table_value_constructor
+ derived_table_list table_reference_list_parens
+ nested_table_reference_list join_table_parens
%type <date_time_type> date_time_type;
%type <interval> interval
@@ -2004,14 +1934,19 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
UNDERSCORE_CHARSET
%type <select_lex> subselect
- get_select_lex get_select_lex_derived
- simple_table
query_specification
- query_term_union_not_ready
- query_term_union_ready
- query_expression_body
- select_paren_derived
table_value_constructor
+ simple_table
+ query_primary
+ query_primary_parens
+ select_into_query_specification
+
+
+%type <select_lex_unit>
+ query_specification_start
+ query_expression_body
+ query_expression
+ query_expression_unit
%type <boolfunc2creator> comp_op
@@ -2023,11 +1958,28 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
%type <virtual_column> opt_check_constraint check_constraint virtual_column_func
column_default_expr
-%type <unit_type> unit_type_decl
+
+%type <unit_operation> unit_type_decl
+
+%type <select_lock>
+ opt_procedure_or_into
+ opt_select_lock_type
+ select_lock_type
+ opt_lock_wait_timeout_new
+
+%type <select_limit> opt_limit_clause limit_clause limit_options
+
+%type <order_limit_lock>
+ query_expression_tail
+ order_or_limit
+ opt_order_limit_lock
+
+%type <select_order> opt_order_clause order_clause order_list
%type <NONE>
analyze_stmt_command
- query verb_clause create change select do drop insert replace insert2
+ query verb_clause create change select select_into
+ do drop insert replace insert2
insert_values update delete truncate rename compound_statement
show describe load alter optimize keycache preload flush
reset purge begin commit rollback savepoint release
@@ -2043,7 +1995,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
assign_to_keycache_parts
preload_list preload_list_or_parts preload_keys preload_keys_parts
select_item_list select_item values_list no_braces
- opt_limit_clause delete_limit_clause fields opt_values values
+ delete_limit_clause fields opt_values values
procedure_list procedure_list2 procedure_item
field_def handler opt_generated_always
opt_ignore opt_column opt_restrict
@@ -2063,9 +2015,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
table_to_table_list table_to_table opt_table_list opt_as
handler_rkey_function handler_read_or_scan
single_multi table_wild_list table_wild_one opt_wild
- union_clause union_list
- subselect_start opt_and charset
- subselect_end select_var_list select_var_list_init help
+ opt_and charset
+ select_var_list select_var_list_init help
opt_extended_describe shutdown
opt_format_json
prepare prepare_src execute deallocate
@@ -2193,8 +2144,8 @@ rule: <-- starts at col 1
query:
END_OF_INPUT
{
- if (likely(!thd->bootstrap) &&
- unlikely(!(thd->lex->select_lex.options & OPTION_FOUND_COMMENT)))
+ if (!thd->bootstrap &&
+ (!(thd->lex->lex_options & OPTION_LEX_FOUND_COMMENT)))
my_yyabort_error((ER_EMPTY_QUERY, MYF(0)));
thd->lex->sql_command= SQLCOM_EMPTY_QUERY;
@@ -2289,6 +2240,7 @@ statement:
| rollback
| savepoint
| select
+ | select_into
| set
| signal_stmt
| show
@@ -2324,6 +2276,8 @@ prepare:
if (unlikely(lex->table_or_sp_used()))
my_yyabort_error((ER_SUBQUERIES_NOT_SUPPORTED, MYF(0),
"PREPARE..FROM"));
+ if (Lex->check_main_unit_semantics())
+ MYSQL_YYABORT;
lex->sql_command= SQLCOM_PREPARE;
lex->prepared_stmt_name= $2;
}
@@ -2346,7 +2300,10 @@ execute:
lex->prepared_stmt_name= $2;
}
execute_using
- {}
+ {
+ if (Lex->check_main_unit_semantics())
+ MYSQL_YYABORT;
+ }
| EXECUTE_SYM IMMEDIATE_SYM prepare_src
{
if (unlikely(Lex->table_or_sp_used()))
@@ -2355,7 +2312,10 @@ execute:
Lex->sql_command= SQLCOM_EXECUTE_IMMEDIATE;
}
execute_using
- {}
+ {
+ if (Lex->check_main_unit_semantics())
+ MYSQL_YYABORT;
+ }
;
execute_using:
@@ -2642,17 +2602,22 @@ connection_name:
/* create a table */
create:
- create_or_replace opt_temporary TABLE_SYM opt_if_not_exists table_ident
+ create_or_replace opt_temporary TABLE_SYM opt_if_not_exists
{
LEX *lex= thd->lex;
lex->create_info.init();
- if (unlikely(lex->set_command_with_check(SQLCOM_CREATE_TABLE, $2,
- $1 | $4)))
+ if (lex->main_select_push())
+ MYSQL_YYABORT;
+ lex->current_select->parsing_place= BEFORE_OPT_LIST;
+ if (lex->set_command_with_check(SQLCOM_CREATE_TABLE, $2, $1 | $4))
MYSQL_YYABORT;
- if (unlikely(!lex->select_lex.add_table_to_list(thd, $5, NULL,
- TL_OPTION_UPDATING,
- TL_WRITE,
- MDL_EXCLUSIVE)))
+ }
+ table_ident
+ {
+ LEX *lex= thd->lex;
+ if (!lex->first_select_lex()->
+ add_table_to_list(thd, $6, NULL, TL_OPTION_UPDATING,
+ TL_WRITE, MDL_EXCLUSIVE))
MYSQL_YYABORT;
lex->alter_info.reset();
/*
@@ -2667,7 +2632,6 @@ create:
create_body
{
LEX *lex= thd->lex;
- lex->current_select= &lex->select_lex;
if ((lex->create_info.used_fields & HA_CREATE_USED_ENGINE) &&
!lex->create_info.db_type)
{
@@ -2676,22 +2640,24 @@ create:
ER_WARN_USING_OTHER_HANDLER,
ER_THD(thd, ER_WARN_USING_OTHER_HANDLER),
hton_name(lex->create_info.db_type)->str,
- $5->table.str);
+ $6->table.str);
}
create_table_set_open_action_and_adjust_tables(lex);
+ Lex->pop_select(); //main select
}
| create_or_replace opt_temporary SEQUENCE_SYM opt_if_not_exists table_ident
{
LEX *lex= thd->lex;
+ if (Lex->main_select_push())
+ MYSQL_YYABORT;
lex->create_info.init();
if (unlikely(lex->set_command_with_check(SQLCOM_CREATE_SEQUENCE, $2,
$1 | $4)))
MYSQL_YYABORT;
- if (unlikely(!lex->select_lex.add_table_to_list(thd, $5, NULL,
- TL_OPTION_UPDATING,
- TL_WRITE,
- MDL_EXCLUSIVE)))
+ if (!lex->first_select_lex()->
+ add_table_to_list(thd, $5, NULL, TL_OPTION_UPDATING,
+ TL_WRITE, MDL_EXCLUSIVE))
MYSQL_YYABORT;
/*
@@ -2714,8 +2680,9 @@ create:
if (unlikely(lex->create_info.seq_create_info->check_and_adjust(1)))
{
my_error(ER_SEQUENCE_INVALID_DATA, MYF(0),
- lex->select_lex.table_list.first->db.str,
- lex->select_lex.table_list.first->table_name.str);
+ lex->first_select_lex()->table_list.first->db.str,
+ lex->first_select_lex()->table_list.first->
+ table_name.str);
MYSQL_YYABORT;
}
@@ -2728,10 +2695,8 @@ create:
Lex->create_info.used_fields|= HA_CREATE_USED_SEQUENCE;
Lex->create_info.sequence= 1;
- lex->current_select= &lex->select_lex;
- if (unlikely((lex->create_info.used_fields &
- HA_CREATE_USED_ENGINE) &&
- !lex->create_info.db_type))
+ if ((lex->create_info.used_fields & HA_CREATE_USED_ENGINE) &&
+ !lex->create_info.db_type)
{
lex->create_info.use_default_db_type(thd);
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
@@ -2741,44 +2706,69 @@ create:
$5->table.str);
}
create_table_set_open_action_and_adjust_tables(lex);
+ Lex->pop_select(); //main select
+ }
+ | create_or_replace opt_unique INDEX_SYM opt_if_not_exists
+ {
+ if (Lex->main_select_push())
+ MYSQL_YYABORT;
}
- | create_or_replace opt_unique INDEX_SYM opt_if_not_exists ident
+ ident
opt_key_algorithm_clause
ON table_ident
{
- if (unlikely(Lex->add_create_index_prepare($8)))
+ if (Lex->add_create_index_prepare($9))
MYSQL_YYABORT;
- if (unlikely(Lex->add_create_index($2, &$5, $6, $1 | $4)))
+ if (Lex->add_create_index($2, &$6, $7, $1 | $4))
MYSQL_YYABORT;
}
'(' key_list ')' opt_lock_wait_timeout normal_key_options
- opt_index_lock_algorithm { }
- | create_or_replace fulltext INDEX_SYM opt_if_not_exists ident
+ opt_index_lock_algorithm
+ {
+ Lex->pop_select(); //main select
+ }
+ | create_or_replace fulltext INDEX_SYM
+ {
+ if (Lex->main_select_push())
+ MYSQL_YYABORT;
+ }
+ opt_if_not_exists ident
ON table_ident
{
- if (unlikely(Lex->add_create_index_prepare($7)))
+ if (Lex->add_create_index_prepare($8))
MYSQL_YYABORT;
- if (unlikely(Lex->add_create_index($2, &$5, HA_KEY_ALG_UNDEF,
- $1 | $4)))
+ if (Lex->add_create_index($2, &$6, HA_KEY_ALG_UNDEF, $1 | $5))
MYSQL_YYABORT;
}
'(' key_list ')' opt_lock_wait_timeout fulltext_key_options
- opt_index_lock_algorithm { }
- | create_or_replace spatial INDEX_SYM opt_if_not_exists ident
+ opt_index_lock_algorithm
+ {
+ Lex->pop_select(); //main select
+ }
+ | create_or_replace spatial INDEX_SYM
+ {
+ if (Lex->main_select_push())
+ MYSQL_YYABORT;
+ }
+ opt_if_not_exists ident
ON table_ident
{
- if (unlikely(Lex->add_create_index_prepare($7)))
+ if (Lex->add_create_index_prepare($8))
MYSQL_YYABORT;
- if (unlikely(Lex->add_create_index($2, &$5, HA_KEY_ALG_UNDEF,
- $1 | $4)))
+ if (Lex->add_create_index($2, &$6, HA_KEY_ALG_UNDEF, $1 | $5))
MYSQL_YYABORT;
}
'(' key_list ')' opt_lock_wait_timeout spatial_key_options
- opt_index_lock_algorithm { }
+ opt_index_lock_algorithm
+ {
+ Lex->pop_select(); //main select
+ }
| create_or_replace DATABASE opt_if_not_exists ident
{
Lex->create_info.default_table_charset= NULL;
Lex->create_info.used_fields= 0;
+ if (Lex->main_select_push())
+ MYSQL_YYABORT;
}
opt_create_database_options
{
@@ -2787,59 +2777,103 @@ create:
$1 | $3)))
MYSQL_YYABORT;
lex->name= $4;
+ Lex->pop_select(); //main select
}
| create_or_replace definer_opt opt_view_suid VIEW_SYM
opt_if_not_exists table_ident
{
- if (unlikely(Lex->add_create_view(thd, $1 | $5,
- DTYPE_ALGORITHM_UNDEFINED, $3,
- $6)))
+ if (Lex->main_select_push())
+ MYSQL_YYABORT;
+ if (Lex->add_create_view(thd, $1 | $5,
+ DTYPE_ALGORITHM_UNDEFINED, $3, $6))
MYSQL_YYABORT;
}
view_list_opt AS view_select
- { }
+ {
+ Lex->pop_select(); //main select
+ }
| create_or_replace view_algorithm definer_opt opt_view_suid VIEW_SYM
opt_if_not_exists table_ident
{
if (unlikely(Lex->add_create_view(thd, $1 | $6, $2, $4, $7)))
MYSQL_YYABORT;
+ if (Lex->main_select_push())
+ MYSQL_YYABORT;
}
view_list_opt AS view_select
- { }
+ {
+ Lex->pop_select(); //main select
+ }
| create_or_replace definer_opt TRIGGER_SYM
- { Lex->create_info.set($1); }
+ {
+ if (Lex->main_select_push())
+ MYSQL_YYABORT;
+ Lex->create_info.set($1);
+ }
trigger_tail
- { }
+ {
+ Lex->pop_select(); //main select
+ }
| create_or_replace definer_opt PROCEDURE_SYM
- { Lex->create_info.set($1); }
+ {
+ if (Lex->main_select_push())
+ MYSQL_YYABORT;
+ Lex->create_info.set($1);
+ }
sp_tail
- { }
+ {
+ Lex->pop_select(); //main select
+ }
| create_or_replace definer_opt EVENT_SYM
- { Lex->create_info.set($1); }
+ {
+ if (Lex->main_select_push())
+ MYSQL_YYABORT;
+ Lex->create_info.set($1);
+ }
event_tail
- { }
+ {
+ Lex->pop_select(); //main select
+ }
| create_or_replace definer FUNCTION_SYM
{
+ if (Lex->main_select_push())
+ MYSQL_YYABORT;
Lex->create_info.set($1);
}
- sf_tail_not_aggregate
- { }
+ sf_tail
+ {
+ Lex->pop_select(); //main select
+ }
| create_or_replace definer AGGREGATE_SYM FUNCTION_SYM
{
+ if (Lex->main_select_push())
+ MYSQL_YYABORT;
Lex->create_info.set($1);
}
sf_tail_aggregate
- { }
+ {
+ Lex->pop_select(); //main select
+ }
| create_or_replace no_definer FUNCTION_SYM
- { Lex->create_info.set($1); }
+ {
+ if (Lex->main_select_push())
+ MYSQL_YYABORT;
+ Lex->create_info.set($1);
+ }
create_function_tail
- { }
+ {
+ Lex->pop_select(); //main select
+ }
| create_or_replace no_definer AGGREGATE_SYM FUNCTION_SYM
{
+ if (Lex->main_select_push())
+ MYSQL_YYABORT;
Lex->create_info.set($1);
}
create_aggregate_function_tail
- { }
+ {
+ Lex->pop_select(); //main select
+ }
| create_or_replace USER_SYM opt_if_not_exists clear_privileges grant_list
opt_require_clause opt_resource_options
{
@@ -3242,7 +3276,7 @@ clear_privileges:
lex->columns.empty();
lex->grant= lex->grant_tot_col= 0;
lex->all_privileges= 0;
- lex->select_lex.db= null_clex_str;
+ lex->first_select_lex()->db= null_clex_str;
lex->ssl_type= SSL_TYPE_NOT_SPECIFIED;
lex->ssl_cipher= lex->x509_subject= lex->x509_issuer= 0;
bzero((char *)&(lex->mqh),sizeof(lex->mqh));
@@ -3741,7 +3775,7 @@ sp_hcond:
signal_stmt:
SIGNAL_SYM signal_value opt_set_signal_information
{
- if (unlikely(Lex->add_signal_statement(thd, $2)))
+ if (Lex->add_signal_statement(thd, $2))
MYSQL_YYABORT;
}
;
@@ -4201,7 +4235,7 @@ assignment_source_expr:
$$->sp_lex_in_use= true;
$$->set_item_and_free_list($3, thd->free_list);
thd->free_list= NULL;
- if (unlikely($$->sphead->restore_lex(thd)))
+ if ($$->sphead->restore_lex(thd))
MYSQL_YYABORT;
}
;
@@ -4210,6 +4244,7 @@ for_loop_bound_expr:
assignment_source_lex
{
Lex->sphead->reset_lex(thd, $1);
+ Lex->current_select->parsing_place= FOR_LOOP_BOUND;
}
expr
{
@@ -4219,6 +4254,7 @@ for_loop_bound_expr:
$$->set_item_and_free_list($3, NULL);
if (unlikely($$->sphead->restore_lex(thd)))
MYSQL_YYABORT;
+ Lex->current_select->parsing_place= NO_MATTER;
}
;
@@ -4452,7 +4488,8 @@ case_stmt_body:
{
if (unlikely(Lex->case_stmt_action_expr($2)))
MYSQL_YYABORT;
- if (unlikely(Lex->sphead->restore_lex(thd)))
+
+ if (Lex->sphead->restore_lex(thd))
MYSQL_YYABORT;
}
simple_when_clause_list
@@ -4654,7 +4691,7 @@ while_body:
LEX *lex= Lex;
if (unlikely(lex->sp_while_loop_expression(thd, $1)))
MYSQL_YYABORT;
- if (unlikely(lex->sphead->restore_lex(thd)))
+ if (lex->sphead->restore_lex(thd))
MYSQL_YYABORT;
}
sp_proc_stmts1 END WHILE_SYM
@@ -4677,7 +4714,7 @@ repeat_body:
if (unlikely(i == NULL) ||
unlikely(lex->sphead->add_instr(i)))
MYSQL_YYABORT;
- if (unlikely(lex->sphead->restore_lex(thd)))
+ if (lex->sphead->restore_lex(thd))
MYSQL_YYABORT;
/* We can shortcut the cont_backpatch here */
i->m_cont_dest= ip+1;
@@ -5157,26 +5194,16 @@ size_number:
*/
create_body:
- '(' create_field_list ')'
+ create_field_list_parens
{ Lex->create_info.option_list= NULL; }
opt_create_table_options opt_create_partitioning opt_create_select {}
| opt_create_table_options opt_create_partitioning opt_create_select {}
- /*
- the following rule is redundant, but there's a shift/reduce
- conflict that prevents the rule above from parsing a syntax like
- CREATE TABLE t1 (SELECT 1);
- */
- | '(' create_select_query_specification ')'
- | '(' create_select_query_specification ')'
- { Select->set_braces(1);} union_list {}
- | '(' create_select_query_specification ')'
- { Select->set_braces(1);} union_order_or_limit {}
| create_like
{
Lex->create_info.add(DDL_options_st::OPT_LIKE);
- TABLE_LIST *src_table= Lex->select_lex.add_table_to_list(thd,
- $1, NULL, 0, TL_READ, MDL_SHARED_READ);
+ TABLE_LIST *src_table= Lex->first_select_lex()->
+ add_table_to_list(thd, $1, NULL, 0, TL_READ, MDL_SHARED_READ);
if (unlikely(! src_table))
MYSQL_YYABORT;
/* CREATE TABLE ... LIKE is not allowed for views. */
@@ -5186,7 +5213,7 @@ create_body:
create_like:
LIKE table_ident { $$= $2; }
- | '(' LIKE table_ident ')' { $$= $3; }
+ | LEFT_PAREN_LIKE LIKE table_ident ')' { $$= $3; }
;
opt_create_select:
@@ -5195,23 +5222,19 @@ opt_create_select:
;
create_select_query_expression:
- opt_with_clause SELECT_SYM create_select_part2 opt_table_expression
- create_select_part4
- {
- Select->set_braces(0);
- Select->set_with_clause($1);
+ query_expression
+ {
+ if (Lex->parsed_insert_select($1->first_select()))
+ MYSQL_YYABORT;
}
- union_clause
- | opt_with_clause SELECT_SYM create_select_part2
- create_select_part3_union_not_ready create_select_part4
+ | LEFT_PAREN_WITH with_clause query_expression_body ')'
{
- Select->set_with_clause($1);
+ SELECT_LEX *first_select= $3->first_select();
+ $3->set_with_clause($2);
+ $2->attach_to(first_select);
+ if (Lex->parsed_insert_select(first_select))
+ MYSQL_YYABORT;
}
- | '(' create_select_query_specification ')'
- | '(' create_select_query_specification ')'
- { Select->set_braces(1);} union_list {}
- | '(' create_select_query_specification ')'
- { Select->set_braces(1);} union_order_or_limit {}
;
opt_create_partitioning:
@@ -5294,13 +5317,17 @@ partition_entry:
thd->parse_error(ER_PARTITION_ENTRY_ERROR);
MYSQL_YYABORT;
}
- DBUG_ASSERT(Lex->part_info->table);
+ if (Lex->main_select_push())
+ MYSQL_YYABORT;
/*
We enter here when opening the frm file to translate
partition info string into part_info data structure.
*/
}
- partition {}
+ partition
+ {
+ Lex->pop_select(); //main select
+ }
;
partition:
@@ -5954,56 +5981,6 @@ opt_versioning_interval_start:
End of partition parser part
*/
-create_select_query_specification:
- opt_with_clause SELECT_SYM create_select_part2 create_select_part3
- create_select_part4
- {
- Select->set_with_clause($1);
- }
- ;
-
-create_select_part2:
- {
- LEX *lex=Lex;
- if (lex->sql_command == SQLCOM_INSERT)
- lex->sql_command= SQLCOM_INSERT_SELECT;
- else if (lex->sql_command == SQLCOM_REPLACE)
- lex->sql_command= SQLCOM_REPLACE_SELECT;
- /*
- The following work only with the local list, the global list
- is created correctly in this case
- */
- lex->current_select->table_list.save_and_clear(&lex->save_list);
- mysql_init_select(lex);
- lex->current_select->parsing_place= SELECT_LIST;
- }
- select_options select_item_list
- {
- Select->parsing_place= NO_MATTER;
- }
- ;
-
-create_select_part3:
- opt_table_expression
- | create_select_part3_union_not_ready
- ;
-
-create_select_part3_union_not_ready:
- table_expression order_or_limit
- | order_or_limit
- ;
-
-create_select_part4:
- opt_select_lock_type
- {
- /*
- The following work only with the local list, the global list
- is created correctly in this case
- */
- Lex->current_select->table_list.push_front(&Lex->save_list);
- }
- ;
-
opt_as:
/* empty */ {}
| AS {}
@@ -6221,7 +6198,7 @@ create_table_option:
}
| UNION_SYM opt_equal
{
- Lex->select_lex.table_list.save_and_clear(&Lex->save_list);
+ Lex->first_select_lex()->table_list.save_and_clear(&Lex->save_list);
}
'(' opt_table_list ')'
{
@@ -6230,8 +6207,8 @@ create_table_option:
from the global list.
*/
LEX *lex=Lex;
- lex->create_info.merge_list= lex->select_lex.table_list;
- lex->select_lex.table_list= lex->save_list;
+ lex->create_info.merge_list= lex->first_select_lex()->table_list;
+ lex->first_select_lex()->table_list= lex->save_list;
/*
When excluding union list from the global list we assume that
elements of the former immediately follow elements which represent
@@ -6432,6 +6409,13 @@ create_field_list:
}
;
+create_field_list_parens:
+ LEFT_PAREN_ALT field_list ')'
+ {
+ Lex->create_last_non_select_table= Lex->last_table();
+ }
+ ;
+
field_list:
field_list_item
| field_list ',' field_list_item
@@ -6726,6 +6710,8 @@ parse_vcol_expr:
Prevent the end user from invoking this command.
*/
MYSQL_YYABORT_UNLESS(Lex->parse_vcol_expr);
+ if (Lex->main_select_push())
+ MYSQL_YYABORT;
}
expr
{
@@ -6733,14 +6719,15 @@ parse_vcol_expr:
if (unlikely(!v))
MYSQL_YYABORT;
Lex->last_field->vcol_info= v;
+ Lex->pop_select(); //main select
}
;
parenthesized_expr:
- subselect
+ remember_tok_start
+ query_expression
{
- $$= new (thd->mem_root) Item_singlerow_subselect(thd, $1);
- if (unlikely($$ == NULL))
+ if (!($$= Lex->create_item_query_expression(thd, $1, $2)))
MYSQL_YYABORT;
}
| expr
@@ -7657,23 +7644,25 @@ alter:
Lex->name= null_clex_str;
Lex->table_type= TABLE_TYPE_UNKNOWN;
Lex->sql_command= SQLCOM_ALTER_TABLE;
- Lex->duplicates= DUP_ERROR;
- Lex->select_lex.init_order();
+ Lex->duplicates= DUP_ERROR;
+ Lex->first_select_lex()->order_list.empty();
Lex->create_info.init();
Lex->create_info.row_type= ROW_TYPE_NOT_USED;
Lex->alter_info.reset();
Lex->no_write_to_binlog= 0;
Lex->create_info.storage_media= HA_SM_DEFAULT;
+ if (Lex->main_select_push())
+ MYSQL_YYABORT;
DBUG_ASSERT(!Lex->m_sql_cmd);
}
alter_options TABLE_SYM table_ident opt_lock_wait_timeout
{
- if (unlikely(!Lex->select_lex.add_table_to_list(thd, $5, NULL,
- TL_OPTION_UPDATING,
- TL_READ_NO_INSERT,
- MDL_SHARED_UPGRADABLE)))
+ if (!Lex->first_select_lex()->
+ add_table_to_list(thd, $5, NULL, TL_OPTION_UPDATING,
+ TL_READ_NO_INSERT, MDL_SHARED_UPGRADABLE))
MYSQL_YYABORT;
- Lex->select_lex.db= (Lex->select_lex.table_list.first)->db;
+ Lex->first_select_lex()->db=
+ (Lex->first_select_lex()->table_list.first)->db;
Lex->create_last_non_select_table= Lex->last_table();
}
alter_commands
@@ -7685,11 +7674,14 @@ alter:
if (unlikely(Lex->m_sql_cmd == NULL))
MYSQL_YYABORT;
}
+ Lex->pop_select(); //main select
}
| ALTER DATABASE ident_or_empty
{
Lex->create_info.default_table_charset= NULL;
Lex->create_info.used_fields= 0;
+ if (Lex->main_select_push())
+ MYSQL_YYABORT;
}
create_database_options
{
@@ -7699,6 +7691,7 @@ alter:
if (lex->name.str == NULL &&
unlikely(lex->copy_db_to(&lex->name)))
MYSQL_YYABORT;
+ Lex->pop_select(); //main select
}
| ALTER DATABASE ident UPGRADE_SYM DATA_SYM DIRECTORY_SYM NAME_SYM
{
@@ -7714,6 +7707,8 @@ alter:
if (unlikely(lex->sphead))
my_yyabort_error((ER_SP_NO_DROP_SP, MYF(0), "PROCEDURE"));
+ if (Lex->main_select_push())
+ MYSQL_YYABORT;
lex->sp_chistics.init();
}
sp_a_chistics
@@ -7722,6 +7717,9 @@ alter:
lex->sql_command= SQLCOM_ALTER_PROCEDURE;
lex->spname= $3;
+ Lex->pop_select(); //main select
+ if (Lex->check_main_unit_semantics())
+ MYSQL_YYABORT;
}
| ALTER FUNCTION_SYM sp_name
{
@@ -7729,6 +7727,8 @@ alter:
if (unlikely(lex->sphead))
my_yyabort_error((ER_SP_NO_DROP_SP, MYF(0), "FUNCTION"));
+ if (Lex->main_select_push())
+ MYSQL_YYABORT;
lex->sp_chistics.init();
}
sp_a_chistics
@@ -7737,14 +7737,23 @@ alter:
lex->sql_command= SQLCOM_ALTER_FUNCTION;
lex->spname= $3;
+ Lex->pop_select(); //main select
+ if (Lex->check_main_unit_semantics())
+ MYSQL_YYABORT;
}
| ALTER view_algorithm definer_opt opt_view_suid VIEW_SYM table_ident
{
- if (unlikely(Lex->add_alter_view(thd, $2, $4, $6)))
+ if (Lex->main_select_push())
+ MYSQL_YYABORT;
+ if (Lex->add_alter_view(thd, $2, $4, $6))
MYSQL_YYABORT;
}
view_list_opt AS view_select
- {}
+ {
+ Lex->pop_select(); //main select
+ if (Lex->check_main_unit_semantics())
+ MYSQL_YYABORT;
+ }
| ALTER definer_opt opt_view_suid VIEW_SYM table_ident
/*
We have two separate rules for ALTER VIEW rather that
@@ -7752,14 +7761,22 @@ alter:
with the ALTER EVENT below.
*/
{
- if (unlikely(Lex->add_alter_view(thd, VIEW_ALGORITHM_INHERIT, $3, $5)))
+ if (Lex->main_select_push())
+ MYSQL_YYABORT;
+ if (Lex->add_alter_view(thd, VIEW_ALGORITHM_INHERIT, $3, $5))
MYSQL_YYABORT;
}
view_list_opt AS view_select
- {}
+ {
+ Lex->pop_select(); //main select
+ if (Lex->check_main_unit_semantics())
+ MYSQL_YYABORT;
+ }
| ALTER definer_opt remember_name EVENT_SYM sp_name
{
- /*
+ if (Lex->main_select_push())
+ MYSQL_YYABORT;
+ /*
It is safe to use Lex->spname because
ALTER EVENT xxx RENATE TO yyy DO ALTER EVENT RENAME TO
is not allowed. Lex->spname is used in the case of RENAME TO
@@ -7791,6 +7808,8 @@ alter:
*/
Lex->sql_command= SQLCOM_ALTER_EVENT;
Lex->stmt_definition_end= (char*)YYLIP->get_cpp_ptr();
+
+ Lex->pop_select(); //main select
}
| ALTER TABLESPACE alter_tablespace_info
{
@@ -7834,16 +7853,17 @@ alter:
lex->create_info.init();
lex->no_write_to_binlog= 0;
DBUG_ASSERT(!lex->m_sql_cmd);
+ if (Lex->main_select_push())
+ MYSQL_YYABORT;
}
table_ident
{
LEX *lex= Lex;
- if (unlikely(!(lex->create_info.seq_create_info=
- new (thd->mem_root) sequence_definition())) ||
- unlikely(!lex->select_lex.add_table_to_list(thd, $5, NULL,
- TL_OPTION_SEQUENCE,
- TL_WRITE,
- MDL_EXCLUSIVE)))
+ if (!(lex->create_info.seq_create_info= new (thd->mem_root)
+ sequence_definition()) ||
+ !lex->first_select_lex()->
+ add_table_to_list(thd, $5, NULL, TL_OPTION_SEQUENCE,
+ TL_WRITE, MDL_EXCLUSIVE))
MYSQL_YYABORT;
}
sequence_defs
@@ -7852,6 +7872,9 @@ alter:
Lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_alter_sequence($3);
if (unlikely(Lex->m_sql_cmd == NULL))
MYSQL_YYABORT;
+ Lex->pop_select(); //main select
+ if (Lex->check_main_unit_semantics())
+ MYSQL_YYABORT;
}
;
@@ -8001,16 +8024,17 @@ alter_commands:
WITH TABLE_SYM table_ident have_partitioning
{
LEX *lex= thd->lex;
- lex->select_lex.db= $6->db;
- if (lex->select_lex.db.str == NULL &&
- unlikely(lex->copy_db_to(&lex->select_lex.db)))
+ lex->first_select_lex()->db=$6->db;
+ if (lex->first_select_lex()->db.str == NULL &&
+ lex->copy_db_to(&lex->first_select_lex()->db))
+ {
MYSQL_YYABORT;
+ }
lex->name= $6->table;
lex->alter_info.partition_flags|= ALTER_PARTITION_EXCHANGE;
- if (unlikely(!lex->select_lex.add_table_to_list(thd, $6, NULL,
- TL_OPTION_UPDATING,
- TL_READ_NO_INSERT,
- MDL_SHARED_NO_WRITE)))
+ if (!lex->first_select_lex()->
+ add_table_to_list(thd, $6, NULL, TL_OPTION_UPDATING,
+ TL_READ_NO_INSERT, MDL_SHARED_NO_WRITE))
MYSQL_YYABORT;
DBUG_ASSERT(!lex->m_sql_cmd);
lex->m_sql_cmd= new (thd->mem_root)
@@ -8249,9 +8273,9 @@ alter_list_item:
| RENAME opt_to table_ident
{
LEX *lex=Lex;
- lex->select_lex.db= $3->db;
- if (lex->select_lex.db.str == NULL &&
- unlikely(lex->copy_db_to(&lex->select_lex.db)))
+ lex->first_select_lex()->db= $3->db;
+ if (lex->first_select_lex()->db.str == NULL &&
+ lex->copy_db_to(&lex->first_select_lex()->db))
MYSQL_YYABORT;
if (unlikely(check_table_name($3->table.str,$3->table.length,
FALSE)) ||
@@ -8946,8 +8970,8 @@ adm_partition:
cache_keys_spec:
{
- Lex->select_lex.alloc_index_hints(thd);
- Select->set_index_hint_type(INDEX_HINT_USE,
+ Lex->first_select_lex()->alloc_index_hints(thd);
+ Select->set_index_hint_type(INDEX_HINT_USE,
INDEX_HINT_MASK_ALL);
}
cache_key_list_or_empty
@@ -8968,217 +8992,218 @@ opt_ignore_leaves:
Select : retrieve data from table
*/
-
select:
- opt_with_clause select_init
- {
- LEX *lex= Lex;
- lex->sql_command= SQLCOM_SELECT;
- lex->current_select->set_with_clause($1);
- }
- ;
-
-select_init:
- SELECT_SYM select_options_and_item_list select_init3
- | table_value_constructor
- | table_value_constructor union_list
- | table_value_constructor union_order_or_limit
- | '(' select_paren ')'
- | '(' select_paren ')' union_list
- | '(' select_paren ')' union_order_or_limit
- ;
-
-union_list_part2:
- SELECT_SYM select_options_and_item_list select_init3_union_query_term
- | table_value_constructor
- | table_value_constructor union_list
- | table_value_constructor union_order_or_limit
- | '(' select_paren_union_query_term ')'
- | '(' select_paren_union_query_term ')' union_list
- | '(' select_paren_union_query_term ')' union_order_or_limit
- ;
-
-select_paren:
+ query_expression_body
{
- Lex->current_select->set_braces(true);
+ if (Lex->push_select($1->fake_select_lex ?
+ $1->fake_select_lex :
+ $1->first_select()))
+ MYSQL_YYABORT;
}
- table_value_constructor
+ opt_procedure_or_into
{
- DBUG_ASSERT(Lex->current_select->braces);
+ Lex->pop_select();
+ if ($1->set_lock_to_the_last_select($3))
+ MYSQL_YYABORT;
+ if (Lex->select_finalize($1))
+ MYSQL_YYABORT;
}
- |
+ | with_clause query_expression_body
{
- /*
- In order to correctly parse UNION's global ORDER BY we need to
- set braces before parsing the clause.
- */
- Lex->current_select->set_braces(true);
+ if (Lex->push_select($2->fake_select_lex ?
+ $2->fake_select_lex :
+ $2->first_select()))
+ MYSQL_YYABORT;
}
- SELECT_SYM select_options_and_item_list select_part3
- opt_select_lock_type
+ opt_procedure_or_into
{
- DBUG_ASSERT(Lex->current_select->braces);
+ Lex->pop_select();
+ $2->set_with_clause($1);
+ $1->attach_to($2->first_select());
+ if ($2->set_lock_to_the_last_select($4))
+ MYSQL_YYABORT;
+ if (Lex->select_finalize($2))
+ MYSQL_YYABORT;
}
- | '(' select_paren ')'
;
-select_paren_union_query_term:
+
+select_into:
+ select_into_query_specification
{
- /*
- In order to correctly parse UNION's global ORDER BY we need to
- set braces before parsing the clause.
- */
- Lex->current_select->set_braces(true);
+ if (Lex->push_select($1))
+ MYSQL_YYABORT;
}
- SELECT_SYM select_options_and_item_list select_part3_union_query_term
- opt_select_lock_type
+ opt_order_limit_lock
{
- DBUG_ASSERT(Lex->current_select->braces);
- }
- | '(' select_paren_union_query_term ')'
+ st_select_lex_unit *unit;
+ if (!(unit= Lex->parsed_body_select($1, $3)))
+ MYSQL_YYABORT;
+ if (Lex->select_finalize(unit))
+ MYSQL_YYABORT;
+ }
+ ;
+
+
+simple_table:
+ query_specification { $$= $1; }
+ | table_value_constructor { $$= $1; }
;
-select_paren_view:
+table_value_constructor:
+ VALUES
+ {
+ if (Lex->parsed_TVC_start())
+ MYSQL_YYABORT;
+ }
+ values_list
+ {
+ if (!($$= Lex->parsed_TVC_end()))
+ MYSQL_YYABORT;
+ }
+ ;
+
+query_specification_start:
+ SELECT_SYM
{
- /*
- In order to correctly parse UNION's global ORDER BY we need to
- set braces before parsing the clause.
- */
- Lex->current_select->set_braces(true);
+ SELECT_LEX *sel;
+ LEX *lex= Lex;
+ if (!(sel= lex->alloc_select(TRUE)) ||
+ lex->push_select(sel))
+ MYSQL_YYABORT;
+ sel->init_select();
+ sel->braces= FALSE;
}
- SELECT_SYM select_options_and_item_list select_part3_view
- opt_select_lock_type
+ select_options
{
- DBUG_ASSERT(Lex->current_select->braces);
+ Select->parsing_place= SELECT_LIST;
}
- | '(' select_paren_view ')'
- ;
+ select_item_list
+ {
+ Select->parsing_place= NO_MATTER;
+ }
+ ;
-/* The equivalent of select_paren for nested queries. */
-select_paren_derived:
+query_specification:
+ query_specification_start
+ opt_from_clause
+ opt_where_clause
+ opt_group_clause
+ opt_having_clause
+ opt_window_clause
{
- Lex->current_select->set_braces(true);
+ $$= Lex->pop_select();
}
- table_value_constructor
+ ;
+
+select_into_query_specification:
+ query_specification_start
+ into
+ opt_from_clause
+ opt_where_clause
+ opt_group_clause
+ opt_having_clause
+ opt_window_clause
{
- DBUG_ASSERT(Lex->current_select->braces);
- $$= Lex->current_select->master_unit()->first_select();
+ $$= Lex->pop_select();
}
- |
+ ;
+
+opt_from_clause:
+ /* Empty */
+ | from_clause
+ ;
+
+
+query_primary:
+ simple_table
+ { $$= $1; }
+ | query_primary_parens
+ { $$= $1; }
+ ;
+
+query_primary_parens:
+ '(' query_expression_unit
{
- Lex->current_select->set_braces(true);
+ if (Lex->parsed_unit_in_brackets($2))
+ MYSQL_YYABORT;
}
- SELECT_SYM select_part2_derived
- opt_table_expression
- opt_order_clause
- opt_limit_clause
- opt_select_lock_type
+ query_expression_tail ')'
{
- DBUG_ASSERT(Lex->current_select->braces);
- $$= Lex->current_select->master_unit()->first_select();
+ $$= Lex->parsed_unit_in_brackets_tail($2, $4);
}
- | '(' select_paren_derived ')' { $$= $2; }
- ;
-
-select_init3:
- opt_table_expression
- opt_select_lock_type
+ | '(' query_primary
{
- /* Parentheses carry no meaning here */
- Lex->current_select->set_braces(false);
+ Lex->push_select($2);
}
- union_clause
- | select_part3_union_not_ready
- opt_select_lock_type
+ query_expression_tail ')'
{
- /* Parentheses carry no meaning here */
- Lex->current_select->set_braces(false);
+ if (!($$= Lex->parsed_select_in_brackets($2, $4)))
+ YYABORT;
}
;
-
-select_init3_union_query_term:
- opt_table_expression
- opt_select_lock_type
+query_expression_unit:
+ query_primary
+ unit_type_decl
+ query_primary
{
- /* Parentheses carry no meaning here */
- Lex->current_select->set_braces(false);
+ if (!($$= Lex->parsed_select_expr_start($1, $3, $2.unit_type,
+ $2.distinct)))
+ YYABORT;
}
- union_clause
- | select_part3_union_not_ready_noproc
- opt_select_lock_type
+ | query_expression_unit
+ unit_type_decl
+ query_primary
{
- /* Parentheses carry no meaning here */
- Lex->current_select->set_braces(false);
+ if (!($$= Lex->parsed_select_expr_cont($1, $3, $2.unit_type,
+ $2.distinct, FALSE)))
+ YYABORT;
}
;
-
-select_init3_view:
- opt_table_expression opt_select_lock_type
+query_expression_body:
+ query_primary
{
- Lex->current_select->set_braces(false);
+ Lex->push_select($1);
}
- | opt_table_expression opt_select_lock_type
+ query_expression_tail
{
- Lex->current_select->set_braces(false);
+ if (!($$= Lex->parsed_body_select($1, $3)))
+ MYSQL_YYABORT;
}
- union_list_view
- | order_or_limit opt_select_lock_type
+ | query_expression_unit
{
- Lex->current_select->set_braces(false);
+ if (Lex->parsed_body_unit($1))
+ MYSQL_YYABORT;
}
- | table_expression order_or_limit opt_select_lock_type
+ query_expression_tail
{
- Lex->current_select->set_braces(false);
+ if (!($$= Lex->parsed_body_unit_tail($1, $3)))
+ MYSQL_YYABORT;
}
;
-/*
- The SELECT parts after select_item_list that cannot be followed by UNION.
-*/
-
-select_part3:
- opt_table_expression
- | select_part3_union_not_ready
- ;
-
-select_part3_union_query_term:
- opt_table_expression
- | select_part3_union_not_ready_noproc
- ;
-
-select_part3_view:
- opt_table_expression
- | order_or_limit
- | table_expression order_or_limit
- ;
-
-select_part3_union_not_ready:
- select_part3_union_not_ready_noproc
- | table_expression procedure_clause
- | table_expression order_or_limit procedure_clause
+query_expression:
+ opt_with_clause
+ query_expression_body
+ {
+ if ($1)
+ {
+ $2->set_with_clause($1);
+ $1->attach_to($2->first_select());
+ }
+ $$= $2;
+ }
;
-select_part3_union_not_ready_noproc:
- order_or_limit
- | into opt_table_expression opt_order_clause opt_limit_clause
- | table_expression into
- | table_expression order_or_limit
- | table_expression order_or_limit into
- ;
-select_options_and_item_list:
- {
- LEX *lex= Lex;
- SELECT_LEX *sel= lex->current_select;
- if (sel->linkage != UNION_TYPE)
- mysql_init_select(lex);
- lex->current_select->parsing_place= SELECT_LIST;
- }
- select_options select_item_list
+subselect:
+ remember_tok_start
+ query_expression
{
- Select->parsing_place= NO_MATTER;
+ if (!($$= Lex->parsed_subselect($2, $1)))
+ YYABORT;
}
;
@@ -9186,18 +9211,6 @@ select_options_and_item_list:
/**
<table expression>, as in the SQL standard.
*/
-table_expression:
- from_clause
- opt_where_clause
- opt_group_clause
- opt_having_clause
- opt_window_clause
- ;
-
-opt_table_expression:
- /* Empty */
- | table_expression
- ;
from_clause:
FROM table_reference_list
@@ -9300,59 +9313,68 @@ select_option:
query_expression_option
| SQL_NO_CACHE_SYM
{
- /*
- Allow this flag only on the first top-level SELECT statement, if
- SQL_CACHE wasn't specified, and only once per query.
- */
- if (unlikely(Lex->current_select != &Lex->select_lex))
- my_yyabort_error((ER_CANT_USE_OPTION_HERE, MYF(0), "SQL_NO_CACHE"));
- if (unlikely(Lex->select_lex.sql_cache == SELECT_LEX::SQL_CACHE))
- my_yyabort_error((ER_WRONG_USAGE, MYF(0), "SQL_CACHE", "SQL_NO_CACHE"));
- if (unlikely(Lex->select_lex.sql_cache == SELECT_LEX::SQL_NO_CACHE))
+ /*
+ Allow this flag once per query.
+ */
+ if (Select->options & OPTION_NO_QUERY_CACHE)
my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "SQL_NO_CACHE"));
-
- Lex->safe_to_cache_query=0;
- Lex->select_lex.options&= ~OPTION_TO_QUERY_CACHE;
- Lex->select_lex.sql_cache= SELECT_LEX::SQL_NO_CACHE;
+ Select->options|= OPTION_NO_QUERY_CACHE;
}
| SQL_CACHE_SYM
{
- /*
- Allow this flag only on the first top-level SELECT statement, if
- SQL_NO_CACHE wasn't specified, and only once per query.
- */
- if (unlikely(Lex->current_select != &Lex->select_lex))
- my_yyabort_error((ER_CANT_USE_OPTION_HERE, MYF(0), "SQL_CACHE"));
- if (unlikely(Lex->select_lex.sql_cache == SELECT_LEX::SQL_NO_CACHE))
- my_yyabort_error((ER_WRONG_USAGE, MYF(0), "SQL_NO_CACHE", "SQL_CACHE"));
- if (unlikely(Lex->select_lex.sql_cache == SELECT_LEX::SQL_CACHE))
+ /*
+ Allow this flag once per query.
+ */
+ if (Select->options & OPTION_TO_QUERY_CACHE)
my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "SQL_CACHE"));
-
- Lex->safe_to_cache_query=1;
- Lex->select_lex.options|= OPTION_TO_QUERY_CACHE;
- Lex->select_lex.sql_cache= SELECT_LEX::SQL_CACHE;
+ Select->options|= OPTION_TO_QUERY_CACHE;
}
;
-opt_select_lock_type:
- /* empty */
- | FOR_SYM UPDATE_SYM opt_lock_wait_timeout
+
+select_lock_type:
+ FOR_SYM UPDATE_SYM opt_lock_wait_timeout_new
{
- LEX *lex=Lex;
- lex->current_select->lock_type= TL_WRITE;
- lex->current_select->set_lock_for_tables(TL_WRITE);
- lex->safe_to_cache_query=0;
+ $$= $3;
+ $$.defined_lock= TRUE;
+ $$.update_lock= TRUE;
}
- | LOCK_SYM IN_SYM SHARE_SYM MODE_SYM opt_lock_wait_timeout
+ | LOCK_SYM IN_SYM SHARE_SYM MODE_SYM opt_lock_wait_timeout_new
{
- LEX *lex=Lex;
- lex->current_select->lock_type= TL_READ_WITH_SHARED_LOCKS;
- lex->current_select->
- set_lock_for_tables(TL_READ_WITH_SHARED_LOCKS);
- lex->safe_to_cache_query=0;
+ $$= $5;
+ $$.defined_lock= TRUE;
+ $$.update_lock= FALSE;
}
;
+opt_select_lock_type:
+ /* empty */
+ {
+ $$.empty();
+ }
+ | select_lock_type
+ {
+ $$= $1;
+ }
+ ;
+
+opt_lock_wait_timeout_new:
+ /* empty */
+ {
+ $$.empty();
+ }
+ | WAIT_SYM ulong_num
+ {
+ $$.defined_timeout= TRUE;
+ $$.timeout= $2;
+ }
+ | NOWAIT_SYM
+ {
+ $$.defined_timeout= TRUE;
+ $$.timeout= 0;
+ }
+ ;
+
select_item_list:
select_item_list ',' select_item
| select_item
@@ -10001,7 +10023,21 @@ column_default_non_parenthesized_expr:
| param_marker { $$= $1; }
| variable
| sum_expr
+ {
+ if (!Lex->select_stack_top)
+ {
+ my_error(ER_INVALID_GROUP_FUNC_USE, MYF(0));
+ MYSQL_YYABORT;
+ }
+ }
| window_func_expr
+ {
+ if (!Lex->select_stack_top)
+ {
+ my_error(ER_WRONG_PLACEMENT_OF_WINDOW_FUNCTION, MYF(0));
+ MYSQL_YYABORT;
+ }
+ }
| inverse_distribution_function
| ROW_SYM '(' expr ',' expr_list ')'
{
@@ -11594,10 +11630,15 @@ esc_table_ref:
/* Equivalent to <table reference list> in the SQL:2003 standard. */
/* Warning - may return NULL in case of incomplete SELECT */
derived_table_list:
- esc_table_ref { $$=$1; }
+ esc_table_ref
+ {
+ $$=$1;
+ Select->add_joined_table($1);
+ }
| derived_table_list ',' esc_table_ref
{
MYSQL_YYABORT_UNLESS($1 && ($$=$3));
+ Select->add_joined_table($3);
}
;
@@ -11616,11 +11657,18 @@ join_table:
left-associative joins.
*/
table_ref normal_join table_ref %prec TABLE_REF_PRIORITY
- { MYSQL_YYABORT_UNLESS($1 && ($$=$3)); $3->straight=$2; }
+ {
+ MYSQL_YYABORT_UNLESS($1 && ($$=$3));
+ Select->add_joined_table($1);
+ Select->add_joined_table($3);
+ $3->straight=$2;
+ }
| table_ref normal_join table_ref
ON
{
MYSQL_YYABORT_UNLESS($1 && $3);
+ Select->add_joined_table($1);
+ Select->add_joined_table($3);
/* Change the current name resolution context to a local context. */
if (unlikely(push_new_name_resolution_context(thd, $1, $3)))
MYSQL_YYABORT;
@@ -11637,6 +11685,8 @@ join_table:
USING
{
MYSQL_YYABORT_UNLESS($1 && $3);
+ Select->add_joined_table($1);
+ Select->add_joined_table($3);
}
'(' using_list ')'
{
@@ -11647,6 +11697,8 @@ join_table:
| table_ref NATURAL inner_join table_factor
{
MYSQL_YYABORT_UNLESS($1 && ($$=$4));
+ Select->add_joined_table($1);
+ Select->add_joined_table($4);
$4->straight=$3;
add_join_natural($1,$4,NULL,Select);
}
@@ -11656,6 +11708,8 @@ join_table:
ON
{
MYSQL_YYABORT_UNLESS($1 && $5);
+ Select->add_joined_table($1);
+ Select->add_joined_table($5);
/* Change the current name resolution context to a local context. */
if (unlikely(push_new_name_resolution_context(thd, $1, $5)))
MYSQL_YYABORT;
@@ -11672,6 +11726,8 @@ join_table:
| table_ref LEFT opt_outer JOIN_SYM table_factor
{
MYSQL_YYABORT_UNLESS($1 && $5);
+ Select->add_joined_table($1);
+ Select->add_joined_table($5);
}
USING '(' using_list ')'
{
@@ -11682,6 +11738,8 @@ join_table:
| table_ref NATURAL LEFT opt_outer JOIN_SYM table_factor
{
MYSQL_YYABORT_UNLESS($1 && $6);
+ Select->add_joined_table($1);
+ Select->add_joined_table($6);
add_join_natural($1,$6,NULL,Select);
$6->outer_join|=JOIN_TYPE_LEFT;
$$=$6;
@@ -11692,6 +11750,8 @@ join_table:
ON
{
MYSQL_YYABORT_UNLESS($1 && $5);
+ Select->add_joined_table($1);
+ Select->add_joined_table($5);
/* Change the current name resolution context to a local context. */
if (unlikely(push_new_name_resolution_context(thd, $1, $5)))
MYSQL_YYABORT;
@@ -11709,6 +11769,8 @@ join_table:
| table_ref RIGHT opt_outer JOIN_SYM table_factor
{
MYSQL_YYABORT_UNLESS($1 && $5);
+ Select->add_joined_table($1);
+ Select->add_joined_table($5);
}
USING '(' using_list ')'
{
@@ -11720,6 +11782,8 @@ join_table:
| table_ref NATURAL RIGHT opt_outer JOIN_SYM table_factor
{
MYSQL_YYABORT_UNLESS($1 && $6);
+ Select->add_joined_table($1);
+ Select->add_joined_table($6);
add_join_natural($6,$1,NULL,Select);
LEX *lex= Lex;
if (unlikely(!($$= lex->current_select->convert_right_join())))
@@ -11755,238 +11819,44 @@ use_partition:
}
;
-/*
- This is a flattening of the rules <table factor> and <table primary>
- in the SQL:2003 standard, since we don't have <sample clause>
-
- I.e.
- <table factor> ::= <table primary> [ <sample clause> ]
-*/
-/* Warning - may return NULL in case of incomplete SELECT */
table_factor:
- table_primary_ident
- | table_primary_derived
+ table_primary_ident { $$= $1; }
+ | table_primary_derived { $$= $1; }
+ | join_table_parens { $$= $1; }
+ | table_reference_list_parens { $$= $1; }
;
-table_primary_ident:
- {
- DBUG_ASSERT(Select);
- SELECT_LEX *sel= Select;
- sel->table_join_options= 0;
- }
- table_ident opt_use_partition opt_for_system_time_clause opt_table_alias opt_key_definition
- {
- if (unlikely(!($$= Select->add_table_to_list(thd, $2, $5,
- Select->get_table_join_options(),
- YYPS->m_lock_type,
- YYPS->m_mdl_type,
- Select->
- pop_index_hints(),
- $3))))
- MYSQL_YYABORT;
- TABLE_LIST *tl= $$;
- Select->add_joined_table(tl);
- if ($4)
- tl->vers_conditions= Lex->vers_conditions;
- }
- ;
-
-
-
-/*
- Represents a flattening of the following rules from the SQL:2003
- standard. This sub-rule corresponds to the sub-rule
- <table primary> ::= ... | <derived table> [ AS ] <correlation name>
-
- <derived table> ::= <table subquery>
- <table subquery> ::= <subquery>
- <subquery> ::= <left paren> <query expression> <right paren>
- <query expression> ::= [ <with clause> ] <query expression body>
-
- For the time being we use the non-standard rule
- select_derived_union which is a compromise between the standard
- and our parser. Possibly this rule could be replaced by our
- query_expression_body.
-*/
-
-table_primary_derived:
- '(' get_select_lex select_derived_union ')' opt_for_system_time_clause opt_table_alias
+table_reference_list_parens:
+ '(' table_reference_list_parens ')' { $$= $2; }
+ | '(' nested_table_reference_list ')'
{
- /* Use $2 instead of Lex->current_select as derived table will
- alter value of Lex->current_select. */
- if (!($3 || $6) && $2->embedding &&
- !$2->embedding->nested_join->join_list.elements)
- {
- /* we have a derived table ($3 == NULL) but no alias,
- Since we are nested in further parentheses so we
- can pass NULL to the outer level parentheses
- Permits parsing of "((((select ...))) as xyz)" */
- $$= 0;
- }
- else if (!$3)
- {
- /* Handle case of derived table, alias may be NULL if there
- are no outer parentheses, add_table_to_list() will throw
- error in this case */
- LEX *lex=Lex;
- lex->check_automatic_up(UNSPECIFIED_TYPE);
- SELECT_LEX *sel= lex->current_select;
- SELECT_LEX_UNIT *unit= sel->master_unit();
- lex->current_select= sel= unit->outer_select();
- Table_ident *ti= new (thd->mem_root) Table_ident(unit);
- if (unlikely(ti == NULL))
- MYSQL_YYABORT;
- if (unlikely(!($$= sel->add_table_to_list(thd,
- ti, $6, 0,
- TL_READ,
- MDL_SHARED_READ))))
- MYSQL_YYABORT;
- sel->add_joined_table($$);
- lex->pop_context();
- lex->nest_level--;
- }
- else if (unlikely($6 != NULL))
- {
- /*
- Tables with or without joins within parentheses cannot
- have aliases, and we ruled out derived tables above.
- */
- thd->parse_error();
+ if (!($$= Select->end_nested_join(thd)))
MYSQL_YYABORT;
- }
- else
- {
- /* nested join: FROM (t1 JOIN t2 ...),
- nest_level is the same as in the outer query */
- $$= $3;
- }
- /*
- Fields in derived table can be used in upper select in
- case of merge. We do not add HAVING fields because we do
- not merge such derived. We do not add union because
- also do not merge them
- */
- if ($$ && $$->derived &&
- !$$->derived->first_select()->next_select())
- $$->select_lex->add_where_field($$->derived->first_select());
- if ($5)
- {
- MYSQL_YYABORT_UNLESS(!$3);
- $$->vers_conditions= Lex->vers_conditions;
- }
}
- /* Represents derived table with WITH clause */
- | '(' get_select_lex subselect_start
- with_clause query_expression_body
- subselect_end ')' opt_for_system_time_clause opt_table_alias
- {
- LEX *lex=Lex;
- SELECT_LEX *sel= $2;
- SELECT_LEX_UNIT *unit= $5->master_unit();
- Table_ident *ti= new (thd->mem_root) Table_ident(unit);
- if (unlikely(ti == NULL))
- MYSQL_YYABORT;
- $5->set_with_clause($4);
- lex->current_select= sel;
- if (unlikely(!($$= sel->add_table_to_list(lex->thd,
- ti, $9, 0,
- TL_READ,
- MDL_SHARED_READ))))
- MYSQL_YYABORT;
- sel->add_joined_table($$);
- if ($8)
- $$->vers_conditions= Lex->vers_conditions;
- }
;
-/*
- This rule accepts just about anything. The reason is that we have
- empty-producing rules in the beginning of rules, in this case
- subselect_start. This forces bison to take a decision which rules to
- reduce by long before it has seen any tokens. This approach ties us
- to a very limited class of parseable languages, and unfortunately
- SQL is not one of them. The chosen 'solution' was this rule, which
- produces just about anything, even complete bogus statements, for
- instance ( table UNION SELECT 1 ).
- Fortunately, we know that the semantic value returned by
- select_derived is NULL if it contained a derived table, and a pointer to
- the base table's TABLE_LIST if it was a base table. So in the rule
- regarding union's, we throw a parse error manually and pretend it
- was bison that did it.
-
- Also worth noting is that this rule concerns query expressions in
- the from clause only. Top level select statements and other types of
- subqueries have their own union rules.
-*/
-select_derived_union:
- select_derived
- | select_derived union_order_or_limit
+nested_table_reference_list:
+ table_ref ',' table_ref
{
- if (unlikely($1))
- {
- thd->parse_error();
+ if (Select->init_nested_join(thd))
MYSQL_YYABORT;
- }
+ Select->add_joined_table($1);
+ Select->add_joined_table($3);
+ $$= $1->embedding;
}
- | select_derived union_head_non_top
+ | nested_table_reference_list ',' table_ref
{
- if (unlikely($1))
- {
- thd->parse_error();
- MYSQL_YYABORT;
- }
- }
- union_list_derived_part2
- | derived_simple_table opt_select_lock_type
- | derived_simple_table order_or_limit opt_select_lock_type
- | derived_simple_table opt_select_lock_type union_list_derived
- ;
-
-union_list_derived_part2:
- query_term_union_not_ready { Lex->pop_context(); }
- | query_term_union_ready { Lex->pop_context(); }
- | query_term_union_ready { Lex->pop_context(); } union_list_derived
- ;
-
-union_list_derived:
- union_head_non_top union_list_derived_part2
- ;
-
-
-/* The equivalent of select_init2 for nested queries. */
-select_init2_derived:
- select_part2_derived
- {
- Select->set_braces(0);
- }
- ;
-
-/* The equivalent of select_part2 for nested queries. */
-select_part2_derived:
- {
- LEX *lex= Lex;
- SELECT_LEX *sel= lex->current_select;
- if (sel->linkage != UNION_TYPE)
- mysql_init_select(lex);
- lex->current_select->parsing_place= SELECT_LIST;
- }
- opt_query_expression_options select_item_list
- {
- Select->parsing_place= NO_MATTER;
+ Select->add_joined_table($3);
+ $$= $1;
}
;
-/* handle contents of parentheses in join expression */
-select_derived:
- get_select_lex_derived derived_table_list
+join_table_parens:
+ '(' join_table_parens ')' { $$= $2; }
+ | '(' join_table ')'
{
LEX *lex= Lex;
- /* for normal joins, $2 != NULL and end_nested_join() != NULL,
- for derived tables, both must equal NULL */
-
- if (unlikely(!($$= $1->end_nested_join(lex->thd)) && $2))
- MYSQL_YYABORT;
- if (unlikely(!$2 && $$))
+ if (!($$= lex->current_select->nest_last_join(thd)))
{
thd->parse_error();
MYSQL_YYABORT;
@@ -11994,86 +11864,59 @@ select_derived:
}
;
-derived_simple_table:
- derived_query_specification { $$= $1; }
- | derived_table_value_constructor { $$= $1; }
- ;
-/*
- Similar to query_specification, but for derived tables.
- Example: the inner parenthesized SELECT in this query:
- SELECT * FROM (SELECT * FROM t1);
-*/
-derived_query_specification:
- SELECT_SYM select_derived_init select_derived2
- {
- if ($2)
- Select->set_braces(1);
- $$= NULL;
- }
- ;
-derived_table_value_constructor:
- VALUES
- {
- Lex->tvc_start();
- }
- values_list
+table_primary_ident:
+ table_ident opt_use_partition opt_for_system_time_clause
+ opt_table_alias_clause opt_key_definition
{
- if (Lex->tvc_finalize_derived())
+ SELECT_LEX *sel= Select;
+ sel->table_join_options= 0;
+ if (!($$= Select->add_table_to_list(thd, $1, $4,
+ Select->get_table_join_options(),
+ YYPS->m_lock_type,
+ YYPS->m_mdl_type,
+ Select->pop_index_hints(),
+ $2)))
MYSQL_YYABORT;
- $$= NULL;
+ TABLE_LIST *tl= $$;
+ if ($3)
+ tl->vers_conditions= Lex->vers_conditions;
}
;
-select_derived2:
- {
- LEX *lex= Lex;
- lex->derived_tables|= DERIVED_SUBQUERY;
- if (unlikely(!lex->expr_allows_subselect ||
- lex->sql_command == (int)SQLCOM_PURGE))
- {
- thd->parse_error();
- MYSQL_YYABORT;
- }
- if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE ||
- unlikely(mysql_new_select(lex, 1, NULL)))
- MYSQL_YYABORT;
- mysql_init_select(lex);
- lex->current_select->linkage= DERIVED_TABLE_TYPE;
- lex->current_select->parsing_place= SELECT_LIST;
- }
- select_options select_item_list
- {
- Select->parsing_place= NO_MATTER;
- }
- opt_table_expression
- ;
+/*
+ Represents a flattening of the following rules from the SQL:2003
+ standard. This sub-rule corresponds to the sub-rule
+ <table primary> ::= ... | <derived table> [ AS ] <correlation name>
-get_select_lex:
- /* Empty */ { $$= Select; }
- ;
+ <derived table> ::= <table subquery>
+ <table subquery> ::= <subquery>
+ <subquery> ::= <left paren> <query expression> <right paren>
+ <query expression> ::= [ <with clause> ] <query expression body>
-get_select_lex_derived:
- get_select_lex
+ For the time being we use the non-standard rule
+ select_derived_union which is a compromise between the standard
+ and our parser. Possibly this rule could be replaced by our
+ query_expression_body.
+*/
+
+table_primary_derived:
+ query_primary_parens opt_for_system_time_clause table_alias_clause
{
- LEX *lex= Lex;
- if (unlikely($1->init_nested_join(lex->thd)))
- MYSQL_YYABORT;
+ if (!($$= Lex->parsed_derived_select($1, $2, $3)))
+ YYABORT;
}
- ;
-
-select_derived_init:
+ | '('
+ query_expression
+ ')' opt_for_system_time_clause table_alias_clause
{
- LEX *lex= Lex;
-
- TABLE_LIST *embedding= lex->current_select->embedding;
- $$= embedding &&
- !embedding->nested_join->join_list.elements;
- /* return true if we are deeply nested */
+ if (!($$= Lex->parsed_derived_unit($2, $4, $5)))
+ YYABORT;
}
;
+
opt_outer:
/* empty */ {}
| OUTER {}
@@ -12204,9 +12047,14 @@ table_alias:
| '='
;
-opt_table_alias:
+opt_table_alias_clause:
/* empty */ { $$=0; }
- | table_alias ident_table_alias
+
+ | table_alias_clause { $$= $1; }
+ ;
+
+table_alias_clause:
+ table_alias ident_table_alias
{
$$= (LEX_CSTRING*) thd->memdup(&$2,sizeof(LEX_STRING));
if (unlikely($$ == NULL))
@@ -12302,7 +12150,7 @@ olap_opt:
SQL-2003: GROUP BY ... CUBE(col1, col2, col3)
*/
LEX *lex=Lex;
- if (unlikely(lex->current_select->linkage == GLOBAL_OPTIONS_TYPE))
+ if (unlikely(lex->current_select->get_linkage() == GLOBAL_OPTIONS_TYPE))
my_yyabort_error((ER_WRONG_USAGE, MYF(0), "WITH CUBE",
"global union parameters"));
lex->current_select->olap= CUBE_TYPE;
@@ -12319,7 +12167,7 @@ olap_opt:
SQL-2003: GROUP BY ... ROLLUP(col1, col2, col3)
*/
LEX *lex= Lex;
- if (unlikely(lex->current_select->linkage == GLOBAL_OPTIONS_TYPE))
+ if (unlikely(lex->current_select->get_linkage() == GLOBAL_OPTIONS_TYPE))
my_yyabort_error((ER_WRONG_USAGE, MYF(0), "WITH ROLLUP",
"global union parameters"));
lex->current_select->olap= ROLLUP_TYPE;
@@ -12379,7 +12227,7 @@ opt_window_partition_clause:
opt_window_order_clause:
/* empty */ { }
- | ORDER_SYM BY order_list
+ | ORDER_SYM BY order_list { Select->order_list= *($3); }
;
opt_window_frame_clause:
@@ -12503,70 +12351,35 @@ alter_order_item:
opt_order_clause:
/* empty */
+ { $$= NULL; }
| order_clause
+ { $$= $1; }
;
order_clause:
ORDER_SYM BY
{
- LEX *lex=Lex;
- SELECT_LEX *sel= lex->current_select;
- SELECT_LEX_UNIT *unit= sel-> master_unit();
- if (unlikely(sel->linkage != GLOBAL_OPTIONS_TYPE &&
- sel->olap != UNSPECIFIED_OLAP_TYPE &&
- (sel->linkage != UNION_TYPE || sel->braces)))
- {
- my_error(ER_WRONG_USAGE, MYF(0),
- "CUBE/ROLLUP", "ORDER BY");
- MYSQL_YYABORT;
- }
- if (lex->sql_command != SQLCOM_ALTER_TABLE &&
- !unit->fake_select_lex)
- {
- /*
- A query of the of the form (SELECT ...) ORDER BY order_list is
- executed in the same way as the query
- SELECT ... ORDER BY order_list
- unless the SELECT construct contains ORDER BY or LIMIT clauses.
- Otherwise we create a fake SELECT_LEX if it has not been
- created yet.
- */
- SELECT_LEX *first_sl= unit->first_select();
- if (unlikely(!unit->is_unit_op() &&
- (first_sl->order_list.elements ||
- first_sl->select_limit) &&
- unit->add_fake_select_lex(thd)))
- MYSQL_YYABORT;
- }
- if (sel->master_unit()->is_unit_op() && !sel->braces)
- {
- /*
- At this point we don't know yet whether this is the last
- select in union or not, but we move ORDER BY to
- fake_select_lex anyway. If there would be one more select
- in union mysql_new_select will correctly throw error.
- */
- DBUG_ASSERT(sel->master_unit()->fake_select_lex);
- lex->current_select= sel->master_unit()->fake_select_lex;
- }
+ thd->where= "ORDER clause";
}
order_list
{
-
+ $$= $4;
}
;
order_list:
order_list ',' order_ident order_dir
{
- if (unlikely(add_order_to_list(thd, $3,(bool) $4)))
- MYSQL_YYABORT;
- }
+ $$= $1;
+ if (add_to_list(thd, *$$, $3,(bool) $4))
+ MYSQL_YYABORT;
+ }
| order_ident order_dir
{
- if (unlikely(add_order_to_list(thd, $1,(bool) $2)))
+ $$= new (thd->mem_root) SQL_I_List<ORDER>();
+ if (add_to_list(thd, *$$, $1, (bool) $2))
MYSQL_YYABORT;
- }
+ }
;
order_dir:
@@ -12576,63 +12389,61 @@ order_dir:
;
opt_limit_clause:
- /* empty */ {}
- | limit_clause {}
+ /* empty */
+ { $$.empty(); }
+ | limit_clause
+ { $$= $1; }
;
-limit_clause_init:
- LIMIT
- {
- SELECT_LEX *sel= Select;
- if (sel->master_unit()->is_unit_op() && !sel->braces)
- {
- /* Move LIMIT that belongs to UNION to fake_select_lex */
- Lex->current_select= sel->master_unit()->fake_select_lex;
- DBUG_ASSERT(Select);
- }
- }
- ;
-
limit_clause:
- limit_clause_init limit_options
+ LIMIT limit_options
{
- SELECT_LEX *sel= Select;
- if (!sel->select_limit->basic_const_item() ||
- sel->select_limit->val_int() > 0)
+ $$= $2;
+ if (!$$.select_limit->basic_const_item() ||
+ $$.select_limit->val_int() > 0)
Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_LIMIT);
}
- | limit_clause_init limit_options
+ | LIMIT limit_options
ROWS_SYM EXAMINED_SYM limit_rows_option
{
+ $$= $2;
Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_LIMIT);
}
- | limit_clause_init ROWS_SYM EXAMINED_SYM limit_rows_option
+ | LIMIT ROWS_SYM EXAMINED_SYM limit_rows_option
{
+ $$.select_limit= 0;
+ $$.offset_limit= 0;
+ $$.explicit_limit= 1;
Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_LIMIT);
}
;
+opt_global_limit_clause:
+ opt_limit_clause
+ {
+ Select->explicit_limit= $1.explicit_limit;
+ Select->select_limit= $1.select_limit;
+ Select->offset_limit= $1.offset_limit;
+ }
+
limit_options:
limit_option
{
- SELECT_LEX *sel= Select;
- sel->select_limit= $1;
- sel->offset_limit= 0;
- sel->explicit_limit= 1;
+ $$.select_limit= $1;
+ $$.offset_limit= 0;
+ $$.explicit_limit= 1;
}
| limit_option ',' limit_option
{
- SELECT_LEX *sel= Select;
- sel->select_limit= $3;
- sel->offset_limit= $1;
- sel->explicit_limit= 1;
+ $$.select_limit= $3;
+ $$.offset_limit= $1;
+ $$.explicit_limit= 1;
}
| limit_option OFFSET_SYM limit_option
{
- SELECT_LEX *sel= Select;
- sel->select_limit= $1;
- sel->offset_limit= $3;
- sel->explicit_limit= 1;
+ $$.select_limit= $1;
+ $$.offset_limit= $3;
+ $$.explicit_limit= 1;
}
;
@@ -12695,6 +12506,77 @@ delete_limit_clause:
| LIMIT limit_option ROWS_SYM EXAMINED_SYM { thd->parse_error(); MYSQL_YYABORT; }
;
+opt_order_limit_lock:
+ /* empty */
+ { $$= NULL; }
+ | order_or_limit
+ {
+ $$= $1;
+ $$->lock.empty();
+ }
+ | order_or_limit select_lock_type
+ {
+ $$= $1;
+ $$->lock= $2;
+ }
+ | select_lock_type
+ {
+ $$= new(thd->mem_root) Lex_order_limit_lock;
+ if (!$$)
+ YYABORT;
+ $$->order_list= NULL;
+ $$->limit.empty();
+ $$->lock= $1;
+ }
+ ;
+query_expression_tail:
+ opt_order_limit_lock
+ ;
+
+opt_procedure_or_into:
+ /* empty */
+ {
+ $$.empty();
+ }
+ | procedure_clause opt_select_lock_type
+ {
+ $$= $2;
+ }
+ | into opt_select_lock_type
+ {
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
+ ER_WARN_DEPRECATED_SYNTAX,
+ ER_THD(thd, ER_WARN_DEPRECATED_SYNTAX),
+ "<select expression> INTO <destination>;",
+ "'SELECT <select list> INTO <destination>"
+ " FROM...'");
+ $$= $2;
+ }
+ ;
+
+
+order_or_limit:
+ order_clause opt_limit_clause
+ {
+ $$= new(thd->mem_root) Lex_order_limit_lock;
+ if (!$$)
+ YYABORT;
+ $$->order_list= $1;
+ $$->limit= $2;
+ }
+ | limit_clause
+ {
+ Lex_order_limit_lock *op= $$= new(thd->mem_root) Lex_order_limit_lock;
+ if (!$$)
+ YYABORT;
+ op->order_list= NULL;
+ op->limit= $1;
+ $$->order_list= NULL;
+ $$->limit= $1;
+ }
+ ;
+
+
opt_plus:
/* empty */
| '+'
@@ -12764,14 +12646,11 @@ bool:
| TRUE_SYM { $$= 1; }
| FALSE_SYM { $$= 0; }
-
procedure_clause:
PROCEDURE_SYM ident /* Procedure name */
{
LEX *lex=Lex;
- DBUG_ASSERT(&lex->select_lex == lex->current_select);
-
lex->proc_list.elements=0;
lex->proc_list.first=0;
lex->proc_list.next= &lex->proc_list.first;
@@ -12791,6 +12670,7 @@ procedure_clause:
parameters are reduced.
*/
Lex->expr_allows_subselect= false;
+ Select->options|= OPTION_PROCEDURE_CLAUSE;
}
'(' procedure_list ')'
{
@@ -12874,6 +12754,7 @@ select_outvar:
into:
INTO into_destination
+ {}
;
into_destination:
@@ -13067,10 +12948,11 @@ table_list:
table_name:
table_ident
{
- if (unlikely(!Select->add_table_to_list(thd, $1, NULL,
- TL_OPTION_UPDATING,
- YYPS->m_lock_type,
- YYPS->m_mdl_type)))
+ if (!thd->lex->current_select_or_default()->
+ add_table_to_list(thd, $1, NULL,
+ TL_OPTION_UPDATING,
+ YYPS->m_lock_type,
+ YYPS->m_mdl_type))
MYSQL_YYABORT;
}
;
@@ -13144,16 +13026,23 @@ insert:
LEX *lex= Lex;
lex->sql_command= SQLCOM_INSERT;
lex->duplicates= DUP_ERROR;
+ if (Lex->main_select_push())
+ MYSQL_YYABORT;
mysql_init_select(lex);
+ lex->current_select->parsing_place= BEFORE_OPT_LIST;
}
insert_lock_option
opt_ignore insert2
{
Select->set_lock_for_tables($3);
- Lex->current_select= &Lex->select_lex;
+ Lex->current_select= Lex->first_select_lex();
}
insert_field_spec opt_insert_update
- {}
+ {
+ Lex->pop_select(); //main select
+ if (Lex->check_main_unit_semantics())
+ MYSQL_YYABORT;
+ }
;
replace:
@@ -13162,15 +13051,22 @@ replace:
LEX *lex=Lex;
lex->sql_command = SQLCOM_REPLACE;
lex->duplicates= DUP_REPLACE;
+ if (Lex->main_select_push())
+ MYSQL_YYABORT;
mysql_init_select(lex);
+ lex->current_select->parsing_place= BEFORE_OPT_LIST;
}
replace_lock_option insert2
{
Select->set_lock_for_tables($3);
- Lex->current_select= &Lex->select_lex;
+ Lex->current_select= Lex->first_select_lex();
}
insert_field_spec
- {}
+ {
+ Lex->pop_select(); //main select
+ if (Lex->check_main_unit_semantics())
+ MYSQL_YYABORT;
+ }
;
insert_lock_option:
@@ -13213,15 +13109,14 @@ insert_table:
table_name_with_opt_use_partition
{
LEX *lex=Lex;
- lex->field_list.empty();
+ //lex->field_list.empty();
lex->many_values.empty();
lex->insert_list=0;
};
insert_field_spec:
insert_values {}
- | '(' ')' insert_values {}
- | '(' fields ')' insert_values {}
+ | insert_field_list insert_values {}
| SET
{
LEX *lex=Lex;
@@ -13229,20 +13124,33 @@ insert_field_spec:
unlikely(lex->many_values.push_back(lex->insert_list,
thd->mem_root)))
MYSQL_YYABORT;
+ lex->current_select->parsing_place= NO_MATTER;
}
ident_eq_list
;
+insert_field_list:
+ LEFT_PAREN_ALT opt_fields ')'
+ {
+ Lex->current_select->parsing_place= AFTER_LIST;
+ }
+ ;
+
+opt_fields:
+ /* empty */
+ | fields
+ ;
+
fields:
fields ',' insert_ident
{ Lex->field_list.push_back($3, thd->mem_root); }
| insert_ident { Lex->field_list.push_back($1, thd->mem_root); }
;
+
+
insert_values:
- VALUES values_list {}
- | VALUE_SYM values_list {}
- | create_select_query_expression {}
+ create_select_query_expression {}
;
values_list:
@@ -13353,6 +13261,8 @@ update:
UPDATE_SYM
{
LEX *lex= Lex;
+ if (Lex->main_select_push())
+ MYSQL_YYABORT;
mysql_init_select(lex);
lex->sql_command= SQLCOM_UPDATE;
lex->duplicates= DUP_ERROR;
@@ -13361,13 +13271,14 @@ update:
SET update_list
{
LEX *lex= Lex;
- if (lex->select_lex.table_list.elements > 1)
+ if (lex->first_select_lex()->table_list.elements > 1)
lex->sql_command= SQLCOM_UPDATE_MULTI;
- else if (unlikely(lex->select_lex.get_table_list()->derived))
+ else if (lex->first_select_lex()->get_table_list()->derived)
{
/* it is single table update and it is update of derived table */
my_error(ER_NON_UPDATABLE_TABLE, MYF(0),
- lex->select_lex.get_table_list()->alias.str, "UPDATE");
+ lex->first_select_lex()->get_table_list()->alias.str,
+ "UPDATE");
MYSQL_YYABORT;
}
/*
@@ -13377,7 +13288,14 @@ update:
*/
Select->set_lock_for_tables($3);
}
- opt_where_clause opt_order_clause delete_limit_clause {}
+ opt_where_clause opt_order_clause delete_limit_clause
+ {
+ if ($10)
+ Select->order_list= *($10);
+ Lex->pop_select(); //main select
+ if (Lex->check_main_unit_semantics())
+ MYSQL_YYABORT;
+ }
;
update_list:
@@ -13424,9 +13342,11 @@ delete:
mysql_init_select(lex);
YYPS->m_lock_type= TL_WRITE_DEFAULT;
YYPS->m_mdl_type= MDL_SHARED_WRITE;
+ if (Lex->main_select_push())
+ MYSQL_YYABORT;
lex->ignore= 0;
- lex->select_lex.init_order();
+ lex->first_select_lex()->order_list.empty();
}
delete_part2
;
@@ -13447,6 +13367,7 @@ delete_part2:
| HISTORY_SYM delete_single_table opt_delete_system_time
{
Lex->last_table()->vers_conditions= Lex->vers_conditions;
+ Lex->pop_select(); //main select
}
;
@@ -13470,7 +13391,12 @@ single_multi:
opt_where_clause
opt_order_clause
delete_limit_clause
- opt_select_expressions {}
+ opt_select_expressions
+ {
+ if ($3)
+ Select->order_list= *($3);
+ Lex->pop_select(); //main select
+ }
| table_wild_list
{
mysql_init_multi_delete(Lex);
@@ -13481,6 +13407,9 @@ single_multi:
{
if (unlikely(multi_delete_set_locks_and_link_aux_tables(Lex)))
MYSQL_YYABORT;
+ Lex->pop_select(); //main select
+ if (Lex->check_main_unit_semantics())
+ MYSQL_YYABORT;
}
| FROM table_alias_ref_list
{
@@ -13492,6 +13421,9 @@ single_multi:
{
if (unlikely(multi_delete_set_locks_and_link_aux_tables(Lex)))
MYSQL_YYABORT;
+ Lex->pop_select(); //main select
+ if (Lex->check_main_unit_semantics())
+ MYSQL_YYABORT;
}
;
@@ -13560,9 +13492,9 @@ truncate:
LEX* lex= Lex;
lex->sql_command= SQLCOM_TRUNCATE;
lex->alter_info.reset();
- lex->select_lex.options= 0;
- lex->select_lex.sql_cache= SELECT_LEX::SQL_CACHE_UNSPECIFIED;
- lex->select_lex.init_order();
+ lex->first_select_lex()->options= 0;
+ lex->sql_cache= LEX::SQL_CACHE_UNSPECIFIED;
+ lex->first_select_lex()->order_list.empty();
YYPS->m_lock_type= TL_WRITE;
YYPS->m_mdl_type= MDL_EXCLUSIVE;
}
@@ -13647,6 +13579,8 @@ show:
LEX *lex=Lex;
lex->wild=0;
lex->ident= null_clex_str;
+ if (Lex->main_select_push())
+ MYSQL_YYABORT;
mysql_init_select(lex);
lex->current_select->parsing_place= SELECT_LIST;
lex->create_info.init();
@@ -13654,6 +13588,7 @@ show:
show_param
{
Select->parsing_place= NO_MATTER;
+ Lex->pop_select(); //main select
}
;
@@ -13669,40 +13604,40 @@ show_param:
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_SHOW_TABLES;
- lex->select_lex.db= $3;
- if (unlikely(prepare_schema_table(thd, lex, 0, SCH_TABLE_NAMES)))
+ lex->first_select_lex()->db= $3;
+ if (prepare_schema_table(thd, lex, 0, SCH_TABLE_NAMES))
MYSQL_YYABORT;
}
| opt_full TRIGGERS_SYM opt_db wild_and_where
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_SHOW_TRIGGERS;
- lex->select_lex.db= $3;
- if (unlikely(prepare_schema_table(thd, lex, 0, SCH_TRIGGERS)))
+ lex->first_select_lex()->db= $3;
+ if (prepare_schema_table(thd, lex, 0, SCH_TRIGGERS))
MYSQL_YYABORT;
}
| EVENTS_SYM opt_db wild_and_where
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_SHOW_EVENTS;
- lex->select_lex.db= $2;
- if (unlikely(prepare_schema_table(thd, lex, 0, SCH_EVENTS)))
+ lex->first_select_lex()->db= $2;
+ if (prepare_schema_table(thd, lex, 0, SCH_EVENTS))
MYSQL_YYABORT;
}
| TABLE_SYM STATUS_SYM opt_db wild_and_where
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_SHOW_TABLE_STATUS;
- lex->select_lex.db= $3;
- if (unlikely(prepare_schema_table(thd, lex, 0, SCH_TABLES)))
+ lex->first_select_lex()->db= $3;
+ if (prepare_schema_table(thd, lex, 0, SCH_TABLES))
MYSQL_YYABORT;
}
| OPEN_SYM TABLES opt_db wild_and_where
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_SHOW_OPEN_TABLES;
- lex->select_lex.db= $3;
- if (unlikely(prepare_schema_table(thd, lex, 0, SCH_OPEN_TABLES)))
+ lex->first_select_lex()->db= $3;
+ if (prepare_schema_table(thd, lex, 0, SCH_OPEN_TABLES))
MYSQL_YYABORT;
}
| PLUGINS_SYM
@@ -13751,12 +13686,13 @@ show_param:
LEX *lex= Lex;
lex->sql_command= SQLCOM_SHOW_BINLOG_EVENTS;
}
- opt_limit_clause
+ opt_global_limit_clause
| RELAYLOG_SYM optional_connection_name EVENTS_SYM binlog_in binlog_from
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_SHOW_RELAYLOG_EVENTS;
- } opt_limit_clause
+ }
+ opt_global_limit_clause
| keys_or_index from_or_in table_ident opt_db opt_where_clause
{
LEX *lex= Lex;
@@ -13798,13 +13734,13 @@ show_param:
LEX_CSTRING var= {STRING_WITH_LEN("error_count")};
(void) create_select_for_variable(thd, &var);
}
- | WARNINGS opt_limit_clause
+ | WARNINGS opt_global_limit_clause
{ Lex->sql_command = SQLCOM_SHOW_WARNS;}
- | ERRORS opt_limit_clause
+ | ERRORS opt_global_limit_clause
{ Lex->sql_command = SQLCOM_SHOW_ERRORS;}
| PROFILES_SYM
{ Lex->sql_command = SQLCOM_SHOW_PROFILES; }
- | PROFILE_SYM opt_profile_defs opt_profile_args opt_limit_clause
+ | PROFILE_SYM opt_profile_defs opt_profile_args opt_global_limit_clause
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_SHOW_PROFILE;
@@ -13866,7 +13802,7 @@ show_param:
{
LEX *lex= Lex;
lex->sql_command = SQLCOM_SHOW_CREATE;
- if (unlikely(!lex->select_lex.add_table_to_list(thd, $3, NULL,0)))
+ if (!lex->first_select_lex()->add_table_to_list(thd, $3, NULL,0))
MYSQL_YYABORT;
lex->create_info.storage_media= HA_SM_DEFAULT;
}
@@ -13874,7 +13810,7 @@ show_param:
{
LEX *lex= Lex;
lex->sql_command = SQLCOM_SHOW_CREATE;
- if (unlikely(!lex->select_lex.add_table_to_list(thd, $3, NULL, 0)))
+ if (!lex->first_select_lex()->add_table_to_list(thd, $3, NULL, 0))
MYSQL_YYABORT;
lex->table_type= TABLE_TYPE_VIEW;
}
@@ -13882,7 +13818,7 @@ show_param:
{
LEX *lex= Lex;
lex->sql_command = SQLCOM_SHOW_CREATE;
- if (unlikely(!lex->select_lex.add_table_to_list(thd, $3, NULL, 0)))
+ if (!lex->first_select_lex()->add_table_to_list(thd, $3, NULL, 0))
MYSQL_YYABORT;
lex->table_type= TABLE_TYPE_SEQUENCE;
}
@@ -14099,7 +14035,7 @@ describe:
mysql_init_select(lex);
lex->current_select->parsing_place= SELECT_LIST;
lex->sql_command= SQLCOM_SHOW_FIELDS;
- lex->select_lex.db= null_clex_str;
+ lex->first_select_lex()->db= null_clex_str;
lex->verbose= 0;
if (unlikely(prepare_schema_table(thd, lex, $2, SCH_COLUMNS)))
MYSQL_YYABORT;
@@ -14113,12 +14049,13 @@ describe:
explainable_command
{
LEX *lex=Lex;
- lex->select_lex.options|= SELECT_DESCRIBE;
+ lex->first_select_lex()->options|= SELECT_DESCRIBE;
}
;
explainable_command:
select
+ | select_into
| insert
| replace
| update
@@ -14139,6 +14076,8 @@ analyze_stmt_command:
opt_extended_describe:
EXTENDED_SYM { Lex->describe|= DESCRIBE_EXTENDED; }
+ | EXTENDED_SYM ALL
+ { Lex->describe|= DESCRIBE_EXTENDED | DESCRIBE_EXTENDED2; }
| PARTITIONS_SYM { Lex->describe|= DESCRIBE_PARTITIONS; }
| opt_format_json {}
;
@@ -14181,8 +14120,7 @@ flush:
lex->type= 0;
lex->no_write_to_binlog= $2;
}
- flush_options
- {}
+ flush_options {}
;
flush_options:
@@ -14199,6 +14137,7 @@ flush_options:
opt_table_list opt_flush_lock
{}
| flush_options_list
+ {}
;
opt_flush_lock:
@@ -14394,6 +14333,8 @@ purge_option:
lex->value_list.empty();
lex->value_list.push_front($2, thd->mem_root);
lex->sql_command= SQLCOM_PURGE_BEFORE;
+ if (Lex->check_main_unit_semantics())
+ MYSQL_YYABORT;
}
;
@@ -14454,7 +14395,7 @@ use:
{
LEX *lex=Lex;
lex->sql_command=SQLCOM_CHANGE_DB;
- lex->select_lex.db= $2;
+ lex->first_select_lex()->db= $2;
}
;
@@ -14471,6 +14412,9 @@ load:
$2 == FILETYPE_CSV ? "LOAD DATA" : "LOAD XML");
MYSQL_YYABORT;
}
+ if (lex->main_select_push())
+ MYSQL_YYABORT;
+ mysql_init_select(lex);
}
load_data_lock opt_local INFILE TEXT_STRING_filesystem
{
@@ -14500,7 +14444,11 @@ load:
opt_xml_rows_identified_by
opt_field_term opt_line_term opt_ignore_lines opt_field_or_var_spec
opt_load_data_set_spec
- {}
+ {
+ Lex->pop_select(); //main select
+ if (Lex->check_main_unit_semantics())
+ MYSQL_YYABORT;
+ }
;
data_or_xml:
@@ -14888,17 +14836,21 @@ opt_with_clause:
with_clause:
- WITH opt_recursive
+ WITH opt_recursive
{
+ LEX *lex= Lex;
With_clause *with_clause=
new With_clause($2, Lex->curr_with_clause);
if (unlikely(with_clause == NULL))
MYSQL_YYABORT;
- Lex->derived_tables|= DERIVED_WITH;
- Lex->curr_with_clause= with_clause;
+ lex->derived_tables|= DERIVED_WITH;
+ lex->curr_with_clause= with_clause;
with_clause->add_to_list(Lex->with_clauses_list_last_next);
+ if (lex->current_select &&
+ lex->current_select->parsing_place == BEFORE_OPT_LIST)
+ lex->current_select->parsing_place= NO_MATTER;
}
- with_list
+ with_list
{
$$= Lex->curr_with_clause;
Lex->curr_with_clause= Lex->curr_with_clause->pop();
@@ -14927,11 +14879,10 @@ with_list_element:
MYSQL_YYABORT;
Lex->with_column_list.empty();
}
- AS '(' remember_name subselect remember_end ')'
+ AS '(' remember_name query_expression remember_end ')'
{
- With_element *elem= new With_element($1, *$2, $7->master_unit());
- if (unlikely(elem == NULL) ||
- unlikely(Lex->curr_with_clause->add_with_element(elem)))
+ With_element *elem= new With_element($1, *$2, $7);
+ if (elem == NULL || Lex->curr_with_clause->add_with_element(elem))
MYSQL_YYABORT;
if (unlikely(elem->set_unparsed_spec(thd, $6+1, $8)))
MYSQL_YYABORT;
@@ -15870,14 +15821,22 @@ set:
SET
{
LEX *lex=Lex;
+ if (lex->main_select_push())
+ MYSQL_YYABORT;
lex->set_stmt_init();
lex->var_list.empty();
sp_create_assignment_lex(thd, yychar == YYEMPTY);
}
start_option_value_list
- {}
+ {
+ Lex->pop_select(); //main select
+ if (Lex->check_main_unit_semantics())
+ MYSQL_YYABORT;
+ }
| SET STATEMENT_SYM
{
+ if (Lex->main_select_push())
+ MYSQL_YYABORT;
Lex->set_stmt_init();
}
set_stmt_option_value_following_option_type_list
@@ -15887,6 +15846,9 @@ set:
my_yyabort_error((ER_SUBQUERIES_NOT_SUPPORTED, MYF(0), "SET STATEMENT"));
lex->stmt_var_list= lex->var_list;
lex->var_list.empty();
+ Lex->pop_select(); //main select
+ if (Lex->check_main_unit_semantics())
+ MYSQL_YYABORT;
}
FOR_SYM verb_clause
{}
@@ -16305,7 +16267,7 @@ table_lock_list:
;
table_lock:
- table_ident opt_table_alias lock_option
+ table_ident opt_table_alias_clause lock_option
{
thr_lock_type lock_type= (thr_lock_type) $3;
bool lock_for_write= (lock_type >= TL_WRITE_ALLOW_WRITE);
@@ -16350,27 +16312,36 @@ unlock:
*/
handler:
- HANDLER_SYM table_ident OPEN_SYM opt_table_alias
+ HANDLER_SYM
+ {
+ if (Lex->main_select_push())
+ MYSQL_YYABORT;
+ }
+ handler_tail
+ {
+ Lex->pop_select(); //main select
+ }
+
+handler_tail:
+ table_ident OPEN_SYM opt_table_alias_clause
{
LEX *lex= Lex;
if (unlikely(lex->sphead))
my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "HANDLER"));
lex->sql_command = SQLCOM_HA_OPEN;
- if (unlikely(!lex->current_select->add_table_to_list(thd, $2, $4,
- 0)))
+ if (!lex->current_select->add_table_to_list(thd, $1, $3, 0))
MYSQL_YYABORT;
}
- | HANDLER_SYM table_ident_nodb CLOSE_SYM
+ | table_ident_nodb CLOSE_SYM
{
LEX *lex= Lex;
if (unlikely(lex->sphead))
my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "HANDLER"));
lex->sql_command = SQLCOM_HA_CLOSE;
- if (unlikely(!lex->current_select->add_table_to_list(thd, $2, 0,
- 0)))
+ if (!lex->current_select->add_table_to_list(thd, $1, 0, 0))
MYSQL_YYABORT;
}
- | HANDLER_SYM table_ident_nodb READ_SYM
+ | table_ident_nodb READ_SYM
{
LEX *lex=Lex;
if (unlikely(lex->sphead))
@@ -16384,15 +16355,24 @@ handler:
lex->current_select->select_limit= one;
lex->current_select->offset_limit= 0;
lex->limit_rows_examined= 0;
- if (unlikely(!lex->current_select->add_table_to_list(thd, $2, 0,
- 0)))
+ if (!lex->current_select->add_table_to_list(thd, $1, 0, 0))
MYSQL_YYABORT;
}
- handler_read_or_scan opt_where_clause opt_limit_clause
+ handler_read_or_scan opt_where_clause opt_global_limit_clause
{
- Lex->expr_allows_subselect= TRUE;
+ LEX *lex=Lex;
+ lex->expr_allows_subselect= TRUE;
+ if (!lex->current_select->explicit_limit)
+ {
+ Item *one= new (thd->mem_root) Item_int(thd, (int32) 1);
+ if (one == NULL)
+ MYSQL_YYABORT;
+ lex->current_select->select_limit= one;
+ lex->current_select->offset_limit= 0;
+ lex->limit_rows_examined= 0;
+ }
/* Stored functions are not supported for HANDLER READ. */
- if (unlikely(Lex->uses_stored_routines()))
+ if (lex->uses_stored_routines())
{
my_error(ER_NOT_SUPPORTED_YET, MYF(0),
"stored functions in HANDLER ... READ");
@@ -17028,212 +17008,27 @@ release:
*/
unit_type_decl:
- UNION_SYM
- { $$= UNION_TYPE; }
+ UNION_SYM union_option
+ { $$.unit_type= UNION_TYPE; $$.distinct= $2; }
| INTERSECT_SYM
- { $$= INTERSECT_TYPE; }
+ { $$.unit_type= INTERSECT_TYPE; $$.distinct= 1; }
| EXCEPT_SYM
- { $$= EXCEPT_TYPE; }
+ { $$.unit_type= EXCEPT_TYPE; $$.distinct= 1; }
-union_clause:
- /* empty */ {}
- | union_list
- ;
-
-union_list:
- unit_type_decl union_option
- {
- if (unlikely(Lex->add_select_to_union_list((bool)$2, $1, TRUE)))
- MYSQL_YYABORT;
- }
- union_list_part2
- {
- /*
- Remove from the name resolution context stack the context of the
- last select in the union.
- */
- Lex->pop_context();
- }
- ;
-
-union_list_view:
- unit_type_decl union_option
- {
- if (unlikely(Lex->add_select_to_union_list((bool)$2, $1, TRUE)))
- MYSQL_YYABORT;
- }
- query_expression_body_view
- {
- Lex->pop_context();
- }
- ;
-
-union_order_or_limit:
- {
- LEX *lex= thd->lex;
- DBUG_ASSERT(lex->current_select->linkage != GLOBAL_OPTIONS_TYPE);
- SELECT_LEX *sel= lex->current_select;
- SELECT_LEX_UNIT *unit= sel->master_unit();
- SELECT_LEX *fake= unit->fake_select_lex;
- if (fake)
- {
- fake->no_table_names_allowed= 1;
- lex->current_select= fake;
- }
- thd->where= "global ORDER clause";
- }
- order_or_limit
- {
- thd->lex->current_select->no_table_names_allowed= 0;
- thd->where= "";
- }
- ;
-
-order_or_limit:
- order_clause opt_limit_clause
- | limit_clause
- ;
-
/*
Start a UNION, for non-top level query expressions.
*/
-union_head_non_top:
- unit_type_decl union_option
- {
- if (unlikely(Lex->add_select_to_union_list((bool)$2, $1, FALSE)))
- MYSQL_YYABORT;
- }
- ;
-
union_option:
/* empty */ { $$=1; }
| DISTINCT { $$=1; }
| ALL { $$=0; }
;
-simple_table:
- query_specification { $$= $1; }
- | table_value_constructor { $$= $1; }
- ;
-
-table_value_constructor:
- VALUES
- {
- Lex->tvc_start();
- }
- values_list
- {
- $$= Lex->current_select;
- if (Lex->tvc_finalize())
- MYSQL_YYABORT;
- }
- ;
-
-/*
- Corresponds to the SQL Standard
- <query specification> ::=
- SELECT [ <set quantifier> ] <select list> <table expression>
-
- Notes:
- - We allow more options in addition to <set quantifier>
- - <table expression> is optional in MariaDB
-*/
-query_specification:
- SELECT_SYM select_init2_derived opt_table_expression
- {
- $$= Lex->current_select->master_unit()->first_select();
- }
- ;
-
-query_term_union_not_ready:
- simple_table order_or_limit opt_select_lock_type { $$= $1; }
- | '(' select_paren_derived ')' union_order_or_limit { $$= $2; }
- ;
-
-query_term_union_ready:
- simple_table opt_select_lock_type { $$= $1; }
- | '(' select_paren_derived ')' { $$= $2; }
- ;
-
-query_expression_body:
- query_term_union_not_ready { $$= $1; }
- | query_term_union_ready { $$= $1; }
- | query_term_union_ready union_list_derived { $$= $1; }
- ;
-
-/* Corresponds to <query expression> in the SQL:2003 standard. */
-subselect:
- subselect_start opt_with_clause query_expression_body subselect_end
- {
- $3->set_with_clause($2);
- $$= $3;
- }
- ;
-
-subselect_start:
- {
- LEX *lex=Lex;
- if (unlikely(!lex->expr_allows_subselect ||
- lex->sql_command == (int)SQLCOM_PURGE))
- {
- thd->parse_error();
- MYSQL_YYABORT;
- }
- /*
- we are making a "derived table" for the parenthesis
- as we need to have a lex level to fit the union
- after the parenthesis, e.g.
- (SELECT .. ) UNION ... becomes
- SELECT * FROM ((SELECT ...) UNION ...)
- */
- if (unlikely(mysql_new_select(Lex, 1, NULL)))
- MYSQL_YYABORT;
- }
- ;
-
-subselect_end:
- {
- LEX *lex=Lex;
-
- lex->check_automatic_up(UNSPECIFIED_TYPE);
- lex->pop_context();
- SELECT_LEX *child= lex->current_select;
- lex->current_select = lex->current_select->return_after_parsing();
- lex->nest_level--;
- lex->current_select->n_child_sum_items += child->n_sum_items;
- /*
- A subselect can add fields to an outer select. Reserve space for
- them.
- */
- lex->current_select->select_n_where_fields+=
- child->select_n_where_fields;
-
- /*
- Aggregate functions in having clause may add fields to an outer
- select. Count them also.
- */
- lex->current_select->select_n_having_items+=
- child->select_n_having_items;
- }
- ;
-
-opt_query_expression_options:
- /* empty */
- | query_expression_option_list
- ;
-
-query_expression_option_list:
- query_expression_option_list query_expression_option
- | query_expression_option
- ;
-
query_expression_option:
STRAIGHT_JOIN { Select->options|= SELECT_STRAIGHT_JOIN; }
| HIGH_PRIORITY
{
- if (unlikely(Lex->check_simple_select(&$1)))
- MYSQL_YYABORT;
YYPS->m_lock_type= TL_READ_HIGH_PRIORITY;
YYPS->m_mdl_type= MDL_SHARED_READ;
Select->options|= SELECT_HIGH_PRIORITY;
@@ -17241,18 +17036,8 @@ query_expression_option:
| DISTINCT { Select->options|= SELECT_DISTINCT; }
| SQL_SMALL_RESULT { Select->options|= SELECT_SMALL_RESULT; }
| SQL_BIG_RESULT { Select->options|= SELECT_BIG_RESULT; }
- | SQL_BUFFER_RESULT
- {
- if (unlikely(Lex->check_simple_select(&$1)))
- MYSQL_YYABORT;
- Select->options|= OPTION_BUFFER_RESULT;
- }
- | SQL_CALC_FOUND_ROWS
- {
- if (unlikely(Lex->check_simple_select(&$1)))
- MYSQL_YYABORT;
- Select->options|= OPTION_FOUND_ROWS;
- }
+ | SQL_BUFFER_RESULT { Select->options|= OPTION_BUFFER_RESULT; }
+ | SQL_CALC_FOUND_ROWS { Select->options|= OPTION_FOUND_ROWS; }
| ALL { Select->options|= SELECT_ALL; }
;
@@ -17340,35 +17125,14 @@ view_select:
lex->parsing_options.allows_variable= FALSE;
lex->create_view->select.str= (char *) YYLIP->get_cpp_ptr();
}
- opt_with_clause query_expression_body_view view_check_option
+ query_expression
+ view_check_option
{
- LEX *lex= Lex;
- size_t len= YYLIP->get_cpp_ptr() - lex->create_view->select.str;
- void *create_view_select= thd->memdup(lex->create_view->select.str, len);
- lex->create_view->select.length= len;
- lex->create_view->select.str= (char *) create_view_select;
- trim_whitespace(thd->charset(),
- &lex->create_view->select);
- lex->create_view->check= $4;
- lex->parsing_options.allows_variable= TRUE;
- lex->current_select->set_with_clause($2);
+ if (Lex->parsed_create_view($2, $3))
+ MYSQL_YYABORT;
}
;
-/*
- SQL Standard <query expression body> for VIEWs.
- Does not include INTO and PROCEDURE clauses.
-*/
-query_expression_body_view:
- SELECT_SYM select_options_and_item_list select_init3_view
- | table_value_constructor
- | table_value_constructor union_order_or_limit
- | table_value_constructor union_list_view
- | '(' select_paren_view ')'
- | '(' select_paren_view ')' union_order_or_limit
- | '(' select_paren_view ')' union_list_view
- ;
-
view_check_option:
/* empty */ { $$= VIEW_CHECK_NONE; }
| WITH CHECK_SYM OPTION { $$= VIEW_CHECK_CASCADED; }
@@ -17467,11 +17231,10 @@ trigger_tail:
sp_proc_stmt alternatives are not saving/restoring LEX, so
lex->query_tables can be wiped out.
*/
- if (unlikely(!lex->select_lex.
- add_table_to_list(thd, $10, (LEX_CSTRING*) 0,
- TL_OPTION_UPDATING,
- TL_READ_NO_INSERT,
- MDL_SHARED_NO_WRITE)))
+ if (!lex->first_select_lex()->
+ add_table_to_list(thd, $10, (LEX_CSTRING*) 0,
+ TL_OPTION_UPDATING, TL_READ_NO_INSERT,
+ MDL_SHARED_NO_WRITE))
MYSQL_YYABORT;
}
;
diff --git a/sql/sql_yacc_ora.yy b/sql/sql_yacc_ora.yy
index 933b9dd2429..28a93806469 100644
--- a/sql/sql_yacc_ora.yy
+++ b/sql/sql_yacc_ora.yy
@@ -189,6 +189,20 @@ void ORAerror(THD *thd, const char *s)
uint offset;
} sp_cursor_name_and_offset;
vers_history_point_t vers_history_point;
+ struct
+ {
+ enum sub_select_type unit_type;
+ bool distinct;
+ } unit_operation;
+ struct
+ {
+ SELECT_LEX *first;
+ SELECT_LEX *prev_last;
+ } select_list;
+ SQL_I_List<ORDER> *select_order;
+ Lex_select_lock select_lock;
+ Lex_select_limit select_limit;
+ Lex_order_limit_lock *order_limit_lock;
/* pointers */
Create_field *create_field;
@@ -234,6 +248,7 @@ void ORAerror(THD *thd, const char *s)
handlerton *db_type;
st_select_lex *select_lex;
+ st_select_lex_unit *select_lex_unit;
struct p_elem_val *p_elem_value;
class Window_frame *window_frame;
class Window_frame_bound *window_frame_bound;
@@ -243,7 +258,6 @@ void ORAerror(THD *thd, const char *s)
/* enums */
enum enum_sp_suid_behaviour sp_suid;
enum enum_view_suid view_suid;
- enum sub_select_type unit_type;
enum Condition_information_item::Name cond_info_item_name;
enum enum_diag_condition_item_name diag_condition_item_name;
enum Diagnostics_information::Which_area diag_area;
@@ -282,10 +296,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
%parse-param { THD *thd }
%lex-param { THD *thd }
/*
- Currently there are 63 shift/reduce conflicts.
+ Currently there are 59 shift/reduce conflicts.
We should not introduce new conflicts any more.
*/
-%expect 63
+%expect 59
/*
Comments for TOKENS.
@@ -436,6 +450,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
%token LEADING /* SQL-2003-R */
%token LEAVE_SYM
%token LEFT /* SQL-2003-R */
+%token LEFT_PAREN_ALT /* INTERNAL */
+%token LEFT_PAREN_WITH /* INTERNAL */
+%token LEFT_PAREN_LIKE /* INTERNAL */
%token LEX_HOSTNAME
%token LIKE /* SQL-2003-R */
%token LIMIT
@@ -1181,7 +1198,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
NCHAR_STRING
%type <lex_str_ptr>
- opt_table_alias
+ opt_table_alias_clause
+ table_alias_clause
%type <ident_cli>
IDENT
@@ -1248,7 +1266,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
opt_temporary all_or_any opt_distinct opt_glimit_clause
opt_ignore_leaves fulltext_options union_option
opt_not
- select_derived_init transaction_access_mode_types
+ transaction_access_mode_types
opt_natural_language_mode opt_query_expansion
opt_ev_status opt_ev_on_completion ev_on_completion opt_ev_comment
ev_alter_on_schedule_completion opt_ev_rename_to opt_ev_sql_stmt
@@ -1371,11 +1389,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
join_table_list join_table
table_factor table_ref esc_table_ref
table_primary_ident table_primary_derived
- select_derived derived_table_list
- select_derived_union
- derived_simple_table
- derived_query_specification
- derived_table_value_constructor
+ derived_table_list table_reference_list_parens
+ nested_table_reference_list join_table_parens
%type <date_time_type> date_time_type;
%type <interval> interval
@@ -1411,14 +1426,19 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
UNDERSCORE_CHARSET
%type <select_lex> subselect
- get_select_lex get_select_lex_derived
- simple_table
query_specification
- query_term_union_not_ready
- query_term_union_ready
- query_expression_body
- select_paren_derived
table_value_constructor
+ simple_table
+ query_primary
+ query_primary_parens
+ select_into_query_specification
+
+
+%type <select_lex_unit>
+ query_specification_start
+ query_expression_body
+ query_expression
+ query_expression_unit
%type <boolfunc2creator> comp_op
@@ -1430,11 +1450,28 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
%type <virtual_column> opt_check_constraint check_constraint virtual_column_func
column_default_expr
-%type <unit_type> unit_type_decl
+
+%type <unit_operation> unit_type_decl
+
+%type <select_lock>
+ opt_procedure_or_into
+ opt_select_lock_type
+ select_lock_type
+ opt_lock_wait_timeout_new
+
+%type <select_limit> opt_limit_clause limit_clause limit_options
+
+%type <order_limit_lock>
+ query_expression_tail
+ order_or_limit
+ opt_order_limit_lock
+
+%type <select_order> opt_order_clause order_clause order_list
%type <NONE>
analyze_stmt_command
- query verb_clause create change select do drop insert replace insert2
+ query verb_clause create change select select_into
+ do drop insert replace insert2
insert_values update delete truncate rename compound_statement
show describe load alter optimize keycache preload flush
reset purge commit rollback savepoint release
@@ -1450,7 +1487,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
assign_to_keycache_parts
preload_list preload_list_or_parts preload_keys preload_keys_parts
select_item_list select_item values_list no_braces
- opt_limit_clause delete_limit_clause fields opt_values values
+ delete_limit_clause fields opt_values values
procedure_list procedure_list2 procedure_item
field_def handler opt_generated_always
opt_ignore opt_column opt_restrict
@@ -1470,9 +1507,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
table_to_table_list table_to_table opt_table_list opt_as
handler_rkey_function handler_read_or_scan
single_multi table_wild_list table_wild_one opt_wild
- union_clause union_list
- subselect_start opt_and charset
- subselect_end select_var_list select_var_list_init help
+ opt_and charset
+ select_var_list select_var_list_init help
opt_extended_describe shutdown
opt_format_json
prepare prepare_src execute deallocate
@@ -1623,8 +1659,8 @@ rule: <-- starts at col 1
query:
END_OF_INPUT
{
- if (likely(!thd->bootstrap) &&
- unlikely(!(thd->lex->select_lex.options & OPTION_FOUND_COMMENT)))
+ if (!thd->bootstrap &&
+ (!(thd->lex->lex_options & OPTION_LEX_FOUND_COMMENT)))
my_yyabort_error((ER_EMPTY_QUERY, MYF(0)));
thd->lex->sql_command= SQLCOM_EMPTY_QUERY;
@@ -1719,6 +1755,7 @@ statement:
| rollback
| savepoint
| select
+ | select_into
| set
| set_assign
| signal_stmt
@@ -2073,17 +2110,22 @@ connection_name:
/* create a table */
create:
- create_or_replace opt_temporary TABLE_SYM opt_if_not_exists table_ident
+ create_or_replace opt_temporary TABLE_SYM opt_if_not_exists
{
LEX *lex= thd->lex;
lex->create_info.init();
- if (unlikely(lex->set_command_with_check(SQLCOM_CREATE_TABLE, $2,
- $1 | $4)))
+ if (lex->main_select_push())
+ MYSQL_YYABORT;
+ lex->current_select->parsing_place= BEFORE_OPT_LIST;
+ if (lex->set_command_with_check(SQLCOM_CREATE_TABLE, $2, $1 | $4))
MYSQL_YYABORT;
- if (unlikely(!lex->select_lex.add_table_to_list(thd, $5, NULL,
- TL_OPTION_UPDATING,
- TL_WRITE,
- MDL_EXCLUSIVE)))
+ }
+ table_ident
+ {
+ LEX *lex= thd->lex;
+ if (!lex->first_select_lex()->
+ add_table_to_list(thd, $6, NULL, TL_OPTION_UPDATING,
+ TL_WRITE, MDL_EXCLUSIVE))
MYSQL_YYABORT;
lex->alter_info.reset();
/*
@@ -2098,7 +2140,6 @@ create:
create_body
{
LEX *lex= thd->lex;
- lex->current_select= &lex->select_lex;
if ((lex->create_info.used_fields & HA_CREATE_USED_ENGINE) &&
!lex->create_info.db_type)
{
@@ -2107,22 +2148,24 @@ create:
ER_WARN_USING_OTHER_HANDLER,
ER_THD(thd, ER_WARN_USING_OTHER_HANDLER),
hton_name(lex->create_info.db_type)->str,
- $5->table.str);
+ $6->table.str);
}
create_table_set_open_action_and_adjust_tables(lex);
+ Lex->pop_select(); //main select
}
| create_or_replace opt_temporary SEQUENCE_SYM opt_if_not_exists table_ident
{
LEX *lex= thd->lex;
+ if (Lex->main_select_push())
+ MYSQL_YYABORT;
lex->create_info.init();
if (unlikely(lex->set_command_with_check(SQLCOM_CREATE_SEQUENCE, $2,
$1 | $4)))
MYSQL_YYABORT;
- if (unlikely(!lex->select_lex.add_table_to_list(thd, $5, NULL,
- TL_OPTION_UPDATING,
- TL_WRITE,
- MDL_EXCLUSIVE)))
+ if (!lex->first_select_lex()->
+ add_table_to_list(thd, $5, NULL, TL_OPTION_UPDATING,
+ TL_WRITE, MDL_EXCLUSIVE))
MYSQL_YYABORT;
/*
@@ -2145,8 +2188,9 @@ create:
if (unlikely(lex->create_info.seq_create_info->check_and_adjust(1)))
{
my_error(ER_SEQUENCE_INVALID_DATA, MYF(0),
- lex->select_lex.table_list.first->db.str,
- lex->select_lex.table_list.first->table_name.str);
+ lex->first_select_lex()->table_list.first->db.str,
+ lex->first_select_lex()->table_list.first->
+ table_name.str);
MYSQL_YYABORT;
}
@@ -2159,10 +2203,8 @@ create:
Lex->create_info.used_fields|= HA_CREATE_USED_SEQUENCE;
Lex->create_info.sequence= 1;
- lex->current_select= &lex->select_lex;
- if (unlikely((lex->create_info.used_fields &
- HA_CREATE_USED_ENGINE) &&
- !lex->create_info.db_type))
+ if ((lex->create_info.used_fields & HA_CREATE_USED_ENGINE) &&
+ !lex->create_info.db_type)
{
lex->create_info.use_default_db_type(thd);
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
@@ -2172,44 +2214,69 @@ create:
$5->table.str);
}
create_table_set_open_action_and_adjust_tables(lex);
+ Lex->pop_select(); //main select
}
- | create_or_replace opt_unique INDEX_SYM opt_if_not_exists ident
+ | create_or_replace opt_unique INDEX_SYM opt_if_not_exists
+ {
+ if (Lex->main_select_push())
+ MYSQL_YYABORT;
+ }
+ ident
opt_key_algorithm_clause
ON table_ident
{
- if (unlikely(Lex->add_create_index_prepare($8)))
+ if (Lex->add_create_index_prepare($9))
MYSQL_YYABORT;
- if (unlikely(Lex->add_create_index($2, &$5, $6, $1 | $4)))
+ if (Lex->add_create_index($2, &$6, $7, $1 | $4))
MYSQL_YYABORT;
}
'(' key_list ')' opt_lock_wait_timeout normal_key_options
- opt_index_lock_algorithm { }
- | create_or_replace fulltext INDEX_SYM opt_if_not_exists ident
+ opt_index_lock_algorithm
+ {
+ Lex->pop_select(); //main select
+ }
+ | create_or_replace fulltext INDEX_SYM
+ {
+ if (Lex->main_select_push())
+ MYSQL_YYABORT;
+ }
+ opt_if_not_exists ident
ON table_ident
{
- if (unlikely(Lex->add_create_index_prepare($7)))
+ if (Lex->add_create_index_prepare($8))
MYSQL_YYABORT;
- if (unlikely(Lex->add_create_index($2, &$5, HA_KEY_ALG_UNDEF,
- $1 | $4)))
+ if (Lex->add_create_index($2, &$6, HA_KEY_ALG_UNDEF, $1 | $5))
MYSQL_YYABORT;
}
'(' key_list ')' opt_lock_wait_timeout fulltext_key_options
- opt_index_lock_algorithm { }
- | create_or_replace spatial INDEX_SYM opt_if_not_exists ident
+ opt_index_lock_algorithm
+ {
+ Lex->pop_select(); //main select
+ }
+ | create_or_replace spatial INDEX_SYM
+ {
+ if (Lex->main_select_push())
+ MYSQL_YYABORT;
+ }
+ opt_if_not_exists ident
ON table_ident
{
- if (unlikely(Lex->add_create_index_prepare($7)))
+ if (Lex->add_create_index_prepare($8))
MYSQL_YYABORT;
- if (unlikely(Lex->add_create_index($2, &$5, HA_KEY_ALG_UNDEF,
- $1 | $4)))
+ if (Lex->add_create_index($2, &$6, HA_KEY_ALG_UNDEF, $1 | $5))
MYSQL_YYABORT;
}
'(' key_list ')' opt_lock_wait_timeout spatial_key_options
- opt_index_lock_algorithm { }
+ opt_index_lock_algorithm
+ {
+ Lex->pop_select(); //main select
+ }
| create_or_replace DATABASE opt_if_not_exists ident
{
Lex->create_info.default_table_charset= NULL;
Lex->create_info.used_fields= 0;
+ if (Lex->main_select_push())
+ MYSQL_YYABORT;
}
opt_create_database_options
{
@@ -2218,52 +2285,94 @@ create:
$1 | $3)))
MYSQL_YYABORT;
lex->name= $4;
+ Lex->pop_select(); //main select
}
| create_or_replace definer_opt opt_view_suid VIEW_SYM
opt_if_not_exists table_ident
{
- if (unlikely(Lex->add_create_view(thd, $1 | $5,
- DTYPE_ALGORITHM_UNDEFINED, $3,
- $6)))
+ if (Lex->main_select_push())
+ MYSQL_YYABORT;
+ if (Lex->add_create_view(thd, $1 | $5,
+ DTYPE_ALGORITHM_UNDEFINED, $3, $6))
MYSQL_YYABORT;
}
view_list_opt AS view_select
- { }
+ {
+ Lex->pop_select(); //main select
+ }
| create_or_replace view_algorithm definer_opt opt_view_suid VIEW_SYM
opt_if_not_exists table_ident
{
- if (unlikely(Lex->add_create_view(thd, $1 | $6, $2, $4, $7)))
+ if (Lex->main_select_push())
+ MYSQL_YYABORT;
+ if (Lex->add_create_view(thd, $1 | $6, $2, $4, $7))
MYSQL_YYABORT;
}
view_list_opt AS view_select
- { }
+ {
+ Lex->pop_select(); //main select
+ }
| create_or_replace definer_opt TRIGGER_SYM
- { Lex->create_info.set($1); }
+ {
+ if (Lex->main_select_push())
+ MYSQL_YYABORT;
+ Lex->create_info.set($1);
+ }
trigger_tail
- { }
+ {
+ Lex->pop_select(); //main select
+ }
| create_or_replace definer_opt PROCEDURE_SYM
- { Lex->create_info.set($1); }
+ {
+ if (Lex->main_select_push())
+ MYSQL_YYABORT;
+ Lex->create_info.set($1);
+ }
sp_tail_standalone
- { }
+ {
+ Lex->pop_select(); //main select
+ }
| create_or_replace definer_opt EVENT_SYM
- { Lex->create_info.set($1); }
+ {
+ if (Lex->main_select_push())
+ MYSQL_YYABORT;
+ Lex->create_info.set($1);
+ }
event_tail
- { }
+ {
+ Lex->pop_select(); //main select
+ }
| create_or_replace definer FUNCTION_SYM
- { Lex->create_info.set($1); }
+ {
+ if (Lex->main_select_push())
+ MYSQL_YYABORT;
+ Lex->create_info.set($1);
+ }
sf_tail_standalone
- { }
+ {
+ Lex->pop_select(); //main select
+ }
| create_or_replace no_definer FUNCTION_SYM
- { Lex->create_info.set($1); }
+ {
+ if (Lex->main_select_push())
+ MYSQL_YYABORT;
+ Lex->create_info.set($1);
+ }
create_function_tail
- { }
+ {
+ Lex->pop_select(); //main select
+ }
| create_or_replace no_definer AGGREGATE_SYM FUNCTION_SYM
{
+ if (Lex->main_select_push())
+ MYSQL_YYABORT;
Lex->create_info.set($1);
Lex->udf.type= UDFTYPE_AGGREGATE;
}
udf_tail
- { }
+ {
+ Lex->pop_select(); //main select
+ }
| create_or_replace USER_SYM opt_if_not_exists clear_privileges grant_list
opt_require_clause opt_resource_options
{
@@ -2886,7 +2995,7 @@ clear_privileges:
lex->columns.empty();
lex->grant= lex->grant_tot_col= 0;
lex->all_privileges= 0;
- lex->select_lex.db= null_clex_str;
+ lex->first_select_lex()->db= null_clex_str;
lex->ssl_type= SSL_TYPE_NOT_SPECIFIED;
lex->ssl_cipher= lex->x509_subject= lex->x509_issuer= 0;
bzero((char *)&(lex->mqh),sizeof(lex->mqh));
@@ -3516,7 +3625,7 @@ raise_stmt:
signal_stmt:
SIGNAL_SYM signal_value opt_set_signal_information
{
- if (unlikely(Lex->add_signal_statement(thd, $2)))
+ if (Lex->add_signal_statement(thd, $2))
MYSQL_YYABORT;
}
;
@@ -3963,7 +4072,9 @@ sp_proc_stmt_return:
;
reset_lex_expr:
- { Lex->sphead->reset_lex(thd); } expr { $$= $2; }
+ { Lex->sphead->reset_lex(thd); }
+ expr
+ { $$= $2; }
;
sp_proc_stmt_exit:
@@ -3979,14 +4090,14 @@ sp_proc_stmt_exit:
}
| EXIT_SYM WHEN_SYM reset_lex_expr
{
- if (unlikely(Lex->sp_exit_statement(thd, $3)) ||
- unlikely(Lex->sphead->restore_lex(thd)))
+ if (Lex->sp_exit_statement(thd, $3) ||
+ Lex->sphead->restore_lex(thd))
MYSQL_YYABORT;
}
| EXIT_SYM label_ident WHEN_SYM reset_lex_expr
{
- if (unlikely(Lex->sp_exit_statement(thd, &$2, $4)) ||
- unlikely(Lex->sphead->restore_lex(thd)))
+ if (Lex->sp_exit_statement(thd, &$2, $4) ||
+ Lex->sphead->restore_lex(thd))
MYSQL_YYABORT;
}
;
@@ -4004,14 +4115,14 @@ sp_proc_stmt_continue:
}
| CONTINUE_SYM WHEN_SYM reset_lex_expr
{
- if (unlikely(Lex->sp_continue_statement(thd, $3)) ||
- unlikely(Lex->sphead->restore_lex(thd)))
+ if (Lex->sp_continue_statement(thd, $3) ||
+ Lex->sphead->restore_lex(thd))
MYSQL_YYABORT;
}
| CONTINUE_SYM label_ident WHEN_SYM reset_lex_expr
{
- if (unlikely(Lex->sp_continue_statement(thd, &$2, $4)) ||
- unlikely(Lex->sphead->restore_lex(thd)))
+ if (Lex->sp_continue_statement(thd, &$2, $4) ||
+ Lex->sphead->restore_lex(thd))
MYSQL_YYABORT;
}
;
@@ -4070,7 +4181,7 @@ assignment_source_expr:
$$->sp_lex_in_use= true;
$$->set_item_and_free_list($3, thd->free_list);
thd->free_list= NULL;
- if (unlikely($$->sphead->restore_lex(thd)))
+ if ($$->sphead->restore_lex(thd))
MYSQL_YYABORT;
}
;
@@ -4079,6 +4190,7 @@ for_loop_bound_expr:
assignment_source_lex
{
Lex->sphead->reset_lex(thd, $1);
+ Lex->current_select->parsing_place= FOR_LOOP_BOUND;
}
expr
{
@@ -4088,6 +4200,7 @@ for_loop_bound_expr:
$$->set_item_and_free_list($3, NULL);
if (unlikely($$->sphead->restore_lex(thd)))
MYSQL_YYABORT;
+ Lex->current_select->parsing_place= NO_MATTER;
}
;
@@ -4309,7 +4422,8 @@ case_stmt_body:
{
if (unlikely(Lex->case_stmt_action_expr($2)))
MYSQL_YYABORT;
- if (unlikely(Lex->sphead->restore_lex(thd)))
+
+ if (Lex->sphead->restore_lex(thd))
MYSQL_YYABORT;
}
simple_when_clause_list
@@ -4601,7 +4715,7 @@ while_body:
LEX *lex= Lex;
if (unlikely(lex->sp_while_loop_expression(thd, $1)))
MYSQL_YYABORT;
- if (unlikely(lex->sphead->restore_lex(thd)))
+ if (lex->sphead->restore_lex(thd))
MYSQL_YYABORT;
}
sp_proc_stmts1 END LOOP_SYM
@@ -4624,7 +4738,7 @@ repeat_body:
if (unlikely(i == NULL) ||
unlikely(lex->sphead->add_instr(i)))
MYSQL_YYABORT;
- if (unlikely(lex->sphead->restore_lex(thd)))
+ if (lex->sphead->restore_lex(thd))
MYSQL_YYABORT;
/* We can shortcut the cont_backpatch here */
i->m_cont_dest= ip+1;
@@ -5104,26 +5218,16 @@ size_number:
*/
create_body:
- '(' create_field_list ')'
+ create_field_list_parens
{ Lex->create_info.option_list= NULL; }
opt_create_table_options opt_create_partitioning opt_create_select {}
| opt_create_table_options opt_create_partitioning opt_create_select {}
- /*
- the following rule is redundant, but there's a shift/reduce
- conflict that prevents the rule above from parsing a syntax like
- CREATE TABLE t1 (SELECT 1);
- */
- | '(' create_select_query_specification ')'
- | '(' create_select_query_specification ')'
- { Select->set_braces(1);} union_list {}
- | '(' create_select_query_specification ')'
- { Select->set_braces(1);} union_order_or_limit {}
| create_like
{
Lex->create_info.add(DDL_options_st::OPT_LIKE);
- TABLE_LIST *src_table= Lex->select_lex.add_table_to_list(thd,
- $1, NULL, 0, TL_READ, MDL_SHARED_READ);
+ TABLE_LIST *src_table= Lex->first_select_lex()->
+ add_table_to_list(thd, $1, NULL, 0, TL_READ, MDL_SHARED_READ);
if (unlikely(! src_table))
MYSQL_YYABORT;
/* CREATE TABLE ... LIKE is not allowed for views. */
@@ -5133,7 +5237,7 @@ create_body:
create_like:
LIKE table_ident { $$= $2; }
- | '(' LIKE table_ident ')' { $$= $3; }
+ | LEFT_PAREN_LIKE LIKE table_ident ')' { $$= $3; }
;
opt_create_select:
@@ -5142,23 +5246,20 @@ opt_create_select:
;
create_select_query_expression:
- opt_with_clause SELECT_SYM create_select_part2 opt_table_expression
- create_select_part4
- {
- Select->set_braces(0);
- Select->set_with_clause($1);
+ query_expression
+ {
+ if (Lex->parsed_insert_select($1->first_select()))
+ MYSQL_YYABORT;
}
- union_clause
- | opt_with_clause SELECT_SYM create_select_part2
- create_select_part3_union_not_ready create_select_part4
+ | LEFT_PAREN_WITH with_clause query_expression_body ')'
{
- Select->set_with_clause($1);
+ SELECT_LEX *first_select= $3->first_select();
+ $3->set_with_clause($2);
+ $2->attach_to(first_select);
+
+ if (Lex->parsed_insert_select(first_select))
+ MYSQL_YYABORT;
}
- | '(' create_select_query_specification ')'
- | '(' create_select_query_specification ')'
- { Select->set_braces(1);} union_list {}
- | '(' create_select_query_specification ')'
- { Select->set_braces(1);} union_order_or_limit {}
;
opt_create_partitioning:
@@ -5246,8 +5347,13 @@ partition_entry:
We enter here when opening the frm file to translate
partition info string into part_info data structure.
*/
+ if (Lex->main_select_push())
+ MYSQL_YYABORT;
+ }
+ partition
+ {
+ Lex->pop_select(); //main select
}
- partition {}
;
partition:
@@ -5901,56 +6007,6 @@ opt_versioning_interval_start:
End of partition parser part
*/
-create_select_query_specification:
- opt_with_clause SELECT_SYM create_select_part2 create_select_part3
- create_select_part4
- {
- Select->set_with_clause($1);
- }
- ;
-
-create_select_part2:
- {
- LEX *lex=Lex;
- if (lex->sql_command == SQLCOM_INSERT)
- lex->sql_command= SQLCOM_INSERT_SELECT;
- else if (lex->sql_command == SQLCOM_REPLACE)
- lex->sql_command= SQLCOM_REPLACE_SELECT;
- /*
- The following work only with the local list, the global list
- is created correctly in this case
- */
- lex->current_select->table_list.save_and_clear(&lex->save_list);
- mysql_init_select(lex);
- lex->current_select->parsing_place= SELECT_LIST;
- }
- select_options select_item_list
- {
- Select->parsing_place= NO_MATTER;
- }
- ;
-
-create_select_part3:
- opt_table_expression
- | create_select_part3_union_not_ready
- ;
-
-create_select_part3_union_not_ready:
- table_expression order_or_limit
- | order_or_limit
- ;
-
-create_select_part4:
- opt_select_lock_type
- {
- /*
- The following work only with the local list, the global list
- is created correctly in this case
- */
- Lex->current_select->table_list.push_front(&Lex->save_list);
- }
- ;
-
opt_as:
/* empty */ {}
| AS {}
@@ -6168,7 +6224,7 @@ create_table_option:
}
| UNION_SYM opt_equal
{
- Lex->select_lex.table_list.save_and_clear(&Lex->save_list);
+ Lex->first_select_lex()->table_list.save_and_clear(&Lex->save_list);
}
'(' opt_table_list ')'
{
@@ -6177,8 +6233,8 @@ create_table_option:
from the global list.
*/
LEX *lex=Lex;
- lex->create_info.merge_list= lex->select_lex.table_list;
- lex->select_lex.table_list= lex->save_list;
+ lex->create_info.merge_list= lex->first_select_lex()->table_list;
+ lex->first_select_lex()->table_list= lex->save_list;
/*
When excluding union list from the global list we assume that
elements of the former immediately follow elements which represent
@@ -6379,6 +6435,13 @@ create_field_list:
}
;
+create_field_list_parens:
+ LEFT_PAREN_ALT field_list ')'
+ {
+ Lex->create_last_non_select_table= Lex->last_table();
+ }
+ ;
+
field_list:
field_list_item
| field_list ',' field_list_item
@@ -6673,6 +6736,8 @@ parse_vcol_expr:
Prevent the end user from invoking this command.
*/
MYSQL_YYABORT_UNLESS(Lex->parse_vcol_expr);
+ if (Lex->main_select_push())
+ MYSQL_YYABORT;
}
expr
{
@@ -6680,14 +6745,15 @@ parse_vcol_expr:
if (unlikely(!v))
MYSQL_YYABORT;
Lex->last_field->vcol_info= v;
+ Lex->pop_select(); //main select
}
;
parenthesized_expr:
- subselect
+ remember_tok_start
+ query_expression
{
- $$= new (thd->mem_root) Item_singlerow_subselect(thd, $1);
- if (unlikely($$ == NULL))
+ if (!($$= Lex->create_item_query_expression(thd, $1, $2)))
MYSQL_YYABORT;
}
| expr
@@ -7713,23 +7779,25 @@ alter:
Lex->name= null_clex_str;
Lex->table_type= TABLE_TYPE_UNKNOWN;
Lex->sql_command= SQLCOM_ALTER_TABLE;
- Lex->duplicates= DUP_ERROR;
- Lex->select_lex.init_order();
+ Lex->duplicates= DUP_ERROR;
+ Lex->first_select_lex()->order_list.empty();
Lex->create_info.init();
Lex->create_info.row_type= ROW_TYPE_NOT_USED;
Lex->alter_info.reset();
Lex->no_write_to_binlog= 0;
Lex->create_info.storage_media= HA_SM_DEFAULT;
+ if (Lex->main_select_push())
+ MYSQL_YYABORT;
DBUG_ASSERT(!Lex->m_sql_cmd);
}
alter_options TABLE_SYM table_ident opt_lock_wait_timeout
{
- if (unlikely(!Lex->select_lex.add_table_to_list(thd, $5, NULL,
- TL_OPTION_UPDATING,
- TL_READ_NO_INSERT,
- MDL_SHARED_UPGRADABLE)))
+ if (!Lex->first_select_lex()->
+ add_table_to_list(thd, $5, NULL, TL_OPTION_UPDATING,
+ TL_READ_NO_INSERT, MDL_SHARED_UPGRADABLE))
MYSQL_YYABORT;
- Lex->select_lex.db= (Lex->select_lex.table_list.first)->db;
+ Lex->first_select_lex()->db=
+ (Lex->first_select_lex()->table_list.first)->db;
Lex->create_last_non_select_table= Lex->last_table();
}
alter_commands
@@ -7741,11 +7809,14 @@ alter:
if (unlikely(Lex->m_sql_cmd == NULL))
MYSQL_YYABORT;
}
+ Lex->pop_select(); //main select
}
| ALTER DATABASE ident_or_empty
{
Lex->create_info.default_table_charset= NULL;
Lex->create_info.used_fields= 0;
+ if (Lex->main_select_push())
+ MYSQL_YYABORT;
}
create_database_options
{
@@ -7755,6 +7826,7 @@ alter:
if (lex->name.str == NULL &&
unlikely(lex->copy_db_to(&lex->name)))
MYSQL_YYABORT;
+ Lex->pop_select(); //main select
}
| ALTER DATABASE ident UPGRADE_SYM DATA_SYM DIRECTORY_SYM NAME_SYM
{
@@ -7770,6 +7842,8 @@ alter:
if (unlikely(lex->sphead))
my_yyabort_error((ER_SP_NO_DROP_SP, MYF(0), "PROCEDURE"));
+ if (Lex->main_select_push())
+ MYSQL_YYABORT;
lex->sp_chistics.init();
}
sp_a_chistics
@@ -7778,6 +7852,9 @@ alter:
lex->sql_command= SQLCOM_ALTER_PROCEDURE;
lex->spname= $3;
+ Lex->pop_select(); //main select
+ if (Lex->check_main_unit_semantics())
+ MYSQL_YYABORT;
}
| ALTER FUNCTION_SYM sp_name
{
@@ -7785,6 +7862,8 @@ alter:
if (unlikely(lex->sphead))
my_yyabort_error((ER_SP_NO_DROP_SP, MYF(0), "FUNCTION"));
+ if (Lex->main_select_push())
+ MYSQL_YYABORT;
lex->sp_chistics.init();
}
sp_a_chistics
@@ -7793,14 +7872,23 @@ alter:
lex->sql_command= SQLCOM_ALTER_FUNCTION;
lex->spname= $3;
+ Lex->pop_select(); //main select
+ if (Lex->check_main_unit_semantics())
+ MYSQL_YYABORT;
}
| ALTER view_algorithm definer_opt opt_view_suid VIEW_SYM table_ident
{
- if (unlikely(Lex->add_alter_view(thd, $2, $4, $6)))
+ if (Lex->main_select_push())
+ MYSQL_YYABORT;
+ if (Lex->add_alter_view(thd, $2, $4, $6))
MYSQL_YYABORT;
}
view_list_opt AS view_select
- {}
+ {
+ Lex->pop_select(); //main select
+ if (Lex->check_main_unit_semantics())
+ MYSQL_YYABORT;
+ }
| ALTER definer_opt opt_view_suid VIEW_SYM table_ident
/*
We have two separate rules for ALTER VIEW rather that
@@ -7808,14 +7896,22 @@ alter:
with the ALTER EVENT below.
*/
{
- if (unlikely(Lex->add_alter_view(thd, VIEW_ALGORITHM_INHERIT, $3, $5)))
+ if (Lex->main_select_push())
+ MYSQL_YYABORT;
+ if (Lex->add_alter_view(thd, VIEW_ALGORITHM_INHERIT, $3, $5))
MYSQL_YYABORT;
}
view_list_opt AS view_select
- {}
+ {
+ Lex->pop_select(); //main select
+ if (Lex->check_main_unit_semantics())
+ MYSQL_YYABORT;
+ }
| ALTER definer_opt remember_name EVENT_SYM sp_name
{
- /*
+ if (Lex->main_select_push())
+ MYSQL_YYABORT;
+ /*
It is safe to use Lex->spname because
ALTER EVENT xxx RENATE TO yyy DO ALTER EVENT RENAME TO
is not allowed. Lex->spname is used in the case of RENAME TO
@@ -7847,6 +7943,8 @@ alter:
*/
Lex->sql_command= SQLCOM_ALTER_EVENT;
Lex->stmt_definition_end= (char*)YYLIP->get_cpp_ptr();
+
+ Lex->pop_select(); //main select
}
| ALTER TABLESPACE alter_tablespace_info
{
@@ -7890,16 +7988,17 @@ alter:
lex->create_info.init();
lex->no_write_to_binlog= 0;
DBUG_ASSERT(!lex->m_sql_cmd);
+ if (Lex->main_select_push())
+ MYSQL_YYABORT;
}
table_ident
{
LEX *lex= Lex;
- if (unlikely(!(lex->create_info.seq_create_info=
- new (thd->mem_root) sequence_definition())) ||
- unlikely(!lex->select_lex.add_table_to_list(thd, $5, NULL,
- TL_OPTION_SEQUENCE,
- TL_WRITE,
- MDL_EXCLUSIVE)))
+ if (!(lex->create_info.seq_create_info= new (thd->mem_root)
+ sequence_definition()) ||
+ !lex->first_select_lex()->
+ add_table_to_list(thd, $5, NULL, TL_OPTION_SEQUENCE,
+ TL_WRITE, MDL_EXCLUSIVE))
MYSQL_YYABORT;
}
sequence_defs
@@ -7908,6 +8007,9 @@ alter:
Lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_alter_sequence($3);
if (unlikely(Lex->m_sql_cmd == NULL))
MYSQL_YYABORT;
+ Lex->pop_select(); //main select
+ if (Lex->check_main_unit_semantics())
+ MYSQL_YYABORT;
}
;
@@ -8057,16 +8159,14 @@ alter_commands:
WITH TABLE_SYM table_ident have_partitioning
{
LEX *lex= thd->lex;
- lex->select_lex.db= $6->db;
- if (lex->select_lex.db.str == NULL &&
- unlikely(lex->copy_db_to(&lex->select_lex.db)))
+ if (lex->first_select_lex()->db.str == NULL &&
+ lex->copy_db_to(&lex->first_select_lex()->db))
MYSQL_YYABORT;
lex->name= $6->table;
lex->alter_info.partition_flags|= ALTER_PARTITION_EXCHANGE;
- if (unlikely(!lex->select_lex.add_table_to_list(thd, $6, NULL,
- TL_OPTION_UPDATING,
- TL_READ_NO_INSERT,
- MDL_SHARED_NO_WRITE)))
+ if (!lex->first_select_lex()->
+ add_table_to_list(thd, $6, NULL, TL_OPTION_UPDATING,
+ TL_READ_NO_INSERT, MDL_SHARED_NO_WRITE))
MYSQL_YYABORT;
DBUG_ASSERT(!lex->m_sql_cmd);
lex->m_sql_cmd= new (thd->mem_root)
@@ -8305,10 +8405,11 @@ alter_list_item:
| RENAME opt_to table_ident
{
LEX *lex=Lex;
- lex->select_lex.db= $3->db;
- if (lex->select_lex.db.str == NULL &&
- unlikely(lex->copy_db_to(&lex->select_lex.db)))
+ lex->first_select_lex()->db= $3->db;
+ if (lex->first_select_lex()->db.str == NULL &&
+ lex->copy_db_to(&lex->first_select_lex()->db))
MYSQL_YYABORT;
+
if (unlikely(check_table_name($3->table.str,$3->table.length,
FALSE)) ||
($3->db.str && unlikely(check_db_name((LEX_STRING*) &$3->db))))
@@ -9002,8 +9103,8 @@ adm_partition:
cache_keys_spec:
{
- Lex->select_lex.alloc_index_hints(thd);
- Select->set_index_hint_type(INDEX_HINT_USE,
+ Lex->first_select_lex()->alloc_index_hints(thd);
+ Select->set_index_hint_type(INDEX_HINT_USE,
INDEX_HINT_MASK_ALL);
}
cache_key_list_or_empty
@@ -9026,215 +9127,211 @@ opt_ignore_leaves:
select:
- opt_with_clause select_init
+ query_expression_body
{
- LEX *lex= Lex;
- lex->sql_command= SQLCOM_SELECT;
- lex->current_select->set_with_clause($1);
- }
- ;
-
-select_init:
- SELECT_SYM select_options_and_item_list select_init3
- | table_value_constructor
- | table_value_constructor union_list
- | table_value_constructor union_order_or_limit
- | '(' select_paren ')'
- | '(' select_paren ')' union_list
- | '(' select_paren ')' union_order_or_limit
- ;
-
-union_list_part2:
- SELECT_SYM select_options_and_item_list select_init3_union_query_term
- | table_value_constructor
- | table_value_constructor union_list
- | table_value_constructor union_order_or_limit
- | '(' select_paren_union_query_term ')'
- | '(' select_paren_union_query_term ')' union_list
- | '(' select_paren_union_query_term ')' union_order_or_limit
- ;
-
-select_paren:
- {
- Lex->current_select->set_braces(true);
+ if (Lex->push_select($1->fake_select_lex ?
+ $1->fake_select_lex :
+ $1->first_select()))
+ MYSQL_YYABORT;
}
- table_value_constructor
+ opt_procedure_or_into
{
- DBUG_ASSERT(Lex->current_select->braces);
+ Lex->pop_select();
+ if (Lex->select_finalize($1))
+ MYSQL_YYABORT;
}
- |
+ | with_clause query_expression_body
{
- /*
- In order to correctly parse UNION's global ORDER BY we need to
- set braces before parsing the clause.
- */
- Lex->current_select->set_braces(true);
+ if (Lex->push_select($2->fake_select_lex ?
+ $2->fake_select_lex :
+ $2->first_select()))
+ MYSQL_YYABORT;
}
- SELECT_SYM select_options_and_item_list select_part3
- opt_select_lock_type
+ opt_procedure_or_into
{
- DBUG_ASSERT(Lex->current_select->braces);
+ Lex->pop_select();
+ $2->set_with_clause($1);
+ $1->attach_to($2->first_select());
+ if (Lex->select_finalize($2))
+ MYSQL_YYABORT;
}
- | '(' select_paren ')'
;
-select_paren_union_query_term:
+
+select_into:
+ select_into_query_specification
{
- /*
- In order to correctly parse UNION's global ORDER BY we need to
- set braces before parsing the clause.
- */
- Lex->current_select->set_braces(true);
+ if (Lex->push_select($1))
+ MYSQL_YYABORT;
}
- SELECT_SYM select_options_and_item_list select_part3_union_query_term
- opt_select_lock_type
+ opt_order_limit_lock
{
- DBUG_ASSERT(Lex->current_select->braces);
- }
- | '(' select_paren_union_query_term ')'
- ;
+ st_select_lex_unit *unit;
+ if (!(unit= Lex->parsed_body_select($1, $3)))
+ MYSQL_YYABORT;
+ if (Lex->select_finalize(unit))
+ MYSQL_YYABORT;
+ }
+ ;
+
-select_paren_view:
+simple_table:
+ query_specification { $$= $1; }
+ | table_value_constructor { $$= $1; }
+ ;
+
+table_value_constructor:
+ VALUES
+ {
+ if (Lex->parsed_TVC_start())
+ MYSQL_YYABORT;
+ }
+ values_list
+ {
+ if (!($$= Lex->parsed_TVC_end()))
+ MYSQL_YYABORT;
+ }
+ ;
+
+query_specification_start:
+ SELECT_SYM
{
- /*
- In order to correctly parse UNION's global ORDER BY we need to
- set braces before parsing the clause.
- */
- Lex->current_select->set_braces(true);
+ SELECT_LEX *sel;
+ LEX *lex= Lex;
+ if (!(sel= lex->alloc_select(TRUE)) ||
+ lex->push_select(sel))
+ MYSQL_YYABORT;
+ sel->init_select();
+ sel->braces= FALSE;
}
- SELECT_SYM select_options_and_item_list select_part3_view
- opt_select_lock_type
+ select_options
{
- DBUG_ASSERT(Lex->current_select->braces);
+ Select->parsing_place= SELECT_LIST;
}
- | '(' select_paren_view ')'
- ;
+ select_item_list
+ {
+ Select->parsing_place= NO_MATTER;
+ }
+ ;
-/* The equivalent of select_paren for nested queries. */
-select_paren_derived:
+query_specification:
+ query_specification_start
+ opt_from_clause
+ opt_where_clause
+ opt_group_clause
+ opt_having_clause
+ opt_window_clause
{
- Lex->current_select->set_braces(true);
+ $$= Lex->pop_select();
}
- table_value_constructor
+ ;
+
+select_into_query_specification:
+ query_specification_start
+ into
+ opt_from_clause
+ opt_where_clause
+ opt_group_clause
+ opt_having_clause
+ opt_window_clause
{
- DBUG_ASSERT(Lex->current_select->braces);
- $$= Lex->current_select->master_unit()->first_select();
+ $$= Lex->pop_select();
}
- |
+ ;
+
+opt_from_clause:
+ /* Empty */
+ | from_clause
+ ;
+
+query_primary:
+ simple_table
+ { $$= $1; }
+ | query_primary_parens
+ { $$= $1; }
+ ;
+
+query_primary_parens:
+ '(' query_expression_unit
{
- Lex->current_select->set_braces(true);
+ if (Lex->parsed_unit_in_brackets($2))
+ MYSQL_YYABORT;
}
- SELECT_SYM select_part2_derived
- opt_table_expression
- opt_order_clause
- opt_limit_clause
- opt_select_lock_type
+ query_expression_tail ')'
{
- DBUG_ASSERT(Lex->current_select->braces);
- $$= Lex->current_select->master_unit()->first_select();
+ $$= Lex->parsed_unit_in_brackets_tail($2, $4);
}
- | '(' select_paren_derived ')' { $$= $2; }
- ;
-
-select_init3:
- opt_table_expression
- opt_select_lock_type
+ | '(' query_primary
{
- /* Parentheses carry no meaning here */
- Lex->current_select->set_braces(false);
+ Lex->push_select($2);
}
- union_clause
- | select_part3_union_not_ready
- opt_select_lock_type
+ query_expression_tail ')'
{
- /* Parentheses carry no meaning here */
- Lex->current_select->set_braces(false);
+ if (!($$= Lex->parsed_select_in_brackets($2, $4)))
+ YYABORT;
}
;
-
-select_init3_union_query_term:
- opt_table_expression
- opt_select_lock_type
+query_expression_unit:
+ query_primary
+ unit_type_decl
+ query_primary
{
- /* Parentheses carry no meaning here */
- Lex->current_select->set_braces(false);
+ if (!($$= Lex->parsed_select_expr_start($1, $3, $2.unit_type,
+ $2.distinct)))
+ YYABORT;
}
- union_clause
- | select_part3_union_not_ready_noproc
- opt_select_lock_type
+ | query_expression_unit
+ unit_type_decl
+ query_primary
{
- /* Parentheses carry no meaning here */
- Lex->current_select->set_braces(false);
+ if (!($$= Lex->parsed_select_expr_cont($1, $3, $2.unit_type,
+ $2.distinct, TRUE)))
+ YYABORT;
}
;
-
-select_init3_view:
- opt_table_expression opt_select_lock_type
+query_expression_body:
+ query_primary
{
- Lex->current_select->set_braces(false);
+ Lex->push_select($1);
}
- | opt_table_expression opt_select_lock_type
+ query_expression_tail
{
- Lex->current_select->set_braces(false);
+ if (!($$= Lex->parsed_body_select($1, $3)))
+ MYSQL_YYABORT;
}
- union_list_view
- | order_or_limit opt_select_lock_type
+ | query_expression_unit
{
- Lex->current_select->set_braces(false);
+ if (Lex->parsed_body_unit($1))
+ MYSQL_YYABORT;
}
- | table_expression order_or_limit opt_select_lock_type
+ query_expression_tail
{
- Lex->current_select->set_braces(false);
+ if (!($$= Lex->parsed_body_unit_tail($1, $3)))
+ MYSQL_YYABORT;
}
;
-/*
- The SELECT parts after select_item_list that cannot be followed by UNION.
-*/
-
-select_part3:
- opt_table_expression
- | select_part3_union_not_ready
- ;
-
-select_part3_union_query_term:
- opt_table_expression
- | select_part3_union_not_ready_noproc
- ;
-
-select_part3_view:
- opt_table_expression
- | order_or_limit
- | table_expression order_or_limit
- ;
-
-select_part3_union_not_ready:
- select_part3_union_not_ready_noproc
- | table_expression procedure_clause
- | table_expression order_or_limit procedure_clause
- ;
-
-select_part3_union_not_ready_noproc:
- order_or_limit
- | into opt_table_expression opt_order_clause opt_limit_clause
- | table_expression into
- | table_expression order_or_limit
- | table_expression order_or_limit into
- ;
-
-select_options_and_item_list:
+query_expression:
+ opt_with_clause
+ query_expression_body
{
- LEX *lex= Lex;
- SELECT_LEX *sel= lex->current_select;
- if (sel->linkage != UNION_TYPE)
- mysql_init_select(lex);
- lex->current_select->parsing_place= SELECT_LIST;
+ if ($1)
+ {
+ $2->set_with_clause($1);
+ $1->attach_to($2->first_select());
+ }
+ $$= $2;
}
- select_options select_item_list
+ ;
+
+subselect:
+ remember_tok_start
+ query_expression
{
- Select->parsing_place= NO_MATTER;
+ if (!($$= Lex->parsed_subselect($2, $1)))
+ YYABORT;
}
;
@@ -9242,18 +9339,6 @@ select_options_and_item_list:
/**
<table expression>, as in the SQL standard.
*/
-table_expression:
- from_clause
- opt_where_clause
- opt_group_clause
- opt_having_clause
- opt_window_clause
- ;
-
-opt_table_expression:
- /* Empty */
- | table_expression
- ;
from_clause:
FROM table_reference_list
@@ -9356,59 +9441,70 @@ select_option:
query_expression_option
| SQL_NO_CACHE_SYM
{
- /*
- Allow this flag only on the first top-level SELECT statement, if
- SQL_CACHE wasn't specified, and only once per query.
- */
- if (unlikely(Lex->current_select != &Lex->select_lex))
- my_yyabort_error((ER_CANT_USE_OPTION_HERE, MYF(0), "SQL_NO_CACHE"));
- if (unlikely(Lex->select_lex.sql_cache == SELECT_LEX::SQL_CACHE))
- my_yyabort_error((ER_WRONG_USAGE, MYF(0), "SQL_CACHE", "SQL_NO_CACHE"));
- if (unlikely(Lex->select_lex.sql_cache == SELECT_LEX::SQL_NO_CACHE))
+ /*
+ Allow this flag once per query.
+ */
+ if (Select->options & OPTION_NO_QUERY_CACHE)
my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "SQL_NO_CACHE"));
-
- Lex->safe_to_cache_query=0;
- Lex->select_lex.options&= ~OPTION_TO_QUERY_CACHE;
- Lex->select_lex.sql_cache= SELECT_LEX::SQL_NO_CACHE;
+ Select->options|= OPTION_NO_QUERY_CACHE;
}
| SQL_CACHE_SYM
{
- /*
- Allow this flag only on the first top-level SELECT statement, if
- SQL_NO_CACHE wasn't specified, and only once per query.
- */
- if (unlikely(Lex->current_select != &Lex->select_lex))
- my_yyabort_error((ER_CANT_USE_OPTION_HERE, MYF(0), "SQL_CACHE"));
- if (unlikely(Lex->select_lex.sql_cache == SELECT_LEX::SQL_NO_CACHE))
- my_yyabort_error((ER_WRONG_USAGE, MYF(0), "SQL_NO_CACHE", "SQL_CACHE"));
- if (unlikely(Lex->select_lex.sql_cache == SELECT_LEX::SQL_CACHE))
+ /*
+ Allow this flag once per query.
+ */
+ if (Select->options & OPTION_TO_QUERY_CACHE)
my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "SQL_CACHE"));
-
- Lex->safe_to_cache_query=1;
- Lex->select_lex.options|= OPTION_TO_QUERY_CACHE;
- Lex->select_lex.sql_cache= SELECT_LEX::SQL_CACHE;
+ Select->options|= OPTION_TO_QUERY_CACHE;
}
;
-opt_select_lock_type:
- /* empty */
- | FOR_SYM UPDATE_SYM opt_lock_wait_timeout
+
+select_lock_type:
+ FOR_SYM UPDATE_SYM opt_lock_wait_timeout_new
{
- LEX *lex=Lex;
- lex->current_select->lock_type= TL_WRITE;
- lex->current_select->set_lock_for_tables(TL_WRITE);
- lex->safe_to_cache_query=0;
+ $$= $3;
+ $$.defined_lock= TRUE;
+ $$.update_lock= TRUE;
}
- | LOCK_SYM IN_SYM SHARE_SYM MODE_SYM opt_lock_wait_timeout
+ | LOCK_SYM IN_SYM SHARE_SYM MODE_SYM opt_lock_wait_timeout_new
{
- LEX *lex=Lex;
- lex->current_select->lock_type= TL_READ_WITH_SHARED_LOCKS;
- lex->current_select->
- set_lock_for_tables(TL_READ_WITH_SHARED_LOCKS);
- lex->safe_to_cache_query=0;
+ $$= $5;
+ $$.defined_lock= TRUE;
+ $$.update_lock= FALSE;
}
;
+
+opt_select_lock_type:
+ /* empty */
+ {
+ $$.empty();
+ }
+ | select_lock_type
+ {
+ $$= $1;
+ }
+ ;
+
+
+opt_lock_wait_timeout_new:
+ /* empty */
+ {
+ $$.empty();
+ }
+ | WAIT_SYM ulong_num
+ {
+ $$.defined_timeout= TRUE;
+ $$.timeout= $2;
+ }
+ | NOWAIT_SYM
+ {
+ $$.defined_timeout= TRUE;
+ $$.timeout= 0;
+ }
+ ;
+
select_item_list:
select_item_list ',' select_item
| select_item
@@ -10105,7 +10201,21 @@ column_default_non_parenthesized_expr:
| param_marker { $$= $1; }
| variable
| sum_expr
+ {
+ if (!Lex->select_stack_top)
+ {
+ my_error(ER_INVALID_GROUP_FUNC_USE, MYF(0));
+ MYSQL_YYABORT;
+ }
+ }
| window_func_expr
+ {
+ if (!Lex->select_stack_top)
+ {
+ my_error(ER_WRONG_PLACEMENT_OF_WINDOW_FUNCTION, MYF(0));
+ MYSQL_YYABORT;
+ }
+ }
| inverse_distribution_function
| ROW_SYM '(' expr ',' expr_list ')'
{
@@ -11734,10 +11844,15 @@ esc_table_ref:
/* Equivalent to <table reference list> in the SQL:2003 standard. */
/* Warning - may return NULL in case of incomplete SELECT */
derived_table_list:
- esc_table_ref { $$=$1; }
+ esc_table_ref
+ {
+ $$=$1;
+ Select->add_joined_table($1);
+ }
| derived_table_list ',' esc_table_ref
{
MYSQL_YYABORT_UNLESS($1 && ($$=$3));
+ Select->add_joined_table($3);
}
;
@@ -11756,11 +11871,18 @@ join_table:
left-associative joins.
*/
table_ref normal_join table_ref %prec TABLE_REF_PRIORITY
- { MYSQL_YYABORT_UNLESS($1 && ($$=$3)); $3->straight=$2; }
+ {
+ MYSQL_YYABORT_UNLESS($1 && ($$=$3));
+ Select->add_joined_table($1);
+ Select->add_joined_table($3);
+ $3->straight=$2;
+ }
| table_ref normal_join table_ref
ON
{
MYSQL_YYABORT_UNLESS($1 && $3);
+ Select->add_joined_table($1);
+ Select->add_joined_table($3);
/* Change the current name resolution context to a local context. */
if (unlikely(push_new_name_resolution_context(thd, $1, $3)))
MYSQL_YYABORT;
@@ -11777,6 +11899,8 @@ join_table:
USING
{
MYSQL_YYABORT_UNLESS($1 && $3);
+ Select->add_joined_table($1);
+ Select->add_joined_table($3);
}
'(' using_list ')'
{
@@ -11787,6 +11911,8 @@ join_table:
| table_ref NATURAL inner_join table_factor
{
MYSQL_YYABORT_UNLESS($1 && ($$=$4));
+ Select->add_joined_table($1);
+ Select->add_joined_table($4);
$4->straight=$3;
add_join_natural($1,$4,NULL,Select);
}
@@ -11796,6 +11922,8 @@ join_table:
ON
{
MYSQL_YYABORT_UNLESS($1 && $5);
+ Select->add_joined_table($1);
+ Select->add_joined_table($5);
/* Change the current name resolution context to a local context. */
if (unlikely(push_new_name_resolution_context(thd, $1, $5)))
MYSQL_YYABORT;
@@ -11812,6 +11940,8 @@ join_table:
| table_ref LEFT opt_outer JOIN_SYM table_factor
{
MYSQL_YYABORT_UNLESS($1 && $5);
+ Select->add_joined_table($1);
+ Select->add_joined_table($5);
}
USING '(' using_list ')'
{
@@ -11822,6 +11952,8 @@ join_table:
| table_ref NATURAL LEFT opt_outer JOIN_SYM table_factor
{
MYSQL_YYABORT_UNLESS($1 && $6);
+ Select->add_joined_table($1);
+ Select->add_joined_table($6);
add_join_natural($1,$6,NULL,Select);
$6->outer_join|=JOIN_TYPE_LEFT;
$$=$6;
@@ -11832,6 +11964,8 @@ join_table:
ON
{
MYSQL_YYABORT_UNLESS($1 && $5);
+ Select->add_joined_table($1);
+ Select->add_joined_table($5);
/* Change the current name resolution context to a local context. */
if (unlikely(push_new_name_resolution_context(thd, $1, $5)))
MYSQL_YYABORT;
@@ -11849,6 +11983,8 @@ join_table:
| table_ref RIGHT opt_outer JOIN_SYM table_factor
{
MYSQL_YYABORT_UNLESS($1 && $5);
+ Select->add_joined_table($1);
+ Select->add_joined_table($5);
}
USING '(' using_list ')'
{
@@ -11860,6 +11996,8 @@ join_table:
| table_ref NATURAL RIGHT opt_outer JOIN_SYM table_factor
{
MYSQL_YYABORT_UNLESS($1 && $6);
+ Select->add_joined_table($1);
+ Select->add_joined_table($6);
add_join_natural($6,$1,NULL,Select);
LEX *lex= Lex;
if (unlikely(!($$= lex->current_select->convert_right_join())))
@@ -11894,238 +12032,45 @@ use_partition:
$$= $3;
}
;
-
-/*
- This is a flattening of the rules <table factor> and <table primary>
- in the SQL:2003 standard, since we don't have <sample clause>
- I.e.
- <table factor> ::= <table primary> [ <sample clause> ]
-*/
-/* Warning - may return NULL in case of incomplete SELECT */
table_factor:
- table_primary_ident
- | table_primary_derived
+ table_primary_ident { $$= $1; }
+ | table_primary_derived { $$= $1; }
+ | join_table_parens { $$= $1; }
+ | table_reference_list_parens { $$= $1; }
;
-table_primary_ident:
+table_reference_list_parens:
+ '(' table_reference_list_parens ')' { $$= $2; }
+ | '(' nested_table_reference_list ')'
{
- DBUG_ASSERT(Select);
- SELECT_LEX *sel= Select;
- sel->table_join_options= 0;
- }
- table_ident opt_use_partition opt_for_system_time_clause opt_table_alias opt_key_definition
- {
- if (unlikely(!($$= Select->add_table_to_list(thd, $2, $5,
- Select->get_table_join_options(),
- YYPS->m_lock_type,
- YYPS->m_mdl_type,
- Select->
- pop_index_hints(),
- $3))))
+ if (!($$= Select->end_nested_join(thd)))
MYSQL_YYABORT;
- Select->add_joined_table($$);
- if ($4)
- $$->vers_conditions= Lex->vers_conditions;
- }
- ;
-
-
-
-/*
- Represents a flattening of the following rules from the SQL:2003
- standard. This sub-rule corresponds to the sub-rule
- <table primary> ::= ... | <derived table> [ AS ] <correlation name>
-
- <derived table> ::= <table subquery>
- <table subquery> ::= <subquery>
- <subquery> ::= <left paren> <query expression> <right paren>
- <query expression> ::= [ <with clause> ] <query expression body>
-
- For the time being we use the non-standard rule
- select_derived_union which is a compromise between the standard
- and our parser. Possibly this rule could be replaced by our
- query_expression_body.
-*/
-
-table_primary_derived:
- '(' get_select_lex select_derived_union ')' opt_for_system_time_clause opt_table_alias
- {
- /* Use $2 instead of Lex->current_select as derived table will
- alter value of Lex->current_select. */
- if (!($3 || $6) && $2->embedding &&
- !$2->embedding->nested_join->join_list.elements)
- {
- /* we have a derived table ($3 == NULL) but no alias,
- Since we are nested in further parentheses so we
- can pass NULL to the outer level parentheses
- Permits parsing of "((((select ...))) as xyz)" */
- $$= 0;
- }
- else if (!$3)
- {
- /* Handle case of derived table, alias may be NULL if there
- are no outer parentheses, add_table_to_list() will throw
- error in this case */
- LEX *lex=Lex;
- lex->check_automatic_up(UNSPECIFIED_TYPE);
- SELECT_LEX *sel= lex->current_select;
- SELECT_LEX_UNIT *unit= sel->master_unit();
- lex->current_select= sel= unit->outer_select();
- Table_ident *ti= new (thd->mem_root) Table_ident(unit);
- if (unlikely(ti == NULL))
- MYSQL_YYABORT;
- if (unlikely(!($$= sel->add_table_to_list(thd,
- ti, $6, 0,
- TL_READ,
- MDL_SHARED_READ))))
- MYSQL_YYABORT;
- sel->add_joined_table($$);
- lex->pop_context();
- lex->nest_level--;
- }
- else if (unlikely($6 != NULL))
- {
- /*
- Tables with or without joins within parentheses cannot
- have aliases, and we ruled out derived tables above.
- */
- thd->parse_error();
- MYSQL_YYABORT;
- }
- else
- {
- /* nested join: FROM (t1 JOIN t2 ...),
- nest_level is the same as in the outer query */
- $$= $3;
- }
- /*
- Fields in derived table can be used in upper select in
- case of merge. We do not add HAVING fields because we do
- not merge such derived. We do not add union because
- also do not merge them
- */
- if ($$ && $$->derived &&
- !$$->derived->first_select()->next_select())
- $$->select_lex->add_where_field($$->derived->first_select());
- if ($5)
- {
- MYSQL_YYABORT_UNLESS(!$3);
- $$->vers_conditions= Lex->vers_conditions;
- }
}
- /* Represents derived table with WITH clause */
- | '(' get_select_lex subselect_start
- with_clause query_expression_body
- subselect_end ')' opt_for_system_time_clause opt_table_alias
- {
- LEX *lex=Lex;
- SELECT_LEX *sel= $2;
- SELECT_LEX_UNIT *unit= $5->master_unit();
- Table_ident *ti= new (thd->mem_root) Table_ident(unit);
- if (unlikely(ti == NULL))
- MYSQL_YYABORT;
- $5->set_with_clause($4);
- lex->current_select= sel;
- if (unlikely(!($$= sel->add_table_to_list(lex->thd,
- ti, $9, 0,
- TL_READ,
- MDL_SHARED_READ))))
- MYSQL_YYABORT;
- sel->add_joined_table($$);
- if ($8)
- $$->vers_conditions= Lex->vers_conditions;
- }
;
-/*
- This rule accepts just about anything. The reason is that we have
- empty-producing rules in the beginning of rules, in this case
- subselect_start. This forces bison to take a decision which rules to
- reduce by long before it has seen any tokens. This approach ties us
- to a very limited class of parseable languages, and unfortunately
- SQL is not one of them. The chosen 'solution' was this rule, which
- produces just about anything, even complete bogus statements, for
- instance ( table UNION SELECT 1 ).
- Fortunately, we know that the semantic value returned by
- select_derived is NULL if it contained a derived table, and a pointer to
- the base table's TABLE_LIST if it was a base table. So in the rule
- regarding union's, we throw a parse error manually and pretend it
- was bison that did it.
-
- Also worth noting is that this rule concerns query expressions in
- the from clause only. Top level select statements and other types of
- subqueries have their own union rules.
-*/
-select_derived_union:
- select_derived
- | select_derived union_order_or_limit
- {
- if (unlikely($1))
- {
- thd->parse_error();
- MYSQL_YYABORT;
- }
- }
- | select_derived union_head_non_top
+nested_table_reference_list:
+ table_ref ',' table_ref
{
- if (unlikely($1))
- {
- thd->parse_error();
+ if (Select->init_nested_join(thd))
MYSQL_YYABORT;
- }
- }
- union_list_derived_part2
- | derived_simple_table opt_select_lock_type
- | derived_simple_table order_or_limit opt_select_lock_type
- | derived_simple_table opt_select_lock_type union_list_derived
- ;
-
-union_list_derived_part2:
- query_term_union_not_ready { Lex->pop_context(); }
- | query_term_union_ready { Lex->pop_context(); }
- | query_term_union_ready { Lex->pop_context(); } union_list_derived
- ;
-
-union_list_derived:
- union_head_non_top union_list_derived_part2
- ;
-
-
-/* The equivalent of select_init2 for nested queries. */
-select_init2_derived:
- select_part2_derived
- {
- Select->set_braces(0);
+ Select->add_joined_table($1);
+ Select->add_joined_table($3);
+ $$= $1->embedding;
}
- ;
-
-/* The equivalent of select_part2 for nested queries. */
-select_part2_derived:
- {
- LEX *lex= Lex;
- SELECT_LEX *sel= lex->current_select;
- if (sel->linkage != UNION_TYPE)
- mysql_init_select(lex);
- lex->current_select->parsing_place= SELECT_LIST;
- }
- opt_query_expression_options select_item_list
+ | nested_table_reference_list ',' table_ref
{
- Select->parsing_place= NO_MATTER;
+ Select->add_joined_table($3);
+ $$= $1;
}
;
-/* handle contents of parentheses in join expression */
-select_derived:
- get_select_lex_derived derived_table_list
+join_table_parens:
+ '(' join_table_parens ')' { $$= $2; }
+ | '(' join_table ')'
{
LEX *lex= Lex;
- /* for normal joins, $2 != NULL and end_nested_join() != NULL,
- for derived tables, both must equal NULL */
-
- if (unlikely(!($$= $1->end_nested_join(lex->thd)) && $2))
- MYSQL_YYABORT;
- if (unlikely(!$2 && $$))
+ if (!($$= lex->current_select->nest_last_join(thd)))
{
thd->parse_error();
MYSQL_YYABORT;
@@ -12133,83 +12078,54 @@ select_derived:
}
;
-derived_simple_table:
- derived_query_specification { $$= $1; }
- | derived_table_value_constructor { $$= $1; }
- ;
-/*
- Similar to query_specification, but for derived tables.
- Example: the inner parenthesized SELECT in this query:
- SELECT * FROM (SELECT * FROM t1);
-*/
-derived_query_specification:
- SELECT_SYM select_derived_init select_derived2
- {
- if ($2)
- Select->set_braces(1);
- $$= NULL;
- }
- ;
-derived_table_value_constructor:
- VALUES
- {
- Lex->tvc_start();
- }
- values_list
+table_primary_ident:
+ table_ident opt_use_partition opt_for_system_time_clause
+ opt_table_alias_clause opt_key_definition
{
- if (Lex->tvc_finalize_derived())
+ SELECT_LEX *sel= Select;
+ sel->table_join_options= 0;
+ if (!($$= Select->add_table_to_list(thd, $1, $4,
+ Select->get_table_join_options(),
+ YYPS->m_lock_type,
+ YYPS->m_mdl_type,
+ Select->pop_index_hints(),
+ $2)))
MYSQL_YYABORT;
- $$= NULL;
+ if ($3)
+ $$->vers_conditions= Lex->vers_conditions;
}
;
-select_derived2:
- {
- LEX *lex= Lex;
- lex->derived_tables|= DERIVED_SUBQUERY;
- if (unlikely(!lex->expr_allows_subselect ||
- lex->sql_command == (int)SQLCOM_PURGE))
- {
- thd->parse_error();
- MYSQL_YYABORT;
- }
- if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE ||
- unlikely(mysql_new_select(lex, 1, NULL)))
- MYSQL_YYABORT;
- mysql_init_select(lex);
- lex->current_select->linkage= DERIVED_TABLE_TYPE;
- lex->current_select->parsing_place= SELECT_LIST;
- }
- select_options select_item_list
- {
- Select->parsing_place= NO_MATTER;
- }
- opt_table_expression
- ;
+/*
+ Represents a flattening of the following rules from the SQL:2003
+ standard. This sub-rule corresponds to the sub-rule
+ <table primary> ::= ... | <derived table> [ AS ] <correlation name>
-get_select_lex:
- /* Empty */ { $$= Select; }
- ;
+ <derived table> ::= <table subquery>
+ <table subquery> ::= <subquery>
+ <subquery> ::= <left paren> <query expression> <right paren>
+ <query expression> ::= [ <with clause> ] <query expression body>
-get_select_lex_derived:
- get_select_lex
+ For the time being we use the non-standard rule
+ select_derived_union which is a compromise between the standard
+ and our parser. Possibly this rule could be replaced by our
+ query_expression_body.
+*/
+
+table_primary_derived:
+ query_primary_parens opt_for_system_time_clause table_alias_clause
{
- LEX *lex= Lex;
- if (unlikely($1->init_nested_join(lex->thd)))
- MYSQL_YYABORT;
+ if (!($$= Lex->parsed_derived_select($1, $2, $3)))
+ YYABORT;
}
- ;
-
-select_derived_init:
+ | '('
+ query_expression
+ ')' opt_for_system_time_clause table_alias_clause
{
- LEX *lex= Lex;
-
- TABLE_LIST *embedding= lex->current_select->embedding;
- $$= embedding &&
- !embedding->nested_join->join_list.elements;
- /* return true if we are deeply nested */
+ if (!($$= Lex->parsed_derived_unit($2, $4, $5)))
+ YYABORT;
}
;
@@ -12343,9 +12259,14 @@ table_alias:
| '='
;
-opt_table_alias:
+opt_table_alias_clause:
/* empty */ { $$=0; }
- | table_alias ident_table_alias
+
+ | table_alias_clause { $$= $1; }
+ ;
+
+table_alias_clause:
+ table_alias ident_table_alias
{
$$= (LEX_CSTRING*) thd->memdup(&$2,sizeof(LEX_STRING));
if (unlikely($$ == NULL))
@@ -12441,7 +12362,7 @@ olap_opt:
SQL-2003: GROUP BY ... CUBE(col1, col2, col3)
*/
LEX *lex=Lex;
- if (unlikely(lex->current_select->linkage == GLOBAL_OPTIONS_TYPE))
+ if (unlikely(lex->current_select->get_linkage() == GLOBAL_OPTIONS_TYPE))
my_yyabort_error((ER_WRONG_USAGE, MYF(0), "WITH CUBE",
"global union parameters"));
lex->current_select->olap= CUBE_TYPE;
@@ -12458,7 +12379,7 @@ olap_opt:
SQL-2003: GROUP BY ... ROLLUP(col1, col2, col3)
*/
LEX *lex= Lex;
- if (unlikely(lex->current_select->linkage == GLOBAL_OPTIONS_TYPE))
+ if (unlikely(lex->current_select->get_linkage() == GLOBAL_OPTIONS_TYPE))
my_yyabort_error((ER_WRONG_USAGE, MYF(0), "WITH ROLLUP",
"global union parameters"));
lex->current_select->olap= ROLLUP_TYPE;
@@ -12518,7 +12439,7 @@ opt_window_partition_clause:
opt_window_order_clause:
/* empty */ { }
- | ORDER_SYM BY order_list
+ | ORDER_SYM BY order_list { Select->order_list= *($3); }
;
opt_window_frame_clause:
@@ -12642,70 +12563,35 @@ alter_order_item:
opt_order_clause:
/* empty */
+ { $$= NULL; }
| order_clause
+ { $$= $1; }
;
order_clause:
ORDER_SYM BY
{
- LEX *lex=Lex;
- SELECT_LEX *sel= lex->current_select;
- SELECT_LEX_UNIT *unit= sel-> master_unit();
- if (unlikely(sel->linkage != GLOBAL_OPTIONS_TYPE &&
- sel->olap != UNSPECIFIED_OLAP_TYPE &&
- (sel->linkage != UNION_TYPE || sel->braces)))
- {
- my_error(ER_WRONG_USAGE, MYF(0),
- "CUBE/ROLLUP", "ORDER BY");
- MYSQL_YYABORT;
- }
- if (lex->sql_command != SQLCOM_ALTER_TABLE &&
- !unit->fake_select_lex)
- {
- /*
- A query of the of the form (SELECT ...) ORDER BY order_list is
- executed in the same way as the query
- SELECT ... ORDER BY order_list
- unless the SELECT construct contains ORDER BY or LIMIT clauses.
- Otherwise we create a fake SELECT_LEX if it has not been
- created yet.
- */
- SELECT_LEX *first_sl= unit->first_select();
- if (unlikely(!unit->is_unit_op() &&
- (first_sl->order_list.elements ||
- first_sl->select_limit) &&
- unit->add_fake_select_lex(thd)))
- MYSQL_YYABORT;
- }
- if (sel->master_unit()->is_unit_op() && !sel->braces)
- {
- /*
- At this point we don't know yet whether this is the last
- select in union or not, but we move ORDER BY to
- fake_select_lex anyway. If there would be one more select
- in union mysql_new_select will correctly throw error.
- */
- DBUG_ASSERT(sel->master_unit()->fake_select_lex);
- lex->current_select= sel->master_unit()->fake_select_lex;
- }
+ thd->where= "ORDER clause";
}
order_list
{
-
+ $$= $4;
}
;
order_list:
order_list ',' order_ident order_dir
{
- if (unlikely(add_order_to_list(thd, $3,(bool) $4)))
- MYSQL_YYABORT;
- }
+ $$= $1;
+ if (add_to_list(thd, *$$, $3,(bool) $4))
+ MYSQL_YYABORT;
+ }
| order_ident order_dir
{
- if (unlikely(add_order_to_list(thd, $1,(bool) $2)))
+ $$= new (thd->mem_root) SQL_I_List<ORDER>();
+ if (add_to_list(thd, *$$, $1, (bool) $2))
MYSQL_YYABORT;
- }
+ }
;
order_dir:
@@ -12715,63 +12601,61 @@ order_dir:
;
opt_limit_clause:
- /* empty */ {}
- | limit_clause {}
+ /* empty */
+ { $$.empty(); }
+ | limit_clause
+ { $$= $1; }
;
-limit_clause_init:
- LIMIT
- {
- SELECT_LEX *sel= Select;
- if (sel->master_unit()->is_unit_op() && !sel->braces)
- {
- /* Move LIMIT that belongs to UNION to fake_select_lex */
- Lex->current_select= sel->master_unit()->fake_select_lex;
- DBUG_ASSERT(Select);
- }
- }
- ;
-
limit_clause:
- limit_clause_init limit_options
+ LIMIT limit_options
{
- SELECT_LEX *sel= Select;
- if (!sel->select_limit->basic_const_item() ||
- sel->select_limit->val_int() > 0)
+ $$= $2;
+ if (!$$.select_limit->basic_const_item() ||
+ $$.select_limit->val_int() > 0)
Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_LIMIT);
}
- | limit_clause_init limit_options
+ | LIMIT limit_options
ROWS_SYM EXAMINED_SYM limit_rows_option
{
+ $$= $2;
Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_LIMIT);
}
- | limit_clause_init ROWS_SYM EXAMINED_SYM limit_rows_option
+ | LIMIT ROWS_SYM EXAMINED_SYM limit_rows_option
{
+ $$.select_limit= 0;
+ $$.offset_limit= 0;
+ $$.explicit_limit= 1;
Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_LIMIT);
}
;
+opt_global_limit_clause:
+ opt_limit_clause
+ {
+ Select->explicit_limit= $1.explicit_limit;
+ Select->select_limit= $1.select_limit;
+ Select->offset_limit= $1.offset_limit;
+ }
+
limit_options:
limit_option
{
- SELECT_LEX *sel= Select;
- sel->select_limit= $1;
- sel->offset_limit= 0;
- sel->explicit_limit= 1;
+ $$.select_limit= $1;
+ $$.offset_limit= 0;
+ $$.explicit_limit= 1;
}
| limit_option ',' limit_option
{
- SELECT_LEX *sel= Select;
- sel->select_limit= $3;
- sel->offset_limit= $1;
- sel->explicit_limit= 1;
+ $$.select_limit= $3;
+ $$.offset_limit= $1;
+ $$.explicit_limit= 1;
}
| limit_option OFFSET_SYM limit_option
{
- SELECT_LEX *sel= Select;
- sel->select_limit= $1;
- sel->offset_limit= $3;
- sel->explicit_limit= 1;
+ $$.select_limit= $1;
+ $$.offset_limit= $3;
+ $$.explicit_limit= 1;
}
;
@@ -12834,6 +12718,77 @@ delete_limit_clause:
| LIMIT limit_option ROWS_SYM EXAMINED_SYM { thd->parse_error(); MYSQL_YYABORT; }
;
+opt_order_limit_lock:
+ /* empty */
+ { $$= NULL; }
+ | order_or_limit
+ {
+ $$= $1;
+ $$->lock.empty();
+ }
+ | order_or_limit select_lock_type
+ {
+ $$= $1;
+ $$->lock= $2;
+ }
+ | select_lock_type
+ {
+ $$= new(thd->mem_root) Lex_order_limit_lock;
+ if (!$$)
+ YYABORT;
+ $$->order_list= NULL;
+ $$->limit.empty();
+ $$->lock= $1;
+ }
+ ;
+query_expression_tail:
+ opt_order_limit_lock
+ ;
+
+opt_procedure_or_into:
+ /* empty */
+ {
+ $$.empty();
+ }
+ | procedure_clause opt_select_lock_type
+ {
+ $$= $2;
+ }
+ | into opt_select_lock_type
+ {
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
+ ER_WARN_DEPRECATED_SYNTAX,
+ ER_THD(thd, ER_WARN_DEPRECATED_SYNTAX),
+ "<select expression> INTO <destination>;",
+ "'SELECT <select list> INTO <destination>"
+ " FROM...'");
+ $$= $2;
+ }
+ ;
+
+
+order_or_limit:
+ order_clause opt_limit_clause
+ {
+ $$= new(thd->mem_root) Lex_order_limit_lock;
+ if (!$$)
+ YYABORT;
+ $$->order_list= $1;
+ $$->limit= $2;
+ }
+ | limit_clause
+ {
+ Lex_order_limit_lock *op= $$= new(thd->mem_root) Lex_order_limit_lock;
+ if (!$$)
+ YYABORT;
+ op->order_list= NULL;
+ op->limit= $1;
+ $$->order_list= NULL;
+ $$->limit= $1;
+ }
+ ;
+
+
opt_plus:
/* empty */
| '+'
@@ -12903,14 +12858,11 @@ bool:
| TRUE_SYM { $$= 1; }
| FALSE_SYM { $$= 0; }
-
procedure_clause:
PROCEDURE_SYM ident /* Procedure name */
{
LEX *lex=Lex;
- DBUG_ASSERT(&lex->select_lex == lex->current_select);
-
lex->proc_list.elements=0;
lex->proc_list.first=0;
lex->proc_list.next= &lex->proc_list.first;
@@ -12930,6 +12882,7 @@ procedure_clause:
parameters are reduced.
*/
Lex->expr_allows_subselect= false;
+ Select->options|= OPTION_PROCEDURE_CLAUSE;
}
'(' procedure_list ')'
{
@@ -13013,6 +12966,7 @@ select_outvar:
into:
INTO into_destination
+ {}
;
into_destination:
@@ -13298,17 +13252,24 @@ insert:
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_INSERT;
- lex->duplicates= DUP_ERROR;
- mysql_init_select(lex);
+ lex->duplicates= DUP_ERROR;
+ if (Lex->main_select_push())
+ MYSQL_YYABORT;
+ mysql_init_select(lex);
+ lex->current_select->parsing_place= BEFORE_OPT_LIST;
}
insert_lock_option
opt_ignore insert2
{
Select->set_lock_for_tables($3);
- Lex->current_select= &Lex->select_lex;
+ Lex->current_select= Lex->first_select_lex();
}
insert_field_spec opt_insert_update
- {}
+ {
+ Lex->pop_select(); //main select
+ if (Lex->check_main_unit_semantics())
+ MYSQL_YYABORT;
+ }
;
replace:
@@ -13317,15 +13278,22 @@ replace:
LEX *lex=Lex;
lex->sql_command = SQLCOM_REPLACE;
lex->duplicates= DUP_REPLACE;
- mysql_init_select(lex);
+ if (Lex->main_select_push())
+ MYSQL_YYABORT;
+ mysql_init_select(lex);
+ lex->current_select->parsing_place= BEFORE_OPT_LIST;
}
replace_lock_option insert2
{
Select->set_lock_for_tables($3);
- Lex->current_select= &Lex->select_lex;
+ Lex->current_select= Lex->first_select_lex();
}
insert_field_spec
- {}
+ {
+ Lex->pop_select(); //main select
+ if (Lex->check_main_unit_semantics())
+ MYSQL_YYABORT;
+ }
;
insert_lock_option:
@@ -13368,15 +13336,14 @@ insert_table:
table_name_with_opt_use_partition
{
LEX *lex=Lex;
- lex->field_list.empty();
+ //lex->field_list.empty();
lex->many_values.empty();
lex->insert_list=0;
};
insert_field_spec:
insert_values {}
- | '(' ')' insert_values {}
- | '(' fields ')' insert_values {}
+ | insert_field_list insert_values {}
| SET
{
LEX *lex=Lex;
@@ -13384,20 +13351,33 @@ insert_field_spec:
unlikely(lex->many_values.push_back(lex->insert_list,
thd->mem_root)))
MYSQL_YYABORT;
+ lex->current_select->parsing_place= NO_MATTER;
}
ident_eq_list
;
+insert_field_list:
+ LEFT_PAREN_ALT opt_fields ')'
+ {
+ Lex->current_select->parsing_place= AFTER_LIST;
+ }
+ ;
+
+opt_fields:
+ /* empty */
+ | fields
+ ;
+
fields:
fields ',' insert_ident
{ Lex->field_list.push_back($3, thd->mem_root); }
| insert_ident { Lex->field_list.push_back($1, thd->mem_root); }
;
+
+
insert_values:
- VALUES values_list {}
- | VALUE_SYM values_list {}
- | create_select_query_expression {}
+ create_select_query_expression {}
;
values_list:
@@ -13508,6 +13488,8 @@ update:
UPDATE_SYM
{
LEX *lex= Lex;
+ if (Lex->main_select_push())
+ MYSQL_YYABORT;
mysql_init_select(lex);
lex->sql_command= SQLCOM_UPDATE;
lex->duplicates= DUP_ERROR;
@@ -13516,13 +13498,14 @@ update:
SET update_list
{
LEX *lex= Lex;
- if (lex->select_lex.table_list.elements > 1)
+ if (lex->first_select_lex()->table_list.elements > 1)
lex->sql_command= SQLCOM_UPDATE_MULTI;
- else if (unlikely(lex->select_lex.get_table_list()->derived))
+ else if (lex->first_select_lex()->get_table_list()->derived)
{
/* it is single table update and it is update of derived table */
my_error(ER_NON_UPDATABLE_TABLE, MYF(0),
- lex->select_lex.get_table_list()->alias.str, "UPDATE");
+ lex->first_select_lex()->get_table_list()->alias.str,
+ "UPDATE");
MYSQL_YYABORT;
}
/*
@@ -13532,7 +13515,14 @@ update:
*/
Select->set_lock_for_tables($3);
}
- opt_where_clause opt_order_clause delete_limit_clause {}
+ opt_where_clause opt_order_clause delete_limit_clause
+ {
+ if ($10)
+ Select->order_list= *($10);
+ Lex->pop_select(); //main select
+ if (Lex->check_main_unit_semantics())
+ MYSQL_YYABORT;
+ }
;
update_list:
@@ -13579,9 +13569,11 @@ delete:
mysql_init_select(lex);
YYPS->m_lock_type= TL_WRITE_DEFAULT;
YYPS->m_mdl_type= MDL_SHARED_WRITE;
+ if (Lex->main_select_push())
+ MYSQL_YYABORT;
lex->ignore= 0;
- lex->select_lex.init_order();
+ lex->first_select_lex()->order_list.empty();
}
delete_part2
;
@@ -13605,6 +13597,7 @@ delete_part2:
}
;
+
delete_single_table:
FROM table_ident opt_use_partition
{
@@ -13625,7 +13618,12 @@ single_multi:
opt_where_clause
opt_order_clause
delete_limit_clause
- opt_select_expressions {}
+ opt_select_expressions
+ {
+ if ($3)
+ Select->order_list= *($3);
+ Lex->pop_select(); //main select
+ }
| table_wild_list
{
mysql_init_multi_delete(Lex);
@@ -13636,6 +13634,9 @@ single_multi:
{
if (unlikely(multi_delete_set_locks_and_link_aux_tables(Lex)))
MYSQL_YYABORT;
+ Lex->pop_select(); //main select
+ if (Lex->check_main_unit_semantics())
+ MYSQL_YYABORT;
}
| FROM table_alias_ref_list
{
@@ -13647,9 +13648,13 @@ single_multi:
{
if (unlikely(multi_delete_set_locks_and_link_aux_tables(Lex)))
MYSQL_YYABORT;
+ Lex->pop_select(); //main select
+ if (Lex->check_main_unit_semantics())
+ MYSQL_YYABORT;
}
;
+
opt_select_expressions:
/* empty */
| RETURNING_SYM select_item_list
@@ -13715,9 +13720,9 @@ truncate:
LEX* lex= Lex;
lex->sql_command= SQLCOM_TRUNCATE;
lex->alter_info.reset();
- lex->select_lex.options= 0;
- lex->select_lex.sql_cache= SELECT_LEX::SQL_CACHE_UNSPECIFIED;
- lex->select_lex.init_order();
+ lex->first_select_lex()->options= 0;
+ lex->sql_cache= LEX::SQL_CACHE_UNSPECIFIED;
+ lex->first_select_lex()->order_list.empty();
YYPS->m_lock_type= TL_WRITE;
YYPS->m_mdl_type= MDL_EXCLUSIVE;
}
@@ -13809,6 +13814,8 @@ show:
LEX *lex=Lex;
lex->wild=0;
lex->ident= null_clex_str;
+ if (Lex->main_select_push())
+ MYSQL_YYABORT;
mysql_init_select(lex);
lex->current_select->parsing_place= SELECT_LIST;
lex->create_info.init();
@@ -13816,6 +13823,7 @@ show:
show_param
{
Select->parsing_place= NO_MATTER;
+ Lex->pop_select(); //main select
}
;
@@ -13831,40 +13839,40 @@ show_param:
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_SHOW_TABLES;
- lex->select_lex.db= $3;
- if (unlikely(prepare_schema_table(thd, lex, 0, SCH_TABLE_NAMES)))
+ lex->first_select_lex()->db= $3;
+ if (prepare_schema_table(thd, lex, 0, SCH_TABLE_NAMES))
MYSQL_YYABORT;
}
| opt_full TRIGGERS_SYM opt_db wild_and_where
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_SHOW_TRIGGERS;
- lex->select_lex.db= $3;
- if (unlikely(prepare_schema_table(thd, lex, 0, SCH_TRIGGERS)))
+ lex->first_select_lex()->db= $3;
+ if (prepare_schema_table(thd, lex, 0, SCH_TRIGGERS))
MYSQL_YYABORT;
}
| EVENTS_SYM opt_db wild_and_where
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_SHOW_EVENTS;
- lex->select_lex.db= $2;
- if (unlikely(prepare_schema_table(thd, lex, 0, SCH_EVENTS)))
+ lex->first_select_lex()->db= $2;
+ if (prepare_schema_table(thd, lex, 0, SCH_EVENTS))
MYSQL_YYABORT;
}
| TABLE_SYM STATUS_SYM opt_db wild_and_where
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_SHOW_TABLE_STATUS;
- lex->select_lex.db= $3;
- if (unlikely(prepare_schema_table(thd, lex, 0, SCH_TABLES)))
+ lex->first_select_lex()->db= $3;
+ if (prepare_schema_table(thd, lex, 0, SCH_TABLES))
MYSQL_YYABORT;
}
| OPEN_SYM TABLES opt_db wild_and_where
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_SHOW_OPEN_TABLES;
- lex->select_lex.db= $3;
- if (unlikely(prepare_schema_table(thd, lex, 0, SCH_OPEN_TABLES)))
+ lex->first_select_lex()->db= $3;
+ if (prepare_schema_table(thd, lex, 0, SCH_OPEN_TABLES))
MYSQL_YYABORT;
}
| PLUGINS_SYM
@@ -13913,12 +13921,13 @@ show_param:
LEX *lex= Lex;
lex->sql_command= SQLCOM_SHOW_BINLOG_EVENTS;
}
- opt_limit_clause
+ opt_global_limit_clause
| RELAYLOG_SYM optional_connection_name EVENTS_SYM binlog_in binlog_from
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_SHOW_RELAYLOG_EVENTS;
- } opt_limit_clause
+ }
+ opt_global_limit_clause
| keys_or_index from_or_in table_ident opt_db opt_where_clause
{
LEX *lex= Lex;
@@ -13960,13 +13969,13 @@ show_param:
LEX_CSTRING var= {STRING_WITH_LEN("error_count")};
(void) create_select_for_variable(thd, &var);
}
- | WARNINGS opt_limit_clause
+ | WARNINGS opt_global_limit_clause
{ Lex->sql_command = SQLCOM_SHOW_WARNS;}
- | ERRORS opt_limit_clause
+ | ERRORS opt_global_limit_clause
{ Lex->sql_command = SQLCOM_SHOW_ERRORS;}
| PROFILES_SYM
{ Lex->sql_command = SQLCOM_SHOW_PROFILES; }
- | PROFILE_SYM opt_profile_defs opt_profile_args opt_limit_clause
+ | PROFILE_SYM opt_profile_defs opt_profile_args opt_global_limit_clause
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_SHOW_PROFILE;
@@ -14028,7 +14037,7 @@ show_param:
{
LEX *lex= Lex;
lex->sql_command = SQLCOM_SHOW_CREATE;
- if (unlikely(!lex->select_lex.add_table_to_list(thd, $3, NULL,0)))
+ if (!lex->first_select_lex()->add_table_to_list(thd, $3, NULL,0))
MYSQL_YYABORT;
lex->create_info.storage_media= HA_SM_DEFAULT;
}
@@ -14036,7 +14045,7 @@ show_param:
{
LEX *lex= Lex;
lex->sql_command = SQLCOM_SHOW_CREATE;
- if (unlikely(!lex->select_lex.add_table_to_list(thd, $3, NULL, 0)))
+ if (!lex->first_select_lex()->add_table_to_list(thd, $3, NULL, 0))
MYSQL_YYABORT;
lex->table_type= TABLE_TYPE_VIEW;
}
@@ -14044,7 +14053,7 @@ show_param:
{
LEX *lex= Lex;
lex->sql_command = SQLCOM_SHOW_CREATE;
- if (unlikely(!lex->select_lex.add_table_to_list(thd, $3, NULL, 0)))
+ if (!lex->first_select_lex()->add_table_to_list(thd, $3, NULL, 0))
MYSQL_YYABORT;
lex->table_type= TABLE_TYPE_SEQUENCE;
}
@@ -14261,7 +14270,7 @@ describe:
mysql_init_select(lex);
lex->current_select->parsing_place= SELECT_LIST;
lex->sql_command= SQLCOM_SHOW_FIELDS;
- lex->select_lex.db= null_clex_str;
+ lex->first_select_lex()->db= null_clex_str;
lex->verbose= 0;
if (unlikely(prepare_schema_table(thd, lex, $2, SCH_COLUMNS)))
MYSQL_YYABORT;
@@ -14275,12 +14284,13 @@ describe:
explainable_command
{
LEX *lex=Lex;
- lex->select_lex.options|= SELECT_DESCRIBE;
+ lex->first_select_lex()->options|= SELECT_DESCRIBE;
}
;
explainable_command:
select
+ | select_into
| insert
| replace
| update
@@ -14301,6 +14311,8 @@ analyze_stmt_command:
opt_extended_describe:
EXTENDED_SYM { Lex->describe|= DESCRIBE_EXTENDED; }
+ | EXTENDED_SYM ALL
+ { Lex->describe|= DESCRIBE_EXTENDED | DESCRIBE_EXTENDED2; }
| PARTITIONS_SYM { Lex->describe|= DESCRIBE_PARTITIONS; }
| opt_format_json {}
;
@@ -14343,8 +14355,7 @@ flush:
lex->type= 0;
lex->no_write_to_binlog= $2;
}
- flush_options
- {}
+ flush_options {}
;
flush_options:
@@ -14361,6 +14372,7 @@ flush_options:
opt_table_list opt_flush_lock
{}
| flush_options_list
+ {}
;
opt_flush_lock:
@@ -14616,7 +14628,7 @@ use:
{
LEX *lex=Lex;
lex->sql_command=SQLCOM_CHANGE_DB;
- lex->select_lex.db= $2;
+ lex->first_select_lex()->db= $2;
}
;
@@ -14633,6 +14645,8 @@ load:
$2 == FILETYPE_CSV ? "LOAD DATA" : "LOAD XML");
MYSQL_YYABORT;
}
+ if (Lex->main_select_push())
+ MYSQL_YYABORT;
}
load_data_lock opt_local INFILE TEXT_STRING_filesystem
{
@@ -14662,7 +14676,11 @@ load:
opt_xml_rows_identified_by
opt_field_term opt_line_term opt_ignore_lines opt_field_or_var_spec
opt_load_data_set_spec
- {}
+ {
+ Lex->pop_select(); //main select
+ if (Lex->check_main_unit_semantics())
+ MYSQL_YYABORT;
+ }
;
data_or_xml:
@@ -15062,17 +15080,21 @@ opt_with_clause:
with_clause:
- WITH opt_recursive
+ WITH opt_recursive
{
+ LEX *lex= Lex;
With_clause *with_clause=
new With_clause($2, Lex->curr_with_clause);
if (unlikely(with_clause == NULL))
MYSQL_YYABORT;
- Lex->derived_tables|= DERIVED_WITH;
- Lex->curr_with_clause= with_clause;
+ lex->derived_tables|= DERIVED_WITH;
+ lex->curr_with_clause= with_clause;
with_clause->add_to_list(Lex->with_clauses_list_last_next);
+ if (lex->current_select &&
+ lex->current_select->parsing_place == BEFORE_OPT_LIST)
+ lex->current_select->parsing_place= NO_MATTER;
}
- with_list
+ with_list
{
$$= Lex->curr_with_clause;
Lex->curr_with_clause= Lex->curr_with_clause->pop();
@@ -15101,11 +15123,10 @@ with_list_element:
MYSQL_YYABORT;
Lex->with_column_list.empty();
}
- AS '(' remember_name subselect remember_end ')'
+ AS '(' remember_name query_expression remember_end ')'
{
- With_element *elem= new With_element($1, *$2, $7->master_unit());
- if (unlikely(elem == NULL) ||
- unlikely(Lex->curr_with_clause->add_with_element(elem)))
+ With_element *elem= new With_element($1, *$2, $7);
+ if (elem == NULL || Lex->curr_with_clause->add_with_element(elem))
MYSQL_YYABORT;
if (unlikely(elem->set_unparsed_spec(thd, $6+1, $8)))
MYSQL_YYABORT;
@@ -16076,14 +16097,22 @@ set:
SET
{
LEX *lex=Lex;
+ if (lex->main_select_push())
+ MYSQL_YYABORT;
lex->set_stmt_init();
lex->var_list.empty();
sp_create_assignment_lex(thd, yychar == YYEMPTY);
}
start_option_value_list
- {}
+ {
+ Lex->pop_select(); //main select
+ if (Lex->check_main_unit_semantics())
+ MYSQL_YYABORT;
+ }
| SET STATEMENT_SYM
{
+ if (Lex->main_select_push())
+ MYSQL_YYABORT;
Lex->set_stmt_init();
}
set_stmt_option_value_following_option_type_list
@@ -16093,6 +16122,9 @@ set:
my_yyabort_error((ER_SUBQUERIES_NOT_SUPPORTED, MYF(0), "SET STATEMENT"));
lex->stmt_var_list= lex->var_list;
lex->var_list.empty();
+ Lex->pop_select(); //main select
+ if (Lex->check_main_unit_semantics())
+ MYSQL_YYABORT;
}
FOR_SYM verb_clause
{}
@@ -16561,7 +16593,7 @@ table_lock_list:
;
table_lock:
- table_ident opt_table_alias lock_option
+ table_ident opt_table_alias_clause lock_option
{
thr_lock_type lock_type= (thr_lock_type) $3;
bool lock_for_write= (lock_type >= TL_WRITE_ALLOW_WRITE);
@@ -16606,27 +16638,36 @@ unlock:
*/
handler:
- HANDLER_SYM table_ident OPEN_SYM opt_table_alias
+ HANDLER_SYM
+ {
+ if (Lex->main_select_push())
+ MYSQL_YYABORT;
+ }
+ handler_tail
+ {
+ Lex->pop_select(); //main select
+ }
+
+handler_tail:
+ table_ident OPEN_SYM opt_table_alias_clause
{
LEX *lex= Lex;
if (unlikely(lex->sphead))
my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "HANDLER"));
lex->sql_command = SQLCOM_HA_OPEN;
- if (unlikely(!lex->current_select->add_table_to_list(thd, $2, $4,
- 0)))
+ if (!lex->current_select->add_table_to_list(thd, $1, $3, 0))
MYSQL_YYABORT;
}
- | HANDLER_SYM table_ident_nodb CLOSE_SYM
+ | table_ident_nodb CLOSE_SYM
{
LEX *lex= Lex;
if (unlikely(lex->sphead))
my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "HANDLER"));
lex->sql_command = SQLCOM_HA_CLOSE;
- if (unlikely(!lex->current_select->add_table_to_list(thd, $2, 0,
- 0)))
+ if (!lex->current_select->add_table_to_list(thd, $1, 0, 0))
MYSQL_YYABORT;
}
- | HANDLER_SYM table_ident_nodb READ_SYM
+ | table_ident_nodb READ_SYM
{
LEX *lex=Lex;
if (unlikely(lex->sphead))
@@ -16640,15 +16681,24 @@ handler:
lex->current_select->select_limit= one;
lex->current_select->offset_limit= 0;
lex->limit_rows_examined= 0;
- if (unlikely(!lex->current_select->add_table_to_list(thd, $2, 0,
- 0)))
+ if (!lex->current_select->add_table_to_list(thd, $1, 0, 0))
MYSQL_YYABORT;
}
- handler_read_or_scan opt_where_clause opt_limit_clause
+ handler_read_or_scan opt_where_clause opt_global_limit_clause
{
- Lex->expr_allows_subselect= TRUE;
+ LEX *lex=Lex;
+ lex->expr_allows_subselect= TRUE;
+ if (!lex->current_select->explicit_limit)
+ {
+ Item *one= new (thd->mem_root) Item_int(thd, (int32) 1);
+ if (one == NULL)
+ MYSQL_YYABORT;
+ lex->current_select->select_limit= one;
+ lex->current_select->offset_limit= 0;
+ lex->limit_rows_examined= 0;
+ }
/* Stored functions are not supported for HANDLER READ. */
- if (unlikely(Lex->uses_stored_routines()))
+ if (lex->uses_stored_routines())
{
my_error(ER_NOT_SUPPORTED_YET, MYF(0),
"stored functions in HANDLER ... READ");
@@ -17300,83 +17350,16 @@ release:
*/
unit_type_decl:
- UNION_SYM
- { $$= UNION_TYPE; }
+ UNION_SYM union_option
+ { $$.unit_type= UNION_TYPE; $$.distinct= $2; }
| INTERSECT_SYM
- { $$= INTERSECT_TYPE; }
+ { $$.unit_type= INTERSECT_TYPE; $$.distinct= 1; }
| EXCEPT_SYM
- { $$= EXCEPT_TYPE; }
-
-
-union_clause:
- /* empty */ {}
- | union_list
- ;
-
-union_list:
- unit_type_decl union_option
- {
- if (unlikely(Lex->add_select_to_union_list((bool)$2, $1, TRUE)))
- MYSQL_YYABORT;
- }
- union_list_part2
- {
- /*
- Remove from the name resolution context stack the context of the
- last select in the union.
- */
- Lex->pop_context();
- }
- ;
-
-union_list_view:
- unit_type_decl union_option
- {
- if (unlikely(Lex->add_select_to_union_list((bool)$2, $1, TRUE)))
- MYSQL_YYABORT;
- }
- query_expression_body_view
- {
- Lex->pop_context();
- }
- ;
-
-union_order_or_limit:
- {
- LEX *lex= thd->lex;
- DBUG_ASSERT(lex->current_select->linkage != GLOBAL_OPTIONS_TYPE);
- SELECT_LEX *sel= lex->current_select;
- SELECT_LEX_UNIT *unit= sel->master_unit();
- SELECT_LEX *fake= unit->fake_select_lex;
- if (fake)
- {
- fake->no_table_names_allowed= 1;
- lex->current_select= fake;
- }
- thd->where= "global ORDER clause";
- }
- order_or_limit
- {
- thd->lex->current_select->no_table_names_allowed= 0;
- thd->where= "";
- }
- ;
-
-order_or_limit:
- order_clause opt_limit_clause
- | limit_clause
- ;
+ { $$.unit_type= EXCEPT_TYPE; $$.distinct= 1; }
/*
Start a UNION, for non-top level query expressions.
*/
-union_head_non_top:
- unit_type_decl union_option
- {
- if (unlikely(Lex->add_select_to_union_list((bool)$2, $1, FALSE)))
- MYSQL_YYABORT;
- }
- ;
union_option:
/* empty */ { $$=1; }
@@ -17384,128 +17367,10 @@ union_option:
| ALL { $$=0; }
;
-simple_table:
- query_specification { $$= $1; }
- | table_value_constructor { $$= $1; }
- ;
-
-table_value_constructor:
- VALUES
- {
- Lex->tvc_start();
- }
- values_list
- {
- $$= Lex->current_select;
- if (Lex->tvc_finalize())
- MYSQL_YYABORT;
- }
- ;
-
-/*
- Corresponds to the SQL Standard
- <query specification> ::=
- SELECT [ <set quantifier> ] <select list> <table expression>
-
- Notes:
- - We allow more options in addition to <set quantifier>
- - <table expression> is optional in MariaDB
-*/
-query_specification:
- SELECT_SYM select_init2_derived opt_table_expression
- {
- $$= Lex->current_select->master_unit()->first_select();
- }
- ;
-
-query_term_union_not_ready:
- simple_table order_or_limit opt_select_lock_type { $$= $1; }
- | '(' select_paren_derived ')' union_order_or_limit { $$= $2; }
- ;
-
-query_term_union_ready:
- simple_table opt_select_lock_type { $$= $1; }
- | '(' select_paren_derived ')' { $$= $2; }
- ;
-
-query_expression_body:
- query_term_union_not_ready { $$= $1; }
- | query_term_union_ready { $$= $1; }
- | query_term_union_ready union_list_derived { $$= $1; }
- ;
-
-/* Corresponds to <query expression> in the SQL:2003 standard. */
-subselect:
- subselect_start opt_with_clause query_expression_body subselect_end
- {
- $3->set_with_clause($2);
- $$= $3;
- }
- ;
-
-subselect_start:
- {
- LEX *lex=Lex;
- if (unlikely(!lex->expr_allows_subselect ||
- lex->sql_command == (int)SQLCOM_PURGE))
- {
- thd->parse_error();
- MYSQL_YYABORT;
- }
- /*
- we are making a "derived table" for the parenthesis
- as we need to have a lex level to fit the union
- after the parenthesis, e.g.
- (SELECT .. ) UNION ... becomes
- SELECT * FROM ((SELECT ...) UNION ...)
- */
- if (unlikely(mysql_new_select(Lex, 1, NULL)))
- MYSQL_YYABORT;
- }
- ;
-
-subselect_end:
- {
- LEX *lex=Lex;
-
- lex->check_automatic_up(UNSPECIFIED_TYPE);
- lex->pop_context();
- SELECT_LEX *child= lex->current_select;
- lex->current_select = lex->current_select->return_after_parsing();
- lex->nest_level--;
- lex->current_select->n_child_sum_items += child->n_sum_items;
- /*
- A subselect can add fields to an outer select. Reserve space for
- them.
- */
- lex->current_select->select_n_where_fields+=
- child->select_n_where_fields;
-
- /*
- Aggregate functions in having clause may add fields to an outer
- select. Count them also.
- */
- lex->current_select->select_n_having_items+=
- child->select_n_having_items;
- }
- ;
-
-opt_query_expression_options:
- /* empty */
- | query_expression_option_list
- ;
-
-query_expression_option_list:
- query_expression_option_list query_expression_option
- | query_expression_option
- ;
-
query_expression_option:
STRAIGHT_JOIN { Select->options|= SELECT_STRAIGHT_JOIN; }
| HIGH_PRIORITY
{
- if (unlikely(Lex->check_simple_select(&$1)))
- MYSQL_YYABORT;
YYPS->m_lock_type= TL_READ_HIGH_PRIORITY;
YYPS->m_mdl_type= MDL_SHARED_READ;
Select->options|= SELECT_HIGH_PRIORITY;
@@ -17514,18 +17379,8 @@ query_expression_option:
| UNIQUE_SYM { Select->options|= SELECT_DISTINCT; }
| SQL_SMALL_RESULT { Select->options|= SELECT_SMALL_RESULT; }
| SQL_BIG_RESULT { Select->options|= SELECT_BIG_RESULT; }
- | SQL_BUFFER_RESULT
- {
- if (unlikely(Lex->check_simple_select(&$1)))
- MYSQL_YYABORT;
- Select->options|= OPTION_BUFFER_RESULT;
- }
- | SQL_CALC_FOUND_ROWS
- {
- if (unlikely(Lex->check_simple_select(&$1)))
- MYSQL_YYABORT;
- Select->options|= OPTION_FOUND_ROWS;
- }
+ | SQL_BUFFER_RESULT { Select->options|= OPTION_BUFFER_RESULT; }
+ | SQL_CALC_FOUND_ROWS { Select->options|= OPTION_FOUND_ROWS; }
| ALL { Select->options|= SELECT_ALL; }
;
@@ -17613,35 +17468,14 @@ view_select:
lex->parsing_options.allows_variable= FALSE;
lex->create_view->select.str= (char *) YYLIP->get_cpp_ptr();
}
- opt_with_clause query_expression_body_view view_check_option
+ query_expression
+ view_check_option
{
- LEX *lex= Lex;
- size_t len= YYLIP->get_cpp_ptr() - lex->create_view->select.str;
- void *create_view_select= thd->memdup(lex->create_view->select.str, len);
- lex->create_view->select.length= len;
- lex->create_view->select.str= (char *) create_view_select;
- trim_whitespace(thd->charset(),
- &lex->create_view->select);
- lex->create_view->check= $4;
- lex->parsing_options.allows_variable= TRUE;
- lex->current_select->set_with_clause($2);
+ if (Lex->parsed_create_view($2, $3))
+ MYSQL_YYABORT;
}
;
-/*
- SQL Standard <query expression body> for VIEWs.
- Does not include INTO and PROCEDURE clauses.
-*/
-query_expression_body_view:
- SELECT_SYM select_options_and_item_list select_init3_view
- | table_value_constructor
- | table_value_constructor union_order_or_limit
- | table_value_constructor union_list_view
- | '(' select_paren_view ')'
- | '(' select_paren_view ')' union_order_or_limit
- | '(' select_paren_view ')' union_list_view
- ;
-
view_check_option:
/* empty */ { $$= VIEW_CHECK_NONE; }
| WITH CHECK_SYM OPTION { $$= VIEW_CHECK_CASCADED; }
@@ -17742,11 +17576,10 @@ trigger_tail:
sp_proc_stmt alternatives are not saving/restoring LEX, so
lex->query_tables can be wiped out.
*/
- if (unlikely(!lex->select_lex.
- add_table_to_list(thd, $10, (LEX_CSTRING*) 0,
- TL_OPTION_UPDATING,
- TL_READ_NO_INSERT,
- MDL_SHARED_NO_WRITE)))
+ if (!lex->first_select_lex()->
+ add_table_to_list(thd, $10, (LEX_CSTRING*) 0,
+ TL_OPTION_UPDATING, TL_READ_NO_INSERT,
+ MDL_SHARED_NO_WRITE))
MYSQL_YYABORT;
}
;
diff --git a/sql/structs.h b/sql/structs.h
index d8b95a3509a..21b3904faa4 100644
--- a/sql/structs.h
+++ b/sql/structs.h
@@ -758,6 +758,43 @@ public:
};
+class st_select_lex;
+
+class Lex_select_lock
+{
+public:
+ struct
+ {
+ uint defined_lock:1;
+ uint update_lock:1;
+ uint defined_timeout:1;
+ };
+ ulong timeout;
+
+
+ void empty()
+ {
+ defined_lock= update_lock= defined_timeout= FALSE;
+ timeout= 0;
+ }
+ void set_to(st_select_lex *sel);
+};
+
+class Lex_select_limit
+{
+public:
+ bool explicit_limit;
+ Item *select_limit, *offset_limit;
+
+ void empty()
+ {
+ explicit_limit= FALSE;
+ select_limit= offset_limit= NULL;
+ }
+};
+
+struct st_order;
+
class Load_data_param
{
protected:
diff --git a/sql/table.cc b/sql/table.cc
index 3d3bc3336ef..276567d8767 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -2733,7 +2733,7 @@ static bool sql_unusable_for_discovery(THD *thd, handlerton *engine,
if (lex->create_info.like())
return 1;
// ... create select
- if (lex->select_lex.item_list.elements)
+ if (lex->first_select_lex()->item_list.elements)
return 1;
// ... temporary
if (create_info->tmp_table())
@@ -4976,13 +4976,13 @@ bool TABLE_LIST::single_table_updatable()
{
if (!updatable)
return false;
- if (view && view->select_lex.table_list.elements == 1)
+ if (view && view->first_select_lex()->table_list.elements == 1)
{
/*
We need to check deeply only single table views. Multi-table views
will be turned to multi-table updates and then checked by leaf tables
*/
- return (((TABLE_LIST *)view->select_lex.table_list.first)->
+ return (((TABLE_LIST *)view->first_select_lex()->table_list.first)->
single_table_updatable());
}
return true;
@@ -5019,7 +5019,8 @@ merge_on_conds(THD *thd, TABLE_LIST *table, bool is_cascaded)
cond= table->on_expr->copy_andor_structure(thd);
if (!table->view)
DBUG_RETURN(cond);
- for (TABLE_LIST *tbl= (TABLE_LIST*)table->view->select_lex.table_list.first;
+ for (TABLE_LIST *tbl=
+ (TABLE_LIST*)table->view->first_select_lex()->table_list.first;
tbl;
tbl= tbl->next_local)
{
@@ -5061,7 +5062,7 @@ bool TABLE_LIST::prep_check_option(THD *thd, uint8 check_opt_type)
{
DBUG_ENTER("TABLE_LIST::prep_check_option");
bool is_cascaded= check_opt_type == VIEW_CHECK_CASCADED;
- TABLE_LIST *merge_underlying_list= view->select_lex.get_table_list();
+ TABLE_LIST *merge_underlying_list= view->first_select_lex()->get_table_list();
for (TABLE_LIST *tbl= merge_underlying_list; tbl; tbl= tbl->next_local)
{
/* see comment of check_opt_type parameter */
@@ -5179,7 +5180,7 @@ TABLE_LIST *TABLE_LIST::find_underlying_table(TABLE *table_to_find)
if (!view)
return 0;
- for (TABLE_LIST *tbl= view->select_lex.get_table_list();
+ for (TABLE_LIST *tbl= view->first_select_lex()->get_table_list();
tbl;
tbl= tbl->next_local)
{
@@ -5367,7 +5368,8 @@ bool TABLE_LIST::set_insert_values(MEM_ROOT *mem_root)
{
DBUG_PRINT("info", ("setting insert_value for view"));
DBUG_ASSERT(is_view_or_derived() && is_merged_derived());
- for (TABLE_LIST *tbl= (TABLE_LIST*)view->select_lex.table_list.first;
+ for (TABLE_LIST *tbl=
+ (TABLE_LIST*)view->first_select_lex()->table_list.first;
tbl;
tbl= tbl->next_local)
if (tbl->set_insert_values(mem_root))
@@ -5534,7 +5536,7 @@ void TABLE_LIST::register_want_access(ulong want_access)
}
if (!view)
return;
- for (TABLE_LIST *tbl= view->select_lex.get_table_list();
+ for (TABLE_LIST *tbl= view->first_select_lex()->get_table_list();
tbl;
tbl= tbl->next_local)
tbl->register_want_access(want_access);
@@ -5726,6 +5728,7 @@ void TABLE_LIST::set_check_materialized()
The subtree should be already excluded
*/
DBUG_ASSERT(!derived->first_select()->first_inner_unit() ||
+ derived->first_select()->first_inner_unit()->with_element ||
derived->first_select()->first_inner_unit()->first_select()->
exclude_from_table_unique_test);
}
@@ -5742,14 +5745,14 @@ TABLE *TABLE_LIST::get_real_join_table()
break;
/* we do not support merging of union yet */
DBUG_ASSERT(tbl->view == NULL ||
- tbl->view->select_lex.next_select() == NULL);
+ tbl->view->first_select_lex()->next_select() == NULL);
DBUG_ASSERT(tbl->derived == NULL ||
tbl->derived->first_select()->next_select() == NULL);
{
List_iterator_fast<TABLE_LIST>
ti(tbl->view != NULL ?
- tbl->view->select_lex.top_join_list :
+ tbl->view->first_select_lex()->top_join_list :
tbl->derived->first_select()->top_join_list);
for (;;)
{
@@ -5920,7 +5923,7 @@ Item *Field_iterator_view::create_item(THD *thd)
Item *create_view_field(THD *thd, TABLE_LIST *view, Item **field_ref,
LEX_CSTRING *name)
{
- bool save_wrapper= thd->lex->select_lex.no_wrap_view_item;
+ bool save_wrapper= thd->lex->first_select_lex()->no_wrap_view_item;
Item *field= *field_ref;
DBUG_ENTER("create_view_field");
@@ -5951,8 +5954,9 @@ Item *create_view_field(THD *thd, TABLE_LIST *view, Item **field_ref,
{
DBUG_RETURN(field);
}
- Name_resolution_context *context= view->view ? &view->view->select_lex.context :
- &thd->lex->select_lex.context;
+ Name_resolution_context *context= (view->view ?
+ &view->view->first_select_lex()->context:
+ &thd->lex->first_select_lex()->context);
Item *item= (new (thd->mem_root)
Item_direct_view_ref(thd, context, field_ref, view->alias.str,
name, view));
@@ -8555,7 +8559,7 @@ bool TR_table::query(ulonglong trx_id)
READ_RECORD info;
int error;
List<TABLE_LIST> dummy;
- SELECT_LEX &slex= thd->lex->select_lex;
+ SELECT_LEX &slex= *(thd->lex->first_select_lex());
Name_resolution_context_backup backup(slex.context, *this);
Item *field= newx Item_field(thd, &slex.context, (*this)[FLD_TRX_ID]);
Item *value= newx Item_int(thd, trx_id);
@@ -8585,7 +8589,7 @@ bool TR_table::query(MYSQL_TIME &commit_time, bool backwards)
READ_RECORD info;
int error;
List<TABLE_LIST> dummy;
- SELECT_LEX &slex= thd->lex->select_lex;
+ SELECT_LEX &slex= *(thd->lex->first_select_lex());
Name_resolution_context_backup backup(slex.context, *this);
Item *field= newx Item_field(thd, &slex.context, (*this)[FLD_COMMIT_TS]);
Item *value= newx Item_datetime_literal(thd, &commit_time, 6);
diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc
index 7a90373e252..0a2735fe0b7 100644
--- a/sql/wsrep_mysqld.cc
+++ b/sql/wsrep_mysqld.cc
@@ -1327,7 +1327,7 @@ static int
create_view_query(THD *thd, uchar** buf, size_t* buf_len)
{
LEX *lex= thd->lex;
- SELECT_LEX *select_lex= &lex->select_lex;
+ SELECT_LEX *select_lex= lex->first_select_lex();
TABLE_LIST *first_table= select_lex->table_list.first;
TABLE_LIST *views = first_table;
LEX_USER *definer;
@@ -1419,7 +1419,7 @@ static bool wsrep_can_run_in_toi(THD *thd, const char *db, const char *table,
DBUG_ASSERT(table_list || db);
LEX* lex= thd->lex;
- SELECT_LEX* select_lex= &lex->select_lex;
+ SELECT_LEX* select_lex= lex->first_select_lex();
TABLE_LIST* first_table= select_lex->table_list.first;
switch (lex->sql_command)