summaryrefslogtreecommitdiff
path: root/sql/sql_yacc_ora.yy
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_yacc_ora.yy')
-rw-r--r--sql/sql_yacc_ora.yy2205
1 files changed, 1244 insertions, 961 deletions
diff --git a/sql/sql_yacc_ora.yy b/sql/sql_yacc_ora.yy
index ec2aeeaefba..7dd065d59ab 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
@@ -1481,7 +1515,7 @@ query:
END_OF_INPUT
{
if (!thd->bootstrap &&
- (!(thd->lex->select_lex.options & OPTION_FOUND_COMMENT)))
+ (!(thd->lex->builtin_select.options & OPTION_FOUND_COMMENT)))
my_yyabort_error((ER_EMPTY_QUERY, MYF(0)));
thd->lex->sql_command= SQLCOM_EMPTY_QUERY;
@@ -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,15 +1985,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 (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->select_lex.add_table_to_list(thd, $5, NULL,
- TL_OPTION_UPDATING,
- TL_WRITE, MDL_EXCLUSIVE))
+ }
+ 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;
lex->alter_info.reset();
/*
@@ -1951,7 +2015,7 @@ create:
create_body
{
LEX *lex= thd->lex;
- lex->current_select= &lex->select_lex;
+ lex->current_select= &lex->builtin_select;
if ((lex->create_info.used_fields & HA_CREATE_USED_ENGINE) &&
!lex->create_info.db_type)
{
@@ -1960,20 +2024,23 @@ 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;
- if (!lex->select_lex.add_table_to_list(thd, $5, NULL,
- TL_OPTION_UPDATING,
- TL_WRITE, MDL_EXCLUSIVE))
+ if (!lex->builtin_select.add_table_to_list(thd, $5, NULL,
+ TL_OPTION_UPDATING,
+ TL_WRITE, MDL_EXCLUSIVE))
MYSQL_YYABORT;
/*
@@ -1996,8 +2063,8 @@ create:
if (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->builtin_select.table_list.first->db.str,
+ lex->builtin_select.table_list.first->table_name.str);
MYSQL_YYABORT;
}
@@ -2009,7 +2076,7 @@ create:
Lex->create_info.used_fields|= HA_CREATE_USED_SEQUENCE;
Lex->create_info.sequence= 1;
- lex->current_select= &lex->select_lex;
+ lex->current_select= &lex->builtin_select;
if ((lex->create_info.used_fields & HA_CREATE_USED_ENGINE) &&
!lex->create_info.db_type)
{
@@ -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
+ {
+ 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 (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
{
@@ -2724,7 +2861,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->builtin_select.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));
@@ -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) ||
@@ -3804,7 +3981,14 @@ sp_proc_stmt_return:
;
reset_lex_expr:
- { Lex->sphead->reset_lex(thd); } expr { $$= $2; }
+ {
+ Lex->sphead->reset_lex(thd);
+ // will be poped in sp_proc_stmt_exit or sp_proc_stmt_continue
+ if (Lex->main_select_push())
+ MYSQL_YYABORT;
+ }
+ expr
+ { $$= $2; }
;
sp_proc_stmt_exit:
@@ -3820,12 +4004,14 @@ sp_proc_stmt_exit:
}
| EXIT_SYM WHEN_SYM reset_lex_expr
{
+ Lex->pop_select(); //main select pushed in reset_lex_expr
if (Lex->sp_exit_statement(thd, $3) ||
Lex->sphead->restore_lex(thd))
MYSQL_YYABORT;
}
| EXIT_SYM label_ident WHEN_SYM reset_lex_expr
{
+ Lex->pop_select(); //main select pushed in reset_lex_expr
if (Lex->sp_exit_statement(thd, &$2, $4) ||
Lex->sphead->restore_lex(thd))
MYSQL_YYABORT;
@@ -3845,12 +4031,14 @@ sp_proc_stmt_continue:
}
| CONTINUE_SYM WHEN_SYM reset_lex_expr
{
+ Lex->pop_select(); //main select pushed in reset_lex_expr
if (Lex->sp_continue_statement(thd, $3) ||
Lex->sphead->restore_lex(thd))
MYSQL_YYABORT;
}
| CONTINUE_SYM label_ident WHEN_SYM reset_lex_expr
{
+ Lex->pop_select(); //main select pushed in reset_lex_expr
if (Lex->sp_continue_statement(thd, &$2, $4) ||
Lex->sphead->restore_lex(thd))
MYSQL_YYABORT;
@@ -3902,6 +4090,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 +4100,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 +4221,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 +4340,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 +4375,9 @@ simple_when_clause:
WHEN_SYM
{
Lex->sphead->reset_lex(thd); /* For expr $3 */
+
+ if (Lex->main_select_push())
+ MYSQL_YYABORT;
}
expr
{
@@ -4181,6 +4386,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 +4404,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 +4654,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 +4667,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 +4683,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 +4713,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 +4770,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,25 +5209,15 @@ 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,
+ TABLE_LIST *src_table= Lex->builtin_select.add_table_to_list(thd,
$1, NULL, 0, TL_READ, MDL_SHARED_READ);
if (! src_table)
MYSQL_YYABORT;
@@ -5010,7 +5228,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 +5237,51 @@ 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;
+
+ // fix "main" select
+ SELECT_LEX *blt= Lex->pop_select();
+ DBUG_ASSERT(blt == &Lex->builtin_select);
+ Lex->push_select(first_select);
}
- 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->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;
+
+ // fix "main" select
+ SELECT_LEX *blt= Lex->pop_select();
+ DBUG_ASSERT(blt == &Lex->builtin_select);
+ Lex->push_select(first_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 +5372,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 +5993,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 {}
@@ -6009,7 +6210,7 @@ create_table_option:
}
| UNION_SYM opt_equal
{
- Lex->select_lex.table_list.save_and_clear(&Lex->save_list);
+ Lex->builtin_select.table_list.save_and_clear(&Lex->save_list);
}
'(' opt_table_list ')'
{
@@ -6018,8 +6219,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->builtin_select.table_list;
+ lex->builtin_select.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
@@ -6195,6 +6396,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 +6670,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 +6679,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;
}
@@ -7468,22 +7694,24 @@ alter:
Lex->table_type= TABLE_TYPE_UNKNOWN;
Lex->sql_command= SQLCOM_ALTER_TABLE;
Lex->duplicates= DUP_ERROR;
- Lex->select_lex.init_order();
+ Lex->builtin_select.init_order();
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 (!Lex->select_lex.add_table_to_list(thd, $5, NULL,
- TL_OPTION_UPDATING,
- TL_READ_NO_INSERT,
- MDL_SHARED_UPGRADABLE))
+ if (!Lex->builtin_select.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->builtin_select.db= (Lex->builtin_select.table_list.first)->db;
Lex->create_last_non_select_table= Lex->last_table();
}
alter_commands
@@ -7495,11 +7723,14 @@ alter:
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 +7739,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 +7755,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 +7765,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 +7775,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 +7785,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 +7809,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 +7856,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,15 +7901,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 (!(lex->create_info.seq_create_info= new (thd->mem_root)
sequence_definition()) ||
- !lex->select_lex.add_table_to_list(thd, $5, NULL,
- TL_OPTION_SEQUENCE,
- TL_WRITE, MDL_EXCLUSIVE))
+ !lex->builtin_select.add_table_to_list(thd, $5, NULL,
+ TL_OPTION_SEQUENCE,
+ TL_WRITE, MDL_EXCLUSIVE))
MYSQL_YYABORT;
}
sequence_defs
@@ -7660,6 +7920,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;
}
;
@@ -7809,18 +8072,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 &&
- lex->copy_db_to(&lex->select_lex.db))
+ if (lex->builtin_select.db.str == NULL &&
+ lex->copy_db_to(&lex->builtin_select.db))
{
MYSQL_YYABORT;
}
lex->name= $6->table;
lex->alter_info.partition_flags|= ALTER_PARTITION_EXCHANGE;
- if (!lex->select_lex.add_table_to_list(thd, $6, NULL,
- TL_OPTION_UPDATING,
- TL_READ_NO_INSERT,
- MDL_SHARED_NO_WRITE))
+ if (!lex->builtin_select.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)
@@ -8061,9 +8323,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 &&
- lex->copy_db_to(&lex->select_lex.db))
+ lex->builtin_select.db= $3->db;
+ if (lex->builtin_select.db.str == NULL &&
+ lex->copy_db_to(&lex->builtin_select.db))
{
MYSQL_YYABORT;
}
@@ -8337,9 +8599,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:
@@ -8365,6 +8631,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
{
@@ -8373,6 +8641,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
}
;
@@ -8401,6 +8670,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();
@@ -8415,6 +8686,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
}
;
@@ -8531,6 +8803,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
{
@@ -8541,6 +8815,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
}
;
@@ -8578,6 +8853,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
{
@@ -8586,6 +8863,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
}
;
@@ -8599,9 +8877,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;
@@ -8695,9 +8977,13 @@ 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:
@@ -8740,8 +9026,8 @@ adm_partition:
cache_keys_spec:
{
- Lex->select_lex.alloc_index_hints(thd);
- Select->set_index_hint_type(INDEX_HINT_USE,
+ Lex->builtin_select.alloc_index_hints(thd);
+ Select->set_index_hint_type(INDEX_HINT_USE,
INDEX_HINT_MASK_ALL);
}
cache_key_list_or_empty
@@ -8764,192 +9050,345 @@ 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;
+
+ 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();
}
;
@@ -8957,18 +9396,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
@@ -9006,59 +9433,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->select_lex)
- my_yyabort_error((ER_CANT_USE_OPTION_HERE, MYF(0), "SQL_NO_CACHE"));
- if (Lex->select_lex.sql_cache == SELECT_LEX::SQL_CACHE)
- my_yyabort_error((ER_WRONG_USAGE, MYF(0), "SQL_CACHE", "SQL_NO_CACHE"));
- if (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 (Lex->current_select != &Lex->select_lex)
- my_yyabort_error((ER_CANT_USE_OPTION_HERE, MYF(0), "SQL_CACHE"));
- if (Lex->select_lex.sql_cache == SELECT_LEX::SQL_NO_CACHE)
- my_yyabort_error((ER_WRONG_USAGE, MYF(0), "SQL_NO_CACHE", "SQL_CACHE"));
- if (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
+ { $$.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
@@ -11362,10 +11793,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);
}
;
@@ -11384,11 +11820,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;
@@ -11405,6 +11848,8 @@ join_table:
USING
{
MYSQL_YYABORT_UNLESS($1 && $3);
+ Select->add_joined_table($1);
+ Select->add_joined_table($3);
}
'(' using_list ')'
{
@@ -11415,6 +11860,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);
}
@@ -11424,6 +11871,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;
@@ -11440,6 +11889,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 ')'
{
@@ -11450,6 +11901,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;
@@ -11460,6 +11913,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;
@@ -11477,6 +11932,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 ')'
{
@@ -11488,6 +11945,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()))
@@ -11522,40 +11981,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
@@ -11573,241 +12062,55 @@ 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();
- 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();
+ Table_ident *ti= new (thd->mem_root) Table_ident($2);
+ if (ti == NULL)
MYSQL_YYABORT;
- }
- if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE ||
- mysql_new_select(lex, 1, NULL))
+ if (!($$= curr_sel->add_table_to_list(lex->thd,
+ ti, $4, 0,
+ TL_READ, MDL_SHARED_READ)))
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
- ;
-
-get_select_lex:
- /* Empty */ { $$= Select; }
- ;
-
-get_select_lex_derived:
- get_select_lex
- {
- LEX *lex= Lex;
- if ($1->init_nested_join(lex->thd))
- 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 */
}
;
@@ -11940,9 +12243,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)
@@ -12109,7 +12417,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:
@@ -12233,64 +12541,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:
@@ -12300,63 +12579,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;
}
;
@@ -12425,6 +12702,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 */
| '+'
@@ -12494,14 +12831,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;
@@ -12521,6 +12855,7 @@ procedure_clause:
parameters are reduced.
*/
Lex->expr_allows_subselect= false;
+ Select->options|= OPTION_PROCEDURE_CLAUSE;
}
'(' procedure_list ')'
{
@@ -12601,8 +12936,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:
@@ -12648,10 +12996,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;
}
;
@@ -12883,17 +13236,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:
@@ -12902,15 +13262,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:
@@ -12956,35 +13323,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:
@@ -13094,6 +13473,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;
@@ -13102,13 +13483,14 @@ update:
SET update_list
{
LEX *lex= Lex;
- if (lex->select_lex.table_list.elements > 1)
+ if (lex->builtin_select.table_list.elements > 1)
lex->sql_command= SQLCOM_UPDATE_MULTI;
- else if (lex->select_lex.get_table_list()->derived)
+ else if (lex->builtin_select.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->builtin_select.get_table_list()->alias.str,
+ "UPDATE");
MYSQL_YYABORT;
}
/*
@@ -13118,7 +13500,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,9 +13553,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->builtin_select.init_order();
}
opt_delete_options single_multi
;
@@ -13185,7 +13576,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 +13592,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 +13606,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;
}
;
@@ -13270,10 +13672,12 @@ truncate:
{
LEX* lex= Lex;
lex->sql_command= SQLCOM_TRUNCATE;
+ if (lex->main_select_push())
+ MYSQL_YYABORT;
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->builtin_select.options= 0;
+ lex->builtin_select.sql_cache= SELECT_LEX::SQL_CACHE_UNSPECIFIED;
+ lex->builtin_select.init_order();
YYPS->m_lock_type= TL_WRITE;
YYPS->m_mdl_type= MDL_EXCLUSIVE;
}
@@ -13284,6 +13688,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 +13770,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 +13779,7 @@ show:
show_param
{
Select->parsing_place= NO_MATTER;
+ Lex->pop_select(); //main select
}
;
@@ -13387,7 +13795,7 @@ show_param:
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_SHOW_TABLES;
- lex->select_lex.db= $3;
+ lex->first_select_lex()->db= $3;
if (prepare_schema_table(thd, lex, 0, SCH_TABLE_NAMES))
MYSQL_YYABORT;
}
@@ -13395,7 +13803,7 @@ show_param:
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_SHOW_TRIGGERS;
- lex->select_lex.db= $3;
+ lex->first_select_lex()->db= $3;
if (prepare_schema_table(thd, lex, 0, SCH_TRIGGERS))
MYSQL_YYABORT;
}
@@ -13403,7 +13811,7 @@ show_param:
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_SHOW_EVENTS;
- lex->select_lex.db= $2;
+ lex->first_select_lex()->db= $2;
if (prepare_schema_table(thd, lex, 0, SCH_EVENTS))
MYSQL_YYABORT;
}
@@ -13411,7 +13819,7 @@ show_param:
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_SHOW_TABLE_STATUS;
- lex->select_lex.db= $3;
+ lex->first_select_lex()->db= $3;
if (prepare_schema_table(thd, lex, 0, SCH_TABLES))
MYSQL_YYABORT;
}
@@ -13419,7 +13827,7 @@ show_param:
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_SHOW_OPEN_TABLES;
- lex->select_lex.db= $3;
+ lex->first_select_lex()->db= $3;
if (prepare_schema_table(thd, lex, 0, SCH_OPEN_TABLES))
MYSQL_YYABORT;
}
@@ -13469,12 +13877,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 +13925,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;
@@ -13583,7 +13992,7 @@ show_param:
{
LEX *lex= Lex;
lex->sql_command = SQLCOM_SHOW_CREATE;
- if (!lex->select_lex.add_table_to_list(thd, $3, NULL,0))
+ if (!lex->builtin_select.add_table_to_list(thd, $3, NULL,0))
MYSQL_YYABORT;
lex->create_info.storage_media= HA_SM_DEFAULT;
}
@@ -13591,7 +14000,7 @@ show_param:
{
LEX *lex= Lex;
lex->sql_command = SQLCOM_SHOW_CREATE;
- if (!lex->select_lex.add_table_to_list(thd, $3, NULL, 0))
+ if (!lex->builtin_select.add_table_to_list(thd, $3, NULL, 0))
MYSQL_YYABORT;
lex->table_type= TABLE_TYPE_VIEW;
}
@@ -13599,7 +14008,7 @@ show_param:
{
LEX *lex= Lex;
lex->sql_command = SQLCOM_SHOW_CREATE;
- if (!lex->select_lex.add_table_to_list(thd, $3, NULL, 0))
+ if (!lex->builtin_select.add_table_to_list(thd, $3, NULL, 0))
MYSQL_YYABORT;
lex->table_type= TABLE_TYPE_SEQUENCE;
}
@@ -13815,7 +14224,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->builtin_select.db= null_clex_str;
lex->verbose= 0;
if (prepare_schema_table(thd, lex, $2, SCH_COLUMNS))
MYSQL_YYABORT;
@@ -13829,7 +14238,7 @@ describe:
explainable_command
{
LEX *lex=Lex;
- lex->select_lex.options|= SELECT_DESCRIBE;
+ lex->first_select_lex()->options|= SELECT_DESCRIBE;
}
;
@@ -13855,6 +14264,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 +14308,7 @@ flush:
lex->type= 0;
lex->no_write_to_binlog= $2;
}
- flush_options
- {}
+ flush_options {}
;
flush_options:
@@ -13915,6 +14325,7 @@ flush_options:
opt_table_list opt_flush_lock
{}
| flush_options_list
+ {}
;
opt_flush_lock:
@@ -14070,9 +14481,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 +14505,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 +14516,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 +14526,7 @@ kill:
kill_type kill_option kill_expr
{
Lex->kill_signal= (killed_state) ($3 | $4);
+ Lex->pop_select(); //main select
}
;
@@ -14150,7 +14570,7 @@ use:
{
LEX *lex=Lex;
lex->sql_command=SQLCOM_CHANGE_DB;
- lex->select_lex.db= $2;
+ lex->builtin_select.db= $2;
}
;
@@ -14167,6 +14587,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 +14615,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 +15023,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 +15066,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 +16019,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 +16044,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 +16479,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 +16516,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 +16550,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 +16564,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 +16601,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 +17264,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 +17281,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 +17293,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 +17382,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, &not_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; }
@@ -17221,11 +17504,11 @@ trigger_tail:
sp_proc_stmt alternatives are not saving/restoring LEX, so
lex->query_tables can be wiped out.
*/
- if (!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->builtin_select.add_table_to_list(thd, $10,
+ (LEX_CSTRING*) 0,
+ TL_OPTION_UPDATING,
+ TL_READ_NO_INSERT,
+ MDL_SHARED_NO_WRITE))
MYSQL_YYABORT;
}
;