diff --git a/mysql-test/suite/compat/oracle/r/sp.result b/mysql-test/suite/compat/oracle/r/sp.result index 5a1c092883152..a5aab9090108c 100644 --- a/mysql-test/suite/compat/oracle/r/sp.result +++ b/mysql-test/suite/compat/oracle/r/sp.result @@ -777,7 +777,7 @@ LOOP NULL END LOOP; RETURN total; -END' at line 2 +END' at line 5 CREATE FUNCTION f1 (lower_bound INT, upper_bound INT, lim INT) RETURN INT AS total INT := 0; @@ -2150,3 +2150,39 @@ END' at line 1 # # End of MDEV-10577 sql_mode=ORACLE: %TYPE in variable declarations # +# +# MDEV-12107 sql_mode=ORACLE: Inside routines the CALL keywoard is optional +# +CREATE OR REPLACE PROCEDURE p1(a INT) AS +BEGIN +SELECT 'This is p1' AS "comment"; +END; +/ +CREATE OR REPLACE PROCEDURE p2 AS +BEGIN +SELECT 'This is p2' AS "comment"; +END; +/ +BEGIN +p1(10); +p2; +END; +/ +comment +This is p1 +comment +This is p2 +CREATE PROCEDURE p3 AS +BEGIN +p1(10); +p2; +END +/ +CALL p3; +comment +This is p1 +comment +This is p2 +DROP PROCEDURE p3; +DROP PROCEDURE p2; +DROP PROCEDURE p1; diff --git a/mysql-test/suite/compat/oracle/t/sp.test b/mysql-test/suite/compat/oracle/t/sp.test index 8caf77485e2c5..0bb6f22873173 100644 --- a/mysql-test/suite/compat/oracle/t/sp.test +++ b/mysql-test/suite/compat/oracle/t/sp.test @@ -1966,3 +1966,35 @@ DELIMITER ;$$ --echo # --echo # End of MDEV-10577 sql_mode=ORACLE: %TYPE in variable declarations --echo # + + +--echo # +--echo # MDEV-12107 sql_mode=ORACLE: Inside routines the CALL keywoard is optional +--echo # +DELIMITER /; +CREATE OR REPLACE PROCEDURE p1(a INT) AS +BEGIN + SELECT 'This is p1' AS "comment"; +END; +/ +CREATE OR REPLACE PROCEDURE p2 AS +BEGIN + SELECT 'This is p2' AS "comment"; +END; +/ +BEGIN + p1(10); + p2; +END; +/ +CREATE PROCEDURE p3 AS +BEGIN + p1(10); + p2; +END +/ +DELIMITER ;/ +CALL p3; +DROP PROCEDURE p3; +DROP PROCEDURE p2; +DROP PROCEDURE p1; diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index b8d150139cfe0..d6e48e511d9ff 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -5588,6 +5588,33 @@ bool LEX::sp_block_finalize(THD *thd, const Lex_spblock_st spblock, } +sp_name *LEX::make_sp_name(THD *thd, LEX_STRING &name) +{ + sp_name *res; + LEX_STRING db; + if (check_routine_name(&name) || + copy_db_to(&db.str, &db.length) || + (!(res= new (thd->mem_root) sp_name(db, name, false)))) + return NULL; + return res; +} + + +sp_name *LEX::make_sp_name(THD *thd, LEX_STRING &name1, LEX_STRING &name2) +{ + sp_name *res; + if (!name1.str || check_db_name(&name1)) + { + my_error(ER_WRONG_DB_NAME, MYF(0), name1.str); + return NULL; + } + if (check_routine_name(&name2) || + (!(res= new (thd->mem_root) sp_name(name1, name2, true)))) + return NULL; + return res; +} + + sp_head *LEX::make_sp_head(THD *thd, sp_name *name, enum stored_procedure_type type) { diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 794e6b44702d0..5fec0bdbb28d1 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -3099,6 +3099,8 @@ struct LEX: public Query_tables_list bool set_system_variable(struct sys_var_with_base *tmp, enum enum_var_type var_type, Item *val); void set_stmt_init(); + sp_name *make_sp_name(THD *thd, LEX_STRING &name); + sp_name *make_sp_name(THD *thd, LEX_STRING &name1, LEX_STRING &name2); sp_head *make_sp_head(THD *thd, sp_name *name, enum stored_procedure_type type); sp_head *make_sp_head_no_recursive(THD *thd, sp_name *name, diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 43fb40bbcf4de..410352dd32885 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -2734,26 +2734,12 @@ clear_privileges: sp_name: ident '.' ident { - if (!$1.str || check_db_name(&$1)) - my_yyabort_error((ER_WRONG_DB_NAME, MYF(0), $1.str)); - if (check_routine_name(&$3)) - MYSQL_YYABORT; - $$= new (thd->mem_root) sp_name($1, $3, true); - if ($$ == NULL) + if (!($$= Lex->make_sp_name(thd, $1, $3))) MYSQL_YYABORT; } | ident { - LEX *lex= thd->lex; - LEX_STRING db; - if (check_routine_name(&$1)) - { - MYSQL_YYABORT; - } - if (lex->copy_db_to(&db.str, &db.length)) - MYSQL_YYABORT; - $$= new (thd->mem_root) sp_name(db, $1, false); - if ($$ == NULL) + if (!($$= Lex->make_sp_name(thd, $1))) MYSQL_YYABORT; } ; diff --git a/sql/sql_yacc_ora.yy b/sql/sql_yacc_ora.yy index d9f1ccd975ed5..c31c1e1ef3696 100644 --- a/sql/sql_yacc_ora.yy +++ b/sql/sql_yacc_ora.yy @@ -2197,26 +2197,12 @@ clear_privileges: sp_name: ident '.' ident { - if (!$1.str || check_db_name(&$1)) - my_yyabort_error((ER_WRONG_DB_NAME, MYF(0), $1.str)); - if (check_routine_name(&$3)) - MYSQL_YYABORT; - $$= new (thd->mem_root) sp_name($1, $3, true); - if ($$ == NULL) + if (!($$= Lex->make_sp_name(thd, $1, $3))) MYSQL_YYABORT; } | ident { - LEX *lex= thd->lex; - LEX_STRING db; - if (check_routine_name(&$1)) - { - MYSQL_YYABORT; - } - if (lex->copy_db_to(&db.str, &db.length)) - MYSQL_YYABORT; - $$= new (thd->mem_root) sp_name(db, $1, false); - if ($$ == NULL) + if (!($$= Lex->make_sp_name(thd, $1))) MYSQL_YYABORT; } ; @@ -3090,7 +3076,22 @@ sp_proc_stmt_if: sp_if END IF_SYM { Lex->sphead->do_cont_backpatch(); } ; - + +sp_statement: + statement + | IDENT_sys + { + // Direct procedure call (without the CALL keyword) + LEX *lex = Lex; + if (!(lex->spname= lex->make_sp_name(thd, $1))) + MYSQL_YYABORT; + lex->sql_command= SQLCOM_CALL; + lex->value_list.empty(); + sp_add_used_routine(lex, thd, lex->spname, TYPE_ENUM_PROCEDURE); + } + opt_sp_cparam_list + ; + sp_proc_stmt_statement: { LEX *lex= thd->lex; @@ -3099,7 +3100,7 @@ sp_proc_stmt_statement: lex->sphead->reset_lex(thd); lex->sphead->m_tmp_query= lip->get_tok_start(); } - statement + sp_statement { LEX *lex= thd->lex; Lex_input_stream *lip= YYLIP;