Commit fbcf0225 authored by Alexander Barkov's avatar Alexander Barkov

MDEV-19804 sql_mode=ORACLE: call procedure in packages

Adding support for the fully qualified package procedure calls:

BEGIN
  CALL db.pkg.proc(args); -- SQL/PSM call style
  db.pkg.proc(args);      -- PL/SQL call style
END;
parent 9b2fa2ae
......@@ -3135,3 +3135,101 @@ collation_connection latin1_swedish_ci
DROP VIEW v_test;
SET sql_mode=ORACLE;
DROP PACKAGE test1;
#
# MDEV-19804 sql_mode=ORACLE: call procedure in packages
#
CALL `db1 `.pkg.p;
ERROR 42000: Incorrect database name 'db1 '
CALL db1.`pkg `.p;
ERROR 42000: Incorrect routine name 'pkg '
CALL db1.pkg.`p `;
ERROR 42000: Incorrect routine name 'p '
SET sql_mode=ORACLE;
CREATE PACKAGE pkg1 as
PROCEDURE p1();
END;
$$
CREATE PACKAGE BODY pkg1 as
PROCEDURE p1() as
BEGIN
SELECT 'test-function' AS c1;
END;
END;
$$
CALL pkg1.p1;
c1
test-function
CALL test.pkg1.p1;
c1
test-function
SET sql_mode=DEFAULT;
CALL test.pkg1.p1;
c1
test-function
SET sql_mode=ORACLE;
BEGIN
CALL pkg1.p1;
CALL test.pkg1.p1;
END
$$
c1
test-function
c1
test-function
BEGIN
pkg1.p1;
test.pkg1.p1;
END
$$
c1
test-function
c1
test-function
DROP PACKAGE pkg1;
CREATE DATABASE db1;
CREATE PACKAGE db1.pkg1 AS
PROCEDURE p1(a OUT TEXT);
END;
$$
CREATE PACKAGE BODY db1.pkg1 AS
PROCEDURE p1(a OUT TEXT) AS
BEGIN
a:= 'This is db1.pkg1.p1';
END;
END;
$$
CREATE DATABASE db2;
CREATE PACKAGE db2.pkg1 AS
FUNCTION var1 RETURN TEXT;
PROCEDURE p1(a OUT TEXT);
PROCEDURE p2_db1_pkg1_p1;
END;
$$
CREATE PACKAGE BODY db2.pkg1 AS
m_var1 TEXT;
FUNCTION var1 RETURN TEXT AS
BEGIN
RETURN m_var1;
END;
PROCEDURE p1(a OUT TEXT) AS
BEGIN
a:= 'This is db2.pkg1.p1';
END;
PROCEDURE p2_db1_pkg1_p1 AS
a TEXT;
BEGIN
db1.pkg1.p1(a);
SELECT a;
END;
BEGIN
db1.pkg1.p1(m_var1);
END;
$$
SELECT db2.pkg1.var1();
db2.pkg1.var1()
This is db1.pkg1.p1
CALL db2.pkg1.p2_db1_pkg1_p1;
a
This is db1.pkg1.p1
DROP DATABASE db1;
DROP DATABASE db2;
......@@ -2895,3 +2895,117 @@ DROP VIEW v_test;
SET sql_mode=ORACLE;
DROP PACKAGE test1;
--echo #
--echo # MDEV-19804 sql_mode=ORACLE: call procedure in packages
--echo #
--error ER_WRONG_DB_NAME
CALL `db1 `.pkg.p;
--error ER_SP_WRONG_NAME
CALL db1.`pkg `.p;
--error ER_SP_WRONG_NAME
CALL db1.pkg.`p `;
SET sql_mode=ORACLE;
DELIMITER $$;
CREATE PACKAGE pkg1 as
PROCEDURE p1();
END;
$$
CREATE PACKAGE BODY pkg1 as
PROCEDURE p1() as
BEGIN
SELECT 'test-function' AS c1;
END;
END;
$$
DELIMITER ;$$
CALL pkg1.p1;
CALL test.pkg1.p1;
# In sql_mode=DEFAULT we support fully qualified package function names
# (this is needed for VIEWs). Let's make sure we also support fully
# qualified package procedure names, for symmetry
SET sql_mode=DEFAULT;
CALL test.pkg1.p1;
SET sql_mode=ORACLE;
DELIMITER $$;
BEGIN
CALL pkg1.p1;
CALL test.pkg1.p1;
END
$$
DELIMITER ;$$
DELIMITER $$;
BEGIN
pkg1.p1;
test.pkg1.p1;
END
$$
DELIMITER ;$$
DROP PACKAGE pkg1;
#
# Testing packages in different databases calling each other
# in routines and in the initialization section.
#
CREATE DATABASE db1;
DELIMITER $$;
CREATE PACKAGE db1.pkg1 AS
PROCEDURE p1(a OUT TEXT);
END;
$$
CREATE PACKAGE BODY db1.pkg1 AS
PROCEDURE p1(a OUT TEXT) AS
BEGIN
a:= 'This is db1.pkg1.p1';
END;
END;
$$
DELIMITER ;$$
CREATE DATABASE db2;
DELIMITER $$;
CREATE PACKAGE db2.pkg1 AS
FUNCTION var1 RETURN TEXT;
PROCEDURE p1(a OUT TEXT);
PROCEDURE p2_db1_pkg1_p1;
END;
$$
CREATE PACKAGE BODY db2.pkg1 AS
m_var1 TEXT;
FUNCTION var1 RETURN TEXT AS
BEGIN
RETURN m_var1;
END;
PROCEDURE p1(a OUT TEXT) AS
BEGIN
a:= 'This is db2.pkg1.p1';
END;
PROCEDURE p2_db1_pkg1_p1 AS
a TEXT;
BEGIN
db1.pkg1.p1(a);
SELECT a;
END;
BEGIN
db1.pkg1.p1(m_var1);
END;
$$
DELIMITER ;$$
SELECT db2.pkg1.var1();
CALL db2.pkg1.p2_db1_pkg1_p1;
DROP DATABASE db1;
DROP DATABASE db2;
......@@ -7893,6 +7893,40 @@ bool LEX::call_statement_start(THD *thd, const LEX_CSTRING *name1,
}
bool LEX::call_statement_start(THD *thd, const LEX_CSTRING &db,
const LEX_CSTRING &pkg,
const LEX_CSTRING &proc)
{
Database_qualified_name q_db_pkg(db, pkg);
Database_qualified_name q_pkg_proc(pkg, proc);
sp_name *spname;
sql_command= SQLCOM_CALL;
if (check_db_name((LEX_STRING*) const_cast<LEX_CSTRING*>(&db)))
{
my_error(ER_WRONG_DB_NAME, MYF(0), db.str);
return NULL;
}
if (check_routine_name(&pkg) ||
check_routine_name(&proc))
return NULL;
// Concat `pkg` and `name` to `pkg.name`
LEX_CSTRING pkg_dot_proc;
if (q_pkg_proc.make_qname(thd->mem_root, &pkg_dot_proc) ||
check_ident_length(&pkg_dot_proc) ||
!(spname= new (thd->mem_root) sp_name(&db, &pkg_dot_proc, true)))
return NULL;
sp_handler_package_function.add_used_routine(thd->lex, thd, spname);
sp_handler_package_body.add_used_routine(thd->lex, thd, &q_db_pkg);
return !(m_sql_cmd= new (thd->mem_root) Sql_cmd_call(spname,
&sp_handler_package_procedure));
}
sp_package *LEX::get_sp_package() const
{
return sphead ? sphead->get_package() : NULL;
......
......@@ -3478,6 +3478,9 @@ struct LEX: public Query_tables_list
bool call_statement_start(THD *thd, const LEX_CSTRING *name);
bool call_statement_start(THD *thd, const LEX_CSTRING *name1,
const LEX_CSTRING *name2);
bool call_statement_start(THD *thd, const LEX_CSTRING &name1,
const LEX_CSTRING &name2,
const LEX_CSTRING &name3);
sp_variable *find_variable(const LEX_CSTRING *name,
sp_pcontext **ctx,
const Sp_rcontext_handler **rh) const;
......
......@@ -3345,9 +3345,29 @@ sp_suid:
;
call:
CALL_SYM sp_name
CALL_SYM ident
{
if (unlikely(Lex->call_statement_start(thd, $2)))
if (unlikely(Lex->call_statement_start(thd, &$2)))
MYSQL_YYABORT;
}
opt_sp_cparam_list
{
if (Lex->check_cte_dependencies_and_resolve_references())
MYSQL_YYABORT;
}
| CALL_SYM ident '.' ident
{
if (unlikely(Lex->call_statement_start(thd, &$2, &$4)))
MYSQL_YYABORT;
}
opt_sp_cparam_list
{
if (Lex->check_cte_dependencies_and_resolve_references())
MYSQL_YYABORT;
}
| CALL_SYM ident '.' ident '.' ident
{
if (unlikely(Lex->call_statement_start(thd, $2, $4, $6)))
MYSQL_YYABORT;
}
opt_sp_cparam_list
......
......@@ -2999,9 +2999,29 @@ sp_suid:
;
call:
CALL_SYM sp_name
CALL_SYM ident
{
if (unlikely(Lex->call_statement_start(thd, $2)))
if (unlikely(Lex->call_statement_start(thd, &$2)))
MYSQL_YYABORT;
}
opt_sp_cparam_list
{
if (Lex->check_cte_dependencies_and_resolve_references())
MYSQL_YYABORT;
}
| CALL_SYM ident '.' ident
{
if (unlikely(Lex->call_statement_start(thd, &$2, &$4)))
MYSQL_YYABORT;
}
opt_sp_cparam_list
{
if (Lex->check_cte_dependencies_and_resolve_references())
MYSQL_YYABORT;
}
| CALL_SYM ident '.' ident '.' ident
{
if (unlikely(Lex->call_statement_start(thd, $2, $4, $6)))
MYSQL_YYABORT;
}
opt_sp_cparam_list
......@@ -3922,12 +3942,30 @@ sp_statement:
MYSQL_YYABORT;
}
opt_sp_cparam_list
{
if (Lex->check_cte_dependencies_and_resolve_references())
MYSQL_YYABORT;
}
| ident_directly_assignable '.' ident
{
if (unlikely(Lex->call_statement_start(thd, &$1, &$3)))
MYSQL_YYABORT;
}
opt_sp_cparam_list
{
if (Lex->check_cte_dependencies_and_resolve_references())
MYSQL_YYABORT;
}
| ident_directly_assignable '.' ident '.' ident
{
if (unlikely(Lex->call_statement_start(thd, $1, $3, $5)))
MYSQL_YYABORT;
}
opt_sp_cparam_list
{
if (Lex->check_cte_dependencies_and_resolve_references())
MYSQL_YYABORT;
}
;
sp_proc_stmt_statement:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment