Commit aed9c656 authored by Alexander Barkov's avatar Alexander Barkov

MDEV-32101 CREATE PACKAGE [BODY] for sql_mode=DEFAULT

This patch adds PACKAGE support with SQL/PSM dialect for sql_mode=DEFAULT:

- CREATE PACKAGE
- DROP PACKAGE
- CREATE PACKAGE BODY
- DROP PACKAGE BODY
- Package function and procedure invocation from outside of the package:
    -- using two step identifiers
    SELECT pkg.f1();
    CALL pkg.p1()

    -- using three step identifiers
    SELECT db.pkg.f1();
    CALL db.pkg.p1();

This is a non-standard MariaDB extension.

However, later this code can be used to implement
the SQL Standard and DB2 dialects of CREATE MODULE.
parent 9bd95e91
#
# MDEV-32101 CREATE PACKAGE [BODY] for sql_mode=DEFAULT
#
CREATE PACKAGE pkg1
PROCEDURE p1();
FUNCTION f1() RETURNS INT;
END;
$$
CREATE PACKAGE BODY pkg1
PROCEDURE p1()
BEGIN SELECT 1;
END;
FUNCTION f1() RETURNS INT RETURN 1;
END;
$$
SHOW PROCEDURE CODE pkg1.p1;
Pos Instruction
0 stmt 0 "SELECT 1"
SHOW FUNCTION CODE pkg1.f1;
Pos Instruction
0 freturn int 1
SHOW PACKAGE BODY CODE pkg1;
Pos Instruction
DROP PACKAGE pkg1;
CREATE PACKAGE pkg1
PROCEDURE p1();
FUNCTION f1() RETURNS INT;
PROCEDURE p2show();
PROCEDURE p2public();
FUNCTION f2public() RETURNS TEXT;
END;
$$
CREATE PACKAGE BODY pkg1
DECLARE a INT DEFAULT 10;
PROCEDURE p1()
BEGIN
DECLARE b INT DEFAULT 20;
SET b=a;
SET b=a+1;
SET a=b;
SET a=b+1;
SET a=a+1;
SET @a=@a+2;
SELECT f1() FROM DUAL;
END;
FUNCTION f1() RETURNS INT
BEGIN
RETURN a;
END;
PROCEDURE p2private()
BEGIN
SELECT 'This is p2private';
END;
PROCEDURE p2public()
BEGIN
SELECT 'This is p2public';
END;
FUNCTION f2private() RETURNS TEXT
BEGIN
RETURN 'This is f2private';
END;
FUNCTION f2public() RETURNS TEXT
BEGIN
RETURN 'This is f2public';
END;
PROCEDURE p2show()
BEGIN
SHOW FUNCTION CODE f2public;
SHOW FUNCTION CODE f2private;
SHOW PROCEDURE CODE p2public;
SHOW PROCEDURE CODE p2private;
SHOW PROCEDURE CODE p2show;
END;
-- Initialization section
SET a=a+1;
BEGIN
DECLARE b INT;
SET b=a;
SET b=a+1;
SET a=b;
SET a=b+1;
END;
END;
$$
SHOW PROCEDURE CODE pkg1.p1;
Pos Instruction
0 set b@0 20
1 set b@0 PACKAGE_BODY.a@0
2 set b@0 PACKAGE_BODY.a@0 + 1
3 set PACKAGE_BODY.a@0 b@0
4 set PACKAGE_BODY.a@0 b@0 + 1
5 set PACKAGE_BODY.a@0 PACKAGE_BODY.a@0 + 1
6 stmt 31 "SET @a=@a+2"
7 stmt 0 "SELECT f1() FROM DUAL"
SHOW FUNCTION CODE pkg1.f1;
Pos Instruction
0 freturn int PACKAGE_BODY.a@0
SHOW PACKAGE BODY CODE pkg1;
Pos Instruction
0 set a@0 10
1 set a@0 a@0 + 1
2 set b@1 NULL
3 set b@1 a@0
4 set b@1 a@0 + 1
5 set a@0 b@1
6 set a@0 b@1 + 1
CALL pkg1.p2show;
Pos Instruction
0 freturn blob 'This is f2public'
Pos Instruction
0 freturn blob 'This is f2private'
Pos Instruction
0 stmt 0 "SELECT 'This is p2public'"
Pos Instruction
0 stmt 0 "SELECT 'This is p2private'"
Pos Instruction
0 stmt 110 "SHOW FUNCTION CODE f2public"
1 stmt 110 "SHOW FUNCTION CODE f2private"
2 stmt 109 "SHOW PROCEDURE CODE p2public"
3 stmt 109 "SHOW PROCEDURE CODE p2private"
4 stmt 109 "SHOW PROCEDURE CODE p2show"
DROP PACKAGE pkg1;
CREATE TABLE t1 (a INT);
CREATE PACKAGE pkg1
PROCEDURE p1();
END;
$$
CREATE PACKAGE BODY pkg1
DECLARE a TYPE OF t1.a DEFAULT 10;
PROCEDURE p1()
BEGIN
DECLARE b TYPE OF t1.a DEFAULT 20;
SET b=a;
SET b=a+1;
SET b=b+1;
SET a=b;
SET a=b+1;
SET a=a+1;
END;
-- Initialization section
SET a=a+1;
BEGIN
DECLARE b TYPE OF t1.a;
SET b=a;
SET b=a+1;
SET a=b;
SET a=b+1;
END;
END;
$$
SHOW PROCEDURE CODE pkg1.p1;
Pos Instruction
0 set b@0 20
1 set b@0 PACKAGE_BODY.a@0
2 set b@0 PACKAGE_BODY.a@0 + 1
3 set b@0 b@0 + 1
4 set PACKAGE_BODY.a@0 b@0
5 set PACKAGE_BODY.a@0 b@0 + 1
6 set PACKAGE_BODY.a@0 PACKAGE_BODY.a@0 + 1
SHOW PACKAGE BODY CODE pkg1;
Pos Instruction
0 set a@0 10
1 set a@0 a@0 + 1
2 set b@1 NULL
3 set b@1 a@0
4 set b@1 a@0 + 1
5 set a@0 b@1
6 set a@0 b@1 + 1
DROP PACKAGE pkg1;
DROP TABLE t1;
CREATE PACKAGE pkg1
PROCEDURE p1();
END;
$$
CREATE PACKAGE BODY pkg1
DECLARE a ROW(a INT,b TEXT) DEFAULT ROW(10,'x10');
PROCEDURE p1()
BEGIN
DECLARE b ROW(a INT,b TEXT) DEFAULT ROW(20,'x20');
SET b=a;
SET a=b;
SET b.a=a.a+1;
SET a.a=b.a+1;
SET a.a=a.a+1;
END;
-- Initialization section
SET a.a:=a.a+1;
BEGIN
DECLARE b ROW(a INT,b TEXT) DEFAULT ROW(30,'x30');
SET b=a;
SET b.a=a.a+1;
SET a=b;
SET a.a=b.a+1;
END;
END;
$$
SHOW PROCEDURE CODE pkg1.p1;
Pos Instruction
0 set b@0 (20,'x20')
1 set b@0 PACKAGE_BODY.a@0
2 set PACKAGE_BODY.a@0 b@0
3 set b.a@0[0] PACKAGE_BODY.a.a@0[0] + 1
4 set PACKAGE_BODY.a.a@0[0] b.a@0[0] + 1
5 set PACKAGE_BODY.a.a@0[0] PACKAGE_BODY.a.a@0[0] + 1
SHOW PACKAGE BODY CODE pkg1;
Pos Instruction
0 set a@0 (10,'x10')
1 set a.a@0[0] a.a@0[0] + 1
2 set b@1 (30,'x30')
3 set b@1 a@0
4 set b.a@1[0] a.a@0[0] + 1
5 set a@0 b@1
6 set a.a@0[0] b.a@1[0] + 1
DROP PACKAGE pkg1;
CREATE TABLE t1 (a INT, b TEXT);
CREATE PACKAGE pkg1
PROCEDURE p1();
END;
$$
CREATE PACKAGE BODY pkg1
DECLARE a ROW TYPE OF t1 DEFAULT ROW(10,'x10');
PROCEDURE p1()
BEGIN
DECLARE b ROW TYPE OF t1 DEFAULT ROW(20,'x20');
SET b=a;
SET a=b;
SET b.a=a.a+1;
SET a.a=b.a+1;
SET a.a=a.a+1;
END;
-- Initialization section
SET a.a=a.a+1;
BEGIN
DECLARE b ROW TYPE OF t1 DEFAULT ROW(30,'x30');
SET b=a;
SET b.a=a.a+1;
SET a=b;
SET a.a=b.a+1;
END;
END;
$$
SHOW PROCEDURE CODE pkg1.p1;
Pos Instruction
0 set b@0 (20,'x20')
1 set b@0 PACKAGE_BODY.a@0
2 set PACKAGE_BODY.a@0 b@0
3 set b.a@0["a"] PACKAGE_BODY.a.a@0["a"] + 1
4 set PACKAGE_BODY.a.a@0["a"] b.a@0["a"] + 1
5 set PACKAGE_BODY.a.a@0["a"] PACKAGE_BODY.a.a@0["a"] + 1
SHOW PACKAGE BODY CODE pkg1;
Pos Instruction
0 set a@0 (10,'x10')
1 set a.a@0["a"] a.a@0["a"] + 1
2 set b@1 (30,'x30')
3 set b@1 a@0
4 set b.a@1["a"] a.a@0["a"] + 1
5 set a@0 b@1
6 set a.a@0["a"] b.a@1["a"] + 1
DROP PACKAGE pkg1;
DROP TABLE t1;
-- source include/have_debug.inc
--echo #
--echo # MDEV-32101 CREATE PACKAGE [BODY] for sql_mode=DEFAULT
--echo #
DELIMITER $$;
CREATE PACKAGE pkg1
PROCEDURE p1();
FUNCTION f1() RETURNS INT;
END;
$$
CREATE PACKAGE BODY pkg1
PROCEDURE p1()
BEGIN SELECT 1;
END;
FUNCTION f1() RETURNS INT RETURN 1;
END;
$$
DELIMITER ;$$
SHOW PROCEDURE CODE pkg1.p1;
SHOW FUNCTION CODE pkg1.f1;
SHOW PACKAGE BODY CODE pkg1;
DROP PACKAGE pkg1;
DELIMITER $$;
CREATE PACKAGE pkg1
PROCEDURE p1();
FUNCTION f1() RETURNS INT;
PROCEDURE p2show();
PROCEDURE p2public();
FUNCTION f2public() RETURNS TEXT;
END;
$$
CREATE PACKAGE BODY pkg1
DECLARE a INT DEFAULT 10;
PROCEDURE p1()
BEGIN
DECLARE b INT DEFAULT 20;
SET b=a;
SET b=a+1;
SET a=b;
SET a=b+1;
SET a=a+1;
SET @a=@a+2;
SELECT f1() FROM DUAL;
END;
FUNCTION f1() RETURNS INT
BEGIN
RETURN a;
END;
PROCEDURE p2private()
BEGIN
SELECT 'This is p2private';
END;
PROCEDURE p2public()
BEGIN
SELECT 'This is p2public';
END;
FUNCTION f2private() RETURNS TEXT
BEGIN
RETURN 'This is f2private';
END;
FUNCTION f2public() RETURNS TEXT
BEGIN
RETURN 'This is f2public';
END;
PROCEDURE p2show()
BEGIN
SHOW FUNCTION CODE f2public;
SHOW FUNCTION CODE f2private;
SHOW PROCEDURE CODE p2public;
SHOW PROCEDURE CODE p2private;
SHOW PROCEDURE CODE p2show;
END;
-- Initialization section
SET a=a+1;
BEGIN
DECLARE b INT;
SET b=a;
SET b=a+1;
SET a=b;
SET a=b+1;
END;
END;
$$
DELIMITER ;$$
SHOW PROCEDURE CODE pkg1.p1;
SHOW FUNCTION CODE pkg1.f1;
SHOW PACKAGE BODY CODE pkg1;
CALL pkg1.p2show;
DROP PACKAGE pkg1;
CREATE TABLE t1 (a INT);
DELIMITER $$;
CREATE PACKAGE pkg1
PROCEDURE p1();
END;
$$
CREATE PACKAGE BODY pkg1
DECLARE a TYPE OF t1.a DEFAULT 10;
PROCEDURE p1()
BEGIN
DECLARE b TYPE OF t1.a DEFAULT 20;
SET b=a;
SET b=a+1;
SET b=b+1;
SET a=b;
SET a=b+1;
SET a=a+1;
END;
-- Initialization section
SET a=a+1;
BEGIN
DECLARE b TYPE OF t1.a;
SET b=a;
SET b=a+1;
SET a=b;
SET a=b+1;
END;
END;
$$
DELIMITER ;$$
SHOW PROCEDURE CODE pkg1.p1;
SHOW PACKAGE BODY CODE pkg1;
DROP PACKAGE pkg1;
DROP TABLE t1;
DELIMITER $$;
CREATE PACKAGE pkg1
PROCEDURE p1();
END;
$$
CREATE PACKAGE BODY pkg1
DECLARE a ROW(a INT,b TEXT) DEFAULT ROW(10,'x10');
PROCEDURE p1()
BEGIN
DECLARE b ROW(a INT,b TEXT) DEFAULT ROW(20,'x20');
SET b=a;
SET a=b;
SET b.a=a.a+1;
SET a.a=b.a+1;
SET a.a=a.a+1;
END;
-- Initialization section
SET a.a:=a.a+1;
BEGIN
DECLARE b ROW(a INT,b TEXT) DEFAULT ROW(30,'x30');
SET b=a;
SET b.a=a.a+1;
SET a=b;
SET a.a=b.a+1;
END;
END;
$$
DELIMITER ;$$
SHOW PROCEDURE CODE pkg1.p1;
SHOW PACKAGE BODY CODE pkg1;
DROP PACKAGE pkg1;
CREATE TABLE t1 (a INT, b TEXT);
DELIMITER $$;
CREATE PACKAGE pkg1
PROCEDURE p1();
END;
$$
CREATE PACKAGE BODY pkg1
DECLARE a ROW TYPE OF t1 DEFAULT ROW(10,'x10');
PROCEDURE p1()
BEGIN
DECLARE b ROW TYPE OF t1 DEFAULT ROW(20,'x20');
SET b=a;
SET a=b;
SET b.a=a.a+1;
SET a.a=b.a+1;
SET a.a=a.a+1;
END;
-- Initialization section
SET a.a=a.a+1;
BEGIN
DECLARE b ROW TYPE OF t1 DEFAULT ROW(30,'x30');
SET b=a;
SET b.a=a.a+1;
SET a=b;
SET a.a=b.a+1;
END;
END;
$$
DELIMITER ;$$
SHOW PROCEDURE CODE pkg1.p1;
SHOW PACKAGE BODY CODE pkg1;
DROP PACKAGE pkg1;
DROP TABLE t1;
This diff is collapsed.
--source include/not_embedded.inc
--source include/default_charset.inc
CREATE DATABASE db1;
CREATE USER u1@localhost IDENTIFIED BY '';
GRANT SELECT ON db1.* TO u1@localhost;
connect (conn1,localhost,u1,,db1);
SELECT CURRENT_USER;
--echo #
--echo # User u1 cannot drop PROCEDURE, PACKAGE, PACKAGE BODY by default
--echo #
--error ER_PROCACCESS_DENIED_ERROR
DROP PROCEDURE p1;
--error ER_PROCACCESS_DENIED_ERROR
DROP PACKAGE pkg1;
--error ER_PROCACCESS_DENIED_ERROR
DROP PACKAGE BODY pkg1;
--echo #
--echo # User u1 cannot create PROCEDURE, PACKAGE, PACKAGE BODY by default
--echo #
DELIMITER $$;
--error ER_DBACCESS_DENIED_ERROR
CREATE PROCEDURE p1()
BEGIN
END;
$$
DELIMITER ;$$
DELIMITER $$;
--error ER_DBACCESS_DENIED_ERROR
CREATE PACKAGE pkg1
PROCEDURE p1();
END;
$$
DELIMITER ;$$
# TODO: this should probably return ER_DBACCESS_DENIED_ERROR
# here, and in the same place in compat/oracle.sp-package-security.test
DELIMITER $$;
--error ER_SP_DOES_NOT_EXIST
CREATE PACKAGE BODY pkg1 AS
PROCEDURE p1() AS BEGIN END;
END;
$$
DELIMITER ;$$
--echo #
--echo # Now create a PACKAGE by root
--echo #
connection default;
USE db1;
DELIMITER $$;
CREATE PROCEDURE p1root()
BEGIN
SELECT 1;
END;
$$
DELIMITER ;$$
DELIMITER $$;
CREATE PACKAGE pkg1
PROCEDURE p1();
FUNCTION f1() RETURNS TEXT;
END;
$$
DELIMITER ;$$
SHOW CREATE PACKAGE pkg1;
--echo #
--echo # u1 cannot SHOW yet:
--echo # - the standalone procedure earlier created by root
--echo # - the package specifications earlier create by root
--echo #
connection conn1;
--error ER_SP_DOES_NOT_EXIST
SHOW CREATE PROCEDURE p1root;
--error ER_SP_DOES_NOT_EXIST
SHOW CREATE PACKAGE pkg1;
--echo #
--echo # User u1 still cannot create a PACKAGE BODY
--echo #
connection conn1;
DELIMITER $$;
--error ER_DBACCESS_DENIED_ERROR
CREATE PACKAGE BODY pkg1
PROCEDURE p1() BEGIN END;
FUNCTION f1() RETURNS TEXT BEGIN RETURN 'This is f1'; END;
END;
$$
DELIMITER ;$$
--echo #
--echo # Now grant EXECUTE:
--echo # - on the standalone procedure earlier created by root
--echo # - on the package specification earlier created by root
--echo #
connection default;
GRANT EXECUTE ON PROCEDURE db1.p1root TO u1@localhost;
GRANT EXECUTE ON PACKAGE db1.pkg1 TO u1@localhost;
--echo #
--echo # Now u1 can do SHOW for:
--echo # - the standalone procedure earlier created by root
--echo # - the package specification earlier created by root
--echo #
disconnect conn1;
connect (conn1,localhost,u1,,db1);
SHOW CREATE PROCEDURE db1.p1root;
SHOW CREATE PACKAGE db1.pkg1;
--echo #
--echo # Now revoke EXECUTE and grant CREATE ROUTINE instead
--echo #
connection default;
REVOKE EXECUTE ON PROCEDURE db1.p1root FROM u1@localhost;
REVOKE EXECUTE ON PACKAGE db1.pkg1 FROM u1@localhost;
GRANT CREATE ROUTINE ON db1.* TO u1@localhost;
--echo #
--echo # Reconnect u1 to make new grants have effect
--echo #
disconnect conn1;
connect (conn1,localhost,u1,,db1);
--echo #
--echo # Now u1 can SHOW:
--echo # - standalone routines earlier created by root
--echo # - package specifications earlier created by root
--echo #
SHOW CREATE PROCEDURE p1root;
SHOW CREATE PACKAGE pkg1;
--echo #
--echo # Now u1 can CREATE, DROP and EXECUTE its own standalone procedures
--echo #
DELIMITER $$;
CREATE PROCEDURE p1()
BEGIN
END;
$$
DELIMITER ;$$
SHOW GRANTS;
CALL p1;
DROP PROCEDURE p1;
SHOW GRANTS;
--echo #
--echo # Now u1 can also CREATE, DROP its own package specifications
--echo #
DELIMITER $$;
CREATE PACKAGE pkg2
PROCEDURE p1();
FUNCTION f1() RETURNS TEXT;
END;
$$
DELIMITER ;$$
SHOW CREATE PACKAGE pkg2;
SHOW GRANTS;
DROP PACKAGE pkg2;
SHOW GRANTS;
--echo #
--echo # Now u1 can also CREATE, DROP package bodies and EXECUTE package body routines
--echo #
DELIMITER $$;
CREATE PACKAGE BODY pkg1
PROCEDURE p1() BEGIN SELECT 'This is pkg1.p1' AS `comment`; END;
FUNCTION f1() RETURNS TEXT BEGIN RETURN 'This is pkg1.f1'; END;
END;
$$
DELIMITER ;$$
SHOW CREATE PACKAGE pkg1;
SHOW CREATE PACKAGE BODY pkg1;
SHOW GRANTS;
CALL pkg1.p1;
SELECT pkg1.f1();
DROP PACKAGE BODY pkg1;
SHOW GRANTS;
--echo #
--echo # Now create a PACKAGE BODY by root.
--echo # u1 does not have EXECUTE access by default.
--echo #
connection default;
DELIMITER $$;
CREATE PACKAGE BODY pkg1
PROCEDURE p1() BEGIN SELECT 'This is pkg1.p1' AS `comment`; END;
FUNCTION f1() RETURNS TEXT RETURN 'This is pkg1.f1';
END;
$$
DELIMITER ;$$
connection conn1;
SHOW CREATE PACKAGE pkg1;
SHOW CREATE PACKAGE BODY pkg1;
--error ER_PROCACCESS_DENIED_ERROR
CALL pkg1.p1;
--error ER_PROCACCESS_DENIED_ERROR
SELECT pkg1.f1();
--echo #
--echo # Now grant EXECUTE to u1 on the PACKAGE BODY created by root
--echo #
connection default;
GRANT EXECUTE ON PACKAGE BODY db1.pkg1 TO u1@localhost;
disconnect conn1;
connect (conn1,localhost,u1,,db1);
SELECT CURRENT_USER;
SHOW GRANTS;
CALL pkg1.p1;
SELECT pkg1.f1();
connection default;
DROP PACKAGE BODY pkg1;
--echo #
--echo # u1 still cannot DROP the package specification earlier created by root.
--echo #
connection conn1;
--error ER_PROCACCESS_DENIED_ERROR
DROP PACKAGE pkg1;
--echo #
--echo # Grant ALTER ROUTINE to u1
--echo #
connection default;
GRANT ALTER ROUTINE ON db1.* TO u1@localhost;
--echo #
--echo # Now u1 can DROP:
--echo # - the standalone procedure earlier created by root
--echo # - the package specification earlier created by root
--echo #
disconnect conn1;
connect (conn1,localhost,u1,,db1);
DROP PACKAGE pkg1;
DROP PROCEDURE p1root;
disconnect conn1;
connection default;
DROP USER u1@localhost;
DROP DATABASE db1;
USE test;
--echo #
--echo # Creator=root, definer=xxx
--echo #
CREATE USER xxx@localhost;
DELIMITER $$;
CREATE DEFINER=xxx@localhost PACKAGE p1
PROCEDURE p1();
END;
$$
CREATE DEFINER=xxx@localhost PACKAGE BODY p1
PROCEDURE p1()
BEGIN
SELECT SESSION_USER(), CURRENT_USER(), 'p1.p1' AS msg;
END;
SELECT SESSION_USER(), CURRENT_USER(), 'package body p1' AS msg;
END;
$$
DELIMITER ;$$
--error ER_PROCACCESS_DENIED_ERROR
CALL p1.p1;
GRANT EXECUTE ON PACKAGE BODY test.p1 TO xxx@localhost;
CALL p1.p1;
DROP PACKAGE p1;
DROP USER xxx@localhost;
--echo #
--echo # Creator=root, definer=xxx, SQL SECURITY INVOKER
--echo #
CREATE USER xxx@localhost;
DELIMITER $$;
CREATE DEFINER=xxx@localhost PACKAGE p1
PROCEDURE p1();
END;
$$
CREATE DEFINER=xxx@localhost PACKAGE BODY p1 SQL SECURITY INVOKER
PROCEDURE p1()
BEGIN
SELECT SESSION_USER(), CURRENT_USER(), 'p1.p1' AS msg;
END;
SELECT SESSION_USER(), CURRENT_USER(), 'package body p1' AS msg;
END;
$$
DELIMITER ;$$
CALL p1.p1;
DROP PACKAGE p1;
DROP USER xxx@localhost;
SET sql_mode='';
CREATE OR REPLACE PACKAGE pkg
PROCEDURE p1();
FUNCTION f1() RETURNS INT;
END;
$$
CREATE OR REPLACE PACKAGE BODY pkg
-- variable declarations
DECLARE a INT DEFAULT 11;
DECLARE b INT DEFAULT 10;
-- routine declarations
PROCEDURE p1()
BEGIN
SELECT CURRENT_USER;
END;
FUNCTION f1() RETURNS INT
BEGIN
RETURN a;
END;
-- initialization section
SET a=a-b;
END;
$$
SHOW CREATE PACKAGE pkg;
Package sql_mode Create Package character_set_client collation_connection Database Collation
pkg CREATE DEFINER=`root`@`localhost` PACKAGE `pkg` PROCEDURE p1();
FUNCTION f1() RETURNS INT;
END latin1 latin1_swedish_ci latin1_swedish_ci
SHOW CREATE PACKAGE BODY pkg;
Package body sql_mode Create Package Body character_set_client collation_connection Database Collation
pkg CREATE DEFINER=`root`@`localhost` PACKAGE BODY `pkg` DECLARE a INT DEFAULT 11;
DECLARE b INT DEFAULT 10;
-- routine declarations
PROCEDURE p1()
BEGIN
SELECT CURRENT_USER;
END;
FUNCTION f1() RETURNS INT
BEGIN
RETURN a;
END;
-- initialization section
SET a=a-b;
END latin1 latin1_swedish_ci latin1_swedish_ci
CALL pkg.p1();
CURRENT_USER
root@localhost
SELECT pkg.f1();
pkg.f1()
1
DROP PACKAGE pkg;
#
# CREATE PACKAGE for sql_mode='';
# Resebmles SQL Standard 'CREATE MODULE'.
#
SET sql_mode='';
DELIMITER $$;
CREATE OR REPLACE PACKAGE pkg
PROCEDURE p1();
FUNCTION f1() RETURNS INT;
END;
$$
DELIMITER ;$$
DELIMITER $$;
CREATE OR REPLACE PACKAGE BODY pkg
-- variable declarations
DECLARE a INT DEFAULT 11;
DECLARE b INT DEFAULT 10;
-- routine declarations
PROCEDURE p1()
BEGIN
SELECT CURRENT_USER;
END;
FUNCTION f1() RETURNS INT
BEGIN
RETURN a;
END;
-- initialization section
SET a=a-b;
END;
$$
DELIMITER ;$$
SHOW CREATE PACKAGE pkg;
SHOW CREATE PACKAGE BODY pkg;
CALL pkg.p1();
SELECT pkg.f1();
DROP PACKAGE pkg;
...@@ -3148,7 +3148,24 @@ collation_connection latin1_swedish_ci ...@@ -3148,7 +3148,24 @@ collation_connection latin1_swedish_ci
DROP VIEW v_test; DROP VIEW v_test;
SET sql_mode=DEFAULT; SET sql_mode=DEFAULT;
CREATE VIEW v_test AS SELECT 1 AS c1 FROM DUAL WHERE 1=test1.f_test(); CREATE VIEW v_test AS SELECT 1 AS c1 FROM DUAL WHERE 1=test1.f_test();
ERROR 42000: FUNCTION test1.f_test does not exist SELECT * FROM v_test;
c1
1
SHOW CREATE VIEW v_test;
View v_test
Create View CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v_test` AS select 1 AS `c1` from DUAL where 1 = `test`.`test1`.`f_test`()
character_set_client latin1
collation_connection latin1_swedish_ci
SET sql_mode=ORACLE;
SELECT * FROM v_test;
c1
1
SHOW CREATE VIEW v_test;
View v_test
Create View CREATE VIEW "v_test" AS select 1 AS "c1" from DUAL where 1 = "test"."test1"."f_test"()
character_set_client latin1
collation_connection latin1_swedish_ci
DROP VIEW v_test;
SET sql_mode=ORACLE; SET sql_mode=ORACLE;
CREATE VIEW v_test AS SELECT 1 AS c1 FROM DUAL WHERE 1=test.test1.f_test(); CREATE VIEW v_test AS SELECT 1 AS c1 FROM DUAL WHERE 1=test.test1.f_test();
SELECT * FROM v_test; SELECT * FROM v_test;
......
...@@ -2854,13 +2854,18 @@ END test1; ...@@ -2854,13 +2854,18 @@ END test1;
$$ $$
DELIMITER ;$$ DELIMITER ;$$
#
# A VIEW created with sql_mode=ORACLE, calling a package routine
#
SET sql_mode=ORACLE; SET sql_mode=ORACLE;
CREATE VIEW v_test AS SELECT 1 AS c1 FROM DUAL WHERE 1=test1.f_test(); CREATE VIEW v_test AS SELECT 1 AS c1 FROM DUAL WHERE 1=test1.f_test();
SELECT * FROM v_test; SELECT * FROM v_test;
--vertical_results --vertical_results
SHOW CREATE VIEW v_test; SHOW CREATE VIEW v_test;
--horizontal_results --horizontal_results
#
# It also works with sql_mode=DEFALT
#
SET sql_mode=DEFAULT; SET sql_mode=DEFAULT;
SELECT * FROM v_test; SELECT * FROM v_test;
--vertical_results --vertical_results
...@@ -2868,10 +2873,24 @@ SHOW CREATE VIEW v_test; ...@@ -2868,10 +2873,24 @@ SHOW CREATE VIEW v_test;
--horizontal_results --horizontal_results
DROP VIEW v_test; DROP VIEW v_test;
#
# A VIEW created with sql_mode=DEFAULT, calling a package routine
#
SET sql_mode=DEFAULT; SET sql_mode=DEFAULT;
--error ER_SP_DOES_NOT_EXIST
CREATE VIEW v_test AS SELECT 1 AS c1 FROM DUAL WHERE 1=test1.f_test(); CREATE VIEW v_test AS SELECT 1 AS c1 FROM DUAL WHERE 1=test1.f_test();
SELECT * FROM v_test;
--vertical_results
SHOW CREATE VIEW v_test;
#
# It also works with sql_mode=ORACLE
#
--horizontal_results
SET sql_mode=ORACLE;
SELECT * FROM v_test;
--vertical_results
SHOW CREATE VIEW v_test;
--horizontal_results
DROP VIEW v_test;
SET sql_mode=ORACLE; SET sql_mode=ORACLE;
......
...@@ -2628,7 +2628,7 @@ Sp_handler::sp_resolve_package_routine(THD *thd, ...@@ -2628,7 +2628,7 @@ Sp_handler::sp_resolve_package_routine(THD *thd,
const Sp_handler **pkg_routine_handler, const Sp_handler **pkg_routine_handler,
Database_qualified_name *pkgname) const Database_qualified_name *pkgname) const
{ {
if (!thd->db.length || !(thd->variables.sql_mode & MODE_ORACLE)) if (!thd->db.length)
return false; return false;
return name->m_explicit_name ? return name->m_explicit_name ?
......
...@@ -157,6 +157,7 @@ class Sp_handler ...@@ -157,6 +157,7 @@ class Sp_handler
} }
virtual enum_sp_type type() const= 0; virtual enum_sp_type type() const= 0;
virtual LEX_CSTRING type_lex_cstring() const= 0; virtual LEX_CSTRING type_lex_cstring() const= 0;
virtual enum_sql_command sqlcom_create() const= 0;
virtual enum_sql_command sqlcom_drop() const= 0; virtual enum_sql_command sqlcom_drop() const= 0;
virtual LEX_CSTRING empty_body_lex_cstring(sql_mode_t mode) const virtual LEX_CSTRING empty_body_lex_cstring(sql_mode_t mode) const
{ {
...@@ -257,6 +258,7 @@ class Sp_handler_procedure: public Sp_handler ...@@ -257,6 +258,7 @@ class Sp_handler_procedure: public Sp_handler
static LEX_CSTRING m_type_str= { STRING_WITH_LEN("PROCEDURE")}; static LEX_CSTRING m_type_str= { STRING_WITH_LEN("PROCEDURE")};
return m_type_str; return m_type_str;
} }
enum_sql_command sqlcom_create() const { return SQLCOM_CREATE_PROCEDURE; }
enum_sql_command sqlcom_drop() const { return SQLCOM_DROP_PROCEDURE; } enum_sql_command sqlcom_drop() const { return SQLCOM_DROP_PROCEDURE; }
LEX_CSTRING empty_body_lex_cstring(sql_mode_t mode) const; LEX_CSTRING empty_body_lex_cstring(sql_mode_t mode) const;
const char *show_create_routine_col1_caption() const const char *show_create_routine_col1_caption() const
...@@ -308,6 +310,7 @@ class Sp_handler_function: public Sp_handler ...@@ -308,6 +310,7 @@ class Sp_handler_function: public Sp_handler
static LEX_CSTRING m_type_str= { STRING_WITH_LEN("FUNCTION")}; static LEX_CSTRING m_type_str= { STRING_WITH_LEN("FUNCTION")};
return m_type_str; return m_type_str;
} }
enum_sql_command sqlcom_create() const { return SQLCOM_CREATE_FUNCTION; }
enum_sql_command sqlcom_drop() const { return SQLCOM_DROP_FUNCTION; } enum_sql_command sqlcom_drop() const { return SQLCOM_DROP_FUNCTION; }
LEX_CSTRING empty_body_lex_cstring(sql_mode_t mode) const; LEX_CSTRING empty_body_lex_cstring(sql_mode_t mode) const;
const char *show_create_routine_col1_caption() const const char *show_create_routine_col1_caption() const
...@@ -378,6 +381,7 @@ class Sp_handler_package_spec: public Sp_handler_package ...@@ -378,6 +381,7 @@ class Sp_handler_package_spec: public Sp_handler_package
static LEX_CSTRING m_type_str= {STRING_WITH_LEN("PACKAGE")}; static LEX_CSTRING m_type_str= {STRING_WITH_LEN("PACKAGE")};
return m_type_str; return m_type_str;
} }
enum_sql_command sqlcom_create() const { return SQLCOM_CREATE_PACKAGE; }
enum_sql_command sqlcom_drop() const { return SQLCOM_DROP_PACKAGE; } enum_sql_command sqlcom_drop() const { return SQLCOM_DROP_PACKAGE; }
LEX_CSTRING empty_body_lex_cstring(sql_mode_t mode) const LEX_CSTRING empty_body_lex_cstring(sql_mode_t mode) const
{ {
...@@ -412,6 +416,7 @@ class Sp_handler_package_body: public Sp_handler_package ...@@ -412,6 +416,7 @@ class Sp_handler_package_body: public Sp_handler_package
static LEX_CSTRING m_type_str= {STRING_WITH_LEN("PACKAGE BODY")}; static LEX_CSTRING m_type_str= {STRING_WITH_LEN("PACKAGE BODY")};
return m_type_str; return m_type_str;
} }
enum_sql_command sqlcom_create() const { return SQLCOM_CREATE_PACKAGE_BODY; }
enum_sql_command sqlcom_drop() const { return SQLCOM_DROP_PACKAGE_BODY; } enum_sql_command sqlcom_drop() const { return SQLCOM_DROP_PACKAGE_BODY; }
LEX_CSTRING empty_body_lex_cstring(sql_mode_t mode) const LEX_CSTRING empty_body_lex_cstring(sql_mode_t mode) const
{ {
...@@ -446,6 +451,7 @@ class Sp_handler_trigger: public Sp_handler ...@@ -446,6 +451,7 @@ class Sp_handler_trigger: public Sp_handler
static LEX_CSTRING m_type_str= { STRING_WITH_LEN("TRIGGER")}; static LEX_CSTRING m_type_str= { STRING_WITH_LEN("TRIGGER")};
return m_type_str; return m_type_str;
} }
enum_sql_command sqlcom_create() const { return SQLCOM_CREATE_TRIGGER; }
enum_sql_command sqlcom_drop() const { return SQLCOM_DROP_TRIGGER; } enum_sql_command sqlcom_drop() const { return SQLCOM_DROP_TRIGGER; }
MDL_key::enum_mdl_namespace get_mdl_type() const MDL_key::enum_mdl_namespace get_mdl_type() const
{ {
......
...@@ -7370,6 +7370,35 @@ sp_name *LEX::make_sp_name(THD *thd, const Lex_ident_sys_st &name1, ...@@ -7370,6 +7370,35 @@ sp_name *LEX::make_sp_name(THD *thd, const Lex_ident_sys_st &name1,
} }
sp_lex_local *LEX::package_routine_start(THD *thd,
const Sp_handler *sph,
const Lex_ident_sys_st &name)
{
DBUG_ASSERT(sphead);
DBUG_ASSERT(sphead->get_package());
thd->m_parser_state->m_yacc.reset_before_substatement();
sp_lex_local *sublex= new (thd->mem_root) sp_lex_local(thd, this);
if (!unlikely(sublex))
return NULL;
sublex->sql_command= sph->sqlcom_create();
sp_name *spname= make_sp_name_package_routine(thd, name);
if (unlikely(!spname))
return NULL;
if (sublex->sql_command == SQLCOM_CREATE_FUNCTION)
(void) is_native_function_with_warn(thd, &name);
enum_sp_aggregate_type atype= sublex->sql_command == SQLCOM_CREATE_FUNCTION ?
NOT_AGGREGATE : DEFAULT_AGGREGATE;
if (unlikely(!sublex->make_sp_head_no_recursive(thd, spname, sph, atype)))
return NULL;
sphead->get_package()->m_current_routine= sublex;
return sublex;
}
sp_head *LEX::make_sp_head(THD *thd, const sp_name *name, sp_head *LEX::make_sp_head(THD *thd, const sp_name *name,
const Sp_handler *sph, const Sp_handler *sph,
enum_sp_aggregate_type agg_type) enum_sp_aggregate_type agg_type)
...@@ -9311,10 +9340,10 @@ sp_package *LEX::get_sp_package() const ...@@ -9311,10 +9340,10 @@ sp_package *LEX::get_sp_package() const
sp_package *LEX::create_package_start(THD *thd, sp_package *LEX::create_package_start(THD *thd,
enum_sql_command command,
const Sp_handler *sph, const Sp_handler *sph,
const sp_name *name_arg, const sp_name *name_arg,
DDL_options_st options) DDL_options_st options,
const st_sp_chistics &chistics)
{ {
sp_package *pkg; sp_package *pkg;
...@@ -9323,7 +9352,7 @@ sp_package *LEX::create_package_start(THD *thd, ...@@ -9323,7 +9352,7 @@ sp_package *LEX::create_package_start(THD *thd,
my_error(ER_SP_NO_RECURSIVE_CREATE, MYF(0), sph->type_str()); my_error(ER_SP_NO_RECURSIVE_CREATE, MYF(0), sph->type_str());
return NULL; return NULL;
} }
if (unlikely(set_command_with_check(command, options))) if (unlikely(set_command_with_check(sph->sqlcom_create(), options)))
return NULL; return NULL;
if (sph->type() == SP_TYPE_PACKAGE_BODY) if (sph->type() == SP_TYPE_PACKAGE_BODY)
{ {
...@@ -9359,6 +9388,7 @@ sp_package *LEX::create_package_start(THD *thd, ...@@ -9359,6 +9388,7 @@ sp_package *LEX::create_package_start(THD *thd,
pkg->reset_thd_mem_root(thd); pkg->reset_thd_mem_root(thd);
pkg->init(this); pkg->init(this);
pkg->make_qname(pkg->get_main_mem_root(), &pkg->m_qname); pkg->make_qname(pkg->get_main_mem_root(), &pkg->m_qname);
pkg->set_c_chistics(chistics);
sphead= pkg; sphead= pkg;
return pkg; return pkg;
} }
......
...@@ -3201,6 +3201,7 @@ class Lex_grant_privilege: public Grant_privilege, public Sql_alloc ...@@ -3201,6 +3201,7 @@ class Lex_grant_privilege: public Grant_privilege, public Sql_alloc
}; };
class sp_lex_local;
class sp_lex_cursor; class sp_lex_cursor;
struct LEX: public Query_tables_list struct LEX: public Query_tables_list
...@@ -3904,6 +3905,9 @@ struct LEX: public Query_tables_list ...@@ -3904,6 +3905,9 @@ struct LEX: public Query_tables_list
const Lex_ident_sys_st &name2); const Lex_ident_sys_st &name2);
sp_name *make_sp_name_package_routine(THD *thd, sp_name *make_sp_name_package_routine(THD *thd,
const Lex_ident_sys_st &name); const Lex_ident_sys_st &name);
sp_lex_local *package_routine_start(THD *thd,
const Sp_handler *sph,
const Lex_ident_sys_st &name);
sp_head *make_sp_head(THD *thd, const sp_name *name, const Sp_handler *sph, sp_head *make_sp_head(THD *thd, const sp_name *name, const Sp_handler *sph,
enum_sp_aggregate_type agg_type); enum_sp_aggregate_type agg_type);
sp_head *make_sp_head_no_recursive(THD *thd, const sp_name *name, sp_head *make_sp_head_no_recursive(THD *thd, const sp_name *name,
...@@ -3916,10 +3920,10 @@ struct LEX: public Query_tables_list ...@@ -3916,10 +3920,10 @@ struct LEX: public Query_tables_list
bool sp_body_finalize_procedure(THD *); bool sp_body_finalize_procedure(THD *);
bool sp_body_finalize_procedure_standalone(THD *, const sp_name *end_name); bool sp_body_finalize_procedure_standalone(THD *, const sp_name *end_name);
sp_package *create_package_start(THD *thd, sp_package *create_package_start(THD *thd,
enum_sql_command command,
const Sp_handler *sph, const Sp_handler *sph,
const sp_name *name, const sp_name *name,
DDL_options_st options); DDL_options_st options,
const st_sp_chistics &chistics);
bool create_package_finalize(THD *thd, bool create_package_finalize(THD *thd,
const sp_name *name, const sp_name *name,
const sp_name *name2, const sp_name *name2,
......
This diff is collapsed.
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