diff options
author | Oleksandr Byelkin <sanja@mariadb.com> | 2015-08-18 13:28:17 +0200 |
---|---|---|
committer | Oleksandr Byelkin <sanja@mariadb.com> | 2015-09-14 16:20:14 +0200 |
commit | 4430d555a34b8471fde9615dc2f8c301f319f65e (patch) | |
tree | 34f71c80e71468e54beec17f97a5b7d647133bd8 /sql/sql_yacc.yy | |
parent | 5fe8b747e9e3440f2f746accca0eb11e287a6713 (diff) | |
download | mariadb-git-mdev-8380.tar.gz |
MDEV-8380: Subquery parse errormdev-8380
backport mysql parser fixes
0034963fbf199696792491bcb79d5f0731c98804
5948561812bc691bd0c13cf518a3fe77d9daf920
Diffstat (limited to 'sql/sql_yacc.yy')
-rw-r--r-- | sql/sql_yacc.yy | 168 |
1 files changed, 97 insertions, 71 deletions
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 811ee4f97d5..d03b05cfb84 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1001,10 +1001,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %parse-param { THD *thd } %lex-param { THD *thd } /* - Currently there are 164 shift/reduce conflicts. + Currently there are 160 shift/reduce conflicts. We should not introduce new conflicts any more. */ -%expect 164 +%expect 160 /* Comments for TOKENS. @@ -1731,6 +1731,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); opt_default_time_precision case_stmt_body opt_bin_mod opt_if_exists_table_element opt_if_not_exists_table_element + opt_into opt_procedure_clause %type <object_ddl_options> create_or_replace @@ -5548,7 +5549,7 @@ create_select: { Select->parsing_place= NO_MATTER; } - opt_select_from + table_expression { /* The following work only with the local list, the global list @@ -5943,11 +5944,6 @@ merge_insert_types: | LAST_SYM { $$= MERGE_INSERT_TO_LAST; } ; -opt_select_from: - opt_limit_clause {} - | select_from select_lock_type - ; - udf_type: STRING_SYM {$$ = (int) STRING_RESULT; } | REAL {$$ = (int) REAL_RESULT; } @@ -8397,6 +8393,7 @@ select_paren_derived: Lex->current_select->set_braces(true); } SELECT_SYM select_part2_derived + table_expression { if (setup_select_in_parentheses(Lex)) MYSQL_YYABORT; @@ -8414,7 +8411,45 @@ select_init2: union_clause ; +/* + Theoretically we can merge all 3 right hand sides of the select_part2 + rule into one, however such a transformation adds one shift/reduce + conflict more. +*/ select_part2: + select_options_and_item_list + opt_order_clause + opt_limit_clause + opt_select_lock_type + | select_options_and_item_list into opt_select_lock_type + | select_options_and_item_list + opt_into + from_clause + opt_where_clause + opt_group_clause + opt_having_clause + opt_order_clause + opt_limit_clause + opt_procedure_clause + opt_into + opt_select_lock_type + { + if ($2 && $10) + { + /* double "INTO" clause */ + my_error(ER_WRONG_USAGE, MYF(0), "INTO", "INTO"); + MYSQL_YYABORT; + } + if ($9 && ($2 || $10)) + { + /* "INTO" with "PROCEDURE ANALYSE" */ + my_error(ER_WRONG_USAGE, MYF(0), "PROCEDURE", "INTO"); + MYSQL_YYABORT; + } + } + ; + +select_options_and_item_list: { LEX *lex= Lex; SELECT_LEX *sel= lex->current_select; @@ -8426,27 +8461,36 @@ select_part2: { Select->parsing_place= NO_MATTER; } - select_into select_lock_type ; -select_into: - opt_order_clause opt_limit_clause {} - | into - | select_from - | into select_from - | select_from into +table_expression: + opt_from_clause + opt_where_clause + opt_group_clause + opt_having_clause + opt_order_clause + opt_limit_clause + opt_procedure_clause + opt_select_lock_type ; -select_from: - FROM join_table_list +from_clause: + FROM table_reference_list + ; + +opt_from_clause: + /* empty */ + | from_clause + ; + +table_reference_list: + join_table_list { Select->context.table_list= Select->context.first_name_resolution_table= Select->table_list.first; } - where_clause group_clause having_clause - opt_order_clause opt_limit_clause procedure_clause - | FROM DUAL_SYM where_clause opt_limit_clause + | DUAL_SYM /* oracle compatibility: oracle always requires FROM clause, and DUAL is system table without fields. Is "SELECT 1 FROM DUAL" any better than "SELECT 1" ? @@ -8530,7 +8574,7 @@ select_option: } ; -select_lock_type: +opt_select_lock_type: /* empty */ | FOR_SYM UPDATE_SYM { @@ -10888,9 +10932,7 @@ select_derived_union: last select in the union. */ Lex->pop_context(); - } - opt_union_order_or_limit - { + if ($1 != NULL) { my_parse_error(ER_THD(thd, ER_SYNTAX_ERROR)); @@ -10910,12 +10952,6 @@ select_init2_derived: my_parse_error(ER_THD(thd, ER_SYNTAX_ERROR)); MYSQL_YYABORT; } - if (sel->linkage == UNION_TYPE && - sel->master_unit()->first_select()->braces) - { - my_parse_error(ER_THD(thd, ER_SYNTAX_ERROR)); - MYSQL_YYABORT; - } } ; @@ -10932,7 +10968,6 @@ select_part2_derived: { Select->parsing_place= NO_MATTER; } - opt_select_from select_lock_type ; /* handle contents of parentheses in join expression */ @@ -10980,7 +11015,7 @@ select_derived2: { Select->parsing_place= NO_MATTER; } - opt_select_from + table_expression ; get_select_lex: @@ -11157,7 +11192,7 @@ opt_all: | ALL ; -where_clause: +opt_where_clause: /* empty */ { Select->where= 0; } | WHERE { @@ -11173,7 +11208,7 @@ where_clause: } ; -having_clause: +opt_having_clause: /* empty */ | HAVING { @@ -11210,7 +11245,7 @@ opt_escape: group by statement in select */ -group_clause: +opt_group_clause: /* empty */ | GROUP_SYM BY group_list olap_opt ; @@ -11358,25 +11393,6 @@ order_dir: | DESC { $$ =0; } ; -opt_limit_clause_init: - /* empty */ - { - LEX *lex= Lex; - SELECT_LEX *sel= lex->current_select; - if (sel->master_unit()->is_union() && !sel->braces) - { - /* Move LIMIT that belongs to UNION to fake_select_lex */ - Lex->current_select= sel->master_unit()->fake_select_lex; - DBUG_ASSERT(Select); - } - sel= lex->current_select; - sel->offset_limit= 0; - sel->select_limit= 0; - lex->limit_rows_examined= 0; - } - | limit_clause {} - ; - opt_limit_clause: /* empty */ {} | limit_clause {} @@ -11574,8 +11590,8 @@ choice: | DEFAULT { $$= HA_CHOICE_UNDEF; } ; -procedure_clause: - /* empty */ +opt_procedure_clause: + /* empty */ { $$= false; } | PROCEDURE_SYM ident /* Procedure name */ { LEX *lex=Lex; @@ -11604,6 +11620,9 @@ procedure_clause: Lex->uncacheable(UNCACHEABLE_SIDEEFFECT); } '(' procedure_list ')' + { + $$= true; + } ; procedure_list: @@ -11680,6 +11699,11 @@ select_outvar: } ; +opt_into: + /* empty */ { $$= false; } + | into { $$= true; } + ; + into: INTO { @@ -12172,7 +12196,7 @@ update: */ Select->set_lock_for_tables($3); } - where_clause opt_order_clause delete_limit_clause {} + opt_where_clause opt_order_clause delete_limit_clause {} ; update_list: @@ -12237,7 +12261,7 @@ single_multi: YYPS->m_lock_type= TL_READ_DEFAULT; YYPS->m_mdl_type= MDL_SHARED_READ; } - where_clause opt_order_clause + opt_where_clause opt_order_clause delete_limit_clause {} opt_select_expressions {} | table_wild_list @@ -12246,7 +12270,7 @@ single_multi: YYPS->m_lock_type= TL_READ_DEFAULT; YYPS->m_mdl_type= MDL_SHARED_READ; } - FROM join_table_list where_clause + FROM join_table_list opt_where_clause { if (multi_delete_set_locks_and_link_aux_tables(Lex)) MYSQL_YYABORT; @@ -12257,7 +12281,7 @@ single_multi: YYPS->m_lock_type= TL_READ_DEFAULT; YYPS->m_mdl_type= MDL_SHARED_READ; } - USING join_table_list where_clause + USING join_table_list opt_where_clause { if (multi_delete_set_locks_and_link_aux_tables(Lex)) MYSQL_YYABORT; @@ -12515,13 +12539,14 @@ show_param: { LEX *lex= Lex; lex->sql_command= SQLCOM_SHOW_BINLOG_EVENTS; - } opt_limit_clause_init + } + opt_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_init - | keys_or_index from_or_in table_ident opt_db where_clause + } opt_limit_clause + | keys_or_index from_or_in table_ident opt_db opt_where_clause { LEX *lex= Lex; lex->sql_command= SQLCOM_SHOW_KEYS; @@ -12556,13 +12581,13 @@ show_param: { (void) create_select_for_variable("warning_count"); } | COUNT_SYM '(' '*' ')' ERRORS { (void) create_select_for_variable("error_count"); } - | WARNINGS opt_limit_clause_init + | WARNINGS opt_limit_clause { Lex->sql_command = SQLCOM_SHOW_WARNS;} - | ERRORS opt_limit_clause_init + | ERRORS opt_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_init + | PROFILE_SYM opt_profile_defs opt_profile_args opt_limit_clause { LEX *lex= Lex; lex->sql_command= SQLCOM_SHOW_PROFILE; @@ -15124,7 +15149,7 @@ handler: if (!lex->current_select->add_table_to_list(lex->thd, $2, 0, 0)) MYSQL_YYABORT; } - handler_read_or_scan where_clause opt_limit_clause + handler_read_or_scan opt_where_clause opt_limit_clause { Lex->expr_allows_subselect= TRUE; /* Stored functions are not supported for HANDLER READ. */ @@ -15843,7 +15868,7 @@ union_order_or_limit: ; order_or_limit: - order_clause opt_limit_clause_init + order_clause opt_limit_clause | limit_clause ; @@ -15855,17 +15880,19 @@ union_option: query_specification: SELECT_SYM select_init2_derived - { + table_expression + { $$= Lex->current_select->master_unit()->first_select(); } | '(' select_paren_derived ')' + opt_union_order_or_limit { $$= Lex->current_select->master_unit()->first_select(); } ; query_expression_body: - query_specification opt_union_order_or_limit + query_specification | query_expression_body UNION_SYM union_option { @@ -15873,7 +15900,6 @@ query_expression_body: MYSQL_YYABORT; } query_specification - opt_union_order_or_limit { Lex->pop_context(); $$= $1; |