From 611488e3d9029f617884e10e47da208b0a77efec Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Wed, 23 May 2018 12:08:35 +0400 Subject: [PATCH] MDEV-16244 sql_mode=ORACLE: Some keywords do not work in variable declarations 1. Adding LEX::make_item_sysvar() and reusing it in sql_yacc.yy and sql_yacc_ora.yy. Removing the "opt_component" rule. 2. Renaming rules to better reflect their purpose: - keyword to keyword_ident - keyword_sp to keyword_label - keyword_sp_not_data_type to keyword_sp_var_and_label Also renaming: - sp_decl_ident_keyword to keyword_sp_decl for naming consistency - keyword_alias to keyword_table_alias, for consistency with ident_table_alias - keyword_sp_data_type to keyword_data_type, as it has nothing SP-specific. 3. Moving GLOBAL_SYM, LOCAL_SYM, SESSION_SYM from keyword_sp_var_and_label to a separate rule keyword_sysvar_type. We don't have system variables with these names anyway. Adding ident_sysvar_name and using it in the grammar that needs a system variable name instead of ident_or_text. This removed a number of shift/reduce conflicts between GLOBAL_SYM/LOCAL_SYM/SESSION_SYM as a variable scope and as a variable name. 4. Moving keywords BEGIN_SYM, END (in both *.yy fiels) and EXCEPTION_SYM (in sql_yacc_ora.yy) into a separate rule keyword_sp_block_section, because in Oracle verb keywords (COMMIT, DO, HANDLER, OPEN, REPAIR, ROLLBACK, SAVEPOINT, SHUTDOWN, TRUNCATE) are good variables names and can appear in e.g. DECLARE, while block keywords (BEGIN, END, EXCEPTION) are not good variable names and cannot appear in DECLARE. 5. Further splitting keyword_directly_not_assignable in sql_yacc_ora.yy: moving keyword_sp_verb_clause out. Renaming the rest of keyword_directly_not_assignable to keyword_sp_head, which represents keywords that can appear in optional clauses in CREATE PROCEDURE/FUNCTION/TRIGGER. 6. Renaming keyword_sp_verb_clause to keyword_verb_clause, as now it does not contains anything SP-specific. As a result or #4,#5,#6, the rule keyword_directly_not_assignable was replaced to three separate rules: - keyword_sp_block - keyword_sp_head - keyword_verb_clause Adding the same rules in sql_yacc.yy, for unification. 6. Adding keyword_sp_head and keyword_verb_clause into keyword_sp_decl. This fixes MDEV-16244. 7. Reorganizing the rest of keyword related rules into two groups: a. Rules defining a list of keywords and consisting of only terminal symbols: - keyword_sp_var_not_label - keyword_sp_head - keyword_sp_verb_clause - keyword_sp_block_section - keyword_sysvar_type b. Rules that combine the above lists into keyword places: - keyword_table_alias - keyword_ident - keyword_label - keyword_sysvar_name - keyword_sp_decl Rules from the group "b" use on the right side only rules from the group "a" (with optional terminal symbols added). Rules from the group "b" DO NOT mutually use each other any more. This makes them easier to read (and see the difference between them). Sorting the right sides of the group "b" keyword rules alphabetically, for yet better readability. --- .../suite/compat/oracle/r/parser.result | 100 +++++++ mysql-test/suite/compat/oracle/t/parser.test | 121 +++++++++ sql/sql_lex.cc | 25 ++ sql/sql_lex.h | 11 + sql/sql_yacc.yy | 245 +++++++++++++----- sql/sql_yacc_ora.yy | 221 ++++++++++------ 6 files changed, 579 insertions(+), 144 deletions(-) diff --git a/mysql-test/suite/compat/oracle/r/parser.result b/mysql-test/suite/compat/oracle/r/parser.result index ac04f4070e99c..28ed8eb8185af 100644 --- a/mysql-test/suite/compat/oracle/r/parser.result +++ b/mysql-test/suite/compat/oracle/r/parser.result @@ -348,3 +348,103 @@ SELECT without VERSIONING FROM t1 SELECT without WITHOUT FROM t1 DROP PROCEDURE p2; DROP PROCEDURE p1; +# +# MDEV-16244 sql_mode=ORACLE: Some keywords do not work in variable declarations +# +SET sql_mode=ORACLE; +DECLARE +do INT; +BEGIN +SELECT do INTO do FROM DUAL; +END; +/ +DECLARE +handler INT; +BEGIN +SELECT handler INTO handler FROM DUAL; +END; +/ +DECLARE +repair INT; +BEGIN +SELECT repair INTO repair FROM DUAL; +END; +/ +DECLARE +shutdown INT; +BEGIN +SELECT shutdown INTO shutdown FROM DUAL; +END; +/ +DECLARE +truncate INT; +BEGIN +SELECT truncate INTO truncate FROM DUAL; +END; +/ +DECLARE +close INT; +BEGIN +SELECT close INTO close FROM DUAL; +END; +/ +DECLARE +commit INT; +BEGIN +SELECT commit INTO commit FROM DUAL; +END; +/ +DECLARE +open INT; +BEGIN +SELECT open INTO open FROM DUAL; +END; +/ +DECLARE +rollback INT; +BEGIN +SELECT rollback INTO rollback FROM DUAL; +END; +/ +DECLARE +savepoint INT; +BEGIN +SELECT savepoint INTO savepoint FROM DUAL; +END; +/ +DECLARE +contains INT; +BEGIN +SELECT contains INTO contains FROM DUAL; +END; +/ +DECLARE +language INT; +BEGIN +SELECT language INTO language FROM DUAL; +END; +/ +DECLARE +no INT; +BEGIN +SELECT no INTO no FROM DUAL; +END; +/ +DECLARE +charset INT; +BEGIN +SELECT charset INTO charset FROM DUAL; +END; +/ +DECLARE +follows INT; +BEGIN +SELECT follows INTO follows FROM DUAL; +END; +/ +DECLARE +precedes INT; +BEGIN +SELECT precedes INTO precedes FROM DUAL; +END; +/ diff --git a/mysql-test/suite/compat/oracle/t/parser.test b/mysql-test/suite/compat/oracle/t/parser.test index c0048e26fa8d9..a8f5eda70161b 100644 --- a/mysql-test/suite/compat/oracle/t/parser.test +++ b/mysql-test/suite/compat/oracle/t/parser.test @@ -87,3 +87,124 @@ CALL p2('without'); DROP PROCEDURE p2; DROP PROCEDURE p1; + + +--echo # +--echo # MDEV-16244 sql_mode=ORACLE: Some keywords do not work in variable declarations +--echo # + +SET sql_mode=ORACLE; +DELIMITER /; + +DECLARE + do INT; +BEGIN + SELECT do INTO do FROM DUAL; +END; +/ + +DECLARE + handler INT; +BEGIN + SELECT handler INTO handler FROM DUAL; +END; +/ + +DECLARE + repair INT; +BEGIN + SELECT repair INTO repair FROM DUAL; +END; +/ + +DECLARE + shutdown INT; +BEGIN + SELECT shutdown INTO shutdown FROM DUAL; +END; +/ + +DECLARE + truncate INT; +BEGIN + SELECT truncate INTO truncate FROM DUAL; +END; +/ + +DECLARE + close INT; +BEGIN + SELECT close INTO close FROM DUAL; +END; +/ + +DECLARE + commit INT; +BEGIN + SELECT commit INTO commit FROM DUAL; +END; +/ + +DECLARE + open INT; +BEGIN + SELECT open INTO open FROM DUAL; +END; +/ + +DECLARE + rollback INT; +BEGIN + SELECT rollback INTO rollback FROM DUAL; +END; +/ + +DECLARE + savepoint INT; +BEGIN + SELECT savepoint INTO savepoint FROM DUAL; +END; +/ + +DECLARE + contains INT; +BEGIN + SELECT contains INTO contains FROM DUAL; +END; +/ + +DECLARE + language INT; +BEGIN + SELECT language INTO language FROM DUAL; +END; +/ + +DECLARE + no INT; +BEGIN + SELECT no INTO no FROM DUAL; +END; +/ + +DECLARE + charset INT; +BEGIN + SELECT charset INTO charset FROM DUAL; +END; +/ +DECLARE + follows INT; +BEGIN + SELECT follows INTO follows FROM DUAL; +END; +/ + +DECLARE + precedes INT; +BEGIN + SELECT precedes INTO precedes FROM DUAL; +END; +/ + +DELIMITER ;/ diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index db7e8e09be4b3..fc1af9837a9c0 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -6626,6 +6626,31 @@ Item *LEX::make_item_colon_ident_ident(THD *thd, } +Item *LEX::make_item_sysvar(THD *thd, + enum_var_type type, + const LEX_CSTRING *name, + const LEX_CSTRING *component) + +{ + Item *item; + DBUG_ASSERT(name->str); + /* + "SELECT @@global.global.variable" is not allowed + Note, "global" can come through TEXT_STRING_sys. + */ + if (component->str && unlikely(check_reserved_words(name))) + { + thd->parse_error(); + return NULL; + } + if (unlikely(!(item= get_system_var(thd, type, name, component)))) + return NULL; + if (!((Item_func_get_system_var*) item)->is_written_to_binlog()) + set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_VARIABLE); + return item; +} + + Item_param *LEX::add_placeholder(THD *thd, const LEX_CSTRING *name, const char *start, const char *end) { diff --git a/sql/sql_lex.h b/sql/sql_lex.h index a462ba3d25213..e5ca2d4221015 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -3630,6 +3630,17 @@ struct LEX: public Query_tables_list Item *make_item_colon_ident_ident(THD *thd, const Lex_ident_cli_st *a, const Lex_ident_cli_st *b); + // For "SELECT @@var", "SELECT @@var.field" + Item *make_item_sysvar(THD *thd, + enum_var_type type, + const LEX_CSTRING *name) + { + return make_item_sysvar(thd, type, name, &null_clex_str); + } + Item *make_item_sysvar(THD *thd, + enum_var_type type, + const LEX_CSTRING *name, + const LEX_CSTRING *component); void sp_block_init(THD *thd, const LEX_CSTRING *label); void sp_block_init(THD *thd) { diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index c389b09d54c06..049b2c0cac9fc 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -888,10 +888,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); %parse-param { THD *thd } %lex-param { THD *thd } /* - Currently there are 68 shift/reduce conflicts. + Currently there are 62 shift/reduce conflicts. We should not introduce new conflicts any more. */ -%expect 68 +%expect 62 /* Comments for TOKENS. @@ -1244,7 +1244,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); %token AVG_ROW_LENGTH %token AVG_SYM /* SQL-2003-N */ %token BACKUP_SYM -%token BEGIN_SYM /* SQL-2003-R */ +%token BEGIN_SYM /* SQL-2003-R, PLSQL-R */ %token BINLOG_SYM %token BIT_SYM /* MYSQL-FUNC */ %token BLOCK_SYM @@ -1318,7 +1318,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); %token DUPLICATE_SYM %token DYNAMIC_SYM /* SQL-2003-R */ %token ENABLE_SYM -%token END /* SQL-2003-R */ +%token END /* SQL-2003-R, PLSQL-R */ %token ENDS_SYM %token ENGINES_SYM %token ENGINE_SYM @@ -1762,7 +1762,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); HEX_NUM HEX_STRING LEX_HOSTNAME ULONGLONG_NUM field_ident select_alias ident_or_text TEXT_STRING_sys TEXT_STRING_literal - opt_component key_cache_name + key_cache_name sp_opt_label BIN_NUM TEXT_STRING_filesystem opt_constraint constraint opt_ident sp_block_label opt_place opt_db @@ -1777,6 +1777,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); sp_decl_ident ident_or_empty ident_table_alias + ident_sysvar_name %type TEXT_STRING @@ -1792,11 +1793,18 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); ident_cli %type - keyword keyword_sp - keyword_alias - keyword_sp_data_type - keyword_sp_not_data_type - keyword_sp_verb_clause + keyword_data_type + keyword_ident + keyword_label + keyword_sp_block_section + keyword_sp_decl + keyword_sp_head + keyword_sp_var_and_label + keyword_sp_var_not_label + keyword_sysvar_name + keyword_sysvar_type + keyword_table_alias + keyword_verb_clause %type table_ident table_ident_nodb references xid @@ -4004,7 +4012,12 @@ condition_information_item_name: ; sp_decl_ident: - ident + IDENT_sys + | keyword_sp_decl + { + if (unlikely($$.copy_ident_cli(thd, &$1))) + MYSQL_YYABORT; + } ; sp_decl_idents: @@ -7632,11 +7645,6 @@ opt_ident: | field_ident { $$= $1; } ; -opt_component: - /* empty */ { $$= null_clex_str; } - | '.' ident { $$= $2; } - ; - string_list: text_string { Lex->last_field->interval_list.push_back($1, thd->mem_root); } @@ -11351,18 +11359,15 @@ variable_aux: LEX *lex= Lex; lex->uncacheable(UNCACHEABLE_SIDEEFFECT); } - | '@' opt_var_ident_type ident_or_text opt_component + | '@' opt_var_ident_type ident_sysvar_name { - /* disallow "SELECT @@global.global.variable" */ - if (unlikely($3.str && $4.str && check_reserved_words(&$3))) - { - thd->parse_error(); + if (unlikely(!($$= Lex->make_item_sysvar(thd, $2, &$3)))) MYSQL_YYABORT; - } - if (unlikely(!($$= get_system_var(thd, $2, &$3, &$4)))) + } + | '@' opt_var_ident_type ident_sysvar_name '.' ident + { + if (unlikely(!($$= Lex->make_item_sysvar(thd, $2, &$3, &$5)))) MYSQL_YYABORT; - if (!((Item_func_get_system_var*) $$)->is_written_to_binlog()) - Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_VARIABLE); } ; @@ -15152,7 +15157,7 @@ IDENT_cli: ident_cli: IDENT | IDENT_QUOTED - | keyword { $$= $1; } + | keyword_ident { $$= $1; } ; IDENT_sys: @@ -15189,16 +15194,32 @@ TEXT_STRING_filesystem: ident_table_alias: IDENT_sys - | keyword_alias + | keyword_table_alias + { + if (unlikely($$.copy_keyword(thd, &$1))) + MYSQL_YYABORT; + } + ; + + +ident_sysvar_name: + IDENT_sys + | keyword_sysvar_name { if (unlikely($$.copy_keyword(thd, &$1))) MYSQL_YYABORT; } + | TEXT_STRING_sys + { + if (unlikely($$.copy_sys(thd, &$1))) + MYSQL_YYABORT; + } ; + ident: IDENT_sys - | keyword + | keyword_ident { if (unlikely($$.copy_keyword(thd, &$1))) MYSQL_YYABORT; @@ -15207,7 +15228,7 @@ ident: label_ident: IDENT_sys - | keyword_sp + | keyword_label { if (unlikely($$.copy_keyword(thd, &$1))) MYSQL_YYABORT; @@ -15285,15 +15306,74 @@ user: user_maybe_role ; /* Keywords which we allow as table aliases. */ -keyword_alias: - keyword_sp - | keyword_sp_verb_clause - | ASCII_SYM +keyword_table_alias: + keyword_data_type + | keyword_sp_block_section + | keyword_sp_head + | keyword_sp_var_and_label + | keyword_sp_var_not_label + | keyword_sysvar_type + | keyword_verb_clause + ; + +/* Keyword that we allow for identifiers (except SP labels) */ +keyword_ident: + keyword_data_type + | keyword_sp_block_section + | keyword_sp_head + | keyword_sp_var_and_label + | keyword_sp_var_not_label + | keyword_sysvar_type + | keyword_verb_clause + | WINDOW_SYM + ; + +/* + Keywords that we allow for labels in SPs. + Should not include keywords that start a statement or SP characteristics. +*/ +keyword_label: + keyword_data_type + | keyword_sp_var_and_label + | keyword_sysvar_type + ; + +keyword_sysvar_name: + keyword_data_type + | keyword_sp_block_section + | keyword_sp_head + | keyword_sp_var_and_label + | keyword_sp_var_not_label + | keyword_verb_clause + | WINDOW_SYM + ; + +keyword_sp_decl: + keyword_data_type + | keyword_sp_block_section + | keyword_sp_head + | keyword_sp_var_and_label + | keyword_sp_var_not_label + | keyword_sysvar_type + | keyword_verb_clause + | WINDOW_SYM + ; + +/* + Keywords that we allow in Oracle-style direct assignments: + xxx := 10; + but do not allow in labels in the default sql_mode: + label: + stmt1; + stmt2; + TODO: check if some of them can migrate to keyword_sp_var_and_label. +*/ +keyword_sp_var_not_label: + ASCII_SYM | BACKUP_SYM | BINLOG_SYM | BYTE_SYM | CACHE_SYM - | CHARSET | CHECKSUM_SYM | CHECKPOINT_SYM | COLUMN_ADD_SYM @@ -15302,21 +15382,17 @@ keyword_alias: | COLUMN_DELETE_SYM | COLUMN_GET_SYM | COMMENT_SYM - | CONTAINS_SYM | DEALLOCATE_SYM | EXAMINED_SYM | EXCLUDE_SYM | EXECUTE_SYM | FLUSH_SYM - | FOLLOWS_SYM | FOLLOWING_SYM | FORMAT_SYM | GET_SYM | HELP_SYM | HOST_SYM | INSTALL_SYM - | LANGUAGE_SYM - | NO_SYM | OPTION | OPTIONS_SYM | OTHERS_SYM @@ -15324,7 +15400,6 @@ keyword_alias: | PARSER_SYM | PERIOD_SYM | PORT_SYM - | PRECEDES_SYM | PRECEDING_SYM | PREPARE_SYM | REMOVE_SYM @@ -15350,22 +15425,52 @@ keyword_alias: | UPGRADE_SYM ; - -/* Keyword that we allow for identifiers (except SP labels) */ -keyword: keyword_alias | WINDOW_SYM; - /* - * Keywords that we allow for labels in SPs. - * Anything that's the beginning of a statement or characteristics - * must be in keyword above, otherwise we get (harmful) shift/reduce - * conflicts. - */ -keyword_sp: - keyword_sp_data_type - | keyword_sp_not_data_type + Keywords that can start optional clauses in SP or trigger declarations + Allowed as identifiers (e.g. table, column names), + but: + - not allowed as SP label names + - not allowed as variable names in Oracle-style assignments: + xxx := 10; + + If we allowed these variables in assignments, there would be conflicts + with SP characteristics, or verb clauses, or compound statements, e.g.: + CREATE PROCEDURE p1 LANGUAGE ... + would be either: + CREATE PROCEDURE p1 LANGUAGE SQL BEGIN END; + or + CREATE PROCEDURE p1 LANGUAGE:=10; + + Note, these variables can still be assigned using quoted identifiers: + `do`:= 10; + "do":= 10; (when ANSI_QUOTES) + or using a SET statement: + SET do= 10; + + Note, some of these keywords are reserved keywords in Oracle. + In case if heavy grammar conflicts are found in the future, + we'll possibly need to make them reserved for sql_mode=ORACLE. + + TODO: Allow these variables as SP lables when sql_mode=ORACLE. + TODO: Allow assigning of "SP characteristics" marked variables + inside compound blocks. + TODO: Allow "follows" and "precedes" as variables in compound blocks: + BEGIN + follows := 10; + END; + as they conflict only with non-block FOR EACH ROW statement: + CREATE TRIGGER .. FOR EACH ROW follows:= 10; + CREATE TRIGGER .. FOR EACH ROW FOLLOWS tr1 a:= 10; +*/ +keyword_sp_head: + CONTAINS_SYM /* SP characteristic */ + | LANGUAGE_SYM /* SP characteristic */ + | NO_SYM /* SP characteristic */ + | CHARSET /* SET CHARSET utf8; */ + | FOLLOWS_SYM /* Conflicts with assignment in FOR EACH */ + | PRECEDES_SYM /* Conflicts with assignment in FOR EACH */ ; - /* Keywords that start a statement. Generally allowed as identifiers (e.g. table, column names) @@ -15373,12 +15478,10 @@ keyword_sp: - not allowed as variable names in Oracle-style assignments: xxx:=10 */ -keyword_sp_verb_clause: - BEGIN_SYM /* Compound. Reserved in Oracle */ - | CLOSE_SYM /* Verb clause. Reserved in Oracle */ +keyword_verb_clause: + CLOSE_SYM /* Verb clause. Reserved in Oracle */ | COMMIT_SYM /* Verb clause. Reserved in Oracle */ | DO_SYM /* Verb clause */ - | END /* Compound. Reserved in Oracle */ | HANDLER_SYM /* Verb clause */ | OPEN_SYM /* Verb clause. Reserved in Oracle */ | REPAIR /* Verb clause */ @@ -15386,14 +15489,28 @@ keyword_sp_verb_clause: | SAVEPOINT_SYM /* Verb clause. Reserved in Oracle */ | SHUTDOWN /* Verb clause */ | TRUNCATE_SYM /* Verb clause. Reserved in Oracle */ - ; + ; + +/* + Keywords that start an SP block section. +*/ +keyword_sp_block_section: + BEGIN_SYM + | END + ; + +keyword_sysvar_type: + GLOBAL_SYM + | LOCAL_SYM + | SESSION_SYM + ; /* These keywords are generally allowed as identifiers, but not allowed as non-delimited SP variable names in sql_mode=ORACLE. */ -keyword_sp_data_type: +keyword_data_type: BIT_SYM | BOOLEAN_SYM | BOOL_SYM @@ -15427,7 +15544,10 @@ keyword_sp_data_type: ; -keyword_sp_not_data_type: +/* + These keywords are fine for both SP variable names and SP labels. +*/ +keyword_sp_var_and_label: ACTION | ADDDATE_SYM | ADMIN_SYM @@ -15525,7 +15645,6 @@ keyword_sp_not_data_type: | GENERATED_SYM | GET_FORMAT | GRANTS - | GLOBAL_SYM | GOTO_SYM | HASH_SYM | HARD_SYM @@ -15556,7 +15675,6 @@ keyword_sp_not_data_type: | LESS_SYM | LEVEL_SYM | LIST_SYM - | LOCAL_SYM | LOCKS_SYM | LOGFILE_SYM | LOGS_SYM @@ -15681,7 +15799,6 @@ keyword_sp_not_data_type: | SECOND_SYM | SEQUENCE_SYM | SERIALIZABLE_SYM - | SESSION_SYM | SETVAL_SYM | SIMPLE_SYM | SHARE_SYM @@ -15933,12 +16050,12 @@ option_value_no_option_type: if (unlikely(Lex->set_user_variable(thd, &$2, $4))) MYSQL_YYABORT; } - | '@' '@' opt_var_ident_type ident equal set_expr_or_default + | '@' '@' opt_var_ident_type ident_sysvar_name equal set_expr_or_default { if (unlikely(Lex->set_system_variable($3, &$4, $6))) MYSQL_YYABORT; } - | '@' '@' opt_var_ident_type ident '.' ident equal set_expr_or_default + | '@' '@' opt_var_ident_type ident_sysvar_name '.' ident equal set_expr_or_default { if (unlikely(Lex->set_system_variable(thd, $3, &$4, &$6, $8))) MYSQL_YYABORT; diff --git a/sql/sql_yacc_ora.yy b/sql/sql_yacc_ora.yy index 5c885a5a2cf46..f0db33f67aedb 100644 --- a/sql/sql_yacc_ora.yy +++ b/sql/sql_yacc_ora.yy @@ -282,10 +282,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); %parse-param { THD *thd } %lex-param { THD *thd } /* - Currently there are 69 shift/reduce conflicts. + Currently there are 63 shift/reduce conflicts. We should not introduce new conflicts any more. */ -%expect 69 +%expect 63 /* Comments for TOKENS. @@ -638,7 +638,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); %token AVG_ROW_LENGTH %token AVG_SYM /* SQL-2003-N */ %token BACKUP_SYM -%token BEGIN_SYM /* SQL-2003-R */ +%token BEGIN_SYM /* SQL-2003-R, PLSQL-R */ %token BINLOG_SYM %token BIT_SYM /* MYSQL-FUNC */ %token BLOCK_SYM @@ -712,7 +712,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); %token DUPLICATE_SYM %token DYNAMIC_SYM /* SQL-2003-R */ %token ENABLE_SYM -%token END /* SQL-2003-R */ +%token END /* SQL-2003-R, PLSQL-R */ %token ENDS_SYM %token ENGINES_SYM %token ENGINE_SYM @@ -745,7 +745,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); %token FORMAT_SYM %token FOUND_SYM /* SQL-2003-R */ %token FULL /* SQL-2003-R */ -%token FUNCTION_SYM /* SQL-2003-R */ +%token FUNCTION_SYM /* SQL-2003-R, Oracle-PLSQL-R */ %token GENERAL %token GENERATED_SYM %token GEOMETRYCOLLECTION @@ -1156,7 +1156,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); HEX_NUM HEX_STRING LEX_HOSTNAME ULONGLONG_NUM field_ident select_alias ident_or_text TEXT_STRING_sys TEXT_STRING_literal - opt_component key_cache_name + key_cache_name sp_opt_label BIN_NUM TEXT_STRING_filesystem opt_constraint constraint opt_ident opt_package_routine_end_name @@ -1173,6 +1173,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); sp_decl_ident ident_or_empty ident_table_alias + ident_sysvar_name ident_directly_assignable %type @@ -1189,14 +1190,19 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); ident_cli %type - keyword keyword_sp - keyword_alias + keyword_data_type + keyword_ident + keyword_label + keyword_sp_block_section + keyword_sp_decl + keyword_sp_head + keyword_sp_var_and_label + keyword_sp_var_not_label + keyword_sysvar_name + keyword_sysvar_type + keyword_table_alias + keyword_verb_clause keyword_directly_assignable - keyword_directly_not_assignable - keyword_sp_data_type - keyword_sp_not_data_type - keyword_sp_verb_clause - sp_decl_ident_keyword %type
table_ident table_ident_nodb references xid @@ -3782,19 +3788,13 @@ condition_information_item_name: sp_decl_ident: IDENT_sys - | sp_decl_ident_keyword + | keyword_sp_decl { if (unlikely($$.copy_ident_cli(thd, &$1))) MYSQL_YYABORT; } ; -sp_decl_ident_keyword: - keyword_directly_assignable - | keyword_sp_not_data_type - ; - - sp_decl_idents: sp_decl_ident { @@ -7701,11 +7701,6 @@ opt_ident: | field_ident { $$= $1; } ; -opt_component: - /* empty */ { $$= null_clex_str; } - | '.' ident { $$= $2; } - ; - string_list: text_string { Lex->last_field->interval_list.push_back($1, thd->mem_root); } @@ -11477,18 +11472,15 @@ variable_aux: LEX *lex= Lex; lex->uncacheable(UNCACHEABLE_SIDEEFFECT); } - | '@' opt_var_ident_type ident_or_text opt_component + | '@' opt_var_ident_type ident_sysvar_name { - /* disallow "SELECT @@global.global.variable" */ - if (unlikely($3.str && $4.str && check_reserved_words(&$3))) - { - thd->parse_error(); + if (unlikely(!($$= Lex->make_item_sysvar(thd, $2, &$3)))) MYSQL_YYABORT; - } - if (unlikely(!($$= get_system_var(thd, $2, &$3, &$4)))) + } + | '@' opt_var_ident_type ident_sysvar_name '.' ident + { + if (unlikely(!($$= Lex->make_item_sysvar(thd, $2, &$3, &$5)))) MYSQL_YYABORT; - if (!((Item_func_get_system_var*) $$)->is_written_to_binlog()) - Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_VARIABLE); } ; @@ -15342,7 +15334,7 @@ IDENT_cli: ident_cli: IDENT | IDENT_QUOTED - | keyword { $$= $1; } + | keyword_ident { $$= $1; } ; IDENT_sys: @@ -15379,30 +15371,41 @@ TEXT_STRING_filesystem: ident_table_alias: IDENT_sys - | keyword_alias + | keyword_table_alias { if (unlikely($$.copy_keyword(thd, &$1))) MYSQL_YYABORT; } ; -ident: + +ident_sysvar_name: IDENT_sys - | keyword + | keyword_sysvar_name { if (unlikely($$.copy_keyword(thd, &$1))) MYSQL_YYABORT; } + | TEXT_STRING_sys + { + if (unlikely($$.copy_sys(thd, &$1))) + MYSQL_YYABORT; + } ; -ident_directly_assignable: + +ident: IDENT_sys - | keyword_directly_assignable + | keyword_ident { if (unlikely($$.copy_keyword(thd, &$1))) MYSQL_YYABORT; } - | keyword_sp + ; + +ident_directly_assignable: + IDENT_sys + | keyword_directly_assignable { if (unlikely($$.copy_keyword(thd, &$1))) MYSQL_YYABORT; @@ -15412,9 +15415,9 @@ ident_directly_assignable: label_ident: IDENT_sys - | keyword_sp + | keyword_label { - if ($$.copy_keyword(thd, &$1)) + if (unlikely($$.copy_keyword(thd, &$1))) MYSQL_YYABORT; } ; @@ -15504,21 +15507,80 @@ user: user_maybe_role ; /* Keywords which we allow as table aliases. */ -keyword_alias: - keyword_sp - | keyword_directly_assignable - | keyword_directly_not_assignable +keyword_table_alias: + keyword_data_type + | keyword_sp_block_section + | keyword_sp_head + | keyword_sp_var_and_label + | keyword_sp_var_not_label + | keyword_sysvar_type + | keyword_verb_clause + | FUNCTION_SYM ; - /* Keyword that we allow for identifiers (except SP labels) */ -keyword: keyword_alias | WINDOW_SYM; +keyword_ident: + keyword_data_type + | keyword_sp_block_section + | keyword_sp_head + | keyword_sp_var_and_label + | keyword_sp_var_not_label + | keyword_sysvar_type + | keyword_verb_clause + | FUNCTION_SYM + | WINDOW_SYM + ; + +/* + Keywords that we allow for labels in SPs. + Should not include keywords that start a statement or SP characteristics. +*/ +keyword_label: + keyword_data_type + | keyword_sp_var_and_label + | keyword_sysvar_type + | FUNCTION_SYM + ; + +keyword_sysvar_name: + keyword_data_type + | keyword_sp_block_section + | keyword_sp_head + | keyword_sp_var_and_label + | keyword_sp_var_not_label + | keyword_verb_clause + | FUNCTION_SYM + | WINDOW_SYM + ; + +keyword_sp_decl: + keyword_sp_head + | keyword_sp_var_and_label + | keyword_sp_var_not_label + | keyword_sysvar_type + | keyword_verb_clause + | WINDOW_SYM + ; + +keyword_directly_assignable: + keyword_data_type + | keyword_sp_var_and_label + | keyword_sp_var_not_label + | keyword_sysvar_type + | FUNCTION_SYM + | WINDOW_SYM + ; /* Keywords that we allow in Oracle-style direct assignments: xxx := 10; + but do not allow in labels in the default sql_mode: + label: + stmt1; + stmt2; + TODO: check if some of them can migrate to keyword_sp_var_and_label. */ -keyword_directly_assignable: +keyword_sp_var_not_label: ASCII_SYM | BACKUP_SYM | BINLOG_SYM @@ -15579,7 +15641,8 @@ keyword_directly_assignable: ; /* - Keywords that are allowed as identifiers (e.g. table, column names), + Keywords that can start optional clauses in SP or trigger declarations + Allowed as identifiers (e.g. table, column names), but: - not allowed as SP label names - not allowed as variable names in Oracle-style assignments: @@ -15614,43 +15677,26 @@ keyword_directly_assignable: CREATE TRIGGER .. FOR EACH ROW follows:= 10; CREATE TRIGGER .. FOR EACH ROW FOLLOWS tr1 a:= 10; */ -keyword_directly_not_assignable: +keyword_sp_head: CONTAINS_SYM /* SP characteristic */ | LANGUAGE_SYM /* SP characteristic */ | NO_SYM /* SP characteristic */ | CHARSET /* SET CHARSET utf8; */ | FOLLOWS_SYM /* Conflicts with assignment in FOR EACH */ | PRECEDES_SYM /* Conflicts with assignment in FOR EACH */ - | keyword_sp_verb_clause ; /* - * Keywords that we allow for labels in SPs. - * Anything that's the beginning of a statement or characteristics - * must be in keyword above, otherwise we get (harmful) shift/reduce - * conflicts. - */ -keyword_sp: - keyword_sp_data_type - | keyword_sp_not_data_type - | FUNCTION_SYM /* Oracle-PLSQL-R */ - ; - - -/* - Keywords that start a statement or an SP block section. + Keywords that start a statement. Generally allowed as identifiers (e.g. table, column names) - not allowed as SP label names - not allowed as variable names in Oracle-style assignments: xxx:=10 */ -keyword_sp_verb_clause: - BEGIN_SYM /* Compound. Reserved in Oracle */ - | CLOSE_SYM /* Verb clause. Reserved in Oracle */ +keyword_verb_clause: + CLOSE_SYM /* Verb clause. Reserved in Oracle */ | COMMIT_SYM /* Verb clause. Reserved in Oracle */ - | EXCEPTION_SYM /* EXCEPTION section in SP blocks */ | DO_SYM /* Verb clause */ - | END /* Compound. Reserved in Oracle */ | HANDLER_SYM /* Verb clause */ | OPEN_SYM /* Verb clause. Reserved in Oracle */ | REPAIR /* Verb clause */ @@ -15658,14 +15704,29 @@ keyword_sp_verb_clause: | SAVEPOINT_SYM /* Verb clause. Reserved in Oracle */ | SHUTDOWN /* Verb clause */ | TRUNCATE_SYM /* Verb clause. Reserved in Oracle */ - ; + ; + +/* + Keywords that start an SP block section. +*/ +keyword_sp_block_section: + BEGIN_SYM + | EXCEPTION_SYM + | END + ; + +keyword_sysvar_type: + GLOBAL_SYM + | LOCAL_SYM + | SESSION_SYM + ; /* These keywords are generally allowed as identifiers, but not allowed as non-delimited SP variable names in sql_mode=ORACLE. */ -keyword_sp_data_type: +keyword_data_type: BIT_SYM | BOOLEAN_SYM | BOOL_SYM @@ -15699,7 +15760,10 @@ keyword_sp_data_type: ; -keyword_sp_not_data_type: +/* + These keywords are fine for both SP variable names and SP labels. +*/ +keyword_sp_var_and_label: ACTION | ADDDATE_SYM | ADMIN_SYM @@ -15795,7 +15859,6 @@ keyword_sp_not_data_type: | GENERATED_SYM | GET_FORMAT | GRANTS - | GLOBAL_SYM | HASH_SYM | HARD_SYM | HOSTS_SYM @@ -15824,7 +15887,6 @@ keyword_sp_not_data_type: | LESS_SYM | LEVEL_SYM | LIST_SYM - | LOCAL_SYM | LOCKS_SYM | LOGFILE_SYM | LOGS_SYM @@ -15948,7 +16010,6 @@ keyword_sp_not_data_type: | SECOND_SYM | SEQUENCE_SYM | SERIALIZABLE_SYM - | SESSION_SYM | SETVAL_SYM | SIMPLE_SYM | SHARE_SYM @@ -16245,12 +16306,12 @@ option_value_no_option_type: if (unlikely(Lex->set_user_variable(thd, &$2, $4))) MYSQL_YYABORT; } - | '@' '@' opt_var_ident_type ident equal set_expr_or_default + | '@' '@' opt_var_ident_type ident_sysvar_name equal set_expr_or_default { if (unlikely(Lex->set_system_variable($3, &$4, $6))) MYSQL_YYABORT; } - | '@' '@' opt_var_ident_type ident '.' ident equal set_expr_or_default + | '@' '@' opt_var_ident_type ident_sysvar_name '.' ident equal set_expr_or_default { if (unlikely(Lex->set_system_variable(thd, $3, &$4, &$6, $8))) MYSQL_YYABORT;