Skip to content

Commit

Permalink
MDEV-16244 sql_mode=ORACLE: Some keywords do not work in variable dec…
Browse files Browse the repository at this point in the history
…larations

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.
  • Loading branch information
abarkov committed May 23, 2018
1 parent d6976a7 commit 611488e
Show file tree
Hide file tree
Showing 6 changed files with 579 additions and 144 deletions.
100 changes: 100 additions & 0 deletions mysql-test/suite/compat/oracle/r/parser.result
Expand Up @@ -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;
/
121 changes: 121 additions & 0 deletions mysql-test/suite/compat/oracle/t/parser.test
Expand Up @@ -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 ;/
25 changes: 25 additions & 0 deletions sql/sql_lex.cc
Expand Up @@ -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)
{
Expand Down
11 changes: 11 additions & 0 deletions sql/sql_lex.h
Expand Up @@ -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)
{
Expand Down

0 comments on commit 611488e

Please sign in to comment.