mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 12:02:42 +01:00
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;
This commit is contained in:
parent
9b2fa2ae8e
commit
fbcf0225e1
6 changed files with 311 additions and 4 deletions
|
@ -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 @@ public:
|
|||
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:
|
||||
|
|
Loading…
Reference in a new issue