maria-developers team mailing list archive
-
maria-developers team
-
Mailing list archive
-
Message #11188
Re: Fwd: [Commits] b32031991e4: initial oracle parser fix
Hello Sanja,
I reviewed your recent changes in "10.3-MDEV-11953"
(and the attached additional patch for sql_yacc_ora.yy)
I have some proposals:
1. Can you please move huge pieces of the code from sql_yacc.yy to LEX
or other relevant classes?
It makes the grammar much more readable (patches are aslo much more
readable).
I'd move the relevant pieces of the code to LEX as a separate patch,
even before fixing the grammar.
2. You're adding too many main_select_push() and pop_select().
Please move them to upper level rules (it should be possible in many cases).
Add new helper rules when needed.
For example, this piece of code repeats many times:
+ {
+ if (Lex->main_select_push())
+ MYSQL_YYABORT;
+ }
+ expr
+ {
+ Lex->pop_select(); //main select
+ $$= $3;
It deserved a rule, say, expr_with_select_push_pop.
You can find a better name :)
- Serg and I spent a lot of time working on this task:
MDEV-8909 union parser cleanup
(and its 13 dependency tasks, and 3 related tasks,
see the "Issue links" section in MDEV).
We think that it should be the parser who disallows bad grammar, instead
of post-analysis with raising errors like
ER_CANT_USE_OPTION_HERE.
Please keep using the same approach.
Thanks!
On 04/06/2018 07:37 PM, Oleksandr Byelkin wrote:
>
>
>
> -------- Weitergeleitete Nachricht --------
> Betreff: [Commits] b32031991e4: initial oracle parser fix
> Datum: Fri, 06 Apr 2018 17:34:31 +0200
> Von: Oleksandr Byelkin <sanja@xxxxxxxxxxx>
> Antwort an: maria-developers@xxxxxxxxxxxxxxxxxxx
> An: commits@xxxxxxxxxxx
>
>
>
> revision-id: b32031991e4ba270f5c221f7f6068732d09efd53
> (mariadb-10.3.5-110-gb32031991e4)
> parent(s): 60a502eb7efbe87bd8e3af3e3ece49a9eb83f8b3
> author: Oleksandr Byelkin
> committer: Oleksandr Byelkin
> timestamp: 2018-04-06 17:05:34 +0200
> message:
>
> initial oracle parser fix
>
> ---
> sql/sql_yacc.yy | 8 +-
> sql/sql_yacc_ora.yy | 2085
> +++++++++++++++++++++++++++++----------------------
> 2 files changed, 1183 insertions(+), 910 deletions(-)
>
> diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
> index e4cbff7114e..9372269b05d 100644
> --- a/sql/sql_yacc.yy
> +++ b/sql/sql_yacc.yy
> @@ -904,7 +904,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t
> *yystacksize);
> %parse-param { THD *thd }
> %lex-param { THD *thd }
> /*
> - Currently there are 96 shift/reduce conflicts.
> + Currently there are 135 shift/reduce conflicts.
> We should not introduce new conflicts any more.
> */
> %expect 135
> @@ -9244,7 +9244,7 @@ table_value_constructor:
> lex->push_select(sel))
> MYSQL_YYABORT;
> sel->init_select();
> - sel->braces= FALSE;
> + sel->braces= FALSE; // just initialisation
> }
> values_list
> {
> @@ -13763,8 +13763,10 @@ single_multi:
> }
> | table_wild_list
> {
> + /* XXX
> if (Lex->main_select_push())
> MYSQL_YYABORT;
> + */
> mysql_init_multi_delete(Lex);
> YYPS->m_lock_type= TL_READ_DEFAULT;
> YYPS->m_mdl_type= MDL_SHARED_READ;
> @@ -13779,8 +13781,10 @@ single_multi:
> }
> | FROM table_alias_ref_list
> {
> + /* XXX
> if (Lex->main_select_push())
> MYSQL_YYABORT;
> + */
> mysql_init_multi_delete(Lex);
> YYPS->m_lock_type= TL_READ_DEFAULT;
> YYPS->m_mdl_type= MDL_SHARED_READ;
> diff --git a/sql/sql_yacc_ora.yy b/sql/sql_yacc_ora.yy
> index c1512434d72..4a3ee348f89 100644
> --- a/sql/sql_yacc_ora.yy
> +++ b/sql/sql_yacc_ora.yy
> @@ -186,6 +186,20 @@ void ORAerror(THD *thd, const char *s)
> LEX_CSTRING name;
> uint offset;
> } sp_cursor_name_and_offset;
> + 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;
> @@ -231,6 +245,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;
> @@ -240,7 +255,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;
> @@ -277,10 +291,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t
> *yystacksize);
> %parse-param { THD *thd }
> %lex-param { THD *thd }
> /*
> - Currently there are 104 shift/reduce conflicts.
> + Currently there are 99 shift/reduce conflicts.
> We should not introduce new conflicts any more.
> */
> -%expect 104
> +%expect 99
>
> /*
> Comments for TOKENS.
> @@ -599,6 +613,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t
> *yystacksize);
> %token LEAVES
> %token LEAVE_SYM
> %token LEFT /* SQL-2003-R */
> +%token LEFT_PAREN_ALT /* INTERNAL */
> +%token LEFT_PAREN_WITH /* INTERNAL */
> +%token LEFT_PAREN_LIKE /* INTERNAL */
> %token LESS_SYM
> %token LEVEL_SYM
> %token LEX_HOSTNAME
> @@ -1063,7 +1080,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 <lex_string_with_pos>
> ident ident_with_tok_start
> @@ -1111,7 +1129,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
> @@ -1231,9 +1249,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_query_specification
> + derived_table_list table_reference_list_parens
> + nested_table_reference_list join_table_parens
> %type <date_time_type> date_time_type;
> %type <interval> interval
>
> @@ -1276,12 +1293,16 @@ bool my_yyoverflow(short **a, YYSTYPE **b,
> size_t *yystacksize);
> UNDERSCORE_CHARSET
>
> %type <select_lex> subselect
> - get_select_lex get_select_lex_derived
> query_specification
> - query_term_union_not_ready
> - query_term_union_ready
> + table_value_constructor
> + simple_table
> + query_primary
> + query_primary_parens
> +
> +%type <select_lex_unit>
> query_expression_body
> - select_paren_derived
> + query_expression
> + query_expression_unit
>
> %type <boolfunc2creator> comp_op
>
> @@ -1293,7 +1314,21 @@ 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_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
> +
> +%type <select_order> opt_order_clause order_clause order_list
>
> %type <NONE>
> analyze_stmt_command
> @@ -1313,7 +1348,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
> @@ -1333,9 +1368,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
> @@ -1606,14 +1640,22 @@ deallocate_or_drop:
> ;
>
> prepare:
> - PREPARE_SYM ident FROM prepare_src
> + PREPARE_SYM
> + {
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> + }
> + ident FROM prepare_src
> {
> LEX *lex= thd->lex;
> if (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;
> + lex->prepared_stmt_name= $3;
> + Lex->pop_select(); //main select
> }
> ;
>
> @@ -1632,10 +1674,21 @@ execute:
> LEX *lex= thd->lex;
> lex->sql_command= SQLCOM_EXECUTE;
> lex->prepared_stmt_name= $2;
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> }
> execute_using
> - {}
> - | EXECUTE_SYM IMMEDIATE_SYM prepare_src
> + {
> + Lex->pop_select(); //main select
> + if (Lex->check_main_unit_semantics())
> + MYSQL_YYABORT;
> + }
> + | EXECUTE_SYM IMMEDIATE_SYM
> + {
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> + }
> + prepare_src
> {
> if (Lex->table_or_sp_used())
> my_yyabort_error((ER_SUBQUERIES_NOT_SUPPORTED, MYF(0),
> @@ -1643,7 +1696,11 @@ execute:
> Lex->sql_command= SQLCOM_EXECUTE_IMMEDIATE;
> }
> execute_using
> - {}
> + {
> + Lex->pop_select(); //main select
> + if (Lex->check_main_unit_semantics())
> + MYSQL_YYABORT;
> + }
> ;
>
> execute_using:
> @@ -1928,13 +1985,20 @@ 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 (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 (!lex->builtin_select.add_table_to_list(thd, $5, NULL,
> + }
> + table_ident
> + {
> + LEX *lex= thd->lex;
> + if (!lex->builtin_select.add_table_to_list(thd, $6, NULL,
> TL_OPTION_UPDATING,
> TL_WRITE,
> MDL_EXCLUSIVE))
> MYSQL_YYABORT;
> @@ -1960,13 +2024,16 @@ 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 (lex->set_command_with_check(SQLCOM_CREATE_SEQUENCE, $2,
> $1 | $4))
> MYSQL_YYABORT;
> @@ -2021,42 +2088,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 (Lex->add_create_index_prepare($8))
> + if (Lex->add_create_index_prepare($9))
> MYSQL_YYABORT;
> - if (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 (Lex->add_create_index_prepare($7))
> + if (Lex->add_create_index_prepare($8))
> MYSQL_YYABORT;
> - if (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 (Lex->add_create_index_prepare($7))
> + if (Lex->add_create_index_prepare($8))
> MYSQL_YYABORT;
> - if (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
> {
> @@ -2064,51 +2158,94 @@ create:
> if (lex->set_command_with_check(SQLCOM_CREATE_DB, 0, $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 (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 (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
> {
> @@ -2815,8 +2952,13 @@ call:
> {
> if (Lex->call_statement_start(thd, $2))
> MYSQL_YYABORT;
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> + }
> + opt_sp_cparam_list
> + {
> + Lex->pop_select(); //main select
> }
> - opt_sp_cparam_list {}
> ;
>
> /* CALL parameters */
> @@ -3346,10 +3488,16 @@ raise_stmt:
> ;
>
> signal_stmt:
> - SIGNAL_SYM signal_value opt_set_signal_information
> + SIGNAL_SYM
> {
> - if (Lex->add_signal_statement(thd, $2))
> + if (Lex->main_select_push())
> + YYABORT;
> + }
> + signal_value opt_set_signal_information
> + {
> + if (Lex->add_signal_statement(thd, $3))
> MYSQL_YYABORT;
> + Lex->pop_select(); //main select
> }
> ;
>
> @@ -3475,9 +3623,14 @@ resignal_stmt:
> ;
>
> get_diagnostics:
> - GET_SYM which_area DIAGNOSTICS_SYM diagnostics_information
> + GET_SYM which_area DIAGNOSTICS_SYM
> + {
> + if (Lex->main_select_push())
> + YYABORT;
> + }
> + diagnostics_information
> {
> - Diagnostics_information *info= $4;
> + Diagnostics_information *info= $5;
>
> info->set_which_da($2);
>
> @@ -3486,6 +3639,7 @@ get_diagnostics:
>
> if (Lex->m_sql_cmd == NULL)
> MYSQL_YYABORT;
> + Lex->pop_select(); //main select
> }
> ;
>
> @@ -3666,8 +3820,26 @@ sp_decl_idents:
>
> sp_opt_default:
> /* Empty */ { $$ = NULL; }
> - | DEFAULT expr { $$ = $2; }
> - | SET_VAR expr { $$ = $2; }
> + | DEFAULT
> + {
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> + }
> + expr
> + {
> + Lex->pop_select(); //main select
> + $$ = $3;
> + }
> + | SET_VAR
> + {
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> + }
> + expr
> + {
> + Lex->pop_select(); //main select
> + $$ = $3;
> + }
> ;
>
> sp_proc_stmt:
> @@ -3784,10 +3956,15 @@ sp_proc_stmt_statement:
>
> sp_proc_stmt_return:
> RETURN_SYM
> - { Lex->sphead->reset_lex(thd); }
> + {
> + Lex->sphead->reset_lex(thd);
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> + }
> expr
> {
> LEX *lex= Lex;
> + lex->pop_select(); //main select
> sp_head *sp= lex->sphead;
> if (sp->m_handler->add_instr_freturn(thd, sp, lex->spcont,
> $3, lex) ||
> @@ -3902,6 +4079,8 @@ assignment_source_expr:
> {
> DBUG_ASSERT(thd->free_list == NULL);
> Lex->sphead->reset_lex(thd, $1);
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> }
> expr
> {
> @@ -3910,6 +4089,7 @@ assignment_source_expr:
> $$->sp_lex_in_use= true;
> $$->set_item_and_free_list($3, thd->free_list);
> thd->free_list= NULL;
> + Lex->pop_select(); //main select
> if ($$->sphead->restore_lex(thd))
> MYSQL_YYABORT;
> }
> @@ -4030,9 +4210,14 @@ sp_fetch_list:
> ;
>
> sp_if:
> - { Lex->sphead->reset_lex(thd); }
> + {
> + Lex->sphead->reset_lex(thd);
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> + }
> expr THEN_SYM
> {
> + Lex->pop_select(); //main select
> LEX *lex= Lex;
> sp_head *sp= lex->sphead;
> sp_pcontext *ctx= lex->spcont;
> @@ -4144,12 +4329,18 @@ case_stmt_specification:
> ;
>
> case_stmt_body:
> - { Lex->sphead->reset_lex(thd); /* For expr $2 */ }
> + {
> + Lex->sphead->reset_lex(thd); /* For expr $2 */
> +
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> + }
> expr
> {
> if (Lex->case_stmt_action_expr($2))
> MYSQL_YYABORT;
>
> + Lex->pop_select(); //main select
> if (Lex->sphead->restore_lex(thd))
> MYSQL_YYABORT;
> }
> @@ -4173,6 +4364,9 @@ simple_when_clause:
> WHEN_SYM
> {
> Lex->sphead->reset_lex(thd); /* For expr $3 */
> +
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> }
> expr
> {
> @@ -4181,6 +4375,8 @@ simple_when_clause:
> LEX *lex= Lex;
> if (lex->case_stmt_action_when($3, true))
> MYSQL_YYABORT;
> +
> + lex->pop_select(); //main select
> /* For expr $3 */
> if (lex->sphead->restore_lex(thd))
> MYSQL_YYABORT;
> @@ -4197,12 +4393,17 @@ searched_when_clause:
> WHEN_SYM
> {
> Lex->sphead->reset_lex(thd); /* For expr $3 */
> +
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> }
> expr
> {
> LEX *lex= Lex;
> if (lex->case_stmt_action_when($3, false))
> MYSQL_YYABORT;
> +
> + lex->pop_select(); //main select
> /* For expr $3 */
> if (lex->sphead->restore_lex(thd))
> MYSQL_YYABORT;
> @@ -4442,6 +4643,7 @@ while_body:
> LEX *lex= Lex;
> if (lex->sp_while_loop_expression(thd, $1))
> MYSQL_YYABORT;
> + Lex->pop_select(); //main select pushed before while_body use
> if (lex->sphead->restore_lex(thd))
> MYSQL_YYABORT;
> }
> @@ -4454,7 +4656,12 @@ while_body:
>
> repeat_body:
> sp_proc_stmts1 UNTIL_SYM
> - { Lex->sphead->reset_lex(thd); }
> + {
> + Lex->sphead->reset_lex(thd);
> +
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> + }
> expr END REPEAT_SYM
> {
> LEX *lex= Lex;
> @@ -4465,6 +4672,8 @@ repeat_body:
> if (i == NULL ||
> lex->sphead->add_instr(i))
> MYSQL_YYABORT;
> +
> + lex->pop_select(); //main select
> if (lex->sphead->restore_lex(thd))
> MYSQL_YYABORT;
> /* We can shortcut the cont_backpatch here */
> @@ -4493,8 +4702,12 @@ sp_labeled_control:
> if (Lex->sp_push_loop_label(thd, &$1))
> MYSQL_YYABORT;
> Lex->sphead->reset_lex(thd);
> +
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> }
> while_body pop_sp_loop_label
> +
> { }
> | labels_declaration_oracle FOR_SYM
> {
> @@ -4546,9 +4759,13 @@ sp_unlabeled_control:
> if (Lex->sp_push_loop_empty_label(thd))
> MYSQL_YYABORT;
> Lex->sphead->reset_lex(thd);
> +
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> }
> while_body
> {
> + // while body pop main select
> Lex->sp_pop_loop_empty_label(thd);
> }
> | FOR_SYM
> @@ -4981,20 +5198,10 @@ 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
> {
>
> @@ -5010,7 +5217,7 @@ create_body:
>
> create_like:
> LIKE table_ident { $$= $2; }
> - | '(' LIKE table_ident ')' { $$= $3; }
> + | LEFT_PAREN_LIKE LIKE table_ident ')' { $$= $3; }
> ;
>
> opt_create_select:
> @@ -5019,23 +5226,42 @@ 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
> + {
> + SELECT_LEX *first_select= $1->first_select();
> +
> + if (Lex->sql_command == SQLCOM_INSERT ||
> + Lex->sql_command == SQLCOM_REPLACE)
> + {
> + if (Lex->sql_command == SQLCOM_INSERT)
> + Lex->sql_command= SQLCOM_INSERT_SELECT;
> + else
> + Lex->sql_command= SQLCOM_REPLACE_SELECT;
> + }
> + Lex->insert_select_hack(first_select);
> + if (Lex->check_main_unit_semantics())
> + 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);
> +
> + Lex->insert_select_hack(first_select);
> + if (Lex->check_main_unit_semantics())
> + MYSQL_YYABORT;
> +
> + if (Lex->sql_command == SQLCOM_INSERT ||
> + Lex->sql_command == SQLCOM_REPLACE)
> + {
> + if (Lex->sql_command == SQLCOM_INSERT)
> + Lex->sql_command= SQLCOM_INSERT_SELECT;
> + else
> + Lex->sql_command= SQLCOM_REPLACE_SELECT;
> + }
> }
> - | '(' 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:
> @@ -5126,8 +5352,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:
> @@ -5742,56 +5973,6 @@ opt_part_option:
> 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 {}
> @@ -6195,6 +6376,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
> @@ -6462,6 +6650,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
> {
> @@ -6469,13 +6659,29 @@ parse_vcol_expr:
> if (!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 (!Lex->expr_allows_subselect ||
> + Lex->sql_command == (int)SQLCOM_PURGE)
> + {
> + thd->parse_error(ER_SYNTAX_ERROR, $1);
> + MYSQL_YYABORT;
> + }
> +
> + // Add the subtree of subquery to the current SELECT_LEX
> + SELECT_LEX *curr_sel= Lex->select_stack_head();
> + DBUG_ASSERT(Lex->current_select == curr_sel);
> + curr_sel->register_unit($2, &curr_sel->context);
> + curr_sel->add_statistics($2);
> +
> + $$= new (thd->mem_root)
> + Item_singlerow_subselect(thd, $2->first_select());
> if ($$ == NULL)
> MYSQL_YYABORT;
> }
> @@ -7474,6 +7680,8 @@ alter:
> 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
> @@ -7494,12 +7702,15 @@ alter:
> Lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_alter_table();
> if (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
> {
> @@ -7508,6 +7719,7 @@ alter:
> lex->name= $3;
> if (lex->name.str == NULL && lex->copy_db_to(&lex->name))
> MYSQL_YYABORT;
> + Lex->pop_select(); //main select
> }
> | ALTER DATABASE ident UPGRADE_SYM DATA_SYM DIRECTORY_SYM NAME_SYM
> {
> @@ -7523,6 +7735,8 @@ alter:
>
> if (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
> @@ -7531,6 +7745,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
> {
> @@ -7538,6 +7755,8 @@ alter:
>
> if (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
> @@ -7546,14 +7765,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 (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
> @@ -7561,14 +7789,22 @@ alter:
> with the ALTER EVENT below.
> */
> {
> + 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
> @@ -7600,6 +7836,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
> {
> @@ -7643,6 +7881,8 @@ 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
> {
> @@ -7660,6 +7900,9 @@ alter:
> Lex->m_sql_cmd= new (thd->mem_root)
> Sql_cmd_alter_sequence($3);
> if (Lex->m_sql_cmd == NULL)
> MYSQL_YYABORT;
> + Lex->pop_select(); //main select
> + if (Lex->check_main_unit_semantics())
> + MYSQL_YYABORT;
> }
> ;
>
> @@ -8336,9 +8579,13 @@ checksum:
> lex->sql_command = SQLCOM_CHECKSUM;
> /* Will be overridden during execution. */
> YYPS->m_lock_type= TL_UNLOCK;
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> }
> table_list opt_checksum_type
> - {}
> + {
> + Lex->pop_select(); //main select
> + }
> ;
>
> opt_checksum_type:
> @@ -8364,6 +8611,8 @@ repair:
> lex->alter_info.reset();
> /* Will be overridden during execution. */
> YYPS->m_lock_type= TL_UNLOCK;
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> }
> repair_table_or_view
> {
> @@ -8372,6 +8621,7 @@ repair:
> lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_repair_table();
> if (lex->m_sql_cmd == NULL)
> MYSQL_YYABORT;
> + Lex->pop_select(); //main select
> }
> ;
>
> @@ -8400,6 +8650,8 @@ analyze:
> ANALYZE_SYM opt_no_write_to_binlog table_or_tables
> {
> LEX *lex=Lex;
> + if (lex->main_select_push())
> + YYABORT;
> lex->sql_command = SQLCOM_ANALYZE;
> lex->no_write_to_binlog= $2;
> lex->check_opt.init();
> @@ -8414,6 +8666,7 @@ analyze:
> lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_analyze_table();
> if (lex->m_sql_cmd == NULL)
> MYSQL_YYABORT;
> + Lex->pop_select(); //main select
> }
> ;
>
> @@ -8530,6 +8783,8 @@ check: CHECK_SYM
> lex->alter_info.reset();
> /* Will be overridden during execution. */
> YYPS->m_lock_type= TL_UNLOCK;
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> }
> check_view_or_table
> {
> @@ -8540,6 +8795,7 @@ check: CHECK_SYM
> lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_check_table();
> if (lex->m_sql_cmd == NULL)
> MYSQL_YYABORT;
> + Lex->pop_select(); //main select
> }
> ;
>
> @@ -8577,6 +8833,8 @@ optimize:
> lex->alter_info.reset();
> /* Will be overridden during execution. */
> YYPS->m_lock_type= TL_UNLOCK;
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> }
> table_list opt_lock_wait_timeout
> {
> @@ -8585,6 +8843,7 @@ optimize:
> lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_optimize_table();
> if (lex->m_sql_cmd == NULL)
> MYSQL_YYABORT;
> + Lex->pop_select(); //main select
> }
> ;
>
> @@ -8598,9 +8857,13 @@ rename:
> RENAME table_or_tables
> {
> Lex->sql_command= SQLCOM_RENAME_TABLE;
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> }
> table_to_table_list
> - {}
> + {
> + Lex->pop_select(); //main select
> + }
> | RENAME USER_SYM clear_privileges rename_list
> {
> Lex->sql_command = SQLCOM_RENAME_USER;
> @@ -8694,10 +8957,14 @@ preload:
> LEX *lex=Lex;
> lex->sql_command=SQLCOM_PRELOAD_KEYS;
> lex->alter_info.reset();
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> }
> preload_list_or_parts
> - {}
> - ;
> + {
> + Lex->pop_select(); //main select
> + }
> + ;
>
> preload_list_or_parts:
> preload_keys_parts
> @@ -8763,192 +9030,353 @@ opt_ignore_leaves:
>
>
> select:
> - opt_with_clause select_init
> + query_expression
> {
> - LEX *lex= Lex;
> - lex->sql_command= SQLCOM_SELECT;
> - lex->current_select->set_with_clause($1);
> + Lex->selects_allow_into= TRUE;
> + Lex->selects_allow_procedure= TRUE;
> + Lex->set_main_unit($1);
> + if (Lex->check_main_unit_semantics())
> + MYSQL_YYABORT;
> +
> + SELECT_LEX *fake= Lex->unit.fake_select_lex;
> + if (fake)
> + {
> + fake->no_table_names_allowed= 1;
> + Lex->push_select(fake);
> + }
> + else
> + Lex->push_select(Lex->first_select_lex());
> + Lex->sql_command= SQLCOM_SELECT;
> }
> ;
>
> -select_init:
> - SELECT_SYM select_options_and_item_list select_init3
> - | '(' 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
> - | '(' select_paren_union_query_term ')'
> - | '(' select_paren_union_query_term ')' union_list
> - | '(' select_paren_union_query_term ')' union_order_or_limit
> +simple_table:
> + query_specification { $$= $1; }
> + | table_value_constructor { $$= $1; }
> ;
> -
> -select_paren:
> +
> +table_value_constructor:
> + VALUES
> + {
> + LEX *lex= Lex;
> + SELECT_LEX *sel;
> + //lex->field_list.empty();
> + lex->many_values.empty();
> + lex->insert_list=0;
> + if (!(sel= lex->alloc_select(TRUE)) ||
> + lex->push_select(sel))
> + MYSQL_YYABORT;
> + sel->init_select();
> + sel->braces= FALSE; // just initialisation
> + }
> + values_list
> + {
> + LEX *lex=Lex;
> + $$= lex->pop_select(); // above TVC select
> + if (!($$->tvc=
> + new (lex->thd->mem_root)
> table_value_constr(lex->many_values,
> + $$,
> +
> $$->options)))
> + MYSQL_YYABORT;
> + lex->many_values.empty();
> + }
> + ;
> +
> +query_specification:
> + 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
> - opt_select_lock_type
> + select_options
> {
> - DBUG_ASSERT(Lex->current_select->braces);
> + Select->parsing_place= SELECT_LIST;
> }
> - | '(' select_paren ')'
> - ;
> -
> -select_paren_union_query_term:
> + select_item_list
> {
> - /*
> - 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->parsing_place= NO_MATTER;
> }
> - SELECT_SYM select_options_and_item_list
> select_part3_union_query_term
> - opt_select_lock_type
> + opt_into
> + opt_from_clause
> + opt_where_clause
> + opt_group_clause
> + opt_having_clause
> + opt_window_clause
> {
> - DBUG_ASSERT(Lex->current_select->braces);
> + $$= Lex->pop_select();
> }
> - | '(' select_paren_union_query_term ')'
> ;
>
> -select_paren_view:
> - {
> - /*
> - 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_SYM select_options_and_item_list select_part3_view
> - opt_select_lock_type
> - {
> - DBUG_ASSERT(Lex->current_select->braces);
> - }
> - | '(' select_paren_view ')'
> +opt_from_clause:
> + /* Empty */
> + | from_clause
> + ;
> +
> +query_primary:
> + simple_table
> + { $$= $1; }
> + | query_primary_parens
> + { $$= $1; }
> ;
>
> -/* The equivalent of select_paren for nested queries. */
> -select_paren_derived:
> +query_primary_parens:
> + '(' query_expression_unit
> {
> - Lex->current_select->set_braces(true);
> + SELECT_LEX *last= $2->pre_last_parse->next_select();
> + int cmp=
> cmp_unit_op($2->first_select()->next_select()->linkage,
> + last->linkage);
> + if (cmp < 0)
> + {
> + if (!check_intersect_prefix($2->first_select()))
> + {
> + if (Lex->pop_new_select_and_wrap() == NULL)
> + MYSQL_YYABORT;
> + }
> + }
> + Lex->push_select($2->fake_select_lex);
> }
> - 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->pop_select();
> + if ($4)
> + {
> + ($4)->set_to($2->fake_select_lex);
> + }
> + $$= $2->first_select();
> }
> - | '(' 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);
> + Lex->pop_select();
> + $$= $2;
> + $$->braces= TRUE;
> + if ($4)
> + {
> + if ($2->next_select())
> + {
> + SELECT_LEX_UNIT *unit= $2->master_unit();
> + if (!unit)
> + unit= Lex->create_unit($2);
> + if (!unit)
> + YYABORT;
> + if (!unit->fake_select_lex->is_set_query_expr_tail)
> + $4->set_to(unit->fake_select_lex);
> + else
> + {
> + $$= Lex->wrap_unit_into_derived(unit);
> + if (!$$)
> + YYABORT;
> + $4->set_to($$);
> + }
> + }
> + else if (!$2->is_set_query_expr_tail)
> + {
> + $4->set_to($2);
> + }
> + else
> + {
> + SELECT_LEX_UNIT *unit= Lex->create_unit($2);
> + if (!unit)
> + YYABORT;
> + $$= Lex->wrap_unit_into_derived(unit);
> + if (!$$)
> + YYABORT;
> + $4->set_to($$);
> + }
> + }
> }
> ;
>
> -
> -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);
> + SELECT_LEX *sel1;
> + SELECT_LEX *sel2;
> + if (!$1->next_select())
> + sel1= $1;
> + else
> + {
> + sel1= Lex->wrap_unit_into_derived($1->master_unit());
> + if (!sel1)
> + YYABORT;
> + }
> + if (!$3->next_select())
> + sel2= $3;
> + else
> + {
> + sel2= Lex->wrap_unit_into_derived($3->master_unit());
> + if (!sel2)
> + YYABORT;
> + }
> + sel1->link_neighbour(sel2);
> + sel2->set_linkage_and_distinct($2.unit_type, $2.distinct);
> + $$= Lex->create_unit(sel1);
> + $$->pre_last_parse= sel1;
> + if ($$ == NULL)
> + 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);
> + SELECT_LEX *sel1;
> + if (!$3->next_select())
> + sel1= $3;
> + else
> + {
> + sel1= Lex->wrap_unit_into_derived($3->master_unit());
> + if (!sel1)
> + YYABORT;
> + }
> + SELECT_LEX *last= $1->pre_last_parse->next_select();
> +
> + int cmp= cmp_unit_op($2.unit_type, last->linkage);
> + if (cmp == 0)
> + {
> + // do nothing, this part will be just connected
> + }
> + else if (cmp > 0)
> + {
> + // Store beginning and continue to connect parts
> + if (Lex->push_new_select($1->pre_last_parse))
> + MYSQL_YYABORT;
> + }
> + else /* cmp < 0 */
> + {
> + // wrap stored part in a select, then continue to connect
> parts
> + if (!check_intersect_prefix($1->first_select()))
> + {
> + if ((last= Lex->pop_new_select_and_wrap()) == NULL)
> + MYSQL_YYABORT;
> + last->set_master_unit($1);
> + }
> + }
> + last->link_neighbour(sel1);
> + sel1->set_master_unit($1);
> + sel1->set_linkage_and_distinct($2.unit_type, $2.distinct);
> + $$= $1;
> + $$->pre_last_parse= last;
> }
> ;
>
> -
> -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);
> + Lex->pop_select();
> + SELECT_LEX *sel= $1;
> + if ($3)
> + {
> + if ($1->next_select())
> + {
> + SELECT_LEX_UNIT *unit= $1->master_unit();
> + if (!unit)
> + unit= Lex->create_unit($1);
> + if (!unit)
> + YYABORT;
> + if (!unit->fake_select_lex->is_set_query_expr_tail)
> + $3->set_to(unit->fake_select_lex);
> + else
> + {
> + SELECT_LEX *sel= Lex->wrap_unit_into_derived(unit);
> + if (!sel)
> + YYABORT;
> + $3->set_to(sel);
> + }
> + }
> + else if (!$1->is_set_query_expr_tail)
> + $3->set_to($1);
> + else
> + {
> + SELECT_LEX_UNIT *unit= $1->master_unit();
> + if (!unit)
> + unit= Lex->create_unit($1);
> + if (!unit)
> + YYABORT;
> + sel= Lex->wrap_unit_into_derived(unit);
> + if (!sel)
> + YYABORT;
> + $3->set_to(sel);
> + }
> + }
> + $$= Lex->create_unit(sel);
> + if ($$ == NULL)
> + YYABORT;
> }
> - union_list_view
> - | order_or_limit opt_select_lock_type
> + | query_expression_unit
> {
> - Lex->current_select->set_braces(false);
> + SELECT_LEX *last= $1->pre_last_parse->next_select();
> + int cmp=
> cmp_unit_op($1->first_select()->next_select()->linkage,
> + last->linkage);
> + if (cmp < 0)
> + {
> + if (!check_intersect_prefix($1->first_select()))
> + {
> + if (Lex->pop_new_select_and_wrap() == NULL)
> + MYSQL_YYABORT;
> + }
> + }
> + Lex->push_select($1->fake_select_lex);
> }
> - | table_expression order_or_limit opt_select_lock_type
> + query_expression_tail
> {
> - Lex->current_select->set_braces(false);
> + Lex->pop_select();
> + if ($3)
> + {
> + ($3)->set_to($1->fake_select_lex);
> + }
> + $$= $1;
> }
> ;
>
> -/*
> - 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
> +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:
> - select_part3_union_not_ready_noproc
> - | table_expression procedure_clause
> - | table_expression order_or_limit procedure_clause
> - ;
> +subselect:
> + remember_tok_start
> + query_expression
> + {
> + if (!Lex->expr_allows_subselect ||
> + Lex->sql_command == (int)SQLCOM_PURGE)
> + {
> + thd->parse_error(ER_SYNTAX_ERROR, $1);
> + MYSQL_YYABORT;
> + }
>
> -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
> - ;
> + // Add the subtree of subquery to the current SELECT_LEX
> + SELECT_LEX *curr_sel= Lex->select_stack_head();
> + DBUG_ASSERT(Lex->current_select == curr_sel);
> + if (curr_sel)
> + {
> + curr_sel->register_unit($2, &curr_sel->context);
> + curr_sel->add_statistics($2);
> + }
>
> -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
> - {
> - Select->parsing_place= NO_MATTER;
> + $$= $2->first_select();
> }
> ;
>
> @@ -8956,18 +9384,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
> @@ -9005,59 +9421,63 @@ 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 (Lex->current_select != &Lex->builtin_select)
> - my_yyabort_error((ER_CANT_USE_OPTION_HERE, MYF(0),
> "SQL_NO_CACHE"));
> - if (Lex->builtin_select.sql_cache == SELECT_LEX::SQL_CACHE)
> - my_yyabort_error((ER_WRONG_USAGE, MYF(0), "SQL_CACHE",
> "SQL_NO_CACHE"));
> - if (Lex->builtin_select.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->builtin_select.options&= ~OPTION_TO_QUERY_CACHE;
> - Lex->builtin_select.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 (Lex->current_select != &Lex->builtin_select)
> - my_yyabort_error((ER_CANT_USE_OPTION_HERE, MYF(0),
> "SQL_CACHE"));
> - if (Lex->builtin_select.sql_cache == SELECT_LEX::SQL_NO_CACHE)
> - my_yyabort_error((ER_WRONG_USAGE, MYF(0), "SQL_NO_CACHE",
> "SQL_CACHE"));
> - if (Lex->builtin_select.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->builtin_select.options|= OPTION_TO_QUERY_CACHE;
> - Lex->builtin_select.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
> + { $$.empty(); }
> + | select_lock_type
> + { $$= $1; }
> + ;
> +
> +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_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
> @@ -11361,10 +11781,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);
> }
> ;
>
> @@ -11383,11 +11808,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 (push_new_name_resolution_context(thd, $1, $3))
> MYSQL_YYABORT;
> @@ -11404,6 +11836,8 @@ join_table:
> USING
> {
> MYSQL_YYABORT_UNLESS($1 && $3);
> + Select->add_joined_table($1);
> + Select->add_joined_table($3);
> }
> '(' using_list ')'
> {
> @@ -11414,6 +11848,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);
> }
> @@ -11423,6 +11859,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 (push_new_name_resolution_context(thd, $1, $5))
> MYSQL_YYABORT;
> @@ -11439,6 +11877,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 ')'
> {
> @@ -11449,6 +11889,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;
> @@ -11459,6 +11901,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 (push_new_name_resolution_context(thd, $1, $5))
> MYSQL_YYABORT;
> @@ -11476,6 +11920,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 ')'
> {
> @@ -11487,6 +11933,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 (!($$= lex->current_select->convert_right_join()))
> @@ -11521,40 +11969,70 @@ 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_reference_list_parens:
> + '(' table_reference_list_parens ')' { $$= $2; }
> + | '(' nested_table_reference_list ')'
> + {
> + if (!($$= Select->end_nested_join(thd)))
> + MYSQL_YYABORT;
> + }
> + ;
> +
> +nested_table_reference_list:
> + table_ref ',' table_ref
> + {
> + if (Select->init_nested_join(thd))
> + MYSQL_YYABORT;
> + Select->add_joined_table($1);
> + Select->add_joined_table($3);
> + $$= $1->embedding;
> + }
> + | nested_table_reference_list ',' table_ref
> + {
> + Select->add_joined_table($3);
> + $$= $1;
> + }
> + ;
> +
> +join_table_parens:
> + '(' join_table_parens ')' { $$= $2; }
> + | '(' join_table ')'
> + {
> + LEX *lex= Lex;
> + if (!($$= lex->current_select->nest_last_join(thd)))
> + {
> + thd->parse_error();
> + MYSQL_YYABORT;
> + }
> + }
> + ;
> +
> +
> table_primary_ident:
> + table_ident opt_use_partition
> + opt_table_alias_clause opt_key_definition
> {
> SELECT_LEX *sel= Select;
> sel->table_join_options= 0;
> - }
> - table_ident opt_use_partition opt_table_alias opt_key_definition
> - {
> - if (!($$= Select->add_table_to_list(thd, $2, $4,
> + if (!($$= Select->add_table_to_list(thd, $1, $3,
>
> Select->get_table_join_options(),
> YYPS->m_lock_type,
> YYPS->m_mdl_type,
> Select->pop_index_hints(),
> - $3)))
> + $2)))
> MYSQL_YYABORT;
> - Select->add_joined_table($$);
> }
> ;
>
>
> -
> /*
> Represents a flattening of the following rules from the SQL:2003
> standard. This sub-rule corresponds to the sub-rule
> @@ -11572,242 +12050,56 @@ table_primary_ident:
> */
>
> table_primary_derived:
> - '(' get_select_lex select_derived_union ')' opt_table_alias
> + query_primary_parens table_alias_clause
> {
> - /* Use $2 instead of Lex->current_select as derived table will
> - alter value of Lex->current_select. */
> - if (!($3 || $5) && $2->embedding &&
> - !$2->embedding->nested_join->join_list.elements)
> + LEX *lex=Lex;
> + lex->derived_tables|= DERIVED_SUBQUERY;
> + $1->linkage= DERIVED_TABLE_TYPE;
> + $1->braces= FALSE;
> + // Add the subtree of subquery to the current SELECT_LEX
> + SELECT_LEX *curr_sel= Lex->select_stack_head();
> + DBUG_ASSERT(Lex->current_select == curr_sel);
> + SELECT_LEX_UNIT *unit= $1->master_unit();
> + if (!unit)
> {
> - /* 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;
> + unit= Lex->create_unit($1);
> + if (!unit)
> + YYABORT;
> }
> - 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 (ti == NULL)
> - MYSQL_YYABORT;
> - if (!($$= sel->add_table_to_list(thd,
> - ti, $5, 0,
> - TL_READ, MDL_SHARED_READ)))
> + curr_sel->register_unit(unit, &curr_sel->context);
> + curr_sel->add_statistics(unit);
>
> - MYSQL_YYABORT;
> - sel->add_joined_table($$);
> - //lex->pop_context("derived");
> - lex->nest_level--;
> - }
> - else if ($5 != 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());
> - }
> - /* Represents derived table with WITH clause */
> - | '(' get_select_lex subselect_start
> - with_clause query_expression_body
> - subselect_end ')' 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 (ti == NULL)
> MYSQL_YYABORT;
> - $5->set_with_clause($4);
> - lex->current_select= sel;
> - if (!($$= sel->add_table_to_list(lex->thd,
> - ti, $8, 0,
> - TL_READ, MDL_SHARED_READ)))
> + if (!($$= curr_sel->add_table_to_list(lex->thd,
> + ti, $2, 0,
> + TL_READ,
> MDL_SHARED_READ)))
> MYSQL_YYABORT;
> - sel->add_joined_table($$);
> - }
> - ;
> -
> -/*
> - 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 ($1)
> - {
> - thd->parse_error();
> - MYSQL_YYABORT;
> - }
> - }
> - | select_derived union_head_non_top
> - {
> - if ($1)
> - {
> - thd->parse_error();
> - MYSQL_YYABORT;
> - }
> }
> - union_list_derived_part2
> - | derived_query_specification opt_select_lock_type
> - | derived_query_specification order_or_limit opt_select_lock_type
> - | derived_query_specification 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;
> - }
> - ;
> -
> -/* handle contents of parentheses in join expression */
> -select_derived:
> - get_select_lex_derived derived_table_list
> + | '('
> + query_expression
> + ')' table_alias_clause
> {
> - LEX *lex= Lex;
> - /* for normal joins, $2 != NULL and end_nested_join() != NULL,
> - for derived tables, both must equal NULL */
> + LEX *lex=Lex;
> + lex->derived_tables|= DERIVED_SUBQUERY;
> + $2->first_select()->linkage= DERIVED_TABLE_TYPE;
>
> - if (!($$= $1->end_nested_join(lex->thd)) && $2)
> - MYSQL_YYABORT;
> - if (!$2 && $$)
> - {
> - thd->parse_error();
> - MYSQL_YYABORT;
> - }
> - }
> - ;
>
> -/*
> - 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;
> - }
> - ;
> + // Add the subtree of subquery to the current SELECT_LEX
> + SELECT_LEX *curr_sel= Lex->select_stack_head();
> + DBUG_ASSERT(Lex->current_select == curr_sel);
> + curr_sel->register_unit($2, &curr_sel->context);
> + curr_sel->add_statistics($2);
>
> -select_derived2:
> - {
> - LEX *lex= Lex;
> - lex->derived_tables|= DERIVED_SUBQUERY;
> - if (!lex->expr_allows_subselect ||
> - lex->sql_command == (int)SQLCOM_PURGE)
> - {
> - thd->parse_error();
> - MYSQL_YYABORT;
> - }
> - if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE ||
> - mysql_new_select(lex, 1, NULL))
> + Table_ident *ti= new (thd->mem_root) Table_ident($2);
> + if (ti == NULL)
> MYSQL_YYABORT;
> - mysql_init_select(lex);
> - lex->current_select->set_linkage(DERIVED_TABLE_TYPE);
> - lex->current_select->parsing_place= SELECT_LIST;
> - }
> - select_options select_item_list
> - {
> - Select->parsing_place= NO_MATTER;
> - }
> - opt_table_expression
> - ;
> -
> -get_select_lex:
> - /* Empty */ { $$= Select; }
> - ;
> -
> -get_select_lex_derived:
> - get_select_lex
> - {
> - LEX *lex= Lex;
> - if ($1->init_nested_join(lex->thd))
> + if (!($$= curr_sel->add_table_to_list(lex->thd,
> + ti, $4, 0,
> + TL_READ,
> MDL_SHARED_READ)))
> MYSQL_YYABORT;
> }
> - ;
> -
> -select_derived_init:
> - {
> - LEX *lex= Lex;
> -
> - TABLE_LIST *embedding= lex->current_select->embedding;
> - $$= embedding &&
> - !embedding->nested_join->join_list.elements;
> - /* return true if we are deeply nested */
> - }
> ;
>
> opt_outer:
> @@ -11939,9 +12231,14 @@ table_alias:
> | '='
> ;
>
> -opt_table_alias:
> +opt_table_alias_clause:
> /* empty */ { $$=0; }
> - | table_alias ident
> +
> + | table_alias_clause { $$= $1; }
> + ;
> +
> +table_alias_clause:
> + table_alias ident
> {
> $$= (LEX_CSTRING*) thd->memdup(&$2,sizeof(LEX_STRING));
> if ($$ == NULL)
> @@ -12108,7 +12405,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:
> @@ -12232,64 +12529,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 (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 (!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 (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 (add_order_to_list(thd, $1,(bool) $2)) MYSQL_YYABORT; }
> + {
> + $$= new (thd->mem_root) SQL_I_List<ORDER>();
> + if (add_to_list(thd, *$$, $1, (bool) $2))
> + MYSQL_YYABORT;
> + }
> ;
>
> order_dir:
> @@ -12299,63 +12567,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;
> }
> ;
>
> @@ -12424,6 +12690,66 @@ delete_limit_clause:
> | LIMIT limit_option ROWS_SYM EXAMINED_SYM { thd->parse_error();
> MYSQL_YYABORT; }
> ;
>
> +query_expression_tail:
> + /* empty */ { $$= NULL; }
> + | order_or_limit opt_select_lock_type
> + {
> + $$= $1;
> + $$->lock= $2;
> + }
> + | order_or_limit procedure_or_into opt_select_lock_type
> + {
> + $$= $1;
> + $$->lock= $3;
> + }
> + | procedure_or_into opt_select_lock_type
> + {
> + $$= new(thd->mem_root) Lex_order_limit_lock;
> + if (!$$)
> + YYABORT;
> + $$->order_list= NULL;
> + $$->limit.empty();
> + $$->lock= $2;
> + }
> + | select_lock_type
> + {
> + $$= new(thd->mem_root) Lex_order_limit_lock;
> + if (!$$)
> + YYABORT;
> + $$->order_list= NULL;
> + $$->limit.empty();
> + $$->lock= $1;
> + }
> + ;
> +
> +procedure_or_into:
> + procedure_clause
> + | into
> + | procedure_clause into
> + ;
> +
> +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 */
> | '+'
> @@ -12493,14 +12819,11 @@ bool:
> | TRUE_SYM { $$= 1; }
> | FALSE_SYM { $$= 0; }
>
> -
> procedure_clause:
> PROCEDURE_SYM ident /* Procedure name */
> {
> LEX *lex=Lex;
>
> - DBUG_ASSERT(&lex->builtin_select == lex->current_select);
> -
> lex->proc_list.elements=0;
> lex->proc_list.first=0;
> lex->proc_list.next= &lex->proc_list.first;
> @@ -12520,6 +12843,7 @@ procedure_clause:
> parameters are reduced.
> */
> Lex->expr_allows_subselect= false;
> + Select->options|= OPTION_PROCEDURE_CLAUSE;
> }
> '(' procedure_list ')'
> {
> @@ -12600,8 +12924,21 @@ select_outvar:
> }
> ;
>
> +opt_into:
> + /* empty */
> + | into
> + ;
> into:
> INTO into_destination
> + {
> + if (!(Select->options & OPTION_INTO_CLAUSE))
> + Select->options|= OPTION_INTO_CLAUSE;
> + else
> + {
> + my_error(ER_CANT_USE_OPTION_HERE, MYF(0), "INTO");
> + MYSQL_YYABORT;
> + }
> + }
> ;
>
> into_destination:
> @@ -12647,10 +12984,15 @@ do:
> LEX *lex=Lex;
> lex->sql_command = SQLCOM_DO;
> mysql_init_select(lex);
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> }
> expr_list
> {
> Lex->insert_list= $3;
> + Lex->pop_select(); //main select
> + if (Lex->check_main_unit_semantics())
> + MYSQL_YYABORT;
> }
> ;
>
> @@ -12882,17 +13224,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->builtin_select;
> + 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:
> @@ -12901,15 +13250,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->builtin_select;
> + 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:
> @@ -12955,35 +13311,47 @@ 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;
> if (!(lex->insert_list= new (thd->mem_root) List_item) ||
> 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:
> @@ -13093,6 +13461,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;
> @@ -13118,7 +13488,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:
> @@ -13164,6 +13541,8 @@ 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->builtin_select.init_order();
> @@ -13185,7 +13564,12 @@ single_multi:
> }
> opt_where_clause opt_order_clause
> delete_limit_clause {}
> - opt_select_expressions {}
> + opt_select_expressions
> + {
> + if ($6)
> + Select->order_list= *($6);
> + Lex->pop_select(); //main select
> + }
> | table_wild_list
> {
> mysql_init_multi_delete(Lex);
> @@ -13196,6 +13580,9 @@ single_multi:
> {
> if (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
> {
> @@ -13207,6 +13594,9 @@ single_multi:
> {
> if (multi_delete_set_locks_and_link_aux_tables(Lex))
> MYSQL_YYABORT;
> + Lex->pop_select(); //main select
> + if (Lex->check_main_unit_semantics())
> + MYSQL_YYABORT;
> }
> ;
>
> @@ -13284,6 +13674,7 @@ truncate:
> lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_truncate_table();
> if (lex->m_sql_cmd == NULL)
> MYSQL_YYABORT;
> + Lex->pop_select(); //main select
> }
> opt_truncate_table_storage_clause { }
> ;
> @@ -13365,6 +13756,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();
> @@ -13372,6 +13765,7 @@ show:
> show_param
> {
> Select->parsing_place= NO_MATTER;
> + Lex->pop_select(); //main select
> }
> ;
>
> @@ -13387,7 +13781,7 @@ show_param:
> {
> LEX *lex= Lex;
> lex->sql_command= SQLCOM_SHOW_TABLES;
> - lex->builtin_select.db= $3;
> + lex->first_select_lex()->db= $3;
> if (prepare_schema_table(thd, lex, 0, SCH_TABLE_NAMES))
> MYSQL_YYABORT;
> }
> @@ -13395,7 +13789,7 @@ show_param:
> {
> LEX *lex= Lex;
> lex->sql_command= SQLCOM_SHOW_TRIGGERS;
> - lex->builtin_select.db= $3;
> + lex->first_select_lex()->db= $3;
> if (prepare_schema_table(thd, lex, 0, SCH_TRIGGERS))
> MYSQL_YYABORT;
> }
> @@ -13403,7 +13797,7 @@ show_param:
> {
> LEX *lex= Lex;
> lex->sql_command= SQLCOM_SHOW_EVENTS;
> - lex->builtin_select.db= $2;
> + lex->first_select_lex()->db= $2;
> if (prepare_schema_table(thd, lex, 0, SCH_EVENTS))
> MYSQL_YYABORT;
> }
> @@ -13411,7 +13805,7 @@ show_param:
> {
> LEX *lex= Lex;
> lex->sql_command= SQLCOM_SHOW_TABLE_STATUS;
> - lex->builtin_select.db= $3;
> + lex->first_select_lex()->db= $3;
> if (prepare_schema_table(thd, lex, 0, SCH_TABLES))
> MYSQL_YYABORT;
> }
> @@ -13419,7 +13813,7 @@ show_param:
> {
> LEX *lex= Lex;
> lex->sql_command= SQLCOM_SHOW_OPEN_TABLES;
> - lex->builtin_select.db= $3;
> + lex->first_select_lex()->db= $3;
> if (prepare_schema_table(thd, lex, 0, SCH_OPEN_TABLES))
> MYSQL_YYABORT;
> }
> @@ -13469,12 +13863,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;
> @@ -13516,13 +13911,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;
> @@ -13829,7 +14224,7 @@ describe:
> explainable_command
> {
> LEX *lex=Lex;
> - lex->builtin_select.options|= SELECT_DESCRIBE;
> + lex->first_select_lex()->options|= SELECT_DESCRIBE;
> }
> ;
>
> @@ -13855,6 +14250,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 {}
> ;
> @@ -13897,8 +14294,7 @@ flush:
> lex->type= 0;
> lex->no_write_to_binlog= $2;
> }
> - flush_options
> - {}
> + flush_options {}
> ;
>
> flush_options:
> @@ -13915,6 +14311,7 @@ flush_options:
> opt_table_list opt_flush_lock
> {}
> | flush_options_list
> + {}
> ;
>
> opt_flush_lock:
> @@ -14070,9 +14467,13 @@ purge:
> LEX *lex=Lex;
> lex->type=0;
> lex->sql_command = SQLCOM_PURGE;
> + if (lex->main_select_push())
> + MYSQL_YYABORT;
> }
> purge_options
> - {}
> + {
> + Lex->pop_select(); //main select
> + }
> ;
>
> purge_options:
> @@ -14090,6 +14491,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;
> }
> ;
>
> @@ -14099,6 +14502,8 @@ kill:
> KILL_SYM
> {
> LEX *lex=Lex;
> + if (lex->main_select_push())
> + YYABORT;
> lex->value_list.empty();
> lex->users_list.empty();
> lex->sql_command= SQLCOM_KILL;
> @@ -14107,6 +14512,7 @@ kill:
> kill_type kill_option kill_expr
> {
> Lex->kill_signal= (killed_state) ($3 | $4);
> + Lex->pop_select(); //main select
> }
> ;
>
> @@ -14167,6 +14573,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
> {
> @@ -14193,7 +14601,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:
> @@ -14597,17 +15009,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 (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();
> @@ -14636,9 +15052,9 @@ 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());
> + With_element *elem= new With_element($1, *$2, $7);
> if (elem == NULL || Lex->curr_with_clause->add_with_element(elem))
> MYSQL_YYABORT;
> if (elem->set_unparsed_spec(thd, $6+1, $8))
> @@ -15589,14 +16005,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
> @@ -15606,6 +16030,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
> {}
> @@ -16038,9 +16465,13 @@ lock:
> if (lex->sphead)
> my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "LOCK"));
> lex->sql_command= SQLCOM_LOCK_TABLES;
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> }
> table_lock_list opt_lock_wait_timeout
> - {}
> + {
> + Lex->pop_select(); //main select
> + }
> ;
>
> opt_lock_wait_timeout:
> @@ -16071,7 +16502,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);
> @@ -16105,9 +16536,13 @@ unlock:
> if (lex->sphead)
> my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "UNLOCK"));
> lex->sql_command= SQLCOM_UNLOCK_TABLES;
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> }
> table_or_tables
> - {}
> + {
> + Lex->pop_select(); //main select
> + }
> ;
>
> /*
> @@ -16115,25 +16550,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 (lex->sphead)
> my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "HANDLER"));
> lex->sql_command = SQLCOM_HA_OPEN;
> - if (!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 (lex->sphead)
> my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "HANDLER"));
> lex->sql_command = SQLCOM_HA_CLOSE;
> - if (!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 (lex->sphead)
> @@ -16141,20 +16587,24 @@ handler:
> lex->expr_allows_subselect= FALSE;
> lex->sql_command = SQLCOM_HA_READ;
> lex->ha_rkey_mode= HA_READ_KEY_EXACT; /* Avoid purify
> warnings */
> - 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;
> - if (!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 (Lex->uses_stored_routines())
> + if (lex->uses_stored_routines())
> {
> my_error(ER_NOT_SUPPORTED_YET, MYF(0),
> "stored functions in HANDLER ... READ");
> @@ -16800,83 +17250,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 (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 (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 (Lex->add_select_to_union_list((bool)$2, $1, FALSE))
> - MYSQL_YYABORT;
> - }
> - ;
>
> union_option:
> /* empty */ { $$=1; }
> @@ -16884,110 +17267,10 @@ union_option:
> | ALL { $$=0; }
> ;
>
> -/*
> - 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:
> - query_specification order_or_limit opt_select_lock_type { $$=
> $1; }
> - | '(' select_paren_derived ')' union_order_or_limit { $$=
> $2; }
> - ;
> -
> -query_term_union_ready:
> - query_specification 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 (!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 (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 (check_simple_select())
> - MYSQL_YYABORT;
> YYPS->m_lock_type= TL_READ_HIGH_PRIORITY;
> YYPS->m_mdl_type= MDL_SHARED_READ;
> Select->options|= SELECT_HIGH_PRIORITY;
> @@ -16996,18 +17279,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 (check_simple_select())
> - MYSQL_YYABORT;
> - Select->options|= OPTION_BUFFER_RESULT;
> - }
> - | SQL_CALC_FOUND_ROWS
> - {
> - if (check_simple_select())
> - 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; }
> ;
>
> @@ -17095,32 +17368,28 @@ 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;
> + SQL_I_List<TABLE_LIST> *save=
> &lex->first_select_lex()->table_list;
> + lex->set_main_unit($2);
> + if (lex->check_main_unit_semantics())
> + MYSQL_YYABORT;
> + lex->first_select_lex()->table_list.push_front(save);
> + lex->current_select= Lex->first_select_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;
> + size_t not_used;
> trim_whitespace(thd->charset(),
> - &lex->create_view->select);
> - lex->create_view->check= $4;
> + &lex->create_view->select, ¬_used);
> + lex->create_view->check= $3;
> lex->parsing_options.allows_variable= TRUE;
> - lex->current_select->set_with_clause($2);
> }
> ;
>
> -/*
> - 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
> - | '(' 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; }
> _______________________________________________
> commits mailing list
> commits@xxxxxxxxxxx
> https://lists.askmonty.org/cgi-bin/mailman/listinfo/commits
>
Follow ups