mirror of
https://github.com/MariaDB/server.git
synced 2026-10-23 18:49:29 +03:00
MDEV-39587 Package-wide TYPE for variable declarations
SET sql_mode=ORACLE;
DELIMITER $$
CREATE OR REPLACE PACKAGE pkg AS
-- Declare a package public data type
TYPE varchar_array IS TABLE OF VARCHAR(2000) INDEX BY INTEGER;
END;
$$
DELIMITER ;
DELIMITER $$
CREATE OR REPLACE PROCEDURE p1 AS
v pkg.varchar_array; -- Use the package public data type
BEGIN
v(0):='test';
SELECT v(0);
END;
$$
DELIMITER ;
Note, the change is done only for sql_mode=ORACLE, because the TYPE
declaration is not available for the default mode.
Where package-wide types are available
--------------------------------------
- Variabe list type:
DECLARE var pkg1.type1;
- RETURN type for a package routine:
CREATE FUNCTION .. RETURN pkg1.type1 ...
- Parameter type for a package routine:
PROCEDURE p1(param1 pkg1.type1);
- Assoc array element type:
TYPE assoc1_t IS TABLE OF pkg1.type1 ...
- REF CURSOR RETURN type:
TYPE cur1_t IS REF CURSOR RETURN pkg1.type1;
Change details
--------------
- Adding a member Lex_length_and_dec_st::m_foreign_module_type
It's set to true when the data type was initialized from a TYPE
in foreign routine (e.g. in PACKAGE spec).
It's needed to prevent use of qualified identifiers in public contexts,
i.e. in schema public routine parameter types and schema publuc function
RETURN types.
Adding a helper method sp_head::check_applicability() which prevents
use of qualified types in public context.
- Adding a helper method sp_head::raise_unknown_data_type().
- Adding methods LEX::set_field_type_typedef_package_spec() for
2-step and 3-step qualified indentifiers.
It's used in field_type_all_with_typedefs which covers cases:
- Variabe list type : DECLARE var pkg1.type1;
- RETURN type : CREATE FUNCTION .. RETURN pkg1.type1 ...
- Parameter type : PROCEDURE p1(param1 pkg1.type1);
- Assoc array element type : TYPE assoc1_t IS TABLE OF pkg1.type1 ...
- Adding a method LEX::declare_type_ref_cursor_return_typedef().
It handles cases when a new TYPE REF CURSOR RETURN is declared,
for both for qualified RETURN types and non-qualified RETURN types:
- TYPE cur0_t IS REF CURSOR RETURN rec1_t;
- TYPE cur0_t IS REF CURSOR RETURN pkg1.rec1_t;
- TYPE cur0_t IS REF CURSOR RETURN db1.pkg1.rec1_t;
The code was moved from LEX::declare_type_ref_cursor() into
LEX::declare_type_ref_cursor_return_typedef() and extended
to cover qualified RETURN types.
- Adding a method Sql_path::find_package_spec_type().
It iterates through all schemas specified in @@path and searches
for the given type in the given package.
- Adding a helper method sp_pcontext::type_defs_add_ref_cursor()
to reuse the code.
- Adding a new method sp_package::get_typedef() to search
for TYPE definitions in PACKAGE specifications.
- Adding a new method sp_head::get_typedef_package_spec()
to search for TYPE definitions used by a PROCEDURE or FUNCTION.
- Adding a helper method
Sp_handler::sp_cache_routine_reentrant_suppress_errors
Adding a method Sp_handler::find_package_spec().
This commit is contained in:
@@ -2937,14 +2937,24 @@ static void print_blob_as_hex(FILE *output_file, const char *str, ulong len)
|
||||
static uint dump_routines_for_db(char *db)
|
||||
{
|
||||
char query_buff[QUERY_LENGTH];
|
||||
const char *routine_type[]= {"FUNCTION",
|
||||
"PROCEDURE",
|
||||
"PACKAGE",
|
||||
"PACKAGE BODY"};
|
||||
const char *create_caption_xml[]= {"Create Function",
|
||||
"Create Procedure",
|
||||
"Create Package",
|
||||
"Create Package Body"};
|
||||
struct routine_dump_param_st
|
||||
{
|
||||
const char *routine_type;
|
||||
const char *create_caption_xml;
|
||||
uint version;
|
||||
};
|
||||
/*
|
||||
Package specifications can have public data type definitions.
|
||||
So dump specifications first, before any other stored objects.
|
||||
Note, before 10.3 packages are not supported.
|
||||
*/
|
||||
const routine_dump_param_st routine_dump_param_array[]=
|
||||
{
|
||||
{"PACKAGE", "Create Package", 100300},
|
||||
{"FUNCTION", "Create Function", 0},
|
||||
{"PROCEDURE", "Create Procedure", 0},
|
||||
{"PACKAGE BODY", "Create Package Body", 100300}
|
||||
};
|
||||
char db_name_buff[NAME_LEN*2+3], name_buff[NAME_LEN*2+3];
|
||||
char *routine_name;
|
||||
uint i;
|
||||
@@ -2953,9 +2963,6 @@ static uint dump_routines_for_db(char *db)
|
||||
|
||||
char db_cl_name[MY_CS_COLLATION_NAME_SIZE];
|
||||
int db_cl_altered= FALSE;
|
||||
// before 10.3 packages are not supported
|
||||
uint upper_bound= mysql_get_server_version(mysql) >= 100300 ?
|
||||
array_elements(routine_type) : 2;
|
||||
DBUG_ENTER("dump_routines_for_db");
|
||||
DBUG_PRINT("enter", ("db: '%s'", db));
|
||||
|
||||
@@ -2985,11 +2992,14 @@ static uint dump_routines_for_db(char *db)
|
||||
fputs("\t<routines>\n", sql_file);
|
||||
|
||||
/* 0, retrieve and dump functions, 1, procedures, etc. */
|
||||
for (i= 0; i < upper_bound; i++)
|
||||
for (i= 0; i < array_elements(routine_dump_param_array); i++)
|
||||
{
|
||||
const routine_dump_param_st *param= &routine_dump_param_array[i];
|
||||
if (mysql_get_server_version(mysql) < param->version)
|
||||
continue;
|
||||
my_snprintf(query_buff, sizeof(query_buff),
|
||||
"SHOW %s STATUS WHERE Db = '%s'",
|
||||
routine_type[i], db_name_buff);
|
||||
param->routine_type, db_name_buff);
|
||||
|
||||
if (mysql_query_with_error_report(mysql, &routine_list_res, query_buff))
|
||||
DBUG_RETURN(1);
|
||||
@@ -3000,10 +3010,10 @@ static uint dump_routines_for_db(char *db)
|
||||
while ((routine_list_row= mysql_fetch_row(routine_list_res)))
|
||||
{
|
||||
routine_name= quote_name(routine_list_row[1], name_buff, 0);
|
||||
DBUG_PRINT("info", ("retrieving CREATE %s for %s", routine_type[i],
|
||||
DBUG_PRINT("info", ("retrieving CREATE %s for %s", param->routine_type,
|
||||
name_buff));
|
||||
my_snprintf(query_buff, sizeof(query_buff), "SHOW CREATE %s %s",
|
||||
routine_type[i], routine_name);
|
||||
param->routine_type, routine_name);
|
||||
|
||||
if (mysql_query_with_error_report(mysql, &routine_res, query_buff))
|
||||
continue;
|
||||
@@ -3032,7 +3042,7 @@ static uint dump_routines_for_db(char *db)
|
||||
if (opt_xml)
|
||||
{
|
||||
print_xml_row(sql_file, "routine", routine_res, &row,
|
||||
create_caption_xml[i]);
|
||||
param->create_caption_xml);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -3040,7 +3050,7 @@ static uint dump_routines_for_db(char *db)
|
||||
|
||||
if (opt_drop)
|
||||
fprintf(sql_file, "/*!50003 DROP %s IF EXISTS %s */;\n",
|
||||
routine_type[i], routine_name);
|
||||
param->routine_type, routine_name);
|
||||
|
||||
if (mysql_num_fields(routine_res) >= 6)
|
||||
{
|
||||
|
||||
@@ -1300,7 +1300,7 @@ ERROR 42000: You have an error in your SQL syntax; check the manual that corresp
|
||||
create table t1 (i int, vc serial as (i));
|
||||
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'as (i))' at line 1
|
||||
create function fs() returns serial return 1;
|
||||
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'serial return 1' at line 1
|
||||
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'return 1' at line 1
|
||||
create table t1 ( id serial );
|
||||
show create table t1;
|
||||
Table Create Table
|
||||
|
||||
@@ -48,27 +48,6 @@ $$
|
||||
/*M!100616 SET @OLD_NOTE_VERBOSITY=@@NOTE_VERBOSITY, NOTE_VERBOSITY=0 */;
|
||||
/*!50003 SET @saved_sql_mode = @@sql_mode */ ;
|
||||
/*!50003 SET sql_mode = 'PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ORACLE,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,NO_AUTO_CREATE_USER,SIMULTANEOUS_ASSIGNMENT' */ ;
|
||||
/*!50003 DROP PROCEDURE IF EXISTS `p1` */;
|
||||
/*!50003 SET @saved_cs_client = @@character_set_client */ ;
|
||||
/*!50003 SET @saved_cs_results = @@character_set_results */ ;
|
||||
/*!50003 SET @saved_col_connection = @@collation_connection */ ;
|
||||
/*!50003 SET character_set_client = latin1 */ ;
|
||||
/*!50003 SET character_set_results = latin1 */ ;
|
||||
/*!50003 SET collation_connection = latin1_swedish_ci */ ;
|
||||
DELIMITER ;;
|
||||
CREATE DEFINER="root"@"localhost" PROCEDURE "p1"()
|
||||
AS
|
||||
BEGIN
|
||||
SELECT pkg1.f1(); -- a standalone routine calls a package routine
|
||||
END
|
||||
;;
|
||||
DELIMITER ;
|
||||
/*!50003 SET sql_mode = @saved_sql_mode */ ;
|
||||
/*!50003 SET character_set_client = @saved_cs_client */ ;
|
||||
/*!50003 SET character_set_results = @saved_cs_results */ ;
|
||||
/*!50003 SET collation_connection = @saved_col_connection */ ;
|
||||
/*!50003 SET @saved_sql_mode = @@sql_mode */ ;
|
||||
/*!50003 SET sql_mode = 'PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ORACLE,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,NO_AUTO_CREATE_USER,SIMULTANEOUS_ASSIGNMENT' */ ;
|
||||
/*!50003 DROP PACKAGE IF EXISTS `pkg1` */;
|
||||
/*!50003 SET @saved_cs_client = @@character_set_client */ ;
|
||||
/*!50003 SET @saved_cs_results = @@character_set_results */ ;
|
||||
@@ -109,6 +88,27 @@ DELIMITER ;
|
||||
/*!50003 SET collation_connection = @saved_col_connection */ ;
|
||||
/*!50003 SET @saved_sql_mode = @@sql_mode */ ;
|
||||
/*!50003 SET sql_mode = 'PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ORACLE,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,NO_AUTO_CREATE_USER,SIMULTANEOUS_ASSIGNMENT' */ ;
|
||||
/*!50003 DROP PROCEDURE IF EXISTS `p1` */;
|
||||
/*!50003 SET @saved_cs_client = @@character_set_client */ ;
|
||||
/*!50003 SET @saved_cs_results = @@character_set_results */ ;
|
||||
/*!50003 SET @saved_col_connection = @@collation_connection */ ;
|
||||
/*!50003 SET character_set_client = latin1 */ ;
|
||||
/*!50003 SET character_set_results = latin1 */ ;
|
||||
/*!50003 SET collation_connection = latin1_swedish_ci */ ;
|
||||
DELIMITER ;;
|
||||
CREATE DEFINER="root"@"localhost" PROCEDURE "p1"()
|
||||
AS
|
||||
BEGIN
|
||||
SELECT pkg1.f1(); -- a standalone routine calls a package routine
|
||||
END
|
||||
;;
|
||||
DELIMITER ;
|
||||
/*!50003 SET sql_mode = @saved_sql_mode */ ;
|
||||
/*!50003 SET character_set_client = @saved_cs_client */ ;
|
||||
/*!50003 SET character_set_results = @saved_cs_results */ ;
|
||||
/*!50003 SET collation_connection = @saved_col_connection */ ;
|
||||
/*!50003 SET @saved_sql_mode = @@sql_mode */ ;
|
||||
/*!50003 SET sql_mode = 'PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ORACLE,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,NO_AUTO_CREATE_USER,SIMULTANEOUS_ASSIGNMENT' */ ;
|
||||
/*!50003 DROP PACKAGE BODY IF EXISTS `pkg1` */;
|
||||
/*!50003 SET @saved_cs_client = @@character_set_client */ ;
|
||||
/*!50003 SET @saved_cs_results = @@character_set_results */ ;
|
||||
@@ -147,15 +147,6 @@ DELIMITER ;
|
||||
<mysqldump xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<database name="test">
|
||||
<routines>
|
||||
<routine Procedure="p1" sql_mode="PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ORACLE,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,NO_AUTO_CREATE_USER,SIMULTANEOUS_ASSIGNMENT" character_set_client="latin1" collation_connection="latin1_swedish_ci" Database_Collation="utf8mb4_uca1400_ai_ci">
|
||||
<![CDATA[
|
||||
CREATE DEFINER="root"@"localhost" PROCEDURE "p1"()
|
||||
AS
|
||||
BEGIN
|
||||
SELECT pkg1.f1(); -- a standalone routine calls a package routine
|
||||
END
|
||||
]]>
|
||||
</routine>
|
||||
<routine Package="pkg1" sql_mode="PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ORACLE,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,NO_AUTO_CREATE_USER,SIMULTANEOUS_ASSIGNMENT" character_set_client="latin1" collation_connection="latin1_swedish_ci" Database_Collation="utf8mb4_uca1400_ai_ci">
|
||||
<![CDATA[
|
||||
CREATE DEFINER="root"@"localhost" PACKAGE "pkg1" AS
|
||||
@@ -170,6 +161,15 @@ CREATE DEFINER="root"@"localhost" PACKAGE "pkg2" AS
|
||||
PROCEDURE p1;
|
||||
FUNCTION f1 RETURN INT;
|
||||
END
|
||||
]]>
|
||||
</routine>
|
||||
<routine Procedure="p1" sql_mode="PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ORACLE,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,NO_AUTO_CREATE_USER,SIMULTANEOUS_ASSIGNMENT" character_set_client="latin1" collation_connection="latin1_swedish_ci" Database_Collation="utf8mb4_uca1400_ai_ci">
|
||||
<![CDATA[
|
||||
CREATE DEFINER="root"@"localhost" PROCEDURE "p1"()
|
||||
AS
|
||||
BEGIN
|
||||
SELECT pkg1.f1(); -- a standalone routine calls a package routine
|
||||
END
|
||||
]]>
|
||||
</routine>
|
||||
<routine Package_body="pkg1" sql_mode="PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ORACLE,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,NO_AUTO_CREATE_USER,SIMULTANEOUS_ASSIGNMENT" character_set_client="latin1" collation_connection="latin1_swedish_ci" Database_Collation="utf8mb4_uca1400_ai_ci">
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
SET sql_mode=ORACLE;
|
||||
#
|
||||
# MDEV-39587 Package-wide TYPE for variable declarations
|
||||
#
|
||||
#
|
||||
# MDEV-40148 Package spec RECORD-field %TYPE anchor is broken
|
||||
#
|
||||
CREATE TABLE t (id INT, name VARCHAR(100));
|
||||
CREATE PACKAGE pkga AS
|
||||
TYPE r IS RECORD (f t.id%TYPE);
|
||||
END;
|
||||
$$
|
||||
CREATE PROCEDURE pa AS
|
||||
v pkga.r; -- HERE
|
||||
BEGIN
|
||||
v.f := 1;
|
||||
IF v.f = 1
|
||||
THEN SELECT 'ok';
|
||||
END IF;
|
||||
END;
|
||||
$$
|
||||
CALL pa;
|
||||
ok
|
||||
ok
|
||||
DROP PROCEDURE pa;
|
||||
DROP PACKAGE pkga;
|
||||
DROP TABLE t;
|
||||
CREATE TABLE t (id INT, name VARCHAR(100));
|
||||
CREATE PACKAGE pkga AS
|
||||
TYPE r IS RECORD (f t.id%TYPE);
|
||||
END;
|
||||
$$
|
||||
CREATE PROCEDURE pa AS
|
||||
v test.pkga.r; -- HERE
|
||||
BEGIN
|
||||
v.f := 1;
|
||||
IF v.f = 1
|
||||
THEN SELECT 'ok';
|
||||
END IF;
|
||||
END;
|
||||
$$
|
||||
CALL pa;
|
||||
ok
|
||||
ok
|
||||
DROP PROCEDURE pa;
|
||||
DROP PACKAGE pkga;
|
||||
DROP TABLE t;
|
||||
CREATE TABLE t (id INT, name VARCHAR(100));
|
||||
INSERT INTO t VALUES (10,'n10');
|
||||
CREATE PACKAGE pkga AS
|
||||
TYPE rec0_t IS RECORD (id t.id%TYPE, name t.name%TYPE);
|
||||
TYPE cur0_t IS REF CURSOR RETURN pkga.rec0_t; -- HERE
|
||||
END;
|
||||
$$
|
||||
CREATE PROCEDURE pa AS
|
||||
c0 pkga.cur0_t;
|
||||
r0 pkga.rec0_t;
|
||||
BEGIN
|
||||
OPEN c0 FOR SELECT id, name FROM t;
|
||||
FETCH c0 INTO r0;
|
||||
CLOSE c0;
|
||||
SELECT r0.id, r0.name;
|
||||
END;
|
||||
$$
|
||||
CALL pa;
|
||||
r0.id r0.name
|
||||
10 n10
|
||||
DROP PROCEDURE pa;
|
||||
DROP PACKAGE pkga;
|
||||
DROP TABLE t;
|
||||
CREATE TABLE t (id INT, name VARCHAR(100));
|
||||
INSERT INTO t VALUES (10,'n10');
|
||||
CREATE PACKAGE pkga AS
|
||||
TYPE rec0_t IS RECORD (id t.id%TYPE, name t.name%TYPE);
|
||||
TYPE cur0_t IS REF CURSOR RETURN test.pkga.rec0_t; -- HERE
|
||||
END;
|
||||
$$
|
||||
CREATE PROCEDURE pa AS
|
||||
c0 pkga.cur0_t;
|
||||
r0 pkga.rec0_t;
|
||||
BEGIN
|
||||
OPEN c0 FOR SELECT id, name FROM t;
|
||||
FETCH c0 INTO r0;
|
||||
CLOSE c0;
|
||||
SELECT r0.id, r0.name;
|
||||
END;
|
||||
$$
|
||||
CALL pa;
|
||||
r0.id r0.name
|
||||
10 n10
|
||||
DROP PROCEDURE pa;
|
||||
DROP PACKAGE pkga;
|
||||
DROP TABLE t;
|
||||
#
|
||||
# MDEV-40216 Assertion `thd->is_error() || thd->killed' failed in bool do_execute_sp(THD *, sp_head *)
|
||||
#
|
||||
CREATE TABLE tb (c_int INT);
|
||||
CREATE PACKAGE pk AS
|
||||
TYPE rec IS RECORD (f tb.c_int%TYPE);
|
||||
TYPE aa IS TABLE OF INT INDEX BY INTEGER;
|
||||
END;
|
||||
$$
|
||||
CREATE PROCEDURE p AS
|
||||
r pk.rec;
|
||||
v pk.aa;
|
||||
BEGIN
|
||||
r.f := 5;
|
||||
v(r.f) := 99;
|
||||
SELECT v(5);
|
||||
END;
|
||||
$$
|
||||
CALL p;
|
||||
v(5)
|
||||
99
|
||||
DROP PROCEDURE p;
|
||||
DROP PACKAGE pk;
|
||||
DROP TABLE tb;
|
||||
@@ -0,0 +1,632 @@
|
||||
SET sql_mode=ORACLE;
|
||||
#
|
||||
# MDEV-39587 Package-wide TYPE for variable declarations
|
||||
#
|
||||
# A too long identifier chain in the TABLE OF type
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE assoc0_t IS TABLE OF cat1.db1.pkg1.rec1_t INDEX BY INTEGER;
|
||||
END;
|
||||
$$
|
||||
ERROR HY000: Unknown data type: '`cat1`.`db1`.`pkg1`'
|
||||
# Assoc array cannot have attributes
|
||||
# Currently this is not allowed by the parser in qualified types
|
||||
# If we ever allow, make sure to call check_data_type_attributes()
|
||||
# which will raise ER_UNSUPPORTED_DATA_TYPE_ATTRIBUTE
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE rec0_t IS RECORD (a INT, b VARCHAR(32));
|
||||
TYPE assoc0_t IS TABLE OF rec0_t INDEX BY INTEGER;
|
||||
END;
|
||||
$$
|
||||
CREATE PROCEDURE p1 AS
|
||||
r0 pkg1.assoc0_t (0); -- Length attribute
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '(0); -- Length attribute
|
||||
BEGIN
|
||||
NULL;
|
||||
END' at line 2
|
||||
CREATE PROCEDURE p1 AS
|
||||
r0 pkg1.assoc0_t (0,0); -- Length and dec attributes
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '(0,0); -- Length and dec attributes
|
||||
BEGIN
|
||||
NULL;
|
||||
END' at line 2
|
||||
CREATE PROCEDURE p1 AS
|
||||
r0 pkg1.assoc0_t CHARACTER SET latin1;
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'CHARACTER SET latin1;
|
||||
BEGIN
|
||||
NULL;
|
||||
END' at line 2
|
||||
CREATE PROCEDURE p1 AS
|
||||
r0 pkg1.assoc0_t COLLATE latin1_bin;
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'COLLATE latin1_bin;
|
||||
BEGIN
|
||||
NULL;
|
||||
END' at line 2
|
||||
DROP PACKAGE pkg1;
|
||||
# PACKAGE spec types cannot be used in schema routine parameters
|
||||
# and schema function RETURN
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE rec0_t IS RECORD (a INT, b VARCHAR(10));
|
||||
TYPE assoc0_t IS TABLE OF rec0_t INDEX BY INTEGER;
|
||||
END;
|
||||
$$
|
||||
CREATE PROCEDURE p1(a pkg1.assoc0_t) AS
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
ERROR HY000: Incorrect usage of parameter_declaration and package_name.type_name
|
||||
CREATE FUNCTION f1 RETURN pkg1.assoc0_t AS
|
||||
BEGIN
|
||||
RETURN NULL;
|
||||
END;
|
||||
$$
|
||||
ERROR HY000: Incorrect usage of RETURN and package_name.type_name
|
||||
DROP PACKAGE pkg1;
|
||||
# A package routine parameter and a package function RETURN
|
||||
# 2-step
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE rec0_t IS RECORD (a INT, b VARCHAR(10));
|
||||
TYPE assoc0_t IS TABLE OF rec0_t INDEX BY INTEGER;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE pkg2 AS
|
||||
PROCEDURE p1;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg2 AS
|
||||
PROCEDURE p2(a pkg1.assoc0_t) AS
|
||||
BEGIN
|
||||
SELECT a(0).a, a(0).b;
|
||||
END;
|
||||
FUNCTION f1 RETURN pkg1.assoc0_t AS
|
||||
res pkg1.assoc0_t;
|
||||
BEGIN
|
||||
res(0).a:= 10;
|
||||
res(0).b:= 'b';
|
||||
RETURN res;
|
||||
END;
|
||||
PROCEDURE p1 AS
|
||||
BEGIN
|
||||
CALL p2(f1());
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
ERROR HY000: Illegal parameter data type associative_array for operation '<routine parameter>'
|
||||
DROP PACKAGE pkg2;
|
||||
DROP PACKAGE pkg1;
|
||||
# RECORD as a package routine parameter and a package function RETURN
|
||||
# 3-step
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE rec0_t IS RECORD (a INT, b VARCHAR(10));
|
||||
TYPE assoc0_t IS TABLE OF rec0_t INDEX BY INTEGER;
|
||||
END;
|
||||
$$
|
||||
CREATE DATABASE test1;
|
||||
USE test1;
|
||||
CREATE PACKAGE pkg2 AS
|
||||
PROCEDURE p1;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg2 AS
|
||||
PROCEDURE p2(a test.pkg1.assoc0_t) AS
|
||||
BEGIN
|
||||
SELECT a(0).a, a(0).b;
|
||||
END;
|
||||
FUNCTION f1 RETURN test.pkg1.assoc0_t AS
|
||||
res test.pkg1.assoc0_t;
|
||||
BEGIN
|
||||
res(0).a:= 10;
|
||||
res(0).b:= 'b';
|
||||
RETURN res;
|
||||
END;
|
||||
PROCEDURE p1 AS
|
||||
BEGIN
|
||||
CALL p2(f1());
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
ERROR HY000: Illegal parameter data type associative_array for operation '<routine parameter>'
|
||||
DROP PACKAGE pkg2;
|
||||
DROP DATABASE test1;
|
||||
USE test;
|
||||
DROP PACKAGE pkg1;
|
||||
# A self-reference to the current spec with error: 2-step
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE assoc0_t IS TABLE OF pkg1.rec0_t INDEX BY INTEGER;
|
||||
END;
|
||||
$$
|
||||
ERROR HY000: Unknown data type: '`pkg1`.`rec0_t`'
|
||||
CREATE DATABASE test1;
|
||||
CREATE PACKAGE test1.pkg1 AS
|
||||
TYPE assoc0_t IS TABLE OF pkg1.rec0_t INDEX BY INTEGER;
|
||||
END;
|
||||
$$
|
||||
ERROR HY000: Unknown data type: '`pkg1`.`rec0_t`'
|
||||
DROP DATABASE test1;
|
||||
# A self-reference to the current spec with success: 2-step
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE rec0_t IS RECORD (a INT, b VARCHAR(32));
|
||||
TYPE assoc0_t IS TABLE OF pkg1.rec0_t INDEX BY INTEGER;
|
||||
END;
|
||||
$$
|
||||
CREATE PROCEDURE p1 AS
|
||||
r0 pkg1.rec0_t;
|
||||
a0 pkg1.assoc0_t;
|
||||
BEGIN
|
||||
r0.a:= 10;
|
||||
r0.b:= 'b';
|
||||
SELECT r0.a, r0.b;
|
||||
END;
|
||||
$$
|
||||
CALL p1;
|
||||
r0.a r0.b
|
||||
10 b
|
||||
DROP PROCEDURE p1;
|
||||
DROP PACKAGE pkg1;
|
||||
CREATE DATABASE test1;
|
||||
CREATE PACKAGE test1.pkg1 AS
|
||||
TYPE rec0_t IS RECORD (a INT, b VARCHAR(32));
|
||||
TYPE assoc0_t IS TABLE OF pkg1.rec0_t INDEX BY INTEGER;
|
||||
END;
|
||||
$$
|
||||
CREATE PROCEDURE test1.p1 AS
|
||||
r0 pkg1.rec0_t; -- This refers to test1.pkg1.rec0_t
|
||||
a0 pkg1.assoc0_t; -- This refers to test1.pkg1.assoc0_t
|
||||
BEGIN
|
||||
r0.a:= 10;
|
||||
r0.b:= 'b';
|
||||
SELECT r0.a, r0.b;
|
||||
END;
|
||||
$$
|
||||
CALL test1.p1;
|
||||
r0.a r0.b
|
||||
10 b
|
||||
DROP PROCEDURE test1.p1;
|
||||
DROP PACKAGE test1.pkg1;
|
||||
DROP DATABASE test1;
|
||||
USE test;
|
||||
# A self-reference to the current spec with error: 3-step
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE assoc0_t IS TABLE OF test.pkg1.rec0_t INDEX BY INTEGER;
|
||||
END;
|
||||
$$
|
||||
ERROR HY000: Unknown data type: '`test`.`pkg1`.`rec0_t`'
|
||||
CREATE DATABASE test1;
|
||||
CREATE PACKAGE test1.pkg1 AS
|
||||
TYPE assoc0_t IS TABLE OF test1.pkg1.rec0_t INDEX BY INTEGER;
|
||||
END;
|
||||
$$
|
||||
ERROR HY000: Unknown data type: '`test1`.`pkg1`.`rec0_t`'
|
||||
DROP DATABASE test1;
|
||||
# A self-reference to the current spec with success: 3-step
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE rec0_t IS RECORD (a INT, b VARCHAR(32));
|
||||
TYPE assoc0_t IS TABLE OF test.pkg1.rec0_t INDEX BY INTEGER;
|
||||
END;
|
||||
$$
|
||||
CREATE PROCEDURE p1 AS
|
||||
r0 pkg1.rec0_t;
|
||||
a0 pkg1.assoc0_t;
|
||||
BEGIN
|
||||
r0.a:= 10;
|
||||
r0.b:= 'b';
|
||||
SELECT r0.a, r0.b;
|
||||
END;
|
||||
$$
|
||||
CALL p1;
|
||||
r0.a r0.b
|
||||
10 b
|
||||
DROP PROCEDURE p1;
|
||||
DROP PACKAGE pkg1;
|
||||
CREATE DATABASE test1;
|
||||
CREATE PACKAGE test1.pkg1 AS
|
||||
TYPE rec0_t IS RECORD (a INT, b VARCHAR(32));
|
||||
TYPE assoc0_t IS TABLE OF test1.pkg1.rec0_t INDEX BY INTEGER;
|
||||
END;
|
||||
$$
|
||||
CREATE PROCEDURE test1.p1 AS
|
||||
r0 pkg1.rec0_t; -- This refers to test1.pkg1.rec0_t
|
||||
a0 pkg1.assoc0_t; -- This refers to test1.pkg1.assoc0_t
|
||||
BEGIN
|
||||
r0.a:= 10;
|
||||
r0.b:= 'b';
|
||||
SELECT r0.a, r0.b;
|
||||
END;
|
||||
$$
|
||||
CALL test1.p1;
|
||||
r0.a r0.b
|
||||
10 b
|
||||
DROP PROCEDURE test1.p1;
|
||||
DROP PACKAGE test1.pkg1;
|
||||
DROP DATABASE test1;
|
||||
# Various working examples
|
||||
CREATE TABLE t1 (a INT, b VARCHAR(30));
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE varchar_array IS TABLE OF VARCHAR(2000) INDEX BY INTEGER;
|
||||
TYPE rec0_t IS RECORD(a INT, b VARCHAR(30));
|
||||
TYPE array0_t IS TABLE OF rec0_t INDEX BY INTEGER;
|
||||
TYPE array1_t IS TABLE OF test.t1.a%TYPE INDEX BY INTEGER;
|
||||
TYPE array2_t IS TABLE OF test.t1%ROWTYPE INDEX BY INTEGER;
|
||||
END;
|
||||
$$
|
||||
# 2-Step + PROCEDURE
|
||||
CREATE PROCEDURE p1 AS
|
||||
v0 pkg1.varchar_array;
|
||||
v1 pkg1.rec0_t;
|
||||
v2 pkg1.array0_t;
|
||||
v3 pkg1.array1_t;
|
||||
v4 pkg1.array2_t;
|
||||
BEGIN
|
||||
v0(0):='test';
|
||||
SELECT v0(0);
|
||||
v1.a:= 1;
|
||||
v1.b:= 'b';
|
||||
SELECT v1.a, v1.b;
|
||||
v2(0):= v1;
|
||||
SELECT v2(0).a, v2(0).b;
|
||||
v3(0):= 10;
|
||||
SELECT v3(0);
|
||||
v4(0):= v1;
|
||||
SELECT v4(0).a, v4(0).b;
|
||||
END;
|
||||
$$
|
||||
CALL p1;
|
||||
v0(0)
|
||||
test
|
||||
v1.a v1.b
|
||||
1 b
|
||||
v2(0).a v2(0).b
|
||||
1 b
|
||||
v3(0)
|
||||
10
|
||||
v4(0).a v4(0).b
|
||||
1 b
|
||||
DROP PROCEDURE p1;
|
||||
# 3-Step + PROCEDURE
|
||||
CREATE DATABASE test1;
|
||||
USE test1;
|
||||
CREATE PROCEDURE p1 AS
|
||||
v0 test.pkg1.varchar_array;
|
||||
v1 test.pkg1.rec0_t;
|
||||
v2 test.pkg1.array0_t;
|
||||
v3 test.pkg1.array1_t;
|
||||
v4 test.pkg1.array2_t;
|
||||
BEGIN
|
||||
v0(0):='test';
|
||||
SELECT v0(0);
|
||||
v1.a:= 1;
|
||||
v1.b:= 'b';
|
||||
SELECT v1.a, v1.b;
|
||||
v2(0):= v1;
|
||||
SELECT v2(0).a, v2(0).b;
|
||||
v3(0):= 10;
|
||||
SELECT v3(0);
|
||||
v4(0):= v1;
|
||||
SELECT v4(0).a, v4(0).b;
|
||||
END;
|
||||
$$
|
||||
CALL p1;
|
||||
v0(0)
|
||||
test
|
||||
v1.a v1.b
|
||||
1 b
|
||||
v2(0).a v2(0).b
|
||||
1 b
|
||||
v3(0)
|
||||
10
|
||||
v4(0).a v4(0).b
|
||||
1 b
|
||||
DROP PROCEDURE p1;
|
||||
DROP DATABASE test1;
|
||||
USE test;
|
||||
# 2-Step + PACKAGE + Declarations in package PROCEDURE
|
||||
CREATE PACKAGE pkg2 AS
|
||||
PROCEDURE p1;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg2 AS
|
||||
PROCEDURE p1 AS
|
||||
v0 pkg1.varchar_array;
|
||||
v1 pkg1.rec0_t;
|
||||
v2 pkg1.array0_t;
|
||||
v3 pkg1.array1_t;
|
||||
v4 pkg1.array2_t;
|
||||
BEGIN
|
||||
v0(0):='test';
|
||||
SELECT v0(0);
|
||||
v1.a:= 1;
|
||||
v1.b:= 'b';
|
||||
SELECT v1.a, v1.b;
|
||||
v2(0):= v1;
|
||||
SELECT v2(0).a, v2(0).b;
|
||||
v3(0):= 10;
|
||||
SELECT v3(0);
|
||||
v4(0):= v1;
|
||||
SELECT v4(0).a, v4(0).b;
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
CALL pkg2.p1;
|
||||
v0(0)
|
||||
test
|
||||
v1.a v1.b
|
||||
1 b
|
||||
v2(0).a v2(0).b
|
||||
1 b
|
||||
v3(0)
|
||||
10
|
||||
v4(0).a v4(0).b
|
||||
1 b
|
||||
DROP PACKAGE pkg2;
|
||||
# 3-Step + PACKAGE + Declarations in package PROCEDURE
|
||||
CREATE DATABASE test1;
|
||||
USE test1;
|
||||
CREATE PACKAGE pkg2 AS
|
||||
PROCEDURE p1;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg2 AS
|
||||
PROCEDURE p1 AS
|
||||
v0 test.pkg1.varchar_array;
|
||||
v1 test.pkg1.rec0_t;
|
||||
v2 test.pkg1.array0_t;
|
||||
v3 test.pkg1.array1_t;
|
||||
v4 test.pkg1.array2_t;
|
||||
BEGIN
|
||||
v0(0):='test';
|
||||
SELECT v0(0);
|
||||
v1.a:= 1;
|
||||
v1.b:= 'b';
|
||||
SELECT v1.a, v1.b;
|
||||
v2(0):= v1;
|
||||
SELECT v2(0).a, v2(0).b;
|
||||
v3(0):= 10;
|
||||
SELECT v3(0);
|
||||
v4(0):= v1;
|
||||
SELECT v4(0).a, v4(0).b;
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
CALL pkg2.p1;
|
||||
v0(0)
|
||||
test
|
||||
v1.a v1.b
|
||||
1 b
|
||||
v2(0).a v2(0).b
|
||||
1 b
|
||||
v3(0)
|
||||
10
|
||||
v4(0).a v4(0).b
|
||||
1 b
|
||||
DROP PACKAGE pkg2;
|
||||
DROP DATABASE test1;
|
||||
USE test;
|
||||
# 3-Step + PACKAGE + Declarations in PACKAGE BODY
|
||||
CREATE DATABASE test1;
|
||||
USE test1;
|
||||
CREATE PACKAGE pkg2 AS
|
||||
PROCEDURE p1;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg2 AS
|
||||
v0 test.pkg1.varchar_array;
|
||||
v1 test.pkg1.rec0_t;
|
||||
v2 test.pkg1.array0_t;
|
||||
v3 test.pkg1.array1_t;
|
||||
v4 test.pkg1.array2_t;
|
||||
PROCEDURE p1 AS
|
||||
BEGIN
|
||||
v0(0):='test';
|
||||
SELECT v0(0);
|
||||
v1.a:= 1;
|
||||
v1.b:= 'b';
|
||||
SELECT v1.a, v1.b;
|
||||
v2(0):= v1;
|
||||
SELECT v2(0).a, v2(0).b;
|
||||
v3(0):= 10;
|
||||
SELECT v3(0);
|
||||
v4(0):= v1;
|
||||
SELECT v4(0).a, v4(0).b;
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
CALL pkg2.p1;
|
||||
v0(0)
|
||||
test
|
||||
v1.a v1.b
|
||||
1 b
|
||||
v2(0).a v2(0).b
|
||||
1 b
|
||||
v3(0)
|
||||
10
|
||||
v4(0).a v4(0).b
|
||||
1 b
|
||||
DROP PACKAGE pkg2;
|
||||
DROP DATABASE test1;
|
||||
USE test;
|
||||
DROP PACKAGE pkg1;
|
||||
DROP TABLE t1;
|
||||
# RECORD + Assoc array in different packages: 2-step
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE rec0_t IS RECORD(a INT, b VARCHAR(30));
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE pkg2 AS
|
||||
TYPE array0_t IS TABLE OF pkg1.rec0_t INDEX BY INTEGER;
|
||||
END;
|
||||
$$
|
||||
CREATE PROCEDURE p1 AS
|
||||
r0 pkg1.rec0_t;
|
||||
a0 pkg2.array0_t;
|
||||
BEGIN
|
||||
r0.a:= 10;
|
||||
r0.b:= 'b';
|
||||
a0(0):= r0;
|
||||
SELECT a0(0).a, a0(0).b;
|
||||
END;
|
||||
$$
|
||||
CALL p1;
|
||||
a0(0).a a0(0).b
|
||||
10 b
|
||||
DROP PROCEDURE p1;
|
||||
DROP PACKAGE pkg2;
|
||||
DROP PACKAGE pkg1;
|
||||
# RECORD + Assoc array in different packages: 3-step
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE rec0_t IS RECORD(a INT, b VARCHAR(30));
|
||||
END;
|
||||
$$
|
||||
CREATE DATABASE test1;
|
||||
USE test1;
|
||||
CREATE PACKAGE pkg2 AS
|
||||
TYPE array0_t IS TABLE OF test.pkg1.rec0_t INDEX BY INTEGER;
|
||||
END;
|
||||
$$
|
||||
CREATE DATABASE test2;
|
||||
USE test2;
|
||||
CREATE PROCEDURE p1 AS
|
||||
r0 test.pkg1.rec0_t;
|
||||
a0 test1.pkg2.array0_t;
|
||||
BEGIN
|
||||
r0.a:= 10;
|
||||
r0.b:= 'b';
|
||||
a0(0):= r0;
|
||||
SELECT a0(0).a, a0(0).b;
|
||||
END;
|
||||
$$
|
||||
CALL p1;
|
||||
a0(0).a a0(0).b
|
||||
10 b
|
||||
DROP PROCEDURE p1;
|
||||
DROP DATABASE test2;
|
||||
USE test1;
|
||||
DROP PACKAGE pkg2;
|
||||
DROP DATABASE test1;
|
||||
USE test;
|
||||
DROP PACKAGE pkg1;
|
||||
#
|
||||
# MDEV-40640 Assertion `li->sphead' failed in bool LEX::sp_package_spec_check_cyclic_dependency(THD *, const Lex_ident_sys_st &, const Lex_ident_sys_st &) const
|
||||
#
|
||||
CREATE PACKAGE p1 AS
|
||||
TYPE rec0_t IS RECORD(x INT);
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE p2 AS
|
||||
TYPE rec0_t IS RECORD(x INT);
|
||||
TYPE assoc0_t IS TABLE OF p1.rec0_t INDEX BY INTEGER;
|
||||
END;
|
||||
$$
|
||||
SHOW CREATE PACKAGE p2;
|
||||
Package sql_mode Create Package character_set_client collation_connection Database Collation
|
||||
p2 PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ORACLE,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,NO_AUTO_CREATE_USER,SIMULTANEOUS_ASSIGNMENT CREATE DEFINER="root"@"localhost" PACKAGE "p2" AS
|
||||
TYPE rec0_t IS RECORD(x INT);
|
||||
TYPE assoc0_t IS TABLE OF p1.rec0_t INDEX BY INTEGER;
|
||||
END latin1 latin1_swedish_ci utf8mb4_uca1400_ai_ci
|
||||
DROP PACKAGE p2;
|
||||
DROP PACKAGE p1;
|
||||
# Replacing the dependency package and removing the type
|
||||
CREATE PACKAGE p1 AS
|
||||
TYPE rec0_t IS RECORD(x INT);
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE p2 AS
|
||||
TYPE rec0_t IS RECORD(x INT);
|
||||
TYPE assoc0_t IS TABLE OF p1.rec0_t INDEX BY INTEGER;
|
||||
END;
|
||||
$$
|
||||
CREATE OR REPLACE PACKAGE p1 AS
|
||||
TYPE rec1_t IS RECORD(x INT); -- There is no type p1.rec0_t any more
|
||||
END;
|
||||
$$
|
||||
SHOW CREATE PACKAGE p2;
|
||||
ERROR HY000: Unknown data type: '`test`.`p1`.`rec0_t`'
|
||||
DROP PACKAGE p2;
|
||||
DROP PACKAGE p1;
|
||||
# Dropping the dependency package
|
||||
CREATE PACKAGE p1 AS
|
||||
TYPE rec0_t IS RECORD(x INT);
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE p2 AS
|
||||
TYPE rec0_t IS RECORD(x INT);
|
||||
TYPE assoc0_t IS TABLE OF p1.rec0_t INDEX BY INTEGER;
|
||||
END;
|
||||
$$
|
||||
DROP PACKAGE p1;
|
||||
SHOW CREATE PACKAGE p2;
|
||||
ERROR HY000: Unknown data type: '`p1`.`rec0_t`'
|
||||
DROP PACKAGE p2;
|
||||
#
|
||||
# MDEV-40666 Cyclic package TYPE dependency built with associative array shows ERROR 1436 (HY000): Thread stack overrun
|
||||
#
|
||||
CREATE PACKAGE fa AS TYPE r IS RECORD(x INT); END;
|
||||
$$
|
||||
CREATE PACKAGE fb AS TYPE r2 IS RECORD(y INT); TYPE arr IS TABLE OF fa.r INDEX BY INTEGER; END;
|
||||
$$
|
||||
CREATE OR REPLACE PACKAGE fa AS TYPE r IS RECORD(x INT); TYPE arr2 IS TABLE OF fb.r2 INDEX BY INTEGER; END;
|
||||
$$
|
||||
ERROR HY000: Unknown data type: '`fb`.`r2`'
|
||||
SHOW CREATE PACKAGE fa;
|
||||
Package sql_mode Create Package character_set_client collation_connection Database Collation
|
||||
fa PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ORACLE,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,NO_AUTO_CREATE_USER,SIMULTANEOUS_ASSIGNMENT CREATE DEFINER="root"@"localhost" PACKAGE "fa" AS TYPE r IS RECORD(x INT); END latin1 latin1_swedish_ci utf8mb4_uca1400_ai_ci
|
||||
SHOW CREATE PACKAGE fb;
|
||||
Package sql_mode Create Package character_set_client collation_connection Database Collation
|
||||
fb PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ORACLE,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,NO_AUTO_CREATE_USER,SIMULTANEOUS_ASSIGNMENT CREATE DEFINER="root"@"localhost" PACKAGE "fb" AS TYPE r2 IS RECORD(y INT); TYPE arr IS TABLE OF fa.r INDEX BY INTEGER; END latin1 latin1_swedish_ci utf8mb4_uca1400_ai_ci
|
||||
DROP PACKAGE fb;
|
||||
DROP PACKAGE fa;
|
||||
CREATE PACKAGE fa AS TYPE r IS RECORD(x INT); END;
|
||||
$$
|
||||
CREATE PACKAGE fb AS TYPE r2 IS RECORD(y INT); TYPE arr IS TABLE OF test.fa.r INDEX BY INTEGER; END;
|
||||
$$
|
||||
CREATE OR REPLACE PACKAGE fa AS TYPE r IS RECORD(x INT); TYPE arr2 IS TABLE OF test.fb.r2 INDEX BY INTEGER; END;
|
||||
$$
|
||||
ERROR HY000: Unknown data type: '`test`.`fb`.`r2`'
|
||||
SHOW CREATE PACKAGE fa;
|
||||
Package sql_mode Create Package character_set_client collation_connection Database Collation
|
||||
fa PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ORACLE,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,NO_AUTO_CREATE_USER,SIMULTANEOUS_ASSIGNMENT CREATE DEFINER="root"@"localhost" PACKAGE "fa" AS TYPE r IS RECORD(x INT); END latin1 latin1_swedish_ci utf8mb4_uca1400_ai_ci
|
||||
SHOW CREATE PACKAGE fb;
|
||||
Package sql_mode Create Package character_set_client collation_connection Database Collation
|
||||
fb PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ORACLE,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,NO_AUTO_CREATE_USER,SIMULTANEOUS_ASSIGNMENT CREATE DEFINER="root"@"localhost" PACKAGE "fb" AS TYPE r2 IS RECORD(y INT); TYPE arr IS TABLE OF test.fa.r INDEX BY INTEGER; END latin1 latin1_swedish_ci utf8mb4_uca1400_ai_ci
|
||||
DROP PACKAGE fb;
|
||||
DROP PACKAGE fa;
|
||||
#
|
||||
# MDEV-40685 Cyclic package TYPE dependency built with stored routine shows ERROR 1436 (HY000): Thread stack overrun
|
||||
#
|
||||
CREATE PACKAGE fa AS
|
||||
TYPE r IS RECORD(x INT);
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE fb AS
|
||||
TYPE r2 IS RECORD(y INT);
|
||||
TYPE arr IS TABLE OF fa.r INDEX BY INTEGER;
|
||||
END;
|
||||
$$
|
||||
CREATE OR REPLACE PACKAGE fa AS
|
||||
TYPE r IS RECORD(x INT);
|
||||
TYPE arr2 IS TABLE OF fb.r2 INDEX BY INTEGER;
|
||||
END;
|
||||
$$
|
||||
ERROR HY000: Unknown data type: '`fb`.`r2`'
|
||||
SHOW CREATE PACKAGE fa;
|
||||
Package sql_mode Create Package character_set_client collation_connection Database Collation
|
||||
fa PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ORACLE,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,NO_AUTO_CREATE_USER,SIMULTANEOUS_ASSIGNMENT CREATE DEFINER="root"@"localhost" PACKAGE "fa" AS
|
||||
TYPE r IS RECORD(x INT);
|
||||
END latin1 latin1_swedish_ci utf8mb4_uca1400_ai_ci
|
||||
DROP PACKAGE fa;
|
||||
DROP PACKAGE fb;
|
||||
@@ -0,0 +1,31 @@
|
||||
SET sql_mode=ORACLE;
|
||||
#
|
||||
# MDEV-39587 Package-wide TYPE for variable declarations
|
||||
# MDEV-40114 Package-wide TYPE variable declarations fail during mariadb-dump restore
|
||||
#
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE rec0_t IS RECORD (a INT, b VARCHAR(30));
|
||||
END;
|
||||
$$
|
||||
CREATE PROCEDURE p1 AS
|
||||
r pkg1.rec0_t;
|
||||
BEGIN
|
||||
r.a:=1;
|
||||
SELECT r.a;
|
||||
END;
|
||||
$$
|
||||
DROP DATABASE test;
|
||||
CREATE DATABASE test;
|
||||
USE test;
|
||||
CALL p1;
|
||||
r.a
|
||||
1
|
||||
SELECT routine_type, routine_name
|
||||
FROM information_schema.routines
|
||||
WHERE routine_schema='test'
|
||||
ORDER BY routine_type, routine_name;
|
||||
routine_type routine_name
|
||||
PACKAGE pkg1
|
||||
PROCEDURE p1
|
||||
DROP PROCEDURE p1;
|
||||
DROP PACKAGE pkg1;
|
||||
@@ -0,0 +1,20 @@
|
||||
SET sql_mode=ORACLE;
|
||||
#
|
||||
# MDEV-39587 Package-wide TYPE for variable declarations
|
||||
#
|
||||
#
|
||||
# MDEV-40686 Event using a package-defined type is silently lost during mariadb-dump / restore
|
||||
#
|
||||
CREATE PACKAGE pkg AS
|
||||
TYPE rec IS RECORD (a INT);
|
||||
END;
|
||||
$$
|
||||
CREATE EVENT ev ON SCHEDULE EVERY 1 HOUR DO
|
||||
DECLARE
|
||||
v pkg.rec;
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
ERROR HY000: Incorrect usage of EVENT and `pkg`.`rec`
|
||||
DROP PACKAGE pkg;
|
||||
@@ -0,0 +1,610 @@
|
||||
#
|
||||
# MDEV-39587 Package-wide TYPE for variable declarations
|
||||
#
|
||||
SET sql_mode=ORACLE;
|
||||
CREATE DATABASE test1;
|
||||
CREATE DATABASE test2;
|
||||
CREATE USER user1@localhost;
|
||||
CREATE USER user2@localhost;
|
||||
GRANT CREATE ROUTINE ON test1.* TO user1@localhost;
|
||||
GRANT CREATE ROUTINE ON test2.* TO user1@localhost;
|
||||
GRANT CREATE ROUTINE ON test1.* TO user2@localhost;
|
||||
GRANT CREATE ROUTINE ON test2.* TO user2@localhost;
|
||||
connect conn_user1, localhost, user1,, test1;
|
||||
SET sql_mode=ORACLE;
|
||||
connect conn_user2, localhost, user2,, test1;
|
||||
SET sql_mode=ORACLE;
|
||||
connection conn_user1;
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE rec0_t IS RECORD (a INT, b VARCHAR(10));
|
||||
TYPE cur0_t IS REF CURSOR RETURN rec0_t;
|
||||
END;
|
||||
$$
|
||||
connection conn_user1;
|
||||
# Start of allowed.inc
|
||||
SELECT CURRENT_USER;
|
||||
CURRENT_USER
|
||||
user1@localhost
|
||||
#
|
||||
# ACL_NONE + same user + same DB
|
||||
#
|
||||
USE test1;
|
||||
# ACL_NONE + same user + same DB + PACKAGE type in the same PACKAGE BODY
|
||||
CREATE PACKAGE BODY pkg1 AS
|
||||
r0 pkg1.rec0_t;
|
||||
END;
|
||||
$$
|
||||
DROP PACKAGE BODY pkg1;
|
||||
CREATE PACKAGE BODY pkg1 AS
|
||||
r0 test1.pkg1.rec0_t;
|
||||
END;
|
||||
$$
|
||||
DROP PACKAGE BODY pkg1;
|
||||
# ACL_NONE + same user + same DB + PACKAGE type in another PACKAGE
|
||||
CREATE PACKAGE pkg2 AS
|
||||
TYPE cur1_t IS REF CURSOR RETURN pkg1.rec0_t;
|
||||
END;
|
||||
$$
|
||||
DROP PACKAGE pkg2;
|
||||
CREATE PACKAGE pkg2 AS
|
||||
TYPE cur1_t IS REF CURSOR RETURN test1.pkg1.rec0_t;
|
||||
END;
|
||||
$$
|
||||
DROP PACKAGE pkg2;
|
||||
# ACL_NONE + same user + same DB + PACKAGE type in another PACKAGE BODY
|
||||
CREATE PACKAGE pkg2 AS
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg2 AS
|
||||
TYPE cur1_t IS REF CURSOR RETURN pkg1.rec0_t;
|
||||
END;
|
||||
$$
|
||||
DROP PACKAGE pkg2;
|
||||
CREATE PACKAGE pkg2 AS
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg2 AS
|
||||
TYPE cur1_t IS REF CURSOR RETURN test1.pkg1.rec0_t;
|
||||
END;
|
||||
$$
|
||||
DROP PACKAGE pkg2;
|
||||
# ACL_NONE + same user + same DB + PACKAGE type in a schema routine
|
||||
CREATE PROCEDURE p1 AS
|
||||
TYPE cur1_t IS REF CURSOR RETURN pkg1.rec0_t;
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
DROP PROCEDURE p1;
|
||||
CREATE PROCEDURE p1 AS
|
||||
TYPE cur1_t IS REF CURSOR RETURN test1.pkg1.rec0_t;
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
DROP PROCEDURE p1;
|
||||
#
|
||||
# ACL_NONE + same user + different DB
|
||||
#
|
||||
USE test2;
|
||||
# ACL_NONE + same user + different DB + PACKAGE type in another PACKAGE
|
||||
CREATE PACKAGE pkg2 AS
|
||||
TYPE cur1_t IS REF CURSOR RETURN test1.pkg1.rec0_t;
|
||||
END;
|
||||
$$
|
||||
DROP PACKAGE pkg2;
|
||||
# ACL_NONE + same user + different DB + PACKAGE type in another PACKAGE BODY
|
||||
CREATE PACKAGE pkg2 AS
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg2 AS
|
||||
TYPE cur1_t IS REF CURSOR RETURN test1.pkg1.rec0_t;
|
||||
END;
|
||||
$$
|
||||
DROP PACKAGE pkg2;
|
||||
# ACL_NONE + same user + different DB + PACKAGE type in a schema routine
|
||||
CREATE PROCEDURE p1 AS
|
||||
TYPE cur1_t IS REF CURSOR RETURN test1.pkg1.rec0_t;
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
DROP PROCEDURE p1;
|
||||
# End of allowed.inc
|
||||
connection conn_user2;
|
||||
# Start of denied.inc
|
||||
SELECT CURRENT_USER;
|
||||
CURRENT_USER
|
||||
user2@localhost
|
||||
#
|
||||
# ACL_NONE + different user + same DB
|
||||
#
|
||||
connection conn_user2;
|
||||
USE test1;
|
||||
# ACL_NONE + different user + same DB + PACKAGE type in the same PACKAGE BODY
|
||||
CREATE PACKAGE BODY pkg1 AS
|
||||
r0 pkg1.rec0_t;
|
||||
END;
|
||||
$$
|
||||
ERROR 42000: execute command denied to user 'user2'@'localhost' for routine 'test1.pkg1'
|
||||
CREATE PACKAGE BODY pkg1 AS
|
||||
r0 test1.pkg1.rec0_t;
|
||||
END;
|
||||
$$
|
||||
ERROR 42000: execute command denied to user 'user2'@'localhost' for routine 'test1.pkg1'
|
||||
# ACL_NONE + different user + same DB + PACKAGE type in another PACKAGE
|
||||
CREATE PACKAGE pkg2 AS
|
||||
TYPE cur1_t IS REF CURSOR RETURN pkg1.rec0_t;
|
||||
END;
|
||||
$$
|
||||
ERROR 42000: execute command denied to user 'user2'@'localhost' for routine 'test1.pkg1'
|
||||
CREATE PACKAGE pkg2 AS
|
||||
TYPE cur1_t IS REF CURSOR RETURN test1.pkg1.rec0_t;
|
||||
END;
|
||||
$$
|
||||
ERROR 42000: execute command denied to user 'user2'@'localhost' for routine 'test1.pkg1'
|
||||
# ACL_NONE + different user + same DB + PACKAGE type in another PACKAGE BODY
|
||||
CREATE PACKAGE pkg2 AS
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg2 AS
|
||||
TYPE cur1_t IS REF CURSOR RETURN pkg1.rec0_t;
|
||||
END;
|
||||
$$
|
||||
ERROR 42000: execute command denied to user 'user2'@'localhost' for routine 'test1.pkg1'
|
||||
DROP PACKAGE pkg2;
|
||||
CREATE PACKAGE pkg2 AS
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg2 AS
|
||||
TYPE cur1_t IS REF CURSOR RETURN test1.pkg1.rec0_t;
|
||||
END;
|
||||
$$
|
||||
ERROR 42000: execute command denied to user 'user2'@'localhost' for routine 'test1.pkg1'
|
||||
DROP PACKAGE pkg2;
|
||||
# ACL_NONE + different user + same DB + PACKAGE type in a schema routine
|
||||
CREATE PROCEDURE p1 AS
|
||||
TYPE cur1_t IS REF CURSOR RETURN pkg1.rec0_t;
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
ERROR 42000: execute command denied to user 'user2'@'localhost' for routine 'test1.pkg1'
|
||||
CREATE PROCEDURE p1 AS
|
||||
TYPE cur1_t IS REF CURSOR RETURN test1.pkg1.rec0_t;
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
ERROR 42000: execute command denied to user 'user2'@'localhost' for routine 'test1.pkg1'
|
||||
#
|
||||
# ACL_NONE + different user + different DB
|
||||
#
|
||||
USE test2;
|
||||
ACL_NONE + different user + different DB + PACKAGE type in another PACKAGE
|
||||
CREATE PACKAGE pkg2 AS
|
||||
TYPE cur1_t IS REF CURSOR RETURN test1.pkg1.rec0_t;
|
||||
END;
|
||||
$$
|
||||
ERROR 42000: execute command denied to user 'user2'@'localhost' for routine 'test1.pkg1'
|
||||
ACL_NONE + different user + different DB + PACKAGE type in another PACKAGE BODY
|
||||
CREATE PACKAGE pkg2 AS
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg2 AS
|
||||
TYPE cur1_t IS REF CURSOR RETURN test1.pkg1.rec0_t;
|
||||
END;
|
||||
$$
|
||||
ERROR 42000: execute command denied to user 'user2'@'localhost' for routine 'test1.pkg1'
|
||||
DROP PACKAGE pkg2;
|
||||
ACL_NONE + different user + different DB + PACKAGE type in a schema routine
|
||||
CREATE PROCEDURE p1 AS
|
||||
TYPE cur1_t IS REF CURSOR RETURN test1.pkg1.rec0_t;
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
ERROR 42000: execute command denied to user 'user2'@'localhost' for routine 'test1.pkg1'
|
||||
# End of denied.inc
|
||||
connection default;
|
||||
GRANT EXECUTE ON PACKAGE test1.pkg1 TO user2@localhost;
|
||||
connection conn_user2;
|
||||
# Start of allowed.inc
|
||||
SELECT CURRENT_USER;
|
||||
CURRENT_USER
|
||||
user2@localhost
|
||||
#
|
||||
# ACL_EXEC_test1.pkg1 + different user + same DB
|
||||
#
|
||||
USE test1;
|
||||
# ACL_EXEC_test1.pkg1 + different user + same DB + PACKAGE type in the same PACKAGE BODY
|
||||
CREATE PACKAGE BODY pkg1 AS
|
||||
r0 pkg1.rec0_t;
|
||||
END;
|
||||
$$
|
||||
DROP PACKAGE BODY pkg1;
|
||||
CREATE PACKAGE BODY pkg1 AS
|
||||
r0 test1.pkg1.rec0_t;
|
||||
END;
|
||||
$$
|
||||
DROP PACKAGE BODY pkg1;
|
||||
# ACL_EXEC_test1.pkg1 + different user + same DB + PACKAGE type in another PACKAGE
|
||||
CREATE PACKAGE pkg2 AS
|
||||
TYPE cur1_t IS REF CURSOR RETURN pkg1.rec0_t;
|
||||
END;
|
||||
$$
|
||||
DROP PACKAGE pkg2;
|
||||
CREATE PACKAGE pkg2 AS
|
||||
TYPE cur1_t IS REF CURSOR RETURN test1.pkg1.rec0_t;
|
||||
END;
|
||||
$$
|
||||
DROP PACKAGE pkg2;
|
||||
# ACL_EXEC_test1.pkg1 + different user + same DB + PACKAGE type in another PACKAGE BODY
|
||||
CREATE PACKAGE pkg2 AS
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg2 AS
|
||||
TYPE cur1_t IS REF CURSOR RETURN pkg1.rec0_t;
|
||||
END;
|
||||
$$
|
||||
DROP PACKAGE pkg2;
|
||||
CREATE PACKAGE pkg2 AS
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg2 AS
|
||||
TYPE cur1_t IS REF CURSOR RETURN test1.pkg1.rec0_t;
|
||||
END;
|
||||
$$
|
||||
DROP PACKAGE pkg2;
|
||||
# ACL_EXEC_test1.pkg1 + different user + same DB + PACKAGE type in a schema routine
|
||||
CREATE PROCEDURE p1 AS
|
||||
TYPE cur1_t IS REF CURSOR RETURN pkg1.rec0_t;
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
DROP PROCEDURE p1;
|
||||
CREATE PROCEDURE p1 AS
|
||||
TYPE cur1_t IS REF CURSOR RETURN test1.pkg1.rec0_t;
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
DROP PROCEDURE p1;
|
||||
#
|
||||
# ACL_EXEC_test1.pkg1 + different user + different DB
|
||||
#
|
||||
USE test2;
|
||||
# ACL_EXEC_test1.pkg1 + different user + different DB + PACKAGE type in another PACKAGE
|
||||
CREATE PACKAGE pkg2 AS
|
||||
TYPE cur1_t IS REF CURSOR RETURN test1.pkg1.rec0_t;
|
||||
END;
|
||||
$$
|
||||
DROP PACKAGE pkg2;
|
||||
# ACL_EXEC_test1.pkg1 + different user + different DB + PACKAGE type in another PACKAGE BODY
|
||||
CREATE PACKAGE pkg2 AS
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg2 AS
|
||||
TYPE cur1_t IS REF CURSOR RETURN test1.pkg1.rec0_t;
|
||||
END;
|
||||
$$
|
||||
DROP PACKAGE pkg2;
|
||||
# ACL_EXEC_test1.pkg1 + different user + different DB + PACKAGE type in a schema routine
|
||||
CREATE PROCEDURE p1 AS
|
||||
TYPE cur1_t IS REF CURSOR RETURN test1.pkg1.rec0_t;
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
DROP PROCEDURE p1;
|
||||
# End of allowed.inc
|
||||
connection default;
|
||||
REVOKE EXECUTE ON PACKAGE test1.pkg1 FROM user2@localhost;
|
||||
connection default;
|
||||
disconnect conn_user1;
|
||||
disconnect conn_user2;
|
||||
DROP USER user1@localhost;
|
||||
DROP USER user2@localhost;
|
||||
DROP PACKAGE test1.pkg1;
|
||||
DROP DATABASE test1;
|
||||
DROP DATABASE test2;
|
||||
#
|
||||
# MDEV-40136 User without any privileges on the package schema can declare and use the package's record types
|
||||
#
|
||||
CREATE DATABASE secdb;
|
||||
CREATE PACKAGE secdb.pkg AS
|
||||
TYPE rec_t IS RECORD (a INT, secret VARCHAR(30));
|
||||
FUNCTION f RETURN INT;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY secdb.pkg AS
|
||||
FUNCTION f RETURN INT AS
|
||||
BEGIN
|
||||
RETURN 42;
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
CREATE DATABASE appdb;
|
||||
CREATE USER u_none@localhost;
|
||||
GRANT ALL ON appdb.* TO u_none@localhost;
|
||||
connect cnone, localhost, u_none,, appdb;
|
||||
SET sql_mode=ORACLE;
|
||||
CREATE PROCEDURE appdb.p AS r secdb.pkg.rec_t;
|
||||
BEGIN
|
||||
r.a:=1;
|
||||
r.secret:='x';
|
||||
SELECT r.a;
|
||||
END;
|
||||
$$
|
||||
ERROR 42000: execute command denied to user 'u_none'@'localhost' for routine 'secdb.pkg'
|
||||
connection default;
|
||||
GRANT EXECUTE ON PACKAGE secdb.pkg TO u_none@localhost;
|
||||
connection cnone;
|
||||
CREATE PROCEDURE
|
||||
appdb.p AS r secdb.pkg.rec_t;
|
||||
BEGIN
|
||||
r.a:=1;
|
||||
r.secret:='x';
|
||||
SELECT r.a;
|
||||
END;
|
||||
$$
|
||||
CALL appdb.p;
|
||||
r.a
|
||||
1
|
||||
SELECT secdb.pkg.f();
|
||||
ERROR 42000: execute command denied to user 'u_none'@'localhost' for routine 'secdb.pkg'
|
||||
connection default;
|
||||
GRANT EXECUTE ON PACKAGE BODY secdb.pkg TO u_none@localhost;
|
||||
connection cnone;
|
||||
SELECT secdb.pkg.f();
|
||||
secdb.pkg.f()
|
||||
42
|
||||
connection default;
|
||||
disconnect cnone;
|
||||
DROP USER u_none@localhost;
|
||||
DROP DATABASE appdb;
|
||||
DROP DATABASE secdb;
|
||||
#
|
||||
# MDEV-40278 Package type is wrongly DENIED when called by a low privilege invoker
|
||||
#
|
||||
CREATE DATABASE secdb;
|
||||
CREATE DATABASE appdb;
|
||||
CREATE USER low@localhost;
|
||||
GRANT ALL ON appdb.* TO low@localhost;
|
||||
CREATE PACKAGE secdb.vault AS
|
||||
TYPE creds IS RECORD(username VARCHAR(64), pw VARCHAR(128));
|
||||
FUNCTION f RETURN INT;
|
||||
END;
|
||||
$$
|
||||
CREATE DEFINER=root@localhost PROCEDURE appdb.p_definer_root_security_none AS
|
||||
r secdb.vault.creds;
|
||||
BEGIN
|
||||
r.username:='admin';
|
||||
SELECT r.username;
|
||||
END;
|
||||
$$
|
||||
CREATE PROCEDURE appdb.p_definer_none_security_none AS
|
||||
r secdb.vault.creds;
|
||||
BEGIN
|
||||
r.username:='admin';
|
||||
SELECT r.username;
|
||||
END;
|
||||
$$
|
||||
CREATE DEFINER=low@localhost PROCEDURE appdb.p_definer_low_security_none AS
|
||||
r secdb.vault.creds;
|
||||
BEGIN
|
||||
r.username:='admin';
|
||||
SELECT r.username;
|
||||
END;
|
||||
$$
|
||||
ERROR 42000: execute command denied to user 'low'@'localhost' for routine 'secdb.vault'
|
||||
CREATE DEFINER=root@localhost PROCEDURE appdb.p_definer_root_security_invoker
|
||||
SQL SECURITY INVOKER AS
|
||||
r secdb.vault.creds;
|
||||
BEGIN
|
||||
r.username:='admin';
|
||||
SELECT r.username;
|
||||
END;
|
||||
$$
|
||||
CREATE PROCEDURE appdb.p_definer_none_security_invoker
|
||||
SQL SECURITY INVOKER AS
|
||||
r secdb.vault.creds;
|
||||
BEGIN
|
||||
r.username:='admin';
|
||||
SELECT r.username;
|
||||
END;
|
||||
$$
|
||||
CREATE DEFINER=low@localhost PROCEDURE appdb.p_definer_low_security_invoker
|
||||
SQL SECURITY INVOKER AS
|
||||
r secdb.vault.creds;
|
||||
BEGIN
|
||||
r.username:='admin';
|
||||
SELECT r.username;
|
||||
END;
|
||||
$$
|
||||
SELECT name, definer, security_type FROM mysql.proc
|
||||
WHERE db='appdb' AND name LIKE 'p_%'
|
||||
ORDER BY definer;
|
||||
name definer security_type
|
||||
p_definer_low_security_invoker low@localhost INVOKER
|
||||
p_definer_root_security_none root@localhost DEFINER
|
||||
p_definer_none_security_none root@localhost DEFINER
|
||||
p_definer_root_security_invoker root@localhost INVOKER
|
||||
p_definer_none_security_invoker root@localhost INVOKER
|
||||
connect lowconn, localhost, low,,appdb;
|
||||
SET sql_mode=ORACLE;
|
||||
CREATE PROCEDURE appdb.p_definer_low1_security_none AS
|
||||
r secdb.vault.creds;
|
||||
BEGIN
|
||||
r.username:='admin';
|
||||
SELECT r.username;
|
||||
END;
|
||||
$$
|
||||
ERROR 42000: execute command denied to user 'low'@'localhost' for routine 'secdb.vault'
|
||||
CREATE PROCEDURE appdb.p_definer_low1_security_invoker
|
||||
SQL SECURITY INVOKER AS
|
||||
r secdb.vault.creds;
|
||||
BEGIN
|
||||
r.username:='admin';
|
||||
SELECT r.username;
|
||||
END;
|
||||
$$
|
||||
ERROR 42000: execute command denied to user 'low'@'localhost' for routine 'secdb.vault'
|
||||
CALL appdb.p_definer_root_security_none();
|
||||
r.username
|
||||
admin
|
||||
CALL appdb.p_definer_none_security_none();
|
||||
r.username
|
||||
admin
|
||||
CALL appdb.p_definer_root_security_invoker();
|
||||
ERROR 42000: execute command denied to user 'low'@'localhost' for routine 'secdb.vault'
|
||||
CALL appdb.p_definer_none_security_invoker();
|
||||
ERROR 42000: execute command denied to user 'low'@'localhost' for routine 'secdb.vault'
|
||||
SHOW WARNINGS;
|
||||
Level Code Message
|
||||
Error 1370 execute command denied to user 'low'@'localhost' for routine 'secdb.vault'
|
||||
connection default;
|
||||
disconnect lowconn;
|
||||
DROP USER low@localhost;
|
||||
DROP DATABASE appdb;
|
||||
DROP DATABASE secdb;
|
||||
# Using secdb.vault package types in package procedure appdb.xxx.p1
|
||||
SET sql_mode=ORACLE;
|
||||
CREATE DATABASE secdb;
|
||||
CREATE DATABASE appdb;
|
||||
CREATE USER low@localhost;
|
||||
GRANT ALL ON appdb.* TO low@localhost;
|
||||
CREATE PACKAGE secdb.vault AS
|
||||
TYPE creds IS RECORD(username VARCHAR(64), pw VARCHAR(128));
|
||||
FUNCTION f RETURN INT;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE appdb.pkg_definer_body_root_security_none AS
|
||||
PROCEDURE p1;
|
||||
END;
|
||||
$$
|
||||
CREATE DEFINER=root@localhost PACKAGE BODY appdb.pkg_definer_body_root_security_none AS
|
||||
PROCEDURE p1 AS
|
||||
r secdb.vault.creds;
|
||||
BEGIN
|
||||
r.username:='admin';
|
||||
SELECT r.username;
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE appdb.pkg_definer_body_none_security_none AS
|
||||
PROCEDURE p1;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY appdb.pkg_definer_body_none_security_none AS
|
||||
PROCEDURE p1 AS
|
||||
r secdb.vault.creds;
|
||||
BEGIN
|
||||
r.username:='admin';
|
||||
SELECT r.username;
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE appdb.pkg_definer_body_low_security_none AS
|
||||
PROCEDURE p1;
|
||||
END;
|
||||
$$
|
||||
CREATE DEFINER=low@localhost PACKAGE BODY appdb.pkg_definer_body_low_security_none AS
|
||||
PROCEDURE p1 AS
|
||||
r secdb.vault.creds;
|
||||
BEGIN
|
||||
r.username:='admin';
|
||||
SELECT r.username;
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
ERROR 42000: execute command denied to user 'low'@'localhost' for routine 'secdb.vault'
|
||||
DROP PACKAGE appdb.pkg_definer_body_low_security_none;
|
||||
CREATE PACKAGE appdb.pkg_definer_body_root_security_invoker AS
|
||||
PROCEDURE p1;
|
||||
END;
|
||||
$$
|
||||
CREATE DEFINER=root@localhost PACKAGE BODY appdb.pkg_definer_body_root_security_invoker
|
||||
SQL SECURITY INVOKER AS
|
||||
PROCEDURE p1 AS
|
||||
r secdb.vault.creds;
|
||||
BEGIN
|
||||
r.username:='admin';
|
||||
SELECT r.username;
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE appdb.pkg_definer_body_none_security_invoker AS
|
||||
PROCEDURE p1;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY appdb.pkg_definer_body_none_security_invoker
|
||||
SQL SECURITY INVOKER AS
|
||||
PROCEDURE p1 AS
|
||||
r secdb.vault.creds;
|
||||
BEGIN
|
||||
r.username:='admin';
|
||||
SELECT r.username;
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE appdb.pkg_definer_body_low_security_invoker AS
|
||||
PROCEDURE p1;
|
||||
END;
|
||||
$$
|
||||
CREATE DEFINER=low@localhost PACKAGE BODY appdb.pkg_definer_body_low_security_invoker
|
||||
SQL SECURITY INVOKER AS
|
||||
PROCEDURE p1 AS
|
||||
r secdb.vault.creds;
|
||||
BEGIN
|
||||
r.username:='admin';
|
||||
SELECT r.username;
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
SELECT type, name, definer, security_type FROM mysql.proc
|
||||
WHERE db='appdb' AND name LIKE 'pkg_%'
|
||||
ORDER BY name, type, definer;
|
||||
type name definer security_type
|
||||
PACKAGE pkg_definer_body_low_security_invoker root@localhost DEFINER
|
||||
PACKAGE BODY pkg_definer_body_low_security_invoker low@localhost INVOKER
|
||||
PACKAGE pkg_definer_body_none_security_invoker root@localhost DEFINER
|
||||
PACKAGE BODY pkg_definer_body_none_security_invoker root@localhost INVOKER
|
||||
PACKAGE pkg_definer_body_none_security_none root@localhost DEFINER
|
||||
PACKAGE BODY pkg_definer_body_none_security_none root@localhost DEFINER
|
||||
PACKAGE pkg_definer_body_root_security_invoker root@localhost DEFINER
|
||||
PACKAGE BODY pkg_definer_body_root_security_invoker root@localhost INVOKER
|
||||
PACKAGE pkg_definer_body_root_security_none root@localhost DEFINER
|
||||
PACKAGE BODY pkg_definer_body_root_security_none root@localhost DEFINER
|
||||
connect lowconn, localhost, low,,appdb;
|
||||
SET sql_mode=ORACLE;
|
||||
CREATE PACKAGE appdb.pkg_definer_body_low_security_none AS
|
||||
PROCEDURE p1;
|
||||
END;
|
||||
$$
|
||||
CREATE DEFINER=low@localhost PACKAGE BODY appdb.pkg_definer_body_low_security_none AS
|
||||
PROCEDURE p1 AS
|
||||
r secdb.vault.creds;
|
||||
BEGIN
|
||||
r.username:='admin';
|
||||
SELECT r.username;
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
ERROR 42000: execute command denied to user 'low'@'localhost' for routine 'secdb.vault'
|
||||
CALL appdb.pkg_definer_body_root_security_none.p1();
|
||||
r.username
|
||||
admin
|
||||
CALL appdb.pkg_definer_body_none_security_none.p1();
|
||||
r.username
|
||||
admin
|
||||
CALL appdb.pkg_definer_body_root_security_invoker.p1();
|
||||
ERROR 42000: execute command denied to user 'low'@'localhost' for routine 'secdb.vault'
|
||||
CALL appdb.pkg_definer_body_none_security_invoker.p1();
|
||||
ERROR 42000: execute command denied to user 'low'@'localhost' for routine 'secdb.vault'
|
||||
connection default;
|
||||
disconnect lowconn;
|
||||
DROP USER low@localhost;
|
||||
DROP DATABASE appdb;
|
||||
DROP DATABASE secdb;
|
||||
@@ -0,0 +1,117 @@
|
||||
SET sql_mode=ORACLE;
|
||||
#
|
||||
# MDEV-39587 Package-wide TYPE for variable declarations
|
||||
#
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE inet6_array IS TABLE OF INET6 INDEX BY INTEGER;
|
||||
END;
|
||||
$$
|
||||
# 2-Step + PROCEDURE
|
||||
CREATE PROCEDURE p1 AS
|
||||
v0 pkg1.inet6_array;
|
||||
BEGIN
|
||||
v0(0):='AA::BB';
|
||||
SELECT v0(0);
|
||||
END;
|
||||
$$
|
||||
CALL p1;
|
||||
v0(0)
|
||||
aa::bb
|
||||
DROP PROCEDURE p1;
|
||||
# 2-Step + PACKAGE + Declarations in package PROCEDURE
|
||||
CREATE PACKAGE pkg2 AS
|
||||
PROCEDURE p1;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg2 AS
|
||||
PROCEDURE p1 AS
|
||||
v0 pkg1.inet6_array;
|
||||
BEGIN
|
||||
v0(0):='AA::BB';
|
||||
SELECT v0(0);
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
CALL pkg2.p1;
|
||||
v0(0)
|
||||
aa::bb
|
||||
DROP PACKAGE pkg2;
|
||||
# 2-Step + PACKAGE + Declaration in PACKAGE BODY
|
||||
CREATE PACKAGE pkg2 AS
|
||||
PROCEDURE p1;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg2 AS
|
||||
v0 pkg1.inet6_array;
|
||||
PROCEDURE p1 AS
|
||||
BEGIN
|
||||
v0(0):='AA::BB';
|
||||
SELECT v0(0);
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
CALL pkg2.p1;
|
||||
v0(0)
|
||||
aa::bb
|
||||
DROP PACKAGE pkg2;
|
||||
# 3-Step + PROCEDURE + Declarations in package PROCEDURE
|
||||
CREATE DATABASE test1;
|
||||
USE test1;
|
||||
CREATE PROCEDURE p1 AS
|
||||
v0 test.pkg1.inet6_array;
|
||||
BEGIN
|
||||
v0(0):='AA::BB';
|
||||
SELECT v0(0);
|
||||
END;
|
||||
$$
|
||||
CALL p1;
|
||||
v0(0)
|
||||
aa::bb
|
||||
DROP PROCEDURE p1;
|
||||
DROP DATABASE test1;
|
||||
USE test;
|
||||
# 3-Step + PACKAGE
|
||||
CREATE DATABASE test1;
|
||||
USE test1;
|
||||
CREATE PACKAGE pkg2 AS
|
||||
PROCEDURE p1;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg2 AS
|
||||
PROCEDURE p1 AS
|
||||
v0 test.pkg1.inet6_array;
|
||||
BEGIN
|
||||
v0(0):='AA::BB';
|
||||
SELECT v0(0);
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
CALL pkg2.p1;
|
||||
v0(0)
|
||||
aa::bb
|
||||
DROP PACKAGE pkg2;
|
||||
DROP DATABASE test1;
|
||||
USE test;
|
||||
# 3-Step + PACKAGE + Declaration in PACKAGE BODY
|
||||
CREATE DATABASE test1;
|
||||
USE test1;
|
||||
CREATE PACKAGE pkg2 AS
|
||||
PROCEDURE p1;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg2 AS
|
||||
v0 test.pkg1.inet6_array;
|
||||
PROCEDURE p1 AS
|
||||
BEGIN
|
||||
v0(0):='AA::BB';
|
||||
SELECT v0(0);
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
CALL pkg2.p1;
|
||||
v0(0)
|
||||
aa::bb
|
||||
DROP PACKAGE pkg2;
|
||||
DROP DATABASE test1;
|
||||
USE test;
|
||||
DROP PACKAGE pkg1;
|
||||
@@ -0,0 +1,22 @@
|
||||
SET sql_mode=ORACLE;
|
||||
#
|
||||
# MDEV-39587 Package-wide TYPE for variable declarations
|
||||
#
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE rec0_t IS RECORD (a INT, b VARCHAR(32));
|
||||
TYPE assoc0_t IS TABLE OF test.pkg1.rec0_t INDEX BY INTEGER;
|
||||
END;
|
||||
$$
|
||||
DROP PACKAGE pkg1;
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE rec0_t IS RECORD (a INT, b VARCHAR(32));
|
||||
TYPE assoc0_t IS TABLE OF TEST.pkg1.rec0_t INDEX BY INTEGER;
|
||||
END;
|
||||
$$
|
||||
DROP PACKAGE pkg1;
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE rec0_t IS RECORD (a INT, b VARCHAR(32));
|
||||
TYPE assoc0_t IS TABLE OF tttt.pkg1.rec0_t INDEX BY INTEGER;
|
||||
END;
|
||||
$$
|
||||
ERROR HY000: Unknown data type: '`tttt`.`pkg1`.`rec0_t`'
|
||||
@@ -0,0 +1,22 @@
|
||||
SET sql_mode=ORACLE;
|
||||
#
|
||||
# MDEV-39587 Package-wide TYPE for variable declarations
|
||||
#
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE rec0_t IS RECORD (a INT, b VARCHAR(32));
|
||||
TYPE assoc0_t IS TABLE OF test.pkg1.rec0_t INDEX BY INTEGER;
|
||||
END;
|
||||
$$
|
||||
DROP PACKAGE pkg1;
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE rec0_t IS RECORD (a INT, b VARCHAR(32));
|
||||
TYPE assoc0_t IS TABLE OF TEST.pkg1.rec0_t INDEX BY INTEGER;
|
||||
END;
|
||||
$$
|
||||
ERROR HY000: Unknown data type: '`TEST`.`pkg1`.`rec0_t`'
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE rec0_t IS RECORD (a INT, b VARCHAR(32));
|
||||
TYPE assoc0_t IS TABLE OF tttt.pkg1.rec0_t INDEX BY INTEGER;
|
||||
END;
|
||||
$$
|
||||
ERROR HY000: Unknown data type: '`tttt`.`pkg1`.`rec0_t`'
|
||||
@@ -0,0 +1,82 @@
|
||||
SET sql_mode=ORACLE;
|
||||
#
|
||||
# MDEV-39587 Package-wide TYPE for variable declarations
|
||||
#
|
||||
# PATH resolving not to CURRENT_SCHEMA
|
||||
CREATE DATABASE test1;
|
||||
CREATE PACKAGE test1.pkg1 AS
|
||||
TYPE rec0_t IS RECORD (a INT, b_test1 VARCHAR(10));
|
||||
END;
|
||||
$$
|
||||
CREATE DATABASE test2;
|
||||
CREATE PACKAGE test2.pkg1 AS
|
||||
TYPE rec0_t IS RECORD (a INT, b_test2 VARCHAR(10));
|
||||
END;
|
||||
$$
|
||||
CREATE PROCEDURE p1 AS
|
||||
a pkg1.rec0_t;
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
ERROR HY000: Unknown data type: '`pkg1`.`rec0_t`'
|
||||
SET PATH 'CURRENT_SCHEMA,test1,test2';
|
||||
CREATE PROCEDURE p1 AS
|
||||
a pkg1.rec0_t;
|
||||
BEGIN
|
||||
a.b_test1:= 10;
|
||||
SELECT a.b_test1;
|
||||
END;
|
||||
$$
|
||||
CALL test.p1();
|
||||
a.b_test1
|
||||
10
|
||||
DROP PROCEDURE p1;
|
||||
SET PATH 'CURRENT_SCHEMA,test2,test1';
|
||||
CREATE PROCEDURE p1 AS
|
||||
a pkg1.rec0_t;
|
||||
BEGIN
|
||||
a.b_test2:= 10;
|
||||
SELECT a.b_test2;
|
||||
END;
|
||||
$$
|
||||
CALL p1();
|
||||
a.b_test2
|
||||
10
|
||||
DROP PROCEDURE p1;
|
||||
SET PATH DEFAULT;
|
||||
DROP DATABASE test1;
|
||||
DROP DATABASE test2;
|
||||
# PATH resolving to CURRENT_SCHEMA
|
||||
CREATE DATABASE test1;
|
||||
CREATE PACKAGE test.pkg1 AS
|
||||
TYPE rec0_t IS RECORD (a INT, b_test VARCHAR(10));
|
||||
END;
|
||||
$$
|
||||
SET PATH 'test1,CURRENT_SCHEMA';
|
||||
CREATE PROCEDURE p1 AS
|
||||
a pkg1.rec0_t;
|
||||
BEGIN
|
||||
a.b_test:= 10;
|
||||
SELECT a.b_test;
|
||||
END;
|
||||
$$
|
||||
CALL p1();
|
||||
a.b_test
|
||||
10
|
||||
DROP PROCEDURE p1;
|
||||
SET PATH 'CURRENT_SCHEMA,test1';
|
||||
CREATE PROCEDURE p1 AS
|
||||
a pkg1.rec0_t;
|
||||
BEGIN
|
||||
a.b_test:= 10;
|
||||
SELECT a.b_test;
|
||||
END;
|
||||
$$
|
||||
CALL p1();
|
||||
a.b_test
|
||||
10
|
||||
DROP PROCEDURE p1;
|
||||
DROP PACKAGE pkg1;
|
||||
DROP DATABASE test1;
|
||||
SET PATH DEFAULT;
|
||||
@@ -0,0 +1,330 @@
|
||||
SET sql_mode=ORACLE;
|
||||
#
|
||||
# MDEV-39587 Package-wide TYPE for variable declarations
|
||||
#
|
||||
# RECORD cannot have attributes
|
||||
# Currently this is not allowed by the parser in qualified types
|
||||
# If we ever allow, make sure to call check_data_type_attributes()
|
||||
# which will raise ER_UNSUPPORTED_DATA_TYPE_ATTRIBUTE
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE rec0_t IS RECORD (a INT, b VARCHAR(32));
|
||||
END;
|
||||
$$
|
||||
CREATE PROCEDURE p1 AS
|
||||
r0 pkg1.rec0_t (0); -- Length attribute
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '(0); -- Length attribute
|
||||
BEGIN
|
||||
NULL;
|
||||
END' at line 2
|
||||
CREATE PROCEDURE p1 AS
|
||||
r0 pkg1.rec0_t (0,0); -- Length and dec attributes
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '(0,0); -- Length and dec attributes
|
||||
BEGIN
|
||||
NULL;
|
||||
END' at line 2
|
||||
CREATE PROCEDURE p1 AS
|
||||
r0 pkg1.rec0_t CHARACTER SET latin1;
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'CHARACTER SET latin1;
|
||||
BEGIN
|
||||
NULL;
|
||||
END' at line 2
|
||||
CREATE PROCEDURE p1 AS
|
||||
r0 pkg1.rec0_t COLLATE latin1_bin;
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'COLLATE latin1_bin;
|
||||
BEGIN
|
||||
NULL;
|
||||
END' at line 2
|
||||
DROP PACKAGE pkg1;
|
||||
# PACKAGE spec types cannot be used in schema routine parameters
|
||||
# and schema function RETURN
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE rec0_t IS RECORD (a INT, b VARCHAR(10));
|
||||
END;
|
||||
$$
|
||||
CREATE PROCEDURE p1(a pkg1.rec0_t) AS
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
ERROR HY000: Incorrect usage of parameter_declaration and package_name.type_name
|
||||
CREATE FUNCTION f1 RETURN pkg1.rec0_t AS
|
||||
BEGIN
|
||||
RETURN NULL;
|
||||
END;
|
||||
$$
|
||||
ERROR HY000: Incorrect usage of RETURN and package_name.type_name
|
||||
DROP PACKAGE pkg1;
|
||||
# RECORD as a package routine parameter and a package function RETURN
|
||||
# 2-step
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE rec0_t IS RECORD (a INT, b VARCHAR(10));
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE pkg2 AS
|
||||
PROCEDURE p1;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg2 AS
|
||||
PROCEDURE p2(r pkg1.rec0_t) AS
|
||||
BEGIN
|
||||
SELECT r.a, r.b;
|
||||
END;
|
||||
FUNCTION f1 RETURN pkg1.rec0_t AS
|
||||
res pkg1.rec0_t;
|
||||
BEGIN
|
||||
res.a:= 10;
|
||||
res.b:= 'b';
|
||||
RETURN res;
|
||||
END;
|
||||
PROCEDURE p1 AS
|
||||
BEGIN
|
||||
CALL p2(f1());
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
CALL pkg2.p1();
|
||||
r.a r.b
|
||||
10 b
|
||||
DROP PACKAGE pkg2;
|
||||
DROP PACKAGE pkg1;
|
||||
# RECORD as a package routine parameter and a package function RETURN
|
||||
# 3-step
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE rec0_t IS RECORD (a INT, b VARCHAR(10));
|
||||
END;
|
||||
$$
|
||||
CREATE DATABASE test1;
|
||||
USE test1;
|
||||
CREATE PACKAGE pkg2 AS
|
||||
PROCEDURE p1;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg2 AS
|
||||
PROCEDURE p2(r test.pkg1.rec0_t) AS
|
||||
BEGIN
|
||||
SELECT r.a, r.b;
|
||||
END;
|
||||
FUNCTION f1 RETURN test.pkg1.rec0_t AS
|
||||
res test.pkg1.rec0_t;
|
||||
BEGIN
|
||||
res.a:= 10;
|
||||
res.b:= 'b';
|
||||
RETURN res;
|
||||
END;
|
||||
PROCEDURE p1 AS
|
||||
BEGIN
|
||||
CALL p2(f1());
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
CALL pkg2.p1();
|
||||
r.a r.b
|
||||
10 b
|
||||
CALL test1.pkg2.p1();
|
||||
r.a r.b
|
||||
10 b
|
||||
USE test;
|
||||
CALL test1.pkg2.p1();
|
||||
r.a r.b
|
||||
10 b
|
||||
USE test1;
|
||||
DROP PACKAGE pkg2;
|
||||
DROP DATABASE test1;
|
||||
USE test;
|
||||
DROP PACKAGE pkg1;
|
||||
# RECORD as a package routine parameter + 2-step self-reference
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE r IS RECORD(x INT);
|
||||
PROCEDURE q(v pkg1.no_such_type); -- 2-step self reference
|
||||
END;
|
||||
$$
|
||||
ERROR HY000: Unknown data type: '`pkg1`.`no_such_type`'
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE r IS RECORD(x INT);
|
||||
PROCEDURE q(v pkg1.r); -- 2-step self reference
|
||||
PROCEDURE exec();
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg1 AS
|
||||
PROCEDURE q(v pkg1.r) AS
|
||||
BEGIN
|
||||
SELECT v.x;
|
||||
END;
|
||||
PROCEDURE exec() AS
|
||||
v pkg1.r;
|
||||
BEGIN
|
||||
v.x:= 10;
|
||||
q(v);
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
CALL pkg1.exec();
|
||||
v.x
|
||||
10
|
||||
DROP PACKAGE pkg1;
|
||||
# RECORD as a package routine parameter + 3-step self-reference
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE r IS RECORD(x INT);
|
||||
PROCEDURE q(v test.pkg1.no_such_type); -- 3-step Self reference
|
||||
END;
|
||||
$$
|
||||
ERROR HY000: Unknown data type: '`pkg1`.`no_such_type`'
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE r IS RECORD(x INT);
|
||||
PROCEDURE q(v test.pkg1.r); -- 3-step self reference
|
||||
PROCEDURE exec();
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg1 AS
|
||||
PROCEDURE q(v test.pkg1.r) AS
|
||||
BEGIN
|
||||
SELECT v.x;
|
||||
END;
|
||||
PROCEDURE exec() AS
|
||||
v test.pkg1.r;
|
||||
BEGIN
|
||||
v.x:= 10;
|
||||
q(v);
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
CALL pkg1.exec();
|
||||
v.x
|
||||
10
|
||||
DROP PACKAGE pkg1;
|
||||
# RECORD as a package function RETURN type + 2-step self-reference
|
||||
CREATE PACKAGE pkg1 AS
|
||||
FUNCTION g RETURN pkg1.no_such_type; -- 2-step self-reference
|
||||
END;
|
||||
$$
|
||||
ERROR HY000: Unknown data type: '`pkg1`.`no_such_type`'
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE r IS RECORD(x INT);
|
||||
FUNCTION g RETURN pkg1.r; -- 2-step self-reference
|
||||
PROCEDURE exec;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg1 AS
|
||||
FUNCTION g RETURN pkg1.r AS
|
||||
v pkg1.r;
|
||||
BEGIN
|
||||
v.x:= 10;
|
||||
RETURN v;
|
||||
END;
|
||||
PROCEDURE exec AS
|
||||
v pkg1.r;
|
||||
BEGIN
|
||||
v:= g();
|
||||
SELECT v.x;
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
CALL pkg1.exec();
|
||||
v.x
|
||||
10
|
||||
DROP PACKAGE pkg1;
|
||||
# RECORD as a package function RETURN type + 3-step self-reference
|
||||
CREATE PACKAGE pkg1 AS
|
||||
FUNCTION g RETURN test.pkg1.no_such_type; -- 3-step self-reference
|
||||
END;
|
||||
$$
|
||||
ERROR HY000: Unknown data type: '`pkg1`.`no_such_type`'
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE r IS RECORD(x INT);
|
||||
FUNCTION g RETURN test.pkg1.r; -- 3-step self-reference
|
||||
PROCEDURE exec;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg1 AS
|
||||
FUNCTION g RETURN test.pkg1.r AS
|
||||
v test.pkg1.r;
|
||||
BEGIN
|
||||
v.x:= 10;
|
||||
RETURN v;
|
||||
END;
|
||||
PROCEDURE exec AS
|
||||
v test.pkg1.r;
|
||||
BEGIN
|
||||
v:= g();
|
||||
SELECT v.x;
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
CALL pkg1.exec();
|
||||
v.x
|
||||
10
|
||||
DROP PACKAGE pkg1;
|
||||
#
|
||||
# MDEV-40721 SIGSEGV in LEX::sp_package_spec_check_cyclic_dependency | LEX::set_field_type_typedef_package_spec
|
||||
#
|
||||
CREATE PACKAGE emp_pkg AS
|
||||
TYPE emp_rec IS RECORD (id INT);
|
||||
FUNCTION get_emp(p_id INT) RETURN emp_rec;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY emp_pkg AS
|
||||
FUNCTION get_emp(p_id INT) RETURN emp_pkg.emp_rec AS
|
||||
v emp_pkg.emp_rec;
|
||||
BEGIN
|
||||
v.id := p_id;
|
||||
RETURN v;
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
CREATE PROCEDURE show_emp AS
|
||||
v emp_pkg.emp_rec;
|
||||
BEGIN
|
||||
v := emp_pkg.get_emp(7);
|
||||
SELECT v.id AS id;
|
||||
END;
|
||||
$$
|
||||
CALL show_emp;
|
||||
id
|
||||
7
|
||||
DROP PROCEDURE show_emp;
|
||||
DROP PACKAGE emp_pkg;
|
||||
CREATE PACKAGE emp_pkg AS
|
||||
TYPE emp_rec IS RECORD (id INT);
|
||||
PROCEDURE get_emp(p_id INT);
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY emp_pkg AS
|
||||
PROCEDURE get_emp(p_id INT) AS
|
||||
v emp_pkg.emp_rec;
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
CREATE PROCEDURE show_emp AS
|
||||
BEGIN
|
||||
emp_pkg.get_emp(7);
|
||||
END;
|
||||
$$
|
||||
CALL show_emp;
|
||||
DROP PROCEDURE show_emp;
|
||||
DROP PACKAGE emp_pkg;
|
||||
CREATE PACKAGE t AS TYPE r IS RECORD (id INT); END; $$
|
||||
CREATE PACKAGE a AS PROCEDURE q; END; $$
|
||||
CREATE PACKAGE BODY a AS PROCEDURE q AS v t.r; BEGIN NULL; END; END; $$
|
||||
CREATE PROCEDURE c AS BEGIN CALL a.q(); END; $$
|
||||
CALL c;
|
||||
DROP PROCEDURE c;
|
||||
DROP PACKAGE a;
|
||||
DROP PACKAGE t;
|
||||
@@ -0,0 +1,715 @@
|
||||
SET sql_mode=ORACLE;
|
||||
#
|
||||
# MDEV-39587 Package-wide TYPE for variable declarations
|
||||
#
|
||||
# REFCURSOR cannot have attributes
|
||||
# Currently this is not allowed by the parser in qualified types
|
||||
# If we ever allow, make sure to call check_data_type_attributes()
|
||||
# which will raise ER_UNSUPPORTED_DATA_TYPE_ATTRIBUTE
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE rec0_t IS RECORD (a INT, b VARCHAR(32));
|
||||
TYPE cur0_t IS REF CURSOR RETURN rec0_t;
|
||||
END;
|
||||
$$
|
||||
CREATE PROCEDURE p1 AS
|
||||
r0 pkg1.cur0_t (0); -- Length attribute
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '(0); -- Length attribute
|
||||
BEGIN
|
||||
NULL;
|
||||
END' at line 2
|
||||
CREATE PROCEDURE p1 AS
|
||||
r0 pkg1.cur0_t (0,0); -- Length and dec attributes
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '(0,0); -- Length and dec attributes
|
||||
BEGIN
|
||||
NULL;
|
||||
END' at line 2
|
||||
CREATE PROCEDURE p1 AS
|
||||
r0 pkg1.cur0_t CHARACTER SET latin1;
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'CHARACTER SET latin1;
|
||||
BEGIN
|
||||
NULL;
|
||||
END' at line 2
|
||||
CREATE PROCEDURE p1 AS
|
||||
r0 pkg1.cur0_t COLLATE latin1_bin;
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'COLLATE latin1_bin;
|
||||
BEGIN
|
||||
NULL;
|
||||
END' at line 2
|
||||
DROP PACKAGE pkg1;
|
||||
# PACKAGE spec types cannot be used in schema routine parameters
|
||||
# and schema function RETURN
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE rec0_t IS RECORD (a INT, b VARCHAR(10));
|
||||
TYPE cur0_t IS REF CURSOR RETURN rec0_t;
|
||||
END;
|
||||
$$
|
||||
CREATE PROCEDURE p1(a pkg1.cur0_t) AS
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
ERROR HY000: Incorrect usage of parameter_declaration and package_name.type_name
|
||||
CREATE FUNCTION f1 RETURN pkg1.cur0_t AS
|
||||
BEGIN
|
||||
RETURN NULL;
|
||||
END;
|
||||
$$
|
||||
ERROR HY000: Incorrect usage of RETURN and package_name.type_name
|
||||
DROP PACKAGE pkg1;
|
||||
# A package routine parameter and a package function RETURN
|
||||
# 2-step
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE rec0_t IS RECORD (a INT, b VARCHAR(10));
|
||||
TYPE cur0_t IS REF CURSOR RETURN rec0_t;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE pkg2 AS
|
||||
PROCEDURE p1;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg2 AS
|
||||
PROCEDURE p2(c pkg1.cur0_t) AS
|
||||
v0 INT;
|
||||
v1 VARCHAR(32);
|
||||
BEGIN
|
||||
FETCH c INTO v0, v1;
|
||||
SELECT v0, v1;
|
||||
CLOSE c;
|
||||
END;
|
||||
FUNCTION f1 RETURN pkg1.cur0_t AS
|
||||
res pkg1.cur0_t;
|
||||
BEGIN
|
||||
OPEN res FOR SELECT 1,'b';
|
||||
RETURN res;
|
||||
END;
|
||||
PROCEDURE p1 AS
|
||||
BEGIN
|
||||
CALL p2(f1());
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
CALL pkg2.p1();
|
||||
v0 v1
|
||||
1 b
|
||||
DROP PACKAGE pkg2;
|
||||
DROP PACKAGE pkg1;
|
||||
# A package routine parameter and a package function RETURN
|
||||
# 3-step
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE rec0_t IS RECORD (a INT, b VARCHAR(10));
|
||||
TYPE cur0_t IS REF CURSOR RETURN rec0_t;
|
||||
END;
|
||||
$$
|
||||
CREATE DATABASE test1;
|
||||
USE test1;
|
||||
CREATE PACKAGE pkg2 AS
|
||||
PROCEDURE p1;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg2 AS
|
||||
PROCEDURE p2(c test.pkg1.cur0_t) AS
|
||||
v0 INT;
|
||||
v1 VARCHAR(32);
|
||||
BEGIN
|
||||
FETCH c INTO v0, v1;
|
||||
SELECT v0, v1;
|
||||
CLOSE c;
|
||||
END;
|
||||
FUNCTION f1 RETURN test.pkg1.cur0_t AS
|
||||
res test.pkg1.cur0_t;
|
||||
BEGIN
|
||||
OPEN res FOR SELECT 1, 'b';
|
||||
RETURN res;
|
||||
END;
|
||||
PROCEDURE p1 AS
|
||||
BEGIN
|
||||
CALL p2(f1());
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
CALL pkg2.p1();
|
||||
v0 v1
|
||||
1 b
|
||||
CALL test1.pkg2.p1();
|
||||
v0 v1
|
||||
1 b
|
||||
USE test;
|
||||
CALL test1.pkg2.p1();
|
||||
v0 v1
|
||||
1 b
|
||||
USE test1;
|
||||
DROP PACKAGE pkg2;
|
||||
DROP DATABASE test1;
|
||||
USE test;
|
||||
DROP PACKAGE pkg1;
|
||||
# A self-reference to the current spec with success: 2-step
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE rec0_t IS RECORD (a INT, b VARCHAR(32));
|
||||
TYPE cur0_t IS REF CURSOR RETURN pkg1.rec0_t; -- Self ref
|
||||
END;
|
||||
$$
|
||||
# Using from the same database
|
||||
CREATE PROCEDURE p1 AS
|
||||
r0 pkg1.rec0_t;
|
||||
c0 pkg1.cur0_t;
|
||||
BEGIN
|
||||
OPEN c0 FOR SELECT 1,'b';
|
||||
FETCH c0 INTO r0;
|
||||
CLOSE c0;
|
||||
SELECT r0.a, r0.b;
|
||||
END;
|
||||
$$
|
||||
CALL p1;
|
||||
r0.a r0.b
|
||||
1 b
|
||||
DROP PROCEDURE p1;
|
||||
# Using from a different database
|
||||
CREATE DATABASE test1;
|
||||
CREATE PROCEDURE test1.p1 AS
|
||||
r0 test.pkg1.rec0_t;
|
||||
c0 test.pkg1.cur0_t;
|
||||
BEGIN
|
||||
OPEN c0 FOR SELECT 1,'b';
|
||||
FETCH c0 INTO r0;
|
||||
CLOSE c0;
|
||||
SELECT r0.a, r0.b;
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
CALL test1.p1;
|
||||
r0.a r0.b
|
||||
1 b
|
||||
DROP DATABASE test1;
|
||||
DROP PACKAGE pkg1;
|
||||
# A self-reference to the current spec with success: 3-step
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE rec0_t IS RECORD (a INT, b VARCHAR(32));
|
||||
TYPE cur0_t IS REF CURSOR RETURN test.pkg1.rec0_t; -- Self ref
|
||||
END;
|
||||
$$
|
||||
# Using from the same database
|
||||
CREATE PROCEDURE p1 AS
|
||||
r0 test.pkg1.rec0_t;
|
||||
c0 test.pkg1.cur0_t;
|
||||
BEGIN
|
||||
OPEN c0 FOR SELECT 1,'b';
|
||||
FETCH c0 INTO r0;
|
||||
CLOSE c0;
|
||||
SELECT r0.a, r0.b;
|
||||
END;
|
||||
$$
|
||||
CALL p1;
|
||||
r0.a r0.b
|
||||
1 b
|
||||
DROP PROCEDURE p1;
|
||||
# Using from a different database
|
||||
CREATE DATABASE test1;
|
||||
CREATE PROCEDURE test1.p1 AS
|
||||
r0 test.pkg1.rec0_t;
|
||||
c0 test.pkg1.cur0_t;
|
||||
BEGIN
|
||||
OPEN c0 FOR SELECT 1,'b';
|
||||
FETCH c0 INTO r0;
|
||||
CLOSE c0;
|
||||
SELECT r0.a, r0.b;
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
CALL test1.p1;
|
||||
r0.a r0.b
|
||||
1 b
|
||||
DROP DATABASE test1;
|
||||
DROP PACKAGE pkg1;
|
||||
# Various working examples
|
||||
CREATE TABLE t1 (a INT, b VARCHAR(30));
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE rec0_t IS RECORD(a INT, b VARCHAR(30));
|
||||
TYPE cur0_t IS REF CURSOR;
|
||||
TYPE cur1_t IS REF CURSOR RETURN rec0_t;
|
||||
TYPE cur2_t IS REF CURSOR RETURN test.t1%ROWTYPE;
|
||||
END;
|
||||
$$
|
||||
# 2-Step + PROCEDURE
|
||||
CREATE PROCEDURE p1 AS
|
||||
v1 pkg1.rec0_t;
|
||||
c0 pkg1.cur0_t;
|
||||
c1 pkg1.cur1_t;
|
||||
c2 pkg1.cur2_t;
|
||||
fetch0 INT;
|
||||
fetch1 VARCHAR(30);
|
||||
BEGIN
|
||||
v1.a:= 1;
|
||||
v1.b:= 'b';
|
||||
OPEN c0 FOR SELECT 10,'bb0';
|
||||
FETCH c0 INTO fetch0, fetch1;
|
||||
SELECT fetch0, fetch1;
|
||||
CLOSE c0;
|
||||
OPEN c1 FOR SELECT 11,'bb1';
|
||||
FETCH c1 INTO fetch0, fetch1;
|
||||
SELECT fetch0, fetch1;
|
||||
CLOSE c1;
|
||||
OPEN c2 FOR SELECT 12,'bb2';
|
||||
FETCH c2 INTO fetch0, fetch1;
|
||||
SELECT fetch0, fetch1;
|
||||
CLOSE c2;
|
||||
END;
|
||||
$$
|
||||
CALL p1;
|
||||
fetch0 fetch1
|
||||
10 bb0
|
||||
fetch0 fetch1
|
||||
11 bb1
|
||||
fetch0 fetch1
|
||||
12 bb2
|
||||
DROP PROCEDURE p1;
|
||||
# 3-Step + PROCEDURE
|
||||
CREATE DATABASE test1;
|
||||
USE test1;
|
||||
CREATE PROCEDURE p1 AS
|
||||
v1 test.pkg1.rec0_t;
|
||||
c0 test.pkg1.cur0_t;
|
||||
c1 test.pkg1.cur1_t;
|
||||
c2 test.pkg1.cur2_t;
|
||||
fetch0 INT;
|
||||
fetch1 VARCHAR(30);
|
||||
BEGIN
|
||||
v1.a:= 1;
|
||||
v1.b:= 'b';
|
||||
OPEN c0 FOR SELECT 10,'bb0';
|
||||
FETCH c0 INTO fetch0, fetch1;
|
||||
SELECT fetch0, fetch1;
|
||||
CLOSE c0;
|
||||
OPEN c1 FOR SELECT 11,'bb1';
|
||||
FETCH c1 INTO fetch0, fetch1;
|
||||
SELECT fetch0, fetch1;
|
||||
CLOSE c1;
|
||||
OPEN c2 FOR SELECT 12,'bb2';
|
||||
FETCH c2 INTO fetch0, fetch1;
|
||||
SELECT fetch0, fetch1;
|
||||
CLOSE c2;
|
||||
END;
|
||||
$$
|
||||
CALL p1;
|
||||
fetch0 fetch1
|
||||
10 bb0
|
||||
fetch0 fetch1
|
||||
11 bb1
|
||||
fetch0 fetch1
|
||||
12 bb2
|
||||
DROP PROCEDURE p1;
|
||||
DROP DATABASE test1;
|
||||
USE test;
|
||||
# 2-Step + PACKAGE + Declarations in package PROCEDURE
|
||||
CREATE PACKAGE pkg2 AS
|
||||
PROCEDURE p1;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg2 AS
|
||||
PROCEDURE p1 AS
|
||||
v1 pkg1.rec0_t;
|
||||
c0 pkg1.cur0_t;
|
||||
c1 pkg1.cur1_t;
|
||||
c2 pkg1.cur2_t;
|
||||
fetch0 INT;
|
||||
fetch1 VARCHAR(30);
|
||||
BEGIN
|
||||
v1.a:= 1;
|
||||
v1.b:= 'b';
|
||||
OPEN c0 FOR SELECT 10,'bb0';
|
||||
FETCH c0 INTO fetch0, fetch1;
|
||||
SELECT fetch0, fetch1;
|
||||
CLOSE c0;
|
||||
OPEN c1 FOR SELECT 11,'bb1';
|
||||
FETCH c1 INTO fetch0, fetch1;
|
||||
SELECT fetch0, fetch1;
|
||||
CLOSE c1;
|
||||
OPEN c2 FOR SELECT 12,'bb2';
|
||||
FETCH c2 INTO fetch0, fetch1;
|
||||
SELECT fetch0, fetch1;
|
||||
CLOSE c2;
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
CALL pkg2.p1;
|
||||
fetch0 fetch1
|
||||
10 bb0
|
||||
fetch0 fetch1
|
||||
11 bb1
|
||||
fetch0 fetch1
|
||||
12 bb2
|
||||
DROP PACKAGE pkg2;
|
||||
# 3-Step + PACKAGE + Declarations in package PROCEDURE
|
||||
CREATE DATABASE test1;
|
||||
USE test1;
|
||||
CREATE PACKAGE pkg2 AS
|
||||
PROCEDURE p1;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg2 AS
|
||||
PROCEDURE p1 AS
|
||||
v1 test.pkg1.rec0_t;
|
||||
c0 test.pkg1.cur0_t;
|
||||
c1 test.pkg1.cur1_t;
|
||||
c2 test.pkg1.cur2_t;
|
||||
fetch0 INT;
|
||||
fetch1 VARCHAR(30);
|
||||
BEGIN
|
||||
v1.a:= 1;
|
||||
v1.b:= 'b';
|
||||
OPEN c0 FOR SELECT 10,'bb0';
|
||||
FETCH c0 INTO fetch0, fetch1;
|
||||
SELECT fetch0, fetch1;
|
||||
CLOSE c0;
|
||||
OPEN c1 FOR SELECT 11,'bb1';
|
||||
FETCH c1 INTO fetch0, fetch1;
|
||||
SELECT fetch0, fetch1;
|
||||
CLOSE c1;
|
||||
OPEN c2 FOR SELECT 12,'bb2';
|
||||
FETCH c2 INTO fetch0, fetch1;
|
||||
SELECT fetch0, fetch1;
|
||||
CLOSE c2;
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
CALL pkg2.p1;
|
||||
fetch0 fetch1
|
||||
10 bb0
|
||||
fetch0 fetch1
|
||||
11 bb1
|
||||
fetch0 fetch1
|
||||
12 bb2
|
||||
DROP PACKAGE pkg2;
|
||||
DROP DATABASE test1;
|
||||
USE test;
|
||||
# 3-Step + PACKAGE + Declarations in PACKAGE BODY
|
||||
CREATE DATABASE test1;
|
||||
USE test1;
|
||||
CREATE PACKAGE pkg2 AS
|
||||
PROCEDURE p1;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg2 AS
|
||||
v1 test.pkg1.rec0_t;
|
||||
c0 test.pkg1.cur0_t;
|
||||
c1 test.pkg1.cur1_t;
|
||||
c2 test.pkg1.cur2_t;
|
||||
fetch0 INT;
|
||||
fetch1 VARCHAR(30);
|
||||
PROCEDURE p1 AS
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
ERROR HY000: 'sys_refcursor' is not allowed in this context
|
||||
DROP PACKAGE pkg2;
|
||||
DROP DATABASE test1;
|
||||
USE test;
|
||||
DROP PACKAGE pkg1;
|
||||
DROP TABLE t1;
|
||||
# RECORD and REFCURSOR in different packages
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE rec0_t IS RECORD(a INT, b VARCHAR(30));
|
||||
END;
|
||||
$$
|
||||
# 2-step type in RETURN in a schema procedure
|
||||
CREATE PROCEDURE p1 AS
|
||||
TYPE cur0_t IS REF CURSOR RETURN pkg1.rec0_t;
|
||||
c0 cur0_t;
|
||||
BEGIN
|
||||
OPEN c0 FOR SELECT 1,'b',3;
|
||||
END;
|
||||
$$
|
||||
ERROR HY000: Illegal parameter data types row<2> and row<3> for operation 'OPEN..FOR'
|
||||
CREATE PROCEDURE p1 AS
|
||||
TYPE cur0_t IS REF CURSOR RETURN pkg1.rec0_t;
|
||||
c0 cur0_t;
|
||||
v0 INT;
|
||||
v1 VARCHAR(10);
|
||||
BEGIN
|
||||
OPEN c0 FOR SELECT 1,'b';
|
||||
FETCH c0 INTO v0, v1;
|
||||
SELECT v0, v1;
|
||||
CLOSE c0;
|
||||
END;
|
||||
$$
|
||||
CALL p1;
|
||||
v0 v1
|
||||
1 b
|
||||
DROP PROCEDURE p1;
|
||||
# 3-step type in RETURN in a schema procedure
|
||||
CREATE PROCEDURE p1 AS
|
||||
TYPE cur0_t IS REF CURSOR RETURN test.pkg1.rec0_t;
|
||||
c0 cur0_t;
|
||||
BEGIN
|
||||
OPEN c0 FOR SELECT 1,'b',3;
|
||||
END;
|
||||
$$
|
||||
ERROR HY000: Illegal parameter data types row<2> and row<3> for operation 'OPEN..FOR'
|
||||
CREATE PROCEDURE p1 AS
|
||||
TYPE cur0_t IS REF CURSOR RETURN test.pkg1.rec0_t;
|
||||
c0 cur0_t;
|
||||
v0 INT;
|
||||
v1 VARCHAR(10);
|
||||
BEGIN
|
||||
OPEN c0 FOR SELECT 1,'b';
|
||||
FETCH c0 INTO v0, v1;
|
||||
SELECT v0, v1;
|
||||
CLOSE c0;
|
||||
END;
|
||||
$$
|
||||
CALL p1;
|
||||
v0 v1
|
||||
1 b
|
||||
DROP PROCEDURE p1;
|
||||
# 2-step type in RETURN in another package
|
||||
CREATE PACKAGE pkg2 AS
|
||||
TYPE cur0_t IS REF CURSOR RETURN pkg1.rec0_t;
|
||||
END;
|
||||
$$
|
||||
# 2-step cursor type with 2-step type in RETURN
|
||||
CREATE PROCEDURE p1 AS
|
||||
c0 pkg2.cur0_t;
|
||||
v0 INT;
|
||||
v1 VARCHAR(10);
|
||||
BEGIN
|
||||
OPEN c0 FOR SELECT 1,'b';
|
||||
FETCH c0 INTO v0, v1;
|
||||
SELECT v0, v1;
|
||||
CLOSE c0;
|
||||
END;
|
||||
$$
|
||||
CALL p1;
|
||||
v0 v1
|
||||
1 b
|
||||
DROP PROCEDURE p1;
|
||||
# 3-step cursor type with 2-step type in RETURN
|
||||
CREATE PROCEDURE p1 AS
|
||||
c0 test.pkg2.cur0_t;
|
||||
v0 INT;
|
||||
v1 VARCHAR(10);
|
||||
BEGIN
|
||||
OPEN c0 FOR SELECT 1,'b';
|
||||
FETCH c0 INTO v0, v1;
|
||||
SELECT v0, v1;
|
||||
CLOSE c0;
|
||||
END;
|
||||
$$
|
||||
CALL p1;
|
||||
v0 v1
|
||||
1 b
|
||||
DROP PROCEDURE p1;
|
||||
# 3-step cursor type (different db) with 2-step type in RETURN
|
||||
CREATE DATABASE test1;
|
||||
USE test1;
|
||||
CREATE PROCEDURE p1 AS
|
||||
c0 test.pkg2.cur0_t;
|
||||
v0 INT;
|
||||
v1 VARCHAR(10);
|
||||
BEGIN
|
||||
OPEN c0 FOR SELECT 1,'b';
|
||||
FETCH c0 INTO v0, v1;
|
||||
SELECT v0, v1;
|
||||
CLOSE c0;
|
||||
END;
|
||||
$$
|
||||
CALL p1;
|
||||
v0 v1
|
||||
1 b
|
||||
DROP PROCEDURE p1;
|
||||
DROP DATABASE test1;
|
||||
USE test;
|
||||
DROP PACKAGE pkg2;
|
||||
DROP PACKAGE pkg1;
|
||||
#
|
||||
# MDEV-40420 ASAN : SIGSEGV in Sp_handler::db_find_routine | Sp_handler::db_find_and_cache_routine
|
||||
#
|
||||
CREATE DATABASE db1;
|
||||
USE db1;
|
||||
CREATE PACKAGE a_pkg AS
|
||||
TYPE arec IS RECORD (x INT, y VARCHAR(10));
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE b_pkg AS
|
||||
TYPE brec IS RECORD (p INT, q VARCHAR(10));
|
||||
TYPE bcur IS REF CURSOR RETURN a_pkg.arec;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE a_pkg AS
|
||||
TYPE arec IS RECORD (x INT, y VARCHAR(10));
|
||||
TYPE acur IS REF CURSOR RETURN b_pkg.brec;
|
||||
END;
|
||||
$$
|
||||
ERROR HY000: Unknown data type: '`b_pkg`.`brec`'
|
||||
# Inject manually a bad CREATE PACKAGE with cyclic dependency
|
||||
SELECT `body` FROM mysql.proc WHERE db='db1' AND name='a_pkg';
|
||||
body
|
||||
AS
|
||||
TYPE arec IS RECORD (x INT, y VARCHAR(10));
|
||||
END
|
||||
UPDATE mysql.proc SET `body`='AS
|
||||
TYPE arec IS RECORD (x INT, y VARCHAR(10));
|
||||
TYPE acur IS REF CURSOR RETURN b_pkg.brec;
|
||||
END'
|
||||
WHERE db='db1' AND name='a_pkg';
|
||||
# Check that it's not allowed to create a PROCEDURE using a
|
||||
# manually injected PACKAGE with a cycle dependency
|
||||
CREATE PROCEDURE p_cycle AS
|
||||
c a_pkg.acur;
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
ERROR HY000: Thread stack overrun: XXX bytes used of a XXX byte stack, and XXX bytes needed. Consider increasing the thread_stack system variable.
|
||||
# The same, after SP cache invalidating
|
||||
SET sql_mode=DEFAULT;
|
||||
# source invalidate_sp_cache.inc
|
||||
SET sql_mode=ORACLE;
|
||||
CREATE PROCEDURE p_cycle AS
|
||||
c a_pkg.acur;
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
ERROR HY000: Thread stack overrun: XXX bytes used of a XXX byte stack, and XXX bytes needed. Consider increasing the thread_stack system variable.
|
||||
# Check that a manually injected PACKAGE with a cycle dependency
|
||||
# can be fixed using CREATE OR REPLACE
|
||||
CREATE OR REPLACE PACKAGE a_pkg AS
|
||||
TYPE arec IS RECORD (x INT, y VARCHAR(10));
|
||||
END;
|
||||
$$
|
||||
DROP DATABASE db1;
|
||||
USE test;
|
||||
# The same layout, with 3-step data type references
|
||||
CREATE DATABASE db1;
|
||||
CREATE DATABASE db2;
|
||||
CREATE PACKAGE db1.a_pkg AS
|
||||
TYPE arec IS RECORD (x INT, y VARCHAR(10));
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE db2.b_pkg AS
|
||||
TYPE brec IS RECORD (p INT, q VARCHAR(10));
|
||||
TYPE bcur IS REF CURSOR RETURN db1.a_pkg.arec;
|
||||
END;
|
||||
$$
|
||||
CREATE OR REPLACE PACKAGE db1.a_pkg AS
|
||||
TYPE arec IS RECORD (x INT, y VARCHAR(10));
|
||||
TYPE acur IS REF CURSOR RETURN db2.b_pkg.brec;
|
||||
END;
|
||||
$$
|
||||
ERROR HY000: Unknown data type: '`db2`.`b_pkg`.`brec`'
|
||||
DROP DATABASE db2;
|
||||
DROP DATABASE db1;
|
||||
#
|
||||
# MDEV-40468 Package that contains a self reference package refcursor crashes the server
|
||||
#
|
||||
CREATE DATABASE db1;
|
||||
USE db1;
|
||||
CREATE TABLE t1 (a INT, b VARCHAR(32));
|
||||
INSERT INTO t1 VALUES (1,'one'),(2,'two');
|
||||
CREATE PACKAGE pkg AS
|
||||
TYPE rec IS RECORD (a INT, b VARCHAR(32));
|
||||
TYPE cur IS REF CURSOR RETURN pkg.rec; -- 2-step self reference
|
||||
END;
|
||||
$$
|
||||
CREATE PROCEDURE p2 AS
|
||||
TYPE localcur IS REF CURSOR RETURN pkg.rec;
|
||||
c localcur;
|
||||
v pkg.rec;
|
||||
BEGIN
|
||||
OPEN c FOR SELECT a,b FROM t1;
|
||||
FETCH c INTO v;
|
||||
CLOSE c;
|
||||
END;
|
||||
$$
|
||||
CALL p2;
|
||||
DROP DATABASE db1;
|
||||
USE test;
|
||||
CREATE DATABASE db1;
|
||||
USE db1;
|
||||
CREATE TABLE t1 (a INT, b VARCHAR(32));
|
||||
INSERT INTO t1 VALUES (1,'one'),(2,'two');
|
||||
CREATE PACKAGE pkg AS
|
||||
TYPE rec IS RECORD (a INT, b VARCHAR(32));
|
||||
TYPE cur IS REF CURSOR RETURN db1.pkg.rec; -- 3-step self-reference
|
||||
END;
|
||||
$$
|
||||
CREATE PROCEDURE p2 AS
|
||||
TYPE localcur IS REF CURSOR RETURN pkg.rec;
|
||||
c localcur;
|
||||
v pkg.rec;
|
||||
BEGIN
|
||||
OPEN c FOR SELECT a,b FROM t1;
|
||||
FETCH c INTO v;
|
||||
CLOSE c;
|
||||
END;
|
||||
$$
|
||||
CALL p2;
|
||||
DROP DATABASE db1;
|
||||
USE test;
|
||||
#
|
||||
# MDEV-40640 Assertion `li->sphead' failed in bool LEX::sp_package_spec_check_cyclic_dependency(THD *, const Lex_ident_sys_st &, const Lex_ident_sys_st &) const
|
||||
#
|
||||
CREATE PACKAGE p1 AS TYPE r IS RECORD(x INT); END;$$
|
||||
CREATE PACKAGE p2 AS TYPE r IS RECORD(x INT); TYPE c IS REF CURSOR RETURN p1.r; END;$$
|
||||
SHOW CREATE PACKAGE p2;
|
||||
Package sql_mode Create Package character_set_client collation_connection Database Collation
|
||||
p2 PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ORACLE,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,NO_AUTO_CREATE_USER,SIMULTANEOUS_ASSIGNMENT CREATE DEFINER="root"@"localhost" PACKAGE "p2" AS TYPE r IS RECORD(x INT); TYPE c IS REF CURSOR RETURN p1.r; END latin1 latin1_swedish_ci utf8mb4_uca1400_ai_ci
|
||||
DROP PACKAGE p2;
|
||||
DROP PACKAGE p1;
|
||||
# Replacing the dependency package and removing the type
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE rec0_t IS RECORD (a INT, b VARCHAR(10));
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE pkg2 AS
|
||||
TYPE cur1_t IS REF CURSOR RETURN pkg1.rec0_t;
|
||||
END
|
||||
$$
|
||||
SHOW CREATE PACKAGE pkg2;
|
||||
Package sql_mode Create Package character_set_client collation_connection Database Collation
|
||||
pkg2 PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ORACLE,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,NO_AUTO_CREATE_USER,SIMULTANEOUS_ASSIGNMENT CREATE DEFINER="root"@"localhost" PACKAGE "pkg2" AS
|
||||
TYPE cur1_t IS REF CURSOR RETURN pkg1.rec0_t;
|
||||
END latin1 latin1_swedish_ci utf8mb4_uca1400_ai_ci
|
||||
CREATE OR REPLACE PACKAGE pkg1 AS
|
||||
TYPE rec1_t IS RECORD (a INT, b VARCHAR(10)); -- There is no rec0_t any more
|
||||
END;
|
||||
$$
|
||||
SHOW CREATE PACKAGE pkg2;
|
||||
ERROR HY000: Unknown data type: '`test`.`pkg1`.`rec0_t`'
|
||||
DROP PACKAGE pkg2;
|
||||
DROP PACKAGE pkg1;
|
||||
# Dropping the dependency package
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE rec0_t IS RECORD (a INT, b VARCHAR(10));
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE pkg2 AS
|
||||
TYPE cur1_t IS REF CURSOR RETURN pkg1.rec0_t;
|
||||
END
|
||||
$$
|
||||
SHOW CREATE PACKAGE pkg2;
|
||||
Package sql_mode Create Package character_set_client collation_connection Database Collation
|
||||
pkg2 PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ORACLE,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,NO_AUTO_CREATE_USER,SIMULTANEOUS_ASSIGNMENT CREATE DEFINER="root"@"localhost" PACKAGE "pkg2" AS
|
||||
TYPE cur1_t IS REF CURSOR RETURN pkg1.rec0_t;
|
||||
END latin1 latin1_swedish_ci utf8mb4_uca1400_ai_ci
|
||||
DROP PACKAGE pkg1;
|
||||
SHOW CREATE PACKAGE pkg2;
|
||||
ERROR HY000: Unknown data type: '`pkg1`.`rec0_t`'
|
||||
DROP PACKAGE pkg2;
|
||||
@@ -0,0 +1,13 @@
|
||||
SET sql_mode=ORACLE;
|
||||
#
|
||||
# MDEV-39587 Package-wide TYPE for variable declarations
|
||||
#
|
||||
#
|
||||
# MDEV-40597 UBSAN | SIGSEGV in ORAparse | parse_sql | sp_compile | Sp_handler::db_load_routine
|
||||
#
|
||||
CREATE DATABASE db1;
|
||||
USE db1;
|
||||
CREATE PACKAGE pkg1500 AS TYPE rec IS RECORD(x INT); END;$$
|
||||
ER_STACK_OVERRUN_NEED_MORE reached;
|
||||
DROP DATABASE db1;
|
||||
USE test;
|
||||
@@ -0,0 +1,84 @@
|
||||
SET sql_mode=ORACLE;
|
||||
#
|
||||
# MDEV-39587 Package-wide TYPE for variable declarations
|
||||
#
|
||||
#
|
||||
# MDEV-40436 Trigger using a package-defined type is silently lost during mariadb-dump / restore
|
||||
#
|
||||
CREATE DATABASE db1;
|
||||
USE db1;
|
||||
CREATE PACKAGE pkg AS
|
||||
TYPE rec IS RECORD (a INT, b VARCHAR(20));
|
||||
END;
|
||||
$$
|
||||
CREATE TABLE t1 (id INT, val VARCHAR(20));
|
||||
CREATE TRIGGER trg BEFORE INSERT ON t1
|
||||
FOR EACH ROW
|
||||
DECLARE
|
||||
r pkg.rec;
|
||||
BEGIN
|
||||
:NEW.val := CONCAT('r-', :NEW.id);
|
||||
END;
|
||||
$$
|
||||
ERROR HY000: Incorrect usage of TRIGGER and `pkg`.`rec`
|
||||
CREATE TRIGGER trg BEFORE INSERT ON t1
|
||||
FOR EACH ROW
|
||||
DECLARE
|
||||
r db1.pkg.rec;
|
||||
BEGIN
|
||||
:NEW.val := CONCAT('r-', :NEW.id);
|
||||
END;
|
||||
$$
|
||||
ERROR HY000: Incorrect usage of TRIGGER and `db1`.`pkg`.`rec`
|
||||
DROP DATABASE db1;
|
||||
USE test;
|
||||
CREATE PACKAGE pkg AS
|
||||
TYPE rec IS RECORD (a INT);
|
||||
END;
|
||||
$$
|
||||
CREATE TABLE t1 (a INT);
|
||||
CREATE TRIGGER trg BEFORE INSERT ON t1
|
||||
FOR EACH ROW
|
||||
DECLARE
|
||||
TYPE c IS REF CURSOR RETURN pkg.rec;
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
ERROR HY000: Incorrect usage of TRIGGER and `pkg`.`rec`
|
||||
CREATE TRIGGER trg BEFORE INSERT ON t1
|
||||
FOR EACH ROW
|
||||
DECLARE
|
||||
TYPE c IS REF CURSOR RETURN test.pkg.rec;
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
ERROR HY000: Incorrect usage of TRIGGER and `test`.`pkg`.`rec`
|
||||
DROP TABLE t1;
|
||||
DROP PACKAGE pkg;
|
||||
CREATE PACKAGE pkg AS
|
||||
TYPE rec IS RECORD (a INT);
|
||||
END;
|
||||
$$
|
||||
CREATE TABLE t1 (a INT);
|
||||
CREATE TRIGGER trg BEFORE INSERT ON t1
|
||||
FOR EACH ROW
|
||||
DECLARE
|
||||
TYPE c IS TABLE OF pkg.rec INDEX BY int;
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
ERROR HY000: Incorrect usage of TRIGGER and `pkg`.`rec`
|
||||
CREATE TRIGGER trg BEFORE INSERT ON t1
|
||||
FOR EACH ROW
|
||||
DECLARE
|
||||
TYPE c IS TABLE OF test.pkg.rec INDEX BY int;
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
ERROR HY000: Incorrect usage of TRIGGER and `test`.`pkg`.`rec`
|
||||
DROP TABLE t1;
|
||||
DROP PACKAGE pkg;
|
||||
156
mysql-test/suite/compat/oracle/r/sp-package-spec-type.result
Normal file
156
mysql-test/suite/compat/oracle/r/sp-package-spec-type.result
Normal file
@@ -0,0 +1,156 @@
|
||||
SET sql_mode=ORACLE;
|
||||
SET NAMES utf8mb3;
|
||||
#
|
||||
# MDEV-39587 Package-wide TYPE for variable declarations
|
||||
#
|
||||
# raise_unknown_data_type
|
||||
CREATE PROCEDURE p1 AS
|
||||
a aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa;
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
ERROR HY000: Unknown data type: '`aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa`.`aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa`'
|
||||
CREATE PROCEDURE p1 AS
|
||||
a aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa;
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
ERROR HY000: Unknown data type: '`aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa`.`aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa`.`aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa`'
|
||||
CREATE PROCEDURE p1 AS
|
||||
a åååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååå.
|
||||
åååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååå;
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
ERROR HY000: Unknown data type: '`åååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååå`.`åååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååå`'
|
||||
CREATE PROCEDURE p1 AS
|
||||
a åååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååå.
|
||||
åååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååå.
|
||||
åååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååå;
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
ERROR HY000: Unknown data type: '`åååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååå`.`åååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååå`.'
|
||||
CREATE PROCEDURE p1 AS
|
||||
a €€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€.
|
||||
€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€;
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
ERROR HY000: Unknown data type: '`€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€`.'
|
||||
CREATE PROCEDURE p1 AS
|
||||
a €€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€.
|
||||
€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€.
|
||||
€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€;
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
ERROR HY000: Unknown data type: '`€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€`..'
|
||||
# PACKAGE gets dropped making an orphan type reference: 2-step
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE rec0_t IS RECORD(a INT, b VARCHAR(30));
|
||||
END;
|
||||
$$
|
||||
CREATE PROCEDURE p1 AS
|
||||
r0 pkg1.rec0_t;
|
||||
BEGIN
|
||||
r0.a:= 10;
|
||||
r0.b:= 'b';
|
||||
SELECT r0.a, r0.b;
|
||||
END;
|
||||
$$
|
||||
CALL p1;
|
||||
r0.a r0.b
|
||||
10 b
|
||||
DROP PACKAGE pkg1;
|
||||
CALL p1;
|
||||
ERROR HY000: Failed to load routine test.p1 (internal code -6). For more details, run SHOW WARNINGS
|
||||
SHOW WARNINGS;
|
||||
Level Code Message
|
||||
Error 4161 Unknown data type: '`pkg1`.`rec0_t`'
|
||||
Error 1457 Failed to load routine test.p1 (internal code -6). For more details, run SHOW WARNINGS
|
||||
DROP PROCEDURE p1;
|
||||
# PACKAGE gets dropped making an orphan type reference: 3-step
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE rec0_t IS RECORD(a INT, b VARCHAR(30));
|
||||
END;
|
||||
$$
|
||||
CREATE DATABASE test1;
|
||||
USE test1;
|
||||
CREATE PROCEDURE p1 AS
|
||||
r0 test.pkg1.rec0_t;
|
||||
BEGIN
|
||||
r0.a:= 10;
|
||||
r0.b:= 'b';
|
||||
SELECT r0.a, r0.b;
|
||||
END;
|
||||
$$
|
||||
CALL p1;
|
||||
r0.a r0.b
|
||||
10 b
|
||||
DROP PACKAGE test.pkg1;
|
||||
CALL p1;
|
||||
ERROR HY000: Failed to load routine test1.p1 (internal code -6). For more details, run SHOW WARNINGS
|
||||
SHOW WARNINGS;
|
||||
Level Code Message
|
||||
Error 4161 Unknown data type: '`test`.`pkg1`.`rec0_t`'
|
||||
Error 1457 Failed to load routine test1.p1 (internal code -6). For more details, run SHOW WARNINGS
|
||||
DROP PROCEDURE p1;
|
||||
DROP DATABASE test1;
|
||||
USE test;
|
||||
# Too long identifier chain
|
||||
CREATE PROCEDURE p1 AS
|
||||
v1 cat1.db1.pkg1.type1;
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
ERROR HY000: Unknown data type: '`cat1`.`db1`.`pkg1`'
|
||||
#
|
||||
# MDEV-40155 Weak REF CURSOR without RETURN is not opened using a dynamic SQL statement
|
||||
#
|
||||
CREATE TABLE t (id INT, name VARCHAR(100));
|
||||
INSERT INTO t VALUES (1,'Test');
|
||||
CREATE PACKAGE pc AS TYPE wc IS REF CURSOR; END;
|
||||
$$
|
||||
CREATE PROCEDURE pdyn AS
|
||||
c pc.wc;
|
||||
vi INT;
|
||||
vn VARCHAR(100);
|
||||
BEGIN
|
||||
OPEN c FOR 'SELECT id, name FROM t';
|
||||
FETCH c INTO vi, vn;
|
||||
SELECT vi, vn;
|
||||
CLOSE c;
|
||||
END;
|
||||
$$
|
||||
CALL pdyn;
|
||||
vi vn
|
||||
1 Test
|
||||
DROP PROCEDURE pdyn;
|
||||
DROP PACKAGE pc;
|
||||
DROP TABLE t;
|
||||
#
|
||||
# MDEV-40153 Assertion `rec->field->head()->charset == nullptr' failed in virtual bool Type_handler_row::Column_definition_prepare_stage1(THD *, MEM_ROOT *, Column_definition *, column_definition_type_t, const Column_derived_attributes *) const
|
||||
#
|
||||
CREATE PACKAGE pk_crash AS
|
||||
TYPE r IS RECORD (b BLOB);
|
||||
FUNCTION f RETURN r;
|
||||
END;
|
||||
$$
|
||||
DROP PACKAGE pk_crash;
|
||||
CREATE PACKAGE pk_crash AS
|
||||
TYPE rec0_t IS RECORD (b BLOB);
|
||||
FUNCTION f(r rec0_t) RETURN INT;
|
||||
END;
|
||||
$$
|
||||
DROP PACKAGE pk_crash;
|
||||
@@ -126,7 +126,7 @@ DROP TABLE t1;
|
||||
#
|
||||
# Qualified syntax is not supported yet in SP
|
||||
# See MDEV-23353 Qualified data types in SP
|
||||
# For now it's trying to parse as "RETURN mariadb_schema.DATE%ROWTYPE"
|
||||
# For now it's trying to parse mariadb_schema as a package name
|
||||
#
|
||||
SET sql_mode=ORACLE;
|
||||
CREATE FUNCTION f1() RETURN mariadb_schema.DATE AS
|
||||
@@ -134,26 +134,17 @@ BEGIN
|
||||
RETURN CURRENT_DATE;
|
||||
END;
|
||||
$$
|
||||
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'AS
|
||||
BEGIN
|
||||
RETURN CURRENT_DATE;
|
||||
END' at line 2
|
||||
ERROR HY000: Unknown data type: '`mariadb_schema`.`DATE`'
|
||||
CREATE PROCEDURE p1(a mariadb_schema.DATE) AS
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ') AS
|
||||
BEGIN
|
||||
NULL;
|
||||
END' at line 1
|
||||
ERROR HY000: Unknown data type: '`mariadb_schema`.`DATE`'
|
||||
CREATE PROCEDURE p1() AS
|
||||
a mariadb_schema.DATE;
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ';
|
||||
BEGIN
|
||||
NULL;
|
||||
END' at line 2
|
||||
ERROR HY000: Unknown data type: '`mariadb_schema`.`DATE`'
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
SET sql_mode=ORACLE;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-39587 Package-wide TYPE for variable declarations
|
||||
--echo #
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-40148 Package spec RECORD-field %TYPE anchor is broken
|
||||
--echo #
|
||||
|
||||
# Two step reference from a procedure to a package spec
|
||||
CREATE TABLE t (id INT, name VARCHAR(100));
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkga AS
|
||||
TYPE r IS RECORD (f t.id%TYPE);
|
||||
END;
|
||||
$$
|
||||
CREATE PROCEDURE pa AS
|
||||
v pkga.r; -- HERE
|
||||
BEGIN
|
||||
v.f := 1;
|
||||
IF v.f = 1
|
||||
THEN SELECT 'ok';
|
||||
END IF;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
CALL pa;
|
||||
DROP PROCEDURE pa;
|
||||
DROP PACKAGE pkga;
|
||||
DROP TABLE t;
|
||||
|
||||
|
||||
# Three step reference from a procedure to a package spec
|
||||
CREATE TABLE t (id INT, name VARCHAR(100));
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkga AS
|
||||
TYPE r IS RECORD (f t.id%TYPE);
|
||||
END;
|
||||
$$
|
||||
CREATE PROCEDURE pa AS
|
||||
v test.pkga.r; -- HERE
|
||||
BEGIN
|
||||
v.f := 1;
|
||||
IF v.f = 1
|
||||
THEN SELECT 'ok';
|
||||
END IF;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
CALL pa;
|
||||
DROP PROCEDURE pa;
|
||||
DROP PACKAGE pkga;
|
||||
DROP TABLE t;
|
||||
|
||||
|
||||
# Two step reference from a package spec to the same package spec
|
||||
CREATE TABLE t (id INT, name VARCHAR(100));
|
||||
INSERT INTO t VALUES (10,'n10');
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkga AS
|
||||
TYPE rec0_t IS RECORD (id t.id%TYPE, name t.name%TYPE);
|
||||
TYPE cur0_t IS REF CURSOR RETURN pkga.rec0_t; -- HERE
|
||||
END;
|
||||
$$
|
||||
CREATE PROCEDURE pa AS
|
||||
c0 pkga.cur0_t;
|
||||
r0 pkga.rec0_t;
|
||||
BEGIN
|
||||
OPEN c0 FOR SELECT id, name FROM t;
|
||||
FETCH c0 INTO r0;
|
||||
CLOSE c0;
|
||||
SELECT r0.id, r0.name;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
CALL pa;
|
||||
DROP PROCEDURE pa;
|
||||
DROP PACKAGE pkga;
|
||||
DROP TABLE t;
|
||||
|
||||
|
||||
# Three step reference from a package spec to the same package spec
|
||||
CREATE TABLE t (id INT, name VARCHAR(100));
|
||||
INSERT INTO t VALUES (10,'n10');
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkga AS
|
||||
TYPE rec0_t IS RECORD (id t.id%TYPE, name t.name%TYPE);
|
||||
TYPE cur0_t IS REF CURSOR RETURN test.pkga.rec0_t; -- HERE
|
||||
END;
|
||||
$$
|
||||
CREATE PROCEDURE pa AS
|
||||
c0 pkga.cur0_t;
|
||||
r0 pkga.rec0_t;
|
||||
BEGIN
|
||||
OPEN c0 FOR SELECT id, name FROM t;
|
||||
FETCH c0 INTO r0;
|
||||
CLOSE c0;
|
||||
SELECT r0.id, r0.name;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
CALL pa;
|
||||
DROP PROCEDURE pa;
|
||||
DROP PACKAGE pkga;
|
||||
DROP TABLE t;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-40216 Assertion `thd->is_error() || thd->killed' failed in bool do_execute_sp(THD *, sp_head *)
|
||||
--echo #
|
||||
|
||||
CREATE TABLE tb (c_int INT);
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pk AS
|
||||
TYPE rec IS RECORD (f tb.c_int%TYPE);
|
||||
TYPE aa IS TABLE OF INT INDEX BY INTEGER;
|
||||
END;
|
||||
$$
|
||||
CREATE PROCEDURE p AS
|
||||
r pk.rec;
|
||||
v pk.aa;
|
||||
BEGIN
|
||||
r.f := 5;
|
||||
v(r.f) := 99;
|
||||
SELECT v(5);
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
CALL p;
|
||||
DROP PROCEDURE p;
|
||||
DROP PACKAGE pk;
|
||||
DROP TABLE tb;
|
||||
675
mysql-test/suite/compat/oracle/t/sp-package-spec-type-assoc.test
Normal file
675
mysql-test/suite/compat/oracle/t/sp-package-spec-type-assoc.test
Normal file
@@ -0,0 +1,675 @@
|
||||
SET sql_mode=ORACLE;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-39587 Package-wide TYPE for variable declarations
|
||||
--echo #
|
||||
|
||||
--echo # A too long identifier chain in the TABLE OF type
|
||||
|
||||
DELIMITER $$;
|
||||
--error ER_UNKNOWN_DATA_TYPE
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE assoc0_t IS TABLE OF cat1.db1.pkg1.rec1_t INDEX BY INTEGER;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
|
||||
--echo # Assoc array cannot have attributes
|
||||
--echo # Currently this is not allowed by the parser in qualified types
|
||||
--echo # If we ever allow, make sure to call check_data_type_attributes()
|
||||
--echo # which will raise ER_UNSUPPORTED_DATA_TYPE_ATTRIBUTE
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE rec0_t IS RECORD (a INT, b VARCHAR(32));
|
||||
TYPE assoc0_t IS TABLE OF rec0_t INDEX BY INTEGER;
|
||||
END;
|
||||
$$
|
||||
--error ER_PARSE_ERROR
|
||||
CREATE PROCEDURE p1 AS
|
||||
r0 pkg1.assoc0_t (0); -- Length attribute
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
--error ER_PARSE_ERROR
|
||||
CREATE PROCEDURE p1 AS
|
||||
r0 pkg1.assoc0_t (0,0); -- Length and dec attributes
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
--error ER_PARSE_ERROR
|
||||
CREATE PROCEDURE p1 AS
|
||||
r0 pkg1.assoc0_t CHARACTER SET latin1;
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
--error ER_PARSE_ERROR
|
||||
CREATE PROCEDURE p1 AS
|
||||
r0 pkg1.assoc0_t COLLATE latin1_bin;
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
DROP PACKAGE pkg1;
|
||||
|
||||
|
||||
--echo # PACKAGE spec types cannot be used in schema routine parameters
|
||||
--echo # and schema function RETURN
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE rec0_t IS RECORD (a INT, b VARCHAR(10));
|
||||
TYPE assoc0_t IS TABLE OF rec0_t INDEX BY INTEGER;
|
||||
END;
|
||||
$$
|
||||
--error ER_WRONG_USAGE
|
||||
CREATE PROCEDURE p1(a pkg1.assoc0_t) AS
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
--error ER_WRONG_USAGE
|
||||
CREATE FUNCTION f1 RETURN pkg1.assoc0_t AS
|
||||
BEGIN
|
||||
RETURN NULL;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
DROP PACKAGE pkg1;
|
||||
|
||||
|
||||
--echo # A package routine parameter and a package function RETURN
|
||||
--echo # 2-step
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE rec0_t IS RECORD (a INT, b VARCHAR(10));
|
||||
TYPE assoc0_t IS TABLE OF rec0_t INDEX BY INTEGER;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE pkg2 AS
|
||||
PROCEDURE p1;
|
||||
END;
|
||||
$$
|
||||
# Assoc array is not supported as a routine parameter and RETURN anyway
|
||||
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
|
||||
CREATE PACKAGE BODY pkg2 AS
|
||||
PROCEDURE p2(a pkg1.assoc0_t) AS
|
||||
BEGIN
|
||||
SELECT a(0).a, a(0).b;
|
||||
END;
|
||||
FUNCTION f1 RETURN pkg1.assoc0_t AS
|
||||
res pkg1.assoc0_t;
|
||||
BEGIN
|
||||
res(0).a:= 10;
|
||||
res(0).b:= 'b';
|
||||
RETURN res;
|
||||
END;
|
||||
PROCEDURE p1 AS
|
||||
BEGIN
|
||||
CALL p2(f1());
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
DROP PACKAGE pkg2;
|
||||
DROP PACKAGE pkg1;
|
||||
|
||||
--echo # RECORD as a package routine parameter and a package function RETURN
|
||||
--echo # 3-step
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE rec0_t IS RECORD (a INT, b VARCHAR(10));
|
||||
TYPE assoc0_t IS TABLE OF rec0_t INDEX BY INTEGER;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
CREATE DATABASE test1;
|
||||
USE test1;
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg2 AS
|
||||
PROCEDURE p1;
|
||||
END;
|
||||
$$
|
||||
# Assoc array is not supported as a routine parameter and RETURN anyway
|
||||
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
|
||||
CREATE PACKAGE BODY pkg2 AS
|
||||
PROCEDURE p2(a test.pkg1.assoc0_t) AS
|
||||
BEGIN
|
||||
SELECT a(0).a, a(0).b;
|
||||
END;
|
||||
FUNCTION f1 RETURN test.pkg1.assoc0_t AS
|
||||
res test.pkg1.assoc0_t;
|
||||
BEGIN
|
||||
res(0).a:= 10;
|
||||
res(0).b:= 'b';
|
||||
RETURN res;
|
||||
END;
|
||||
PROCEDURE p1 AS
|
||||
BEGIN
|
||||
CALL p2(f1());
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
DROP PACKAGE pkg2;
|
||||
DROP DATABASE test1;
|
||||
USE test;
|
||||
DROP PACKAGE pkg1;
|
||||
|
||||
|
||||
--echo # A self-reference to the current spec with error: 2-step
|
||||
|
||||
DELIMITER $$;
|
||||
--error ER_UNKNOWN_DATA_TYPE
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE assoc0_t IS TABLE OF pkg1.rec0_t INDEX BY INTEGER;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
CREATE DATABASE test1;
|
||||
DELIMITER $$;
|
||||
--error ER_UNKNOWN_DATA_TYPE
|
||||
CREATE PACKAGE test1.pkg1 AS
|
||||
TYPE assoc0_t IS TABLE OF pkg1.rec0_t INDEX BY INTEGER;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
DROP DATABASE test1;
|
||||
|
||||
|
||||
--echo # A self-reference to the current spec with success: 2-step
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE rec0_t IS RECORD (a INT, b VARCHAR(32));
|
||||
TYPE assoc0_t IS TABLE OF pkg1.rec0_t INDEX BY INTEGER;
|
||||
END;
|
||||
$$
|
||||
CREATE PROCEDURE p1 AS
|
||||
r0 pkg1.rec0_t;
|
||||
a0 pkg1.assoc0_t;
|
||||
BEGIN
|
||||
r0.a:= 10;
|
||||
r0.b:= 'b';
|
||||
SELECT r0.a, r0.b;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
CALL p1;
|
||||
DROP PROCEDURE p1;
|
||||
DROP PACKAGE pkg1;
|
||||
|
||||
CREATE DATABASE test1;
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE test1.pkg1 AS
|
||||
TYPE rec0_t IS RECORD (a INT, b VARCHAR(32));
|
||||
TYPE assoc0_t IS TABLE OF pkg1.rec0_t INDEX BY INTEGER;
|
||||
END;
|
||||
$$
|
||||
CREATE PROCEDURE test1.p1 AS
|
||||
r0 pkg1.rec0_t; -- This refers to test1.pkg1.rec0_t
|
||||
a0 pkg1.assoc0_t; -- This refers to test1.pkg1.assoc0_t
|
||||
BEGIN
|
||||
r0.a:= 10;
|
||||
r0.b:= 'b';
|
||||
SELECT r0.a, r0.b;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
CALL test1.p1;
|
||||
DROP PROCEDURE test1.p1;
|
||||
DROP PACKAGE test1.pkg1;
|
||||
DROP DATABASE test1;
|
||||
USE test;
|
||||
|
||||
|
||||
--echo # A self-reference to the current spec with error: 3-step
|
||||
|
||||
DELIMITER $$;
|
||||
--error ER_UNKNOWN_DATA_TYPE
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE assoc0_t IS TABLE OF test.pkg1.rec0_t INDEX BY INTEGER;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
CREATE DATABASE test1;
|
||||
DELIMITER $$;
|
||||
--error ER_UNKNOWN_DATA_TYPE
|
||||
CREATE PACKAGE test1.pkg1 AS
|
||||
TYPE assoc0_t IS TABLE OF test1.pkg1.rec0_t INDEX BY INTEGER;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
DROP DATABASE test1;
|
||||
|
||||
|
||||
--echo # A self-reference to the current spec with success: 3-step
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE rec0_t IS RECORD (a INT, b VARCHAR(32));
|
||||
TYPE assoc0_t IS TABLE OF test.pkg1.rec0_t INDEX BY INTEGER;
|
||||
END;
|
||||
$$
|
||||
CREATE PROCEDURE p1 AS
|
||||
r0 pkg1.rec0_t;
|
||||
a0 pkg1.assoc0_t;
|
||||
BEGIN
|
||||
r0.a:= 10;
|
||||
r0.b:= 'b';
|
||||
SELECT r0.a, r0.b;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
CALL p1;
|
||||
DROP PROCEDURE p1;
|
||||
DROP PACKAGE pkg1;
|
||||
|
||||
|
||||
CREATE DATABASE test1;
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE test1.pkg1 AS
|
||||
TYPE rec0_t IS RECORD (a INT, b VARCHAR(32));
|
||||
TYPE assoc0_t IS TABLE OF test1.pkg1.rec0_t INDEX BY INTEGER;
|
||||
END;
|
||||
$$
|
||||
CREATE PROCEDURE test1.p1 AS
|
||||
r0 pkg1.rec0_t; -- This refers to test1.pkg1.rec0_t
|
||||
a0 pkg1.assoc0_t; -- This refers to test1.pkg1.assoc0_t
|
||||
BEGIN
|
||||
r0.a:= 10;
|
||||
r0.b:= 'b';
|
||||
SELECT r0.a, r0.b;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
CALL test1.p1;
|
||||
DROP PROCEDURE test1.p1;
|
||||
DROP PACKAGE test1.pkg1;
|
||||
DROP DATABASE test1;
|
||||
|
||||
|
||||
--echo # Various working examples
|
||||
CREATE TABLE t1 (a INT, b VARCHAR(30));
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE varchar_array IS TABLE OF VARCHAR(2000) INDEX BY INTEGER;
|
||||
TYPE rec0_t IS RECORD(a INT, b VARCHAR(30));
|
||||
TYPE array0_t IS TABLE OF rec0_t INDEX BY INTEGER;
|
||||
TYPE array1_t IS TABLE OF test.t1.a%TYPE INDEX BY INTEGER;
|
||||
TYPE array2_t IS TABLE OF test.t1%ROWTYPE INDEX BY INTEGER;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
--echo # 2-Step + PROCEDURE
|
||||
DELIMITER $$;
|
||||
CREATE PROCEDURE p1 AS
|
||||
v0 pkg1.varchar_array;
|
||||
v1 pkg1.rec0_t;
|
||||
v2 pkg1.array0_t;
|
||||
v3 pkg1.array1_t;
|
||||
v4 pkg1.array2_t;
|
||||
BEGIN
|
||||
v0(0):='test';
|
||||
SELECT v0(0);
|
||||
v1.a:= 1;
|
||||
v1.b:= 'b';
|
||||
SELECT v1.a, v1.b;
|
||||
v2(0):= v1;
|
||||
SELECT v2(0).a, v2(0).b;
|
||||
v3(0):= 10;
|
||||
SELECT v3(0);
|
||||
v4(0):= v1;
|
||||
SELECT v4(0).a, v4(0).b;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
CALL p1;
|
||||
DROP PROCEDURE p1;
|
||||
|
||||
--echo # 3-Step + PROCEDURE
|
||||
CREATE DATABASE test1;
|
||||
USE test1;
|
||||
DELIMITER $$;
|
||||
CREATE PROCEDURE p1 AS
|
||||
v0 test.pkg1.varchar_array;
|
||||
v1 test.pkg1.rec0_t;
|
||||
v2 test.pkg1.array0_t;
|
||||
v3 test.pkg1.array1_t;
|
||||
v4 test.pkg1.array2_t;
|
||||
BEGIN
|
||||
v0(0):='test';
|
||||
SELECT v0(0);
|
||||
v1.a:= 1;
|
||||
v1.b:= 'b';
|
||||
SELECT v1.a, v1.b;
|
||||
v2(0):= v1;
|
||||
SELECT v2(0).a, v2(0).b;
|
||||
v3(0):= 10;
|
||||
SELECT v3(0);
|
||||
v4(0):= v1;
|
||||
SELECT v4(0).a, v4(0).b;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
CALL p1;
|
||||
DROP PROCEDURE p1;
|
||||
DROP DATABASE test1;
|
||||
USE test;
|
||||
|
||||
--echo # 2-Step + PACKAGE + Declarations in package PROCEDURE
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg2 AS
|
||||
PROCEDURE p1;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg2 AS
|
||||
PROCEDURE p1 AS
|
||||
v0 pkg1.varchar_array;
|
||||
v1 pkg1.rec0_t;
|
||||
v2 pkg1.array0_t;
|
||||
v3 pkg1.array1_t;
|
||||
v4 pkg1.array2_t;
|
||||
BEGIN
|
||||
v0(0):='test';
|
||||
SELECT v0(0);
|
||||
v1.a:= 1;
|
||||
v1.b:= 'b';
|
||||
SELECT v1.a, v1.b;
|
||||
v2(0):= v1;
|
||||
SELECT v2(0).a, v2(0).b;
|
||||
v3(0):= 10;
|
||||
SELECT v3(0);
|
||||
v4(0):= v1;
|
||||
SELECT v4(0).a, v4(0).b;
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
CALL pkg2.p1;
|
||||
DROP PACKAGE pkg2;
|
||||
|
||||
--echo # 3-Step + PACKAGE + Declarations in package PROCEDURE
|
||||
CREATE DATABASE test1;
|
||||
USE test1;
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg2 AS
|
||||
PROCEDURE p1;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg2 AS
|
||||
PROCEDURE p1 AS
|
||||
v0 test.pkg1.varchar_array;
|
||||
v1 test.pkg1.rec0_t;
|
||||
v2 test.pkg1.array0_t;
|
||||
v3 test.pkg1.array1_t;
|
||||
v4 test.pkg1.array2_t;
|
||||
BEGIN
|
||||
v0(0):='test';
|
||||
SELECT v0(0);
|
||||
v1.a:= 1;
|
||||
v1.b:= 'b';
|
||||
SELECT v1.a, v1.b;
|
||||
v2(0):= v1;
|
||||
SELECT v2(0).a, v2(0).b;
|
||||
v3(0):= 10;
|
||||
SELECT v3(0);
|
||||
v4(0):= v1;
|
||||
SELECT v4(0).a, v4(0).b;
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
CALL pkg2.p1;
|
||||
DROP PACKAGE pkg2;
|
||||
DROP DATABASE test1;
|
||||
USE test;
|
||||
|
||||
--echo # 3-Step + PACKAGE + Declarations in PACKAGE BODY
|
||||
CREATE DATABASE test1;
|
||||
USE test1;
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg2 AS
|
||||
PROCEDURE p1;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg2 AS
|
||||
v0 test.pkg1.varchar_array;
|
||||
v1 test.pkg1.rec0_t;
|
||||
v2 test.pkg1.array0_t;
|
||||
v3 test.pkg1.array1_t;
|
||||
v4 test.pkg1.array2_t;
|
||||
PROCEDURE p1 AS
|
||||
BEGIN
|
||||
v0(0):='test';
|
||||
SELECT v0(0);
|
||||
v1.a:= 1;
|
||||
v1.b:= 'b';
|
||||
SELECT v1.a, v1.b;
|
||||
v2(0):= v1;
|
||||
SELECT v2(0).a, v2(0).b;
|
||||
v3(0):= 10;
|
||||
SELECT v3(0);
|
||||
v4(0):= v1;
|
||||
SELECT v4(0).a, v4(0).b;
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
CALL pkg2.p1;
|
||||
DROP PACKAGE pkg2;
|
||||
DROP DATABASE test1;
|
||||
USE test;
|
||||
|
||||
DROP PACKAGE pkg1;
|
||||
DROP TABLE t1;
|
||||
|
||||
|
||||
--echo # RECORD + Assoc array in different packages: 2-step
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE rec0_t IS RECORD(a INT, b VARCHAR(30));
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg2 AS
|
||||
TYPE array0_t IS TABLE OF pkg1.rec0_t INDEX BY INTEGER;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PROCEDURE p1 AS
|
||||
r0 pkg1.rec0_t;
|
||||
a0 pkg2.array0_t;
|
||||
BEGIN
|
||||
r0.a:= 10;
|
||||
r0.b:= 'b';
|
||||
a0(0):= r0;
|
||||
SELECT a0(0).a, a0(0).b;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
CALL p1;
|
||||
DROP PROCEDURE p1;
|
||||
|
||||
DROP PACKAGE pkg2;
|
||||
DROP PACKAGE pkg1;
|
||||
|
||||
|
||||
--echo # RECORD + Assoc array in different packages: 3-step
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE rec0_t IS RECORD(a INT, b VARCHAR(30));
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
CREATE DATABASE test1;
|
||||
USE test1;
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg2 AS
|
||||
TYPE array0_t IS TABLE OF test.pkg1.rec0_t INDEX BY INTEGER;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
CREATE DATABASE test2;
|
||||
USE test2;
|
||||
DELIMITER $$;
|
||||
CREATE PROCEDURE p1 AS
|
||||
r0 test.pkg1.rec0_t;
|
||||
a0 test1.pkg2.array0_t;
|
||||
BEGIN
|
||||
r0.a:= 10;
|
||||
r0.b:= 'b';
|
||||
a0(0):= r0;
|
||||
SELECT a0(0).a, a0(0).b;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
CALL p1;
|
||||
DROP PROCEDURE p1;
|
||||
DROP DATABASE test2;
|
||||
|
||||
USE test1;
|
||||
DROP PACKAGE pkg2;
|
||||
DROP DATABASE test1;
|
||||
USE test;
|
||||
DROP PACKAGE pkg1;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-40640 Assertion `li->sphead' failed in bool LEX::sp_package_spec_check_cyclic_dependency(THD *, const Lex_ident_sys_st &, const Lex_ident_sys_st &) const
|
||||
--echo #
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE p1 AS
|
||||
TYPE rec0_t IS RECORD(x INT);
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE p2 AS
|
||||
TYPE rec0_t IS RECORD(x INT);
|
||||
TYPE assoc0_t IS TABLE OF p1.rec0_t INDEX BY INTEGER;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
SHOW CREATE PACKAGE p2;
|
||||
DROP PACKAGE p2;
|
||||
DROP PACKAGE p1;
|
||||
|
||||
--echo # Replacing the dependency package and removing the type
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE p1 AS
|
||||
TYPE rec0_t IS RECORD(x INT);
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE p2 AS
|
||||
TYPE rec0_t IS RECORD(x INT);
|
||||
TYPE assoc0_t IS TABLE OF p1.rec0_t INDEX BY INTEGER;
|
||||
END;
|
||||
$$
|
||||
CREATE OR REPLACE PACKAGE p1 AS
|
||||
TYPE rec1_t IS RECORD(x INT); -- There is no type p1.rec0_t any more
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
--error ER_UNKNOWN_DATA_TYPE
|
||||
SHOW CREATE PACKAGE p2;
|
||||
DROP PACKAGE p2;
|
||||
DROP PACKAGE p1;
|
||||
|
||||
--echo # Dropping the dependency package
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE p1 AS
|
||||
TYPE rec0_t IS RECORD(x INT);
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE p2 AS
|
||||
TYPE rec0_t IS RECORD(x INT);
|
||||
TYPE assoc0_t IS TABLE OF p1.rec0_t INDEX BY INTEGER;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
DROP PACKAGE p1;
|
||||
--error ER_UNKNOWN_DATA_TYPE
|
||||
SHOW CREATE PACKAGE p2;
|
||||
DROP PACKAGE p2;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-40666 Cyclic package TYPE dependency built with associative array shows ERROR 1436 (HY000): Thread stack overrun
|
||||
--echo #
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE fa AS TYPE r IS RECORD(x INT); END;
|
||||
$$
|
||||
CREATE PACKAGE fb AS TYPE r2 IS RECORD(y INT); TYPE arr IS TABLE OF fa.r INDEX BY INTEGER; END;
|
||||
$$
|
||||
--error ER_UNKNOWN_DATA_TYPE
|
||||
CREATE OR REPLACE PACKAGE fa AS TYPE r IS RECORD(x INT); TYPE arr2 IS TABLE OF fb.r2 INDEX BY INTEGER; END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
SHOW CREATE PACKAGE fa;
|
||||
SHOW CREATE PACKAGE fb;
|
||||
DROP PACKAGE fb;
|
||||
DROP PACKAGE fa;
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE fa AS TYPE r IS RECORD(x INT); END;
|
||||
$$
|
||||
CREATE PACKAGE fb AS TYPE r2 IS RECORD(y INT); TYPE arr IS TABLE OF test.fa.r INDEX BY INTEGER; END;
|
||||
$$
|
||||
--error ER_UNKNOWN_DATA_TYPE
|
||||
CREATE OR REPLACE PACKAGE fa AS TYPE r IS RECORD(x INT); TYPE arr2 IS TABLE OF test.fb.r2 INDEX BY INTEGER; END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
SHOW CREATE PACKAGE fa;
|
||||
SHOW CREATE PACKAGE fb;
|
||||
DROP PACKAGE fb;
|
||||
DROP PACKAGE fa;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-40685 Cyclic package TYPE dependency built with stored routine shows ERROR 1436 (HY000): Thread stack overrun
|
||||
--echo #
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE fa AS
|
||||
TYPE r IS RECORD(x INT);
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE fb AS
|
||||
TYPE r2 IS RECORD(y INT);
|
||||
TYPE arr IS TABLE OF fa.r INDEX BY INTEGER;
|
||||
END;
|
||||
$$
|
||||
--error ER_UNKNOWN_DATA_TYPE
|
||||
CREATE OR REPLACE PACKAGE fa AS
|
||||
TYPE r IS RECORD(x INT);
|
||||
TYPE arr2 IS TABLE OF fb.r2 INDEX BY INTEGER;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
SHOW CREATE PACKAGE fa;
|
||||
DROP PACKAGE fa;
|
||||
DROP PACKAGE fb;
|
||||
@@ -0,0 +1,45 @@
|
||||
# Embedded server doesn't support external clients
|
||||
--source include/not_embedded.inc
|
||||
|
||||
SET sql_mode=ORACLE;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-39587 Package-wide TYPE for variable declarations
|
||||
--echo # MDEV-40114 Package-wide TYPE variable declarations fail during mariadb-dump restore
|
||||
--echo #
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE rec0_t IS RECORD (a INT, b VARCHAR(30));
|
||||
END;
|
||||
$$
|
||||
|
||||
CREATE PROCEDURE p1 AS
|
||||
r pkg1.rec0_t;
|
||||
BEGIN
|
||||
r.a:=1;
|
||||
SELECT r.a;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
--exec $MYSQL_DUMP --skip-comments --routines --databases test > $MYSQLTEST_VARDIR/tmp/b40114.sql
|
||||
|
||||
DROP DATABASE test;
|
||||
|
||||
CREATE DATABASE test;
|
||||
|
||||
--exec $MYSQL test < $MYSQLTEST_VARDIR/tmp/b40114.sql 2>&1
|
||||
|
||||
USE test;
|
||||
CALL p1;
|
||||
|
||||
SELECT routine_type, routine_name
|
||||
FROM information_schema.routines
|
||||
WHERE routine_schema='test'
|
||||
ORDER BY routine_type, routine_name;
|
||||
|
||||
--remove_file $MYSQLTEST_VARDIR/tmp/b40114.sql
|
||||
|
||||
DROP PROCEDURE p1;
|
||||
DROP PACKAGE pkg1;
|
||||
@@ -0,0 +1,25 @@
|
||||
SET sql_mode=ORACLE;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-39587 Package-wide TYPE for variable declarations
|
||||
--echo #
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-40686 Event using a package-defined type is silently lost during mariadb-dump / restore
|
||||
--echo #
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg AS
|
||||
TYPE rec IS RECORD (a INT);
|
||||
END;
|
||||
$$
|
||||
--error ER_WRONG_USAGE
|
||||
CREATE EVENT ev ON SCHEDULE EVERY 1 HOUR DO
|
||||
DECLARE
|
||||
v pkg.rec;
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
DROP PACKAGE pkg;
|
||||
@@ -0,0 +1,145 @@
|
||||
--echo # Start of allowed.inc
|
||||
|
||||
SELECT CURRENT_USER;
|
||||
|
||||
--echo #
|
||||
--echo # $acl + $user + same DB
|
||||
--echo #
|
||||
|
||||
USE test1;
|
||||
|
||||
--echo # $acl + $user + same DB + PACKAGE type in the same PACKAGE BODY
|
||||
|
||||
# Does not work !!!
|
||||
#DELIMITER $$;
|
||||
#CREATE PACKAGE BODY pkg1 AS
|
||||
# r0 rec0_t;
|
||||
#END;
|
||||
#$$
|
||||
#DELIMITER ;$$
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE BODY pkg1 AS
|
||||
r0 pkg1.rec0_t;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
DROP PACKAGE BODY pkg1;
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE BODY pkg1 AS
|
||||
r0 test1.pkg1.rec0_t;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
DROP PACKAGE BODY pkg1;
|
||||
|
||||
--echo # $acl + $user + same DB + PACKAGE type in another PACKAGE
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg2 AS
|
||||
TYPE cur1_t IS REF CURSOR RETURN pkg1.rec0_t;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
DROP PACKAGE pkg2;
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg2 AS
|
||||
TYPE cur1_t IS REF CURSOR RETURN test1.pkg1.rec0_t;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
DROP PACKAGE pkg2;
|
||||
|
||||
--echo # $acl + $user + same DB + PACKAGE type in another PACKAGE BODY
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg2 AS
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg2 AS
|
||||
TYPE cur1_t IS REF CURSOR RETURN pkg1.rec0_t;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
DROP PACKAGE pkg2;
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg2 AS
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg2 AS
|
||||
TYPE cur1_t IS REF CURSOR RETURN test1.pkg1.rec0_t;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
DROP PACKAGE pkg2;
|
||||
|
||||
|
||||
--echo # $acl + $user + same DB + PACKAGE type in a schema routine
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PROCEDURE p1 AS
|
||||
TYPE cur1_t IS REF CURSOR RETURN pkg1.rec0_t;
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
DROP PROCEDURE p1;
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PROCEDURE p1 AS
|
||||
TYPE cur1_t IS REF CURSOR RETURN test1.pkg1.rec0_t;
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
DROP PROCEDURE p1;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # $acl + $user + different DB
|
||||
--echo #
|
||||
|
||||
USE test2;
|
||||
|
||||
--echo # $acl + $user + different DB + PACKAGE type in another PACKAGE
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg2 AS
|
||||
TYPE cur1_t IS REF CURSOR RETURN test1.pkg1.rec0_t;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
DROP PACKAGE pkg2;
|
||||
|
||||
--echo # $acl + $user + different DB + PACKAGE type in another PACKAGE BODY
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg2 AS
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg2 AS
|
||||
TYPE cur1_t IS REF CURSOR RETURN test1.pkg1.rec0_t;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
DROP PACKAGE pkg2;
|
||||
|
||||
|
||||
--echo # $acl + $user + different DB + PACKAGE type in a schema routine
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PROCEDURE p1 AS
|
||||
TYPE cur1_t IS REF CURSOR RETURN test1.pkg1.rec0_t;
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
DROP PROCEDURE p1;
|
||||
|
||||
--echo # End of allowed.inc
|
||||
@@ -0,0 +1,150 @@
|
||||
--echo # Start of denied.inc
|
||||
|
||||
SELECT CURRENT_USER;
|
||||
|
||||
--echo #
|
||||
--echo # $acl + $user + same DB
|
||||
--echo #
|
||||
|
||||
connection conn_user2;
|
||||
USE test1;
|
||||
|
||||
--echo # $acl + $user + same DB + PACKAGE type in the same PACKAGE BODY
|
||||
|
||||
# Does not work !!!
|
||||
#DELIMITER $$;
|
||||
#CREATE PACKAGE BODY pkg1 AS
|
||||
# r0 rec0_t;
|
||||
#END;
|
||||
#$$
|
||||
#DELIMITER ;$$
|
||||
|
||||
DELIMITER $$;
|
||||
--error ER_PROCACCESS_DENIED_ERROR
|
||||
CREATE PACKAGE BODY pkg1 AS
|
||||
r0 pkg1.rec0_t;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
|
||||
DELIMITER $$;
|
||||
--error ER_PROCACCESS_DENIED_ERROR
|
||||
CREATE PACKAGE BODY pkg1 AS
|
||||
r0 test1.pkg1.rec0_t;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
|
||||
--echo # $acl + $user + same DB + PACKAGE type in another PACKAGE
|
||||
|
||||
DELIMITER $$;
|
||||
--error ER_PROCACCESS_DENIED_ERROR
|
||||
CREATE PACKAGE pkg2 AS
|
||||
TYPE cur1_t IS REF CURSOR RETURN pkg1.rec0_t;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
DELIMITER $$;
|
||||
--error ER_PROCACCESS_DENIED_ERROR
|
||||
CREATE PACKAGE pkg2 AS
|
||||
TYPE cur1_t IS REF CURSOR RETURN test1.pkg1.rec0_t;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
--echo # $acl + $user + same DB + PACKAGE type in another PACKAGE BODY
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg2 AS
|
||||
END;
|
||||
$$
|
||||
--error ER_PROCACCESS_DENIED_ERROR
|
||||
CREATE PACKAGE BODY pkg2 AS
|
||||
TYPE cur1_t IS REF CURSOR RETURN pkg1.rec0_t;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
DROP PACKAGE pkg2;
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg2 AS
|
||||
END;
|
||||
$$
|
||||
--error ER_PROCACCESS_DENIED_ERROR
|
||||
CREATE PACKAGE BODY pkg2 AS
|
||||
TYPE cur1_t IS REF CURSOR RETURN test1.pkg1.rec0_t;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
DROP PACKAGE pkg2;
|
||||
|
||||
|
||||
--echo # $acl + $user + same DB + PACKAGE type in a schema routine
|
||||
|
||||
DELIMITER $$;
|
||||
--error ER_PROCACCESS_DENIED_ERROR
|
||||
CREATE PROCEDURE p1 AS
|
||||
TYPE cur1_t IS REF CURSOR RETURN pkg1.rec0_t;
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
DELIMITER $$;
|
||||
--error ER_PROCACCESS_DENIED_ERROR
|
||||
CREATE PROCEDURE p1 AS
|
||||
TYPE cur1_t IS REF CURSOR RETURN test1.pkg1.rec0_t;
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # $acl + $user + different DB
|
||||
--echo #
|
||||
|
||||
USE test2;
|
||||
|
||||
--echo $acl + $user + different DB + PACKAGE type in another PACKAGE
|
||||
|
||||
DELIMITER $$;
|
||||
--error ER_PROCACCESS_DENIED_ERROR
|
||||
CREATE PACKAGE pkg2 AS
|
||||
TYPE cur1_t IS REF CURSOR RETURN test1.pkg1.rec0_t;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
--echo $acl + $user + different DB + PACKAGE type in another PACKAGE BODY
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg2 AS
|
||||
END;
|
||||
$$
|
||||
--error ER_PROCACCESS_DENIED_ERROR
|
||||
CREATE PACKAGE BODY pkg2 AS
|
||||
TYPE cur1_t IS REF CURSOR RETURN test1.pkg1.rec0_t;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
DROP PACKAGE pkg2;
|
||||
|
||||
--echo $acl + $user + different DB + PACKAGE type in a schema routine
|
||||
|
||||
DELIMITER $$;
|
||||
--error ER_PROCACCESS_DENIED_ERROR
|
||||
CREATE PROCEDURE p1 AS
|
||||
TYPE cur1_t IS REF CURSOR RETURN test1.pkg1.rec0_t;
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
--echo # End of denied.inc
|
||||
409
mysql-test/suite/compat/oracle/t/sp-package-spec-type-grant.test
Normal file
409
mysql-test/suite/compat/oracle/t/sp-package-spec-type-grant.test
Normal file
@@ -0,0 +1,409 @@
|
||||
# Grant tests not performed with embedded server
|
||||
--source include/not_embedded.inc
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-39587 Package-wide TYPE for variable declarations
|
||||
--echo #
|
||||
|
||||
SET sql_mode=ORACLE;
|
||||
|
||||
CREATE DATABASE test1;
|
||||
CREATE DATABASE test2;
|
||||
CREATE USER user1@localhost;
|
||||
CREATE USER user2@localhost;
|
||||
GRANT CREATE ROUTINE ON test1.* TO user1@localhost;
|
||||
GRANT CREATE ROUTINE ON test2.* TO user1@localhost;
|
||||
GRANT CREATE ROUTINE ON test1.* TO user2@localhost;
|
||||
GRANT CREATE ROUTINE ON test2.* TO user2@localhost;
|
||||
|
||||
connect (conn_user1, localhost, user1,, test1);
|
||||
SET sql_mode=ORACLE;
|
||||
|
||||
connect (conn_user2, localhost, user2,, test1);
|
||||
SET sql_mode=ORACLE;
|
||||
|
||||
connection conn_user1;
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE rec0_t IS RECORD (a INT, b VARCHAR(10));
|
||||
TYPE cur0_t IS REF CURSOR RETURN rec0_t;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
connection conn_user1;
|
||||
--let acl=ACL_NONE
|
||||
--let user=same user
|
||||
--source sp-package-spec-type-grant-allowed.inc
|
||||
|
||||
connection conn_user2;
|
||||
--let acl=ACL_NONE
|
||||
--let user=different user
|
||||
--source sp-package-spec-type-grant-denied.inc
|
||||
|
||||
connection default;
|
||||
GRANT EXECUTE ON PACKAGE test1.pkg1 TO user2@localhost;
|
||||
connection conn_user2;
|
||||
--let acl=ACL_EXEC_test1.pkg1
|
||||
--let user=different user
|
||||
--source sp-package-spec-type-grant-allowed.inc
|
||||
connection default;
|
||||
REVOKE EXECUTE ON PACKAGE test1.pkg1 FROM user2@localhost;
|
||||
|
||||
|
||||
connection default;
|
||||
disconnect conn_user1;
|
||||
disconnect conn_user2;
|
||||
DROP USER user1@localhost;
|
||||
DROP USER user2@localhost;
|
||||
DROP PACKAGE test1.pkg1;
|
||||
DROP DATABASE test1;
|
||||
DROP DATABASE test2;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-40136 User without any privileges on the package schema can declare and use the package's record types
|
||||
--echo #
|
||||
|
||||
CREATE DATABASE secdb;
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE secdb.pkg AS
|
||||
TYPE rec_t IS RECORD (a INT, secret VARCHAR(30));
|
||||
FUNCTION f RETURN INT;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY secdb.pkg AS
|
||||
FUNCTION f RETURN INT AS
|
||||
BEGIN
|
||||
RETURN 42;
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
|
||||
DELIMITER ;$$
|
||||
CREATE DATABASE appdb;
|
||||
CREATE USER u_none@localhost;
|
||||
# No privilege on secdb
|
||||
GRANT ALL ON appdb.* TO u_none@localhost;
|
||||
|
||||
connect (cnone, localhost, u_none,, appdb);
|
||||
SET sql_mode=ORACLE;
|
||||
|
||||
# The server does not allow a package to be created using a record type
|
||||
# defined in a package owned by another schema,
|
||||
# as the user u_none has no EXECUTE privilege on the PACKAGE secdb.pkg.
|
||||
|
||||
DELIMITER $$;
|
||||
--error ER_PROCACCESS_DENIED_ERROR
|
||||
CREATE PROCEDURE appdb.p AS r secdb.pkg.rec_t;
|
||||
BEGIN
|
||||
r.a:=1;
|
||||
r.secret:='x';
|
||||
SELECT r.a;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
connection default;
|
||||
GRANT EXECUTE ON PACKAGE secdb.pkg TO u_none@localhost;
|
||||
connection cnone;
|
||||
|
||||
# Now u_none can use the data type secdb.pkg
|
||||
DELIMITER $$;
|
||||
CREATE PROCEDURE
|
||||
appdb.p AS r secdb.pkg.rec_t;
|
||||
BEGIN
|
||||
r.a:=1;
|
||||
r.secret:='x';
|
||||
SELECT r.a;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
CALL appdb.p;
|
||||
|
||||
# However it cannot execute the routine without the EXECUTE privilege
|
||||
# on the PACKAGE BODY secdb.pkg (privileges on a PACKAGE does not
|
||||
# automatically give privileges on its PACKAGE BODY)
|
||||
|
||||
--error ER_PROCACCESS_DENIED_ERROR
|
||||
SELECT secdb.pkg.f();
|
||||
|
||||
# Now grant privileges on PACKAGE BODY and execute a package routine
|
||||
|
||||
connection default;
|
||||
GRANT EXECUTE ON PACKAGE BODY secdb.pkg TO u_none@localhost;
|
||||
connection cnone;
|
||||
SELECT secdb.pkg.f();
|
||||
|
||||
connection default;
|
||||
disconnect cnone;
|
||||
DROP USER u_none@localhost;
|
||||
DROP DATABASE appdb;
|
||||
DROP DATABASE secdb;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-40278 Package type is wrongly DENIED when called by a low privilege invoker
|
||||
--echo #
|
||||
|
||||
CREATE DATABASE secdb;
|
||||
CREATE DATABASE appdb;
|
||||
CREATE USER low@localhost;
|
||||
GRANT ALL ON appdb.* TO low@localhost; # NO privilege on secdb
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE secdb.vault AS
|
||||
TYPE creds IS RECORD(username VARCHAR(64), pw VARCHAR(128));
|
||||
FUNCTION f RETURN INT;
|
||||
END;
|
||||
$$
|
||||
|
||||
CREATE DEFINER=root@localhost PROCEDURE appdb.p_definer_root_security_none AS
|
||||
r secdb.vault.creds;
|
||||
BEGIN
|
||||
r.username:='admin';
|
||||
SELECT r.username;
|
||||
END;
|
||||
$$
|
||||
|
||||
CREATE PROCEDURE appdb.p_definer_none_security_none AS
|
||||
r secdb.vault.creds;
|
||||
BEGIN
|
||||
r.username:='admin';
|
||||
SELECT r.username;
|
||||
END;
|
||||
$$
|
||||
|
||||
--error ER_PROCACCESS_DENIED_ERROR
|
||||
CREATE DEFINER=low@localhost PROCEDURE appdb.p_definer_low_security_none AS
|
||||
r secdb.vault.creds;
|
||||
BEGIN
|
||||
r.username:='admin';
|
||||
SELECT r.username;
|
||||
END;
|
||||
$$
|
||||
|
||||
|
||||
# With invoker
|
||||
|
||||
CREATE DEFINER=root@localhost PROCEDURE appdb.p_definer_root_security_invoker
|
||||
SQL SECURITY INVOKER AS
|
||||
r secdb.vault.creds;
|
||||
BEGIN
|
||||
r.username:='admin';
|
||||
SELECT r.username;
|
||||
END;
|
||||
$$
|
||||
|
||||
CREATE PROCEDURE appdb.p_definer_none_security_invoker
|
||||
SQL SECURITY INVOKER AS
|
||||
r secdb.vault.creds;
|
||||
BEGIN
|
||||
r.username:='admin';
|
||||
SELECT r.username;
|
||||
END;
|
||||
$$
|
||||
|
||||
CREATE DEFINER=low@localhost PROCEDURE appdb.p_definer_low_security_invoker
|
||||
SQL SECURITY INVOKER AS
|
||||
r secdb.vault.creds;
|
||||
BEGIN
|
||||
r.username:='admin';
|
||||
SELECT r.username;
|
||||
END;
|
||||
$$
|
||||
|
||||
DELIMITER ;$$
|
||||
|
||||
SELECT name, definer, security_type FROM mysql.proc
|
||||
WHERE db='appdb' AND name LIKE 'p_%'
|
||||
ORDER BY definer;
|
||||
|
||||
connect(lowconn, localhost, low,,appdb);
|
||||
SET sql_mode=ORACLE;
|
||||
|
||||
DELIMITER $$;
|
||||
--error ER_PROCACCESS_DENIED_ERROR
|
||||
CREATE PROCEDURE appdb.p_definer_low1_security_none AS
|
||||
r secdb.vault.creds;
|
||||
BEGIN
|
||||
r.username:='admin';
|
||||
SELECT r.username;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
DELIMITER $$;
|
||||
--error ER_PROCACCESS_DENIED_ERROR
|
||||
CREATE PROCEDURE appdb.p_definer_low1_security_invoker
|
||||
SQL SECURITY INVOKER AS
|
||||
r secdb.vault.creds;
|
||||
BEGIN
|
||||
r.username:='admin';
|
||||
SELECT r.username;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
|
||||
CALL appdb.p_definer_root_security_none();
|
||||
CALL appdb.p_definer_none_security_none();
|
||||
--error ER_PROCACCESS_DENIED_ERROR
|
||||
CALL appdb.p_definer_root_security_invoker();
|
||||
--error ER_PROCACCESS_DENIED_ERROR
|
||||
CALL appdb.p_definer_none_security_invoker();
|
||||
SHOW WARNINGS;
|
||||
|
||||
--connection default
|
||||
--disconnect lowconn
|
||||
DROP USER low@localhost;
|
||||
DROP DATABASE appdb;
|
||||
DROP DATABASE secdb;
|
||||
|
||||
|
||||
--echo # Using secdb.vault package types in package procedure appdb.xxx.p1
|
||||
|
||||
|
||||
SET sql_mode=ORACLE;
|
||||
CREATE DATABASE secdb;
|
||||
CREATE DATABASE appdb;
|
||||
CREATE USER low@localhost;
|
||||
GRANT ALL ON appdb.* TO low@localhost; # NO privilege on secdb
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE secdb.vault AS
|
||||
TYPE creds IS RECORD(username VARCHAR(64), pw VARCHAR(128));
|
||||
FUNCTION f RETURN INT;
|
||||
END;
|
||||
$$
|
||||
|
||||
CREATE PACKAGE appdb.pkg_definer_body_root_security_none AS
|
||||
PROCEDURE p1;
|
||||
END;
|
||||
$$
|
||||
CREATE DEFINER=root@localhost PACKAGE BODY appdb.pkg_definer_body_root_security_none AS
|
||||
PROCEDURE p1 AS
|
||||
r secdb.vault.creds;
|
||||
BEGIN
|
||||
r.username:='admin';
|
||||
SELECT r.username;
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
|
||||
CREATE PACKAGE appdb.pkg_definer_body_none_security_none AS
|
||||
PROCEDURE p1;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY appdb.pkg_definer_body_none_security_none AS
|
||||
PROCEDURE p1 AS
|
||||
r secdb.vault.creds;
|
||||
BEGIN
|
||||
r.username:='admin';
|
||||
SELECT r.username;
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
|
||||
CREATE PACKAGE appdb.pkg_definer_body_low_security_none AS
|
||||
PROCEDURE p1;
|
||||
END;
|
||||
$$
|
||||
--error ER_PROCACCESS_DENIED_ERROR
|
||||
CREATE DEFINER=low@localhost PACKAGE BODY appdb.pkg_definer_body_low_security_none AS
|
||||
PROCEDURE p1 AS
|
||||
r secdb.vault.creds;
|
||||
BEGIN
|
||||
r.username:='admin';
|
||||
SELECT r.username;
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
DROP PACKAGE appdb.pkg_definer_body_low_security_none;
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE appdb.pkg_definer_body_root_security_invoker AS
|
||||
PROCEDURE p1;
|
||||
END;
|
||||
$$
|
||||
CREATE DEFINER=root@localhost PACKAGE BODY appdb.pkg_definer_body_root_security_invoker
|
||||
SQL SECURITY INVOKER AS
|
||||
PROCEDURE p1 AS
|
||||
r secdb.vault.creds;
|
||||
BEGIN
|
||||
r.username:='admin';
|
||||
SELECT r.username;
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
|
||||
CREATE PACKAGE appdb.pkg_definer_body_none_security_invoker AS
|
||||
PROCEDURE p1;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY appdb.pkg_definer_body_none_security_invoker
|
||||
SQL SECURITY INVOKER AS
|
||||
PROCEDURE p1 AS
|
||||
r secdb.vault.creds;
|
||||
BEGIN
|
||||
r.username:='admin';
|
||||
SELECT r.username;
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
|
||||
CREATE PACKAGE appdb.pkg_definer_body_low_security_invoker AS
|
||||
PROCEDURE p1;
|
||||
END;
|
||||
$$
|
||||
CREATE DEFINER=low@localhost PACKAGE BODY appdb.pkg_definer_body_low_security_invoker
|
||||
SQL SECURITY INVOKER AS
|
||||
PROCEDURE p1 AS
|
||||
r secdb.vault.creds;
|
||||
BEGIN
|
||||
r.username:='admin';
|
||||
SELECT r.username;
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
|
||||
|
||||
SELECT type, name, definer, security_type FROM mysql.proc
|
||||
WHERE db='appdb' AND name LIKE 'pkg_%'
|
||||
ORDER BY name, type, definer;
|
||||
|
||||
connect(lowconn, localhost, low,,appdb);
|
||||
SET sql_mode=ORACLE;
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE appdb.pkg_definer_body_low_security_none AS
|
||||
PROCEDURE p1;
|
||||
END;
|
||||
$$
|
||||
--error ER_PROCACCESS_DENIED_ERROR
|
||||
CREATE DEFINER=low@localhost PACKAGE BODY appdb.pkg_definer_body_low_security_none AS
|
||||
PROCEDURE p1 AS
|
||||
r secdb.vault.creds;
|
||||
BEGIN
|
||||
r.username:='admin';
|
||||
SELECT r.username;
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
CALL appdb.pkg_definer_body_root_security_none.p1();
|
||||
CALL appdb.pkg_definer_body_none_security_none.p1();
|
||||
--error ER_PROCACCESS_DENIED_ERROR
|
||||
CALL appdb.pkg_definer_body_root_security_invoker.p1();
|
||||
--error ER_PROCACCESS_DENIED_ERROR
|
||||
CALL appdb.pkg_definer_body_none_security_invoker.p1();
|
||||
|
||||
--connection default
|
||||
--disconnect lowconn
|
||||
DROP USER low@localhost;
|
||||
DROP DATABASE appdb;
|
||||
DROP DATABASE secdb;
|
||||
129
mysql-test/suite/compat/oracle/t/sp-package-spec-type-inet6.test
Normal file
129
mysql-test/suite/compat/oracle/t/sp-package-spec-type-inet6.test
Normal file
@@ -0,0 +1,129 @@
|
||||
SET sql_mode=ORACLE;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-39587 Package-wide TYPE for variable declarations
|
||||
--echo #
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE inet6_array IS TABLE OF INET6 INDEX BY INTEGER;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
--echo # 2-Step + PROCEDURE
|
||||
DELIMITER $$;
|
||||
CREATE PROCEDURE p1 AS
|
||||
v0 pkg1.inet6_array;
|
||||
BEGIN
|
||||
v0(0):='AA::BB';
|
||||
SELECT v0(0);
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
CALL p1;
|
||||
DROP PROCEDURE p1;
|
||||
|
||||
--echo # 2-Step + PACKAGE + Declarations in package PROCEDURE
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg2 AS
|
||||
PROCEDURE p1;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg2 AS
|
||||
PROCEDURE p1 AS
|
||||
v0 pkg1.inet6_array;
|
||||
BEGIN
|
||||
v0(0):='AA::BB';
|
||||
SELECT v0(0);
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
CALL pkg2.p1;
|
||||
DROP PACKAGE pkg2;
|
||||
|
||||
--echo # 2-Step + PACKAGE + Declaration in PACKAGE BODY
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg2 AS
|
||||
PROCEDURE p1;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg2 AS
|
||||
v0 pkg1.inet6_array;
|
||||
PROCEDURE p1 AS
|
||||
BEGIN
|
||||
v0(0):='AA::BB';
|
||||
SELECT v0(0);
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
CALL pkg2.p1;
|
||||
DROP PACKAGE pkg2;
|
||||
|
||||
|
||||
--echo # 3-Step + PROCEDURE + Declarations in package PROCEDURE
|
||||
CREATE DATABASE test1;
|
||||
USE test1;
|
||||
DELIMITER $$;
|
||||
CREATE PROCEDURE p1 AS
|
||||
v0 test.pkg1.inet6_array;
|
||||
BEGIN
|
||||
v0(0):='AA::BB';
|
||||
SELECT v0(0);
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
CALL p1;
|
||||
DROP PROCEDURE p1;
|
||||
DROP DATABASE test1;
|
||||
USE test;
|
||||
|
||||
--echo # 3-Step + PACKAGE
|
||||
CREATE DATABASE test1;
|
||||
USE test1;
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg2 AS
|
||||
PROCEDURE p1;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg2 AS
|
||||
PROCEDURE p1 AS
|
||||
v0 test.pkg1.inet6_array;
|
||||
BEGIN
|
||||
v0(0):='AA::BB';
|
||||
SELECT v0(0);
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
CALL pkg2.p1;
|
||||
DROP PACKAGE pkg2;
|
||||
DROP DATABASE test1;
|
||||
USE test;
|
||||
|
||||
--echo # 3-Step + PACKAGE + Declaration in PACKAGE BODY
|
||||
CREATE DATABASE test1;
|
||||
USE test1;
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg2 AS
|
||||
PROCEDURE p1;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg2 AS
|
||||
v0 test.pkg1.inet6_array;
|
||||
PROCEDURE p1 AS
|
||||
BEGIN
|
||||
v0(0):='AA::BB';
|
||||
SELECT v0(0);
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
CALL pkg2.p1;
|
||||
DROP PACKAGE pkg2;
|
||||
DROP DATABASE test1;
|
||||
USE test;
|
||||
|
||||
DROP PACKAGE pkg1;
|
||||
@@ -0,0 +1,38 @@
|
||||
if (`SELECT @@lower_case_table_names=0`)
|
||||
{
|
||||
--skip Test requires: lower_case_table_names>0
|
||||
}
|
||||
|
||||
|
||||
SET sql_mode=ORACLE;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-39587 Package-wide TYPE for variable declarations
|
||||
--echo #
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE rec0_t IS RECORD (a INT, b VARCHAR(32));
|
||||
TYPE assoc0_t IS TABLE OF test.pkg1.rec0_t INDEX BY INTEGER;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
DROP PACKAGE pkg1;
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE rec0_t IS RECORD (a INT, b VARCHAR(32));
|
||||
TYPE assoc0_t IS TABLE OF TEST.pkg1.rec0_t INDEX BY INTEGER;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
DROP PACKAGE pkg1;
|
||||
|
||||
DELIMITER $$;
|
||||
--error ER_UNKNOWN_DATA_TYPE
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE rec0_t IS RECORD (a INT, b VARCHAR(32));
|
||||
TYPE assoc0_t IS TABLE OF tttt.pkg1.rec0_t INDEX BY INTEGER;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
@@ -0,0 +1,38 @@
|
||||
if (`SELECT @@lower_case_table_names>0`)
|
||||
{
|
||||
--skip Test requires: lower_case_table_names=0
|
||||
}
|
||||
|
||||
|
||||
SET sql_mode=ORACLE;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-39587 Package-wide TYPE for variable declarations
|
||||
--echo #
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE rec0_t IS RECORD (a INT, b VARCHAR(32));
|
||||
TYPE assoc0_t IS TABLE OF test.pkg1.rec0_t INDEX BY INTEGER;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
DROP PACKAGE pkg1;
|
||||
|
||||
DELIMITER $$;
|
||||
--error ER_UNKNOWN_DATA_TYPE
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE rec0_t IS RECORD (a INT, b VARCHAR(32));
|
||||
TYPE assoc0_t IS TABLE OF TEST.pkg1.rec0_t INDEX BY INTEGER;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
DELIMITER $$;
|
||||
--error ER_UNKNOWN_DATA_TYPE
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE rec0_t IS RECORD (a INT, b VARCHAR(32));
|
||||
TYPE assoc0_t IS TABLE OF tttt.pkg1.rec0_t INDEX BY INTEGER;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
113
mysql-test/suite/compat/oracle/t/sp-package-spec-type-path.test
Normal file
113
mysql-test/suite/compat/oracle/t/sp-package-spec-type-path.test
Normal file
@@ -0,0 +1,113 @@
|
||||
SET sql_mode=ORACLE;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-39587 Package-wide TYPE for variable declarations
|
||||
--echo #
|
||||
|
||||
|
||||
--echo # PATH resolving not to CURRENT_SCHEMA
|
||||
|
||||
CREATE DATABASE test1;
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE test1.pkg1 AS
|
||||
TYPE rec0_t IS RECORD (a INT, b_test1 VARCHAR(10));
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
CREATE DATABASE test2;
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE test2.pkg1 AS
|
||||
TYPE rec0_t IS RECORD (a INT, b_test2 VARCHAR(10));
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
DELIMITER $$;
|
||||
--error ER_UNKNOWN_DATA_TYPE
|
||||
CREATE PROCEDURE p1 AS
|
||||
a pkg1.rec0_t;
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
|
||||
# Have pkg1.rec0_t resolve to test1.pkg1.rec0_t
|
||||
SET PATH 'CURRENT_SCHEMA,test1,test2';
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PROCEDURE p1 AS
|
||||
a pkg1.rec0_t;
|
||||
BEGIN
|
||||
a.b_test1:= 10;
|
||||
SELECT a.b_test1;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
CALL test.p1();
|
||||
DROP PROCEDURE p1;
|
||||
|
||||
|
||||
# Have pkg1.rec0_t resolve to test2.pkg1.rec0_t
|
||||
SET PATH 'CURRENT_SCHEMA,test2,test1';
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PROCEDURE p1 AS
|
||||
a pkg1.rec0_t;
|
||||
BEGIN
|
||||
a.b_test2:= 10;
|
||||
SELECT a.b_test2;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
CALL p1();
|
||||
DROP PROCEDURE p1;
|
||||
|
||||
SET PATH DEFAULT;
|
||||
|
||||
DROP DATABASE test1;
|
||||
DROP DATABASE test2;
|
||||
|
||||
|
||||
--echo # PATH resolving to CURRENT_SCHEMA
|
||||
|
||||
CREATE DATABASE test1;
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE test.pkg1 AS
|
||||
TYPE rec0_t IS RECORD (a INT, b_test VARCHAR(10));
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
SET PATH 'test1,CURRENT_SCHEMA';
|
||||
DELIMITER $$;
|
||||
CREATE PROCEDURE p1 AS
|
||||
a pkg1.rec0_t;
|
||||
BEGIN
|
||||
a.b_test:= 10;
|
||||
SELECT a.b_test;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
CALL p1();
|
||||
DROP PROCEDURE p1;
|
||||
|
||||
SET PATH 'CURRENT_SCHEMA,test1';
|
||||
DELIMITER $$;
|
||||
CREATE PROCEDURE p1 AS
|
||||
a pkg1.rec0_t;
|
||||
BEGIN
|
||||
a.b_test:= 10;
|
||||
SELECT a.b_test;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
CALL p1();
|
||||
DROP PROCEDURE p1;
|
||||
|
||||
DROP PACKAGE pkg1;
|
||||
DROP DATABASE test1;
|
||||
|
||||
SET PATH DEFAULT;
|
||||
@@ -0,0 +1,371 @@
|
||||
SET sql_mode=ORACLE;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-39587 Package-wide TYPE for variable declarations
|
||||
--echo #
|
||||
|
||||
--echo # RECORD cannot have attributes
|
||||
--echo # Currently this is not allowed by the parser in qualified types
|
||||
--echo # If we ever allow, make sure to call check_data_type_attributes()
|
||||
--echo # which will raise ER_UNSUPPORTED_DATA_TYPE_ATTRIBUTE
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE rec0_t IS RECORD (a INT, b VARCHAR(32));
|
||||
END;
|
||||
$$
|
||||
--error ER_PARSE_ERROR
|
||||
CREATE PROCEDURE p1 AS
|
||||
r0 pkg1.rec0_t (0); -- Length attribute
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
--error ER_PARSE_ERROR
|
||||
CREATE PROCEDURE p1 AS
|
||||
r0 pkg1.rec0_t (0,0); -- Length and dec attributes
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
--error ER_PARSE_ERROR
|
||||
CREATE PROCEDURE p1 AS
|
||||
r0 pkg1.rec0_t CHARACTER SET latin1;
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
--error ER_PARSE_ERROR
|
||||
CREATE PROCEDURE p1 AS
|
||||
r0 pkg1.rec0_t COLLATE latin1_bin;
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
DROP PACKAGE pkg1;
|
||||
|
||||
|
||||
--echo # PACKAGE spec types cannot be used in schema routine parameters
|
||||
--echo # and schema function RETURN
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE rec0_t IS RECORD (a INT, b VARCHAR(10));
|
||||
END;
|
||||
$$
|
||||
--error ER_WRONG_USAGE
|
||||
CREATE PROCEDURE p1(a pkg1.rec0_t) AS
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
--error ER_WRONG_USAGE
|
||||
CREATE FUNCTION f1 RETURN pkg1.rec0_t AS
|
||||
BEGIN
|
||||
RETURN NULL;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
DROP PACKAGE pkg1;
|
||||
|
||||
|
||||
--echo # RECORD as a package routine parameter and a package function RETURN
|
||||
--echo # 2-step
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE rec0_t IS RECORD (a INT, b VARCHAR(10));
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE pkg2 AS
|
||||
PROCEDURE p1;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg2 AS
|
||||
PROCEDURE p2(r pkg1.rec0_t) AS
|
||||
BEGIN
|
||||
SELECT r.a, r.b;
|
||||
END;
|
||||
FUNCTION f1 RETURN pkg1.rec0_t AS
|
||||
res pkg1.rec0_t;
|
||||
BEGIN
|
||||
res.a:= 10;
|
||||
res.b:= 'b';
|
||||
RETURN res;
|
||||
END;
|
||||
PROCEDURE p1 AS
|
||||
BEGIN
|
||||
CALL p2(f1());
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
CALL pkg2.p1();
|
||||
DROP PACKAGE pkg2;
|
||||
DROP PACKAGE pkg1;
|
||||
|
||||
|
||||
--echo # RECORD as a package routine parameter and a package function RETURN
|
||||
--echo # 3-step
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE rec0_t IS RECORD (a INT, b VARCHAR(10));
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
CREATE DATABASE test1;
|
||||
USE test1;
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg2 AS
|
||||
PROCEDURE p1;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg2 AS
|
||||
PROCEDURE p2(r test.pkg1.rec0_t) AS
|
||||
BEGIN
|
||||
SELECT r.a, r.b;
|
||||
END;
|
||||
FUNCTION f1 RETURN test.pkg1.rec0_t AS
|
||||
res test.pkg1.rec0_t;
|
||||
BEGIN
|
||||
res.a:= 10;
|
||||
res.b:= 'b';
|
||||
RETURN res;
|
||||
END;
|
||||
PROCEDURE p1 AS
|
||||
BEGIN
|
||||
CALL p2(f1());
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
CALL pkg2.p1();
|
||||
CALL test1.pkg2.p1();
|
||||
USE test;
|
||||
CALL test1.pkg2.p1();
|
||||
USE test1;
|
||||
DROP PACKAGE pkg2;
|
||||
DROP DATABASE test1;
|
||||
USE test;
|
||||
DROP PACKAGE pkg1;
|
||||
|
||||
|
||||
--echo # RECORD as a package routine parameter + 2-step self-reference
|
||||
|
||||
DELIMITER $$;
|
||||
--error ER_UNKNOWN_DATA_TYPE
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE r IS RECORD(x INT);
|
||||
PROCEDURE q(v pkg1.no_such_type); -- 2-step self reference
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE r IS RECORD(x INT);
|
||||
PROCEDURE q(v pkg1.r); -- 2-step self reference
|
||||
PROCEDURE exec();
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg1 AS
|
||||
PROCEDURE q(v pkg1.r) AS
|
||||
BEGIN
|
||||
SELECT v.x;
|
||||
END;
|
||||
PROCEDURE exec() AS
|
||||
v pkg1.r;
|
||||
BEGIN
|
||||
v.x:= 10;
|
||||
q(v);
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
CALL pkg1.exec();
|
||||
DROP PACKAGE pkg1;
|
||||
|
||||
|
||||
--echo # RECORD as a package routine parameter + 3-step self-reference
|
||||
|
||||
DELIMITER $$;
|
||||
--error ER_UNKNOWN_DATA_TYPE
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE r IS RECORD(x INT);
|
||||
PROCEDURE q(v test.pkg1.no_such_type); -- 3-step Self reference
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE r IS RECORD(x INT);
|
||||
PROCEDURE q(v test.pkg1.r); -- 3-step self reference
|
||||
PROCEDURE exec();
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg1 AS
|
||||
PROCEDURE q(v test.pkg1.r) AS
|
||||
BEGIN
|
||||
SELECT v.x;
|
||||
END;
|
||||
PROCEDURE exec() AS
|
||||
v test.pkg1.r;
|
||||
BEGIN
|
||||
v.x:= 10;
|
||||
q(v);
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
CALL pkg1.exec();
|
||||
DROP PACKAGE pkg1;
|
||||
|
||||
|
||||
--echo # RECORD as a package function RETURN type + 2-step self-reference
|
||||
|
||||
DELIMITER $$;
|
||||
--error ER_UNKNOWN_DATA_TYPE
|
||||
CREATE PACKAGE pkg1 AS
|
||||
FUNCTION g RETURN pkg1.no_such_type; -- 2-step self-reference
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE r IS RECORD(x INT);
|
||||
FUNCTION g RETURN pkg1.r; -- 2-step self-reference
|
||||
PROCEDURE exec;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg1 AS
|
||||
FUNCTION g RETURN pkg1.r AS
|
||||
v pkg1.r;
|
||||
BEGIN
|
||||
v.x:= 10;
|
||||
RETURN v;
|
||||
END;
|
||||
PROCEDURE exec AS
|
||||
v pkg1.r;
|
||||
BEGIN
|
||||
v:= g();
|
||||
SELECT v.x;
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
CALL pkg1.exec();
|
||||
DROP PACKAGE pkg1;
|
||||
|
||||
|
||||
--echo # RECORD as a package function RETURN type + 3-step self-reference
|
||||
|
||||
DELIMITER $$;
|
||||
--error ER_UNKNOWN_DATA_TYPE
|
||||
CREATE PACKAGE pkg1 AS
|
||||
FUNCTION g RETURN test.pkg1.no_such_type; -- 3-step self-reference
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE r IS RECORD(x INT);
|
||||
FUNCTION g RETURN test.pkg1.r; -- 3-step self-reference
|
||||
PROCEDURE exec;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg1 AS
|
||||
FUNCTION g RETURN test.pkg1.r AS
|
||||
v test.pkg1.r;
|
||||
BEGIN
|
||||
v.x:= 10;
|
||||
RETURN v;
|
||||
END;
|
||||
PROCEDURE exec AS
|
||||
v test.pkg1.r;
|
||||
BEGIN
|
||||
v:= g();
|
||||
SELECT v.x;
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
CALL pkg1.exec();
|
||||
DROP PACKAGE pkg1;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-40721 SIGSEGV in LEX::sp_package_spec_check_cyclic_dependency | LEX::set_field_type_typedef_package_spec
|
||||
--echo #
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE emp_pkg AS
|
||||
TYPE emp_rec IS RECORD (id INT);
|
||||
FUNCTION get_emp(p_id INT) RETURN emp_rec;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY emp_pkg AS
|
||||
FUNCTION get_emp(p_id INT) RETURN emp_pkg.emp_rec AS
|
||||
v emp_pkg.emp_rec;
|
||||
BEGIN
|
||||
v.id := p_id;
|
||||
RETURN v;
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
CREATE PROCEDURE show_emp AS
|
||||
v emp_pkg.emp_rec;
|
||||
BEGIN
|
||||
v := emp_pkg.get_emp(7);
|
||||
SELECT v.id AS id;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
CALL show_emp;
|
||||
DROP PROCEDURE show_emp;
|
||||
DROP PACKAGE emp_pkg;
|
||||
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE emp_pkg AS
|
||||
TYPE emp_rec IS RECORD (id INT);
|
||||
PROCEDURE get_emp(p_id INT);
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY emp_pkg AS
|
||||
PROCEDURE get_emp(p_id INT) AS
|
||||
v emp_pkg.emp_rec;
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
CREATE PROCEDURE show_emp AS
|
||||
BEGIN
|
||||
emp_pkg.get_emp(7);
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
CALL show_emp;
|
||||
DROP PROCEDURE show_emp;
|
||||
DROP PACKAGE emp_pkg;
|
||||
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE t AS TYPE r IS RECORD (id INT); END; $$
|
||||
CREATE PACKAGE a AS PROCEDURE q; END; $$
|
||||
CREATE PACKAGE BODY a AS PROCEDURE q AS v t.r; BEGIN NULL; END; END; $$
|
||||
CREATE PROCEDURE c AS BEGIN CALL a.q(); END; $$
|
||||
DELIMITER ;$$
|
||||
CALL c;
|
||||
DROP PROCEDURE c;
|
||||
DROP PACKAGE a;
|
||||
DROP PACKAGE t;
|
||||
@@ -0,0 +1,808 @@
|
||||
SET sql_mode=ORACLE;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-39587 Package-wide TYPE for variable declarations
|
||||
--echo #
|
||||
|
||||
--echo # REFCURSOR cannot have attributes
|
||||
--echo # Currently this is not allowed by the parser in qualified types
|
||||
--echo # If we ever allow, make sure to call check_data_type_attributes()
|
||||
--echo # which will raise ER_UNSUPPORTED_DATA_TYPE_ATTRIBUTE
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE rec0_t IS RECORD (a INT, b VARCHAR(32));
|
||||
TYPE cur0_t IS REF CURSOR RETURN rec0_t;
|
||||
END;
|
||||
$$
|
||||
--error ER_PARSE_ERROR
|
||||
CREATE PROCEDURE p1 AS
|
||||
r0 pkg1.cur0_t (0); -- Length attribute
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
--error ER_PARSE_ERROR
|
||||
CREATE PROCEDURE p1 AS
|
||||
r0 pkg1.cur0_t (0,0); -- Length and dec attributes
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
--error ER_PARSE_ERROR
|
||||
CREATE PROCEDURE p1 AS
|
||||
r0 pkg1.cur0_t CHARACTER SET latin1;
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
--error ER_PARSE_ERROR
|
||||
CREATE PROCEDURE p1 AS
|
||||
r0 pkg1.cur0_t COLLATE latin1_bin;
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
DROP PACKAGE pkg1;
|
||||
|
||||
|
||||
|
||||
--echo # PACKAGE spec types cannot be used in schema routine parameters
|
||||
--echo # and schema function RETURN
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE rec0_t IS RECORD (a INT, b VARCHAR(10));
|
||||
TYPE cur0_t IS REF CURSOR RETURN rec0_t;
|
||||
END;
|
||||
$$
|
||||
--error ER_WRONG_USAGE
|
||||
CREATE PROCEDURE p1(a pkg1.cur0_t) AS
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
--error ER_WRONG_USAGE
|
||||
CREATE FUNCTION f1 RETURN pkg1.cur0_t AS
|
||||
BEGIN
|
||||
RETURN NULL;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
DROP PACKAGE pkg1;
|
||||
|
||||
|
||||
--echo # A package routine parameter and a package function RETURN
|
||||
--echo # 2-step
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE rec0_t IS RECORD (a INT, b VARCHAR(10));
|
||||
TYPE cur0_t IS REF CURSOR RETURN rec0_t;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE pkg2 AS
|
||||
PROCEDURE p1;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg2 AS
|
||||
PROCEDURE p2(c pkg1.cur0_t) AS
|
||||
v0 INT;
|
||||
v1 VARCHAR(32);
|
||||
BEGIN
|
||||
FETCH c INTO v0, v1;
|
||||
SELECT v0, v1;
|
||||
CLOSE c;
|
||||
END;
|
||||
FUNCTION f1 RETURN pkg1.cur0_t AS
|
||||
res pkg1.cur0_t;
|
||||
BEGIN
|
||||
OPEN res FOR SELECT 1,'b';
|
||||
RETURN res;
|
||||
END;
|
||||
PROCEDURE p1 AS
|
||||
BEGIN
|
||||
CALL p2(f1());
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
CALL pkg2.p1();
|
||||
DROP PACKAGE pkg2;
|
||||
DROP PACKAGE pkg1;
|
||||
|
||||
|
||||
--echo # A package routine parameter and a package function RETURN
|
||||
--echo # 3-step
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE rec0_t IS RECORD (a INT, b VARCHAR(10));
|
||||
TYPE cur0_t IS REF CURSOR RETURN rec0_t;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
CREATE DATABASE test1;
|
||||
USE test1;
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg2 AS
|
||||
PROCEDURE p1;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg2 AS
|
||||
PROCEDURE p2(c test.pkg1.cur0_t) AS
|
||||
v0 INT;
|
||||
v1 VARCHAR(32);
|
||||
BEGIN
|
||||
FETCH c INTO v0, v1;
|
||||
SELECT v0, v1;
|
||||
CLOSE c;
|
||||
END;
|
||||
FUNCTION f1 RETURN test.pkg1.cur0_t AS
|
||||
res test.pkg1.cur0_t;
|
||||
BEGIN
|
||||
OPEN res FOR SELECT 1, 'b';
|
||||
RETURN res;
|
||||
END;
|
||||
PROCEDURE p1 AS
|
||||
BEGIN
|
||||
CALL p2(f1());
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
CALL pkg2.p1();
|
||||
CALL test1.pkg2.p1();
|
||||
USE test;
|
||||
CALL test1.pkg2.p1();
|
||||
USE test1;
|
||||
DROP PACKAGE pkg2;
|
||||
DROP DATABASE test1;
|
||||
USE test;
|
||||
DROP PACKAGE pkg1;
|
||||
|
||||
|
||||
--echo # A self-reference to the current spec with success: 2-step
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE rec0_t IS RECORD (a INT, b VARCHAR(32));
|
||||
TYPE cur0_t IS REF CURSOR RETURN pkg1.rec0_t; -- Self ref
|
||||
END;
|
||||
$$
|
||||
|
||||
--echo # Using from the same database
|
||||
CREATE PROCEDURE p1 AS
|
||||
r0 pkg1.rec0_t;
|
||||
c0 pkg1.cur0_t;
|
||||
BEGIN
|
||||
OPEN c0 FOR SELECT 1,'b';
|
||||
FETCH c0 INTO r0;
|
||||
CLOSE c0;
|
||||
SELECT r0.a, r0.b;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
CALL p1;
|
||||
DROP PROCEDURE p1;
|
||||
|
||||
--echo # Using from a different database
|
||||
CREATE DATABASE test1;
|
||||
DELIMITER $$;
|
||||
CREATE PROCEDURE test1.p1 AS
|
||||
r0 test.pkg1.rec0_t;
|
||||
c0 test.pkg1.cur0_t;
|
||||
BEGIN
|
||||
OPEN c0 FOR SELECT 1,'b';
|
||||
FETCH c0 INTO r0;
|
||||
CLOSE c0;
|
||||
SELECT r0.a, r0.b;
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
CALL test1.p1;
|
||||
DROP DATABASE test1;
|
||||
|
||||
DROP PACKAGE pkg1;
|
||||
|
||||
|
||||
--echo # A self-reference to the current spec with success: 3-step
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE rec0_t IS RECORD (a INT, b VARCHAR(32));
|
||||
TYPE cur0_t IS REF CURSOR RETURN test.pkg1.rec0_t; -- Self ref
|
||||
END;
|
||||
$$
|
||||
|
||||
--echo # Using from the same database
|
||||
CREATE PROCEDURE p1 AS
|
||||
r0 test.pkg1.rec0_t;
|
||||
c0 test.pkg1.cur0_t;
|
||||
BEGIN
|
||||
OPEN c0 FOR SELECT 1,'b';
|
||||
FETCH c0 INTO r0;
|
||||
CLOSE c0;
|
||||
SELECT r0.a, r0.b;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
CALL p1;
|
||||
DROP PROCEDURE p1;
|
||||
|
||||
--echo # Using from a different database
|
||||
CREATE DATABASE test1;
|
||||
DELIMITER $$;
|
||||
CREATE PROCEDURE test1.p1 AS
|
||||
r0 test.pkg1.rec0_t;
|
||||
c0 test.pkg1.cur0_t;
|
||||
BEGIN
|
||||
OPEN c0 FOR SELECT 1,'b';
|
||||
FETCH c0 INTO r0;
|
||||
CLOSE c0;
|
||||
SELECT r0.a, r0.b;
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
CALL test1.p1;
|
||||
DROP DATABASE test1;
|
||||
|
||||
DROP PACKAGE pkg1;
|
||||
|
||||
|
||||
--echo # Various working examples
|
||||
CREATE TABLE t1 (a INT, b VARCHAR(30));
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE rec0_t IS RECORD(a INT, b VARCHAR(30));
|
||||
TYPE cur0_t IS REF CURSOR;
|
||||
TYPE cur1_t IS REF CURSOR RETURN rec0_t;
|
||||
TYPE cur2_t IS REF CURSOR RETURN test.t1%ROWTYPE;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
--echo # 2-Step + PROCEDURE
|
||||
DELIMITER $$;
|
||||
CREATE PROCEDURE p1 AS
|
||||
v1 pkg1.rec0_t;
|
||||
c0 pkg1.cur0_t;
|
||||
c1 pkg1.cur1_t;
|
||||
c2 pkg1.cur2_t;
|
||||
fetch0 INT;
|
||||
fetch1 VARCHAR(30);
|
||||
BEGIN
|
||||
v1.a:= 1;
|
||||
v1.b:= 'b';
|
||||
|
||||
OPEN c0 FOR SELECT 10,'bb0';
|
||||
FETCH c0 INTO fetch0, fetch1;
|
||||
SELECT fetch0, fetch1;
|
||||
CLOSE c0;
|
||||
|
||||
OPEN c1 FOR SELECT 11,'bb1';
|
||||
FETCH c1 INTO fetch0, fetch1;
|
||||
SELECT fetch0, fetch1;
|
||||
CLOSE c1;
|
||||
|
||||
OPEN c2 FOR SELECT 12,'bb2';
|
||||
FETCH c2 INTO fetch0, fetch1;
|
||||
SELECT fetch0, fetch1;
|
||||
CLOSE c2;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
CALL p1;
|
||||
DROP PROCEDURE p1;
|
||||
|
||||
--echo # 3-Step + PROCEDURE
|
||||
CREATE DATABASE test1;
|
||||
USE test1;
|
||||
DELIMITER $$;
|
||||
CREATE PROCEDURE p1 AS
|
||||
v1 test.pkg1.rec0_t;
|
||||
c0 test.pkg1.cur0_t;
|
||||
c1 test.pkg1.cur1_t;
|
||||
c2 test.pkg1.cur2_t;
|
||||
fetch0 INT;
|
||||
fetch1 VARCHAR(30);
|
||||
BEGIN
|
||||
v1.a:= 1;
|
||||
v1.b:= 'b';
|
||||
|
||||
OPEN c0 FOR SELECT 10,'bb0';
|
||||
FETCH c0 INTO fetch0, fetch1;
|
||||
SELECT fetch0, fetch1;
|
||||
CLOSE c0;
|
||||
|
||||
OPEN c1 FOR SELECT 11,'bb1';
|
||||
FETCH c1 INTO fetch0, fetch1;
|
||||
SELECT fetch0, fetch1;
|
||||
CLOSE c1;
|
||||
|
||||
OPEN c2 FOR SELECT 12,'bb2';
|
||||
FETCH c2 INTO fetch0, fetch1;
|
||||
SELECT fetch0, fetch1;
|
||||
CLOSE c2;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
CALL p1;
|
||||
DROP PROCEDURE p1;
|
||||
DROP DATABASE test1;
|
||||
USE test;
|
||||
|
||||
--echo # 2-Step + PACKAGE + Declarations in package PROCEDURE
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg2 AS
|
||||
PROCEDURE p1;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg2 AS
|
||||
PROCEDURE p1 AS
|
||||
v1 pkg1.rec0_t;
|
||||
c0 pkg1.cur0_t;
|
||||
c1 pkg1.cur1_t;
|
||||
c2 pkg1.cur2_t;
|
||||
fetch0 INT;
|
||||
fetch1 VARCHAR(30);
|
||||
BEGIN
|
||||
v1.a:= 1;
|
||||
v1.b:= 'b';
|
||||
|
||||
OPEN c0 FOR SELECT 10,'bb0';
|
||||
FETCH c0 INTO fetch0, fetch1;
|
||||
SELECT fetch0, fetch1;
|
||||
CLOSE c0;
|
||||
|
||||
OPEN c1 FOR SELECT 11,'bb1';
|
||||
FETCH c1 INTO fetch0, fetch1;
|
||||
SELECT fetch0, fetch1;
|
||||
CLOSE c1;
|
||||
|
||||
OPEN c2 FOR SELECT 12,'bb2';
|
||||
FETCH c2 INTO fetch0, fetch1;
|
||||
SELECT fetch0, fetch1;
|
||||
CLOSE c2;
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
CALL pkg2.p1;
|
||||
DROP PACKAGE pkg2;
|
||||
|
||||
--echo # 3-Step + PACKAGE + Declarations in package PROCEDURE
|
||||
CREATE DATABASE test1;
|
||||
USE test1;
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg2 AS
|
||||
PROCEDURE p1;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg2 AS
|
||||
PROCEDURE p1 AS
|
||||
v1 test.pkg1.rec0_t;
|
||||
c0 test.pkg1.cur0_t;
|
||||
c1 test.pkg1.cur1_t;
|
||||
c2 test.pkg1.cur2_t;
|
||||
fetch0 INT;
|
||||
fetch1 VARCHAR(30);
|
||||
BEGIN
|
||||
v1.a:= 1;
|
||||
v1.b:= 'b';
|
||||
|
||||
OPEN c0 FOR SELECT 10,'bb0';
|
||||
FETCH c0 INTO fetch0, fetch1;
|
||||
SELECT fetch0, fetch1;
|
||||
CLOSE c0;
|
||||
|
||||
OPEN c1 FOR SELECT 11,'bb1';
|
||||
FETCH c1 INTO fetch0, fetch1;
|
||||
SELECT fetch0, fetch1;
|
||||
CLOSE c1;
|
||||
|
||||
OPEN c2 FOR SELECT 12,'bb2';
|
||||
FETCH c2 INTO fetch0, fetch1;
|
||||
SELECT fetch0, fetch1;
|
||||
CLOSE c2;
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
CALL pkg2.p1;
|
||||
DROP PACKAGE pkg2;
|
||||
DROP DATABASE test1;
|
||||
USE test;
|
||||
|
||||
--echo # 3-Step + PACKAGE + Declarations in PACKAGE BODY
|
||||
CREATE DATABASE test1;
|
||||
USE test1;
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg2 AS
|
||||
PROCEDURE p1;
|
||||
END;
|
||||
$$
|
||||
--error ER_NOT_ALLOWED_IN_THIS_CONTEXT
|
||||
CREATE PACKAGE BODY pkg2 AS
|
||||
v1 test.pkg1.rec0_t;
|
||||
c0 test.pkg1.cur0_t;
|
||||
c1 test.pkg1.cur1_t;
|
||||
c2 test.pkg1.cur2_t;
|
||||
fetch0 INT;
|
||||
fetch1 VARCHAR(30);
|
||||
PROCEDURE p1 AS
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
DROP PACKAGE pkg2;
|
||||
DROP DATABASE test1;
|
||||
USE test;
|
||||
|
||||
DROP PACKAGE pkg1;
|
||||
DROP TABLE t1;
|
||||
|
||||
|
||||
--echo # RECORD and REFCURSOR in different packages
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE rec0_t IS RECORD(a INT, b VARCHAR(30));
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
--echo # 2-step type in RETURN in a schema procedure
|
||||
DELIMITER $$;
|
||||
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
|
||||
CREATE PROCEDURE p1 AS
|
||||
TYPE cur0_t IS REF CURSOR RETURN pkg1.rec0_t;
|
||||
c0 cur0_t;
|
||||
BEGIN
|
||||
OPEN c0 FOR SELECT 1,'b',3;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PROCEDURE p1 AS
|
||||
TYPE cur0_t IS REF CURSOR RETURN pkg1.rec0_t;
|
||||
c0 cur0_t;
|
||||
v0 INT;
|
||||
v1 VARCHAR(10);
|
||||
BEGIN
|
||||
OPEN c0 FOR SELECT 1,'b';
|
||||
FETCH c0 INTO v0, v1;
|
||||
SELECT v0, v1;
|
||||
CLOSE c0;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
CALL p1;
|
||||
DROP PROCEDURE p1;
|
||||
|
||||
|
||||
--echo # 3-step type in RETURN in a schema procedure
|
||||
|
||||
DELIMITER $$;
|
||||
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
|
||||
CREATE PROCEDURE p1 AS
|
||||
TYPE cur0_t IS REF CURSOR RETURN test.pkg1.rec0_t;
|
||||
c0 cur0_t;
|
||||
BEGIN
|
||||
OPEN c0 FOR SELECT 1,'b',3;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PROCEDURE p1 AS
|
||||
TYPE cur0_t IS REF CURSOR RETURN test.pkg1.rec0_t;
|
||||
c0 cur0_t;
|
||||
v0 INT;
|
||||
v1 VARCHAR(10);
|
||||
BEGIN
|
||||
OPEN c0 FOR SELECT 1,'b';
|
||||
FETCH c0 INTO v0, v1;
|
||||
SELECT v0, v1;
|
||||
CLOSE c0;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
CALL p1;
|
||||
DROP PROCEDURE p1;
|
||||
|
||||
|
||||
--echo # 2-step type in RETURN in another package
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg2 AS
|
||||
TYPE cur0_t IS REF CURSOR RETURN pkg1.rec0_t;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
--echo # 2-step cursor type with 2-step type in RETURN
|
||||
DELIMITER $$;
|
||||
CREATE PROCEDURE p1 AS
|
||||
c0 pkg2.cur0_t;
|
||||
v0 INT;
|
||||
v1 VARCHAR(10);
|
||||
BEGIN
|
||||
OPEN c0 FOR SELECT 1,'b';
|
||||
FETCH c0 INTO v0, v1;
|
||||
SELECT v0, v1;
|
||||
CLOSE c0;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
CALL p1;
|
||||
DROP PROCEDURE p1;
|
||||
|
||||
--echo # 3-step cursor type with 2-step type in RETURN
|
||||
DELIMITER $$;
|
||||
CREATE PROCEDURE p1 AS
|
||||
c0 test.pkg2.cur0_t;
|
||||
v0 INT;
|
||||
v1 VARCHAR(10);
|
||||
BEGIN
|
||||
OPEN c0 FOR SELECT 1,'b';
|
||||
FETCH c0 INTO v0, v1;
|
||||
SELECT v0, v1;
|
||||
CLOSE c0;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
CALL p1;
|
||||
DROP PROCEDURE p1;
|
||||
|
||||
|
||||
--echo # 3-step cursor type (different db) with 2-step type in RETURN
|
||||
CREATE DATABASE test1;
|
||||
USE test1;
|
||||
DELIMITER $$;
|
||||
CREATE PROCEDURE p1 AS
|
||||
c0 test.pkg2.cur0_t;
|
||||
v0 INT;
|
||||
v1 VARCHAR(10);
|
||||
BEGIN
|
||||
OPEN c0 FOR SELECT 1,'b';
|
||||
FETCH c0 INTO v0, v1;
|
||||
SELECT v0, v1;
|
||||
CLOSE c0;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
CALL p1;
|
||||
DROP PROCEDURE p1;
|
||||
DROP DATABASE test1;
|
||||
USE test;
|
||||
|
||||
DROP PACKAGE pkg2;
|
||||
|
||||
DROP PACKAGE pkg1;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-40420 ASAN : SIGSEGV in Sp_handler::db_find_routine | Sp_handler::db_find_and_cache_routine
|
||||
--echo #
|
||||
|
||||
CREATE DATABASE db1;
|
||||
USE db1;
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE a_pkg AS
|
||||
TYPE arec IS RECORD (x INT, y VARCHAR(10));
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE b_pkg AS
|
||||
TYPE brec IS RECORD (p INT, q VARCHAR(10));
|
||||
TYPE bcur IS REF CURSOR RETURN a_pkg.arec;
|
||||
END;
|
||||
$$
|
||||
--error ER_UNKNOWN_DATA_TYPE
|
||||
CREATE PACKAGE a_pkg AS
|
||||
TYPE arec IS RECORD (x INT, y VARCHAR(10));
|
||||
TYPE acur IS REF CURSOR RETURN b_pkg.brec;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
--echo # Inject manually a bad CREATE PACKAGE with cyclic dependency
|
||||
|
||||
SELECT `body` FROM mysql.proc WHERE db='db1' AND name='a_pkg';
|
||||
UPDATE mysql.proc SET `body`='AS
|
||||
TYPE arec IS RECORD (x INT, y VARCHAR(10));
|
||||
TYPE acur IS REF CURSOR RETURN b_pkg.brec;
|
||||
END'
|
||||
WHERE db='db1' AND name='a_pkg';
|
||||
|
||||
--echo # Check that it's not allowed to create a PROCEDURE using a
|
||||
--echo # manually injected PACKAGE with a cycle dependency
|
||||
|
||||
DELIMITER $$;
|
||||
--replace_regex /[0-9]* bytes used of a [0-9]* byte stack, and [0-9]* bytes needed/XXX bytes used of a XXX byte stack, and XXX bytes needed/
|
||||
--error ER_STACK_OVERRUN_NEED_MORE
|
||||
CREATE PROCEDURE p_cycle AS
|
||||
c a_pkg.acur;
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
--echo # The same, after SP cache invalidating
|
||||
SET sql_mode=DEFAULT;
|
||||
--source include/invalidate_sp_cache.inc
|
||||
SET sql_mode=ORACLE;
|
||||
DELIMITER $$;
|
||||
--replace_regex /[0-9]* bytes used of a [0-9]* byte stack, and [0-9]* bytes needed/XXX bytes used of a XXX byte stack, and XXX bytes needed/
|
||||
--error ER_STACK_OVERRUN_NEED_MORE
|
||||
CREATE PROCEDURE p_cycle AS
|
||||
c a_pkg.acur;
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
|
||||
--echo # Check that a manually injected PACKAGE with a cycle dependency
|
||||
--echo # can be fixed using CREATE OR REPLACE
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE OR REPLACE PACKAGE a_pkg AS
|
||||
TYPE arec IS RECORD (x INT, y VARCHAR(10));
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
DROP DATABASE db1;
|
||||
USE test;
|
||||
|
||||
--echo # The same layout, with 3-step data type references
|
||||
|
||||
CREATE DATABASE db1;
|
||||
CREATE DATABASE db2;
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE db1.a_pkg AS
|
||||
TYPE arec IS RECORD (x INT, y VARCHAR(10));
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE db2.b_pkg AS
|
||||
TYPE brec IS RECORD (p INT, q VARCHAR(10));
|
||||
TYPE bcur IS REF CURSOR RETURN db1.a_pkg.arec;
|
||||
END;
|
||||
$$
|
||||
--error ER_UNKNOWN_DATA_TYPE
|
||||
CREATE OR REPLACE PACKAGE db1.a_pkg AS
|
||||
TYPE arec IS RECORD (x INT, y VARCHAR(10));
|
||||
TYPE acur IS REF CURSOR RETURN db2.b_pkg.brec;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
DROP DATABASE db2;
|
||||
DROP DATABASE db1;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-40468 Package that contains a self reference package refcursor crashes the server
|
||||
--echo #
|
||||
|
||||
# 2-step qualified self-reference
|
||||
|
||||
CREATE DATABASE db1;
|
||||
USE db1;
|
||||
CREATE TABLE t1 (a INT, b VARCHAR(32));
|
||||
INSERT INTO t1 VALUES (1,'one'),(2,'two');
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg AS
|
||||
TYPE rec IS RECORD (a INT, b VARCHAR(32));
|
||||
TYPE cur IS REF CURSOR RETURN pkg.rec; -- 2-step self reference
|
||||
END;
|
||||
$$
|
||||
CREATE PROCEDURE p2 AS
|
||||
TYPE localcur IS REF CURSOR RETURN pkg.rec;
|
||||
c localcur;
|
||||
v pkg.rec;
|
||||
BEGIN
|
||||
OPEN c FOR SELECT a,b FROM t1;
|
||||
FETCH c INTO v;
|
||||
CLOSE c;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
CALL p2;
|
||||
DROP DATABASE db1;
|
||||
USE test;
|
||||
|
||||
|
||||
# 3-step qualified reference
|
||||
|
||||
CREATE DATABASE db1;
|
||||
USE db1;
|
||||
CREATE TABLE t1 (a INT, b VARCHAR(32));
|
||||
INSERT INTO t1 VALUES (1,'one'),(2,'two');
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg AS
|
||||
TYPE rec IS RECORD (a INT, b VARCHAR(32));
|
||||
TYPE cur IS REF CURSOR RETURN db1.pkg.rec; -- 3-step self-reference
|
||||
END;
|
||||
$$
|
||||
CREATE PROCEDURE p2 AS
|
||||
TYPE localcur IS REF CURSOR RETURN pkg.rec;
|
||||
c localcur;
|
||||
v pkg.rec;
|
||||
BEGIN
|
||||
OPEN c FOR SELECT a,b FROM t1;
|
||||
FETCH c INTO v;
|
||||
CLOSE c;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
CALL p2;
|
||||
DROP DATABASE db1;
|
||||
USE test;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-40640 Assertion `li->sphead' failed in bool LEX::sp_package_spec_check_cyclic_dependency(THD *, const Lex_ident_sys_st &, const Lex_ident_sys_st &) const
|
||||
--echo #
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE p1 AS TYPE r IS RECORD(x INT); END;$$
|
||||
CREATE PACKAGE p2 AS TYPE r IS RECORD(x INT); TYPE c IS REF CURSOR RETURN p1.r; END;$$
|
||||
DELIMITER ;$$
|
||||
SHOW CREATE PACKAGE p2;
|
||||
DROP PACKAGE p2;
|
||||
DROP PACKAGE p1;
|
||||
|
||||
--echo # Replacing the dependency package and removing the type
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE rec0_t IS RECORD (a INT, b VARCHAR(10));
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE pkg2 AS
|
||||
TYPE cur1_t IS REF CURSOR RETURN pkg1.rec0_t;
|
||||
END
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
SHOW CREATE PACKAGE pkg2;
|
||||
DELIMITER $$;
|
||||
CREATE OR REPLACE PACKAGE pkg1 AS
|
||||
TYPE rec1_t IS RECORD (a INT, b VARCHAR(10)); -- There is no rec0_t any more
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
--error ER_UNKNOWN_DATA_TYPE
|
||||
SHOW CREATE PACKAGE pkg2;
|
||||
DROP PACKAGE pkg2;
|
||||
DROP PACKAGE pkg1;
|
||||
|
||||
|
||||
--echo # Dropping the dependency package
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE rec0_t IS RECORD (a INT, b VARCHAR(10));
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE pkg2 AS
|
||||
TYPE cur1_t IS REF CURSOR RETURN pkg1.rec0_t;
|
||||
END
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
SHOW CREATE PACKAGE pkg2;
|
||||
DROP PACKAGE pkg1;
|
||||
--error ER_UNKNOWN_DATA_TYPE
|
||||
SHOW CREATE PACKAGE pkg2;
|
||||
DROP PACKAGE pkg2;
|
||||
@@ -0,0 +1,35 @@
|
||||
SET sql_mode=ORACLE;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-39587 Package-wide TYPE for variable declarations
|
||||
--echo #
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-40597 UBSAN | SIGSEGV in ORAparse | parse_sql | sp_compile | Sp_handler::db_load_routine
|
||||
--echo #
|
||||
|
||||
CREATE DATABASE db1;
|
||||
USE db1;
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg1500 AS TYPE rec IS RECORD(x INT); END;$$
|
||||
DELIMITER ;$$
|
||||
|
||||
--disable_query_log
|
||||
--let $i= 1500
|
||||
while ($i)
|
||||
{
|
||||
--let $prev= $i
|
||||
--dec $i
|
||||
--error 0,ER_STACK_OVERRUN_NEED_MORE
|
||||
--eval CREATE PACKAGE pkg$i AS TYPE rec IS RECORD(x INT); TYPE cur IS REF CURSOR RETURN pkg$prev.rec; END;
|
||||
if ($mysql_errname == "ER_STACK_OVERRUN_NEED_MORE")
|
||||
{
|
||||
--echo $mysql_errname reached;
|
||||
--let $i= 0;
|
||||
}
|
||||
}
|
||||
--enable_query_log
|
||||
|
||||
DROP DATABASE db1;
|
||||
USE test;
|
||||
@@ -0,0 +1,148 @@
|
||||
SET sql_mode=ORACLE;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-39587 Package-wide TYPE for variable declarations
|
||||
--echo #
|
||||
|
||||
#--echo #
|
||||
#--echo # MDEV-40430 Cross db package type inside a trigger crashes the server
|
||||
#--echo #
|
||||
#
|
||||
#CREATE DATABASE db1;
|
||||
#CREATE DATABASE db2;
|
||||
#CREATE TABLE db2.t1 (id INT, note VARCHAR(40));
|
||||
#DELIMITER $$;
|
||||
#CREATE PACKAGE db1.pkg AS
|
||||
# TYPE rec IS RECORD (a INT, b VARCHAR(20));
|
||||
#END;
|
||||
#$$
|
||||
#CREATE TRIGGER db2.trg BEFORE INSERT ON db2.t1
|
||||
#FOR EACH ROW
|
||||
#DECLARE
|
||||
# r db1.pkg.rec;
|
||||
#BEGIN
|
||||
# r.a := :NEW.id;
|
||||
# :NEW.note := 'x';
|
||||
#END;
|
||||
#$$
|
||||
#DELIMITER ;$$
|
||||
#INSERT INTO db2.t1 (id) VALUES (1);
|
||||
#DROP DATABASE db2;
|
||||
#DROP DATABASE db1;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-40436 Trigger using a package-defined type is silently lost during mariadb-dump / restore
|
||||
--echo #
|
||||
|
||||
# Using package types inside triggers is not yet allowed because
|
||||
# of dump/restore problems (MDEV-40436)
|
||||
|
||||
CREATE DATABASE db1;
|
||||
USE db1;
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg AS
|
||||
TYPE rec IS RECORD (a INT, b VARCHAR(20));
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
CREATE TABLE t1 (id INT, val VARCHAR(20));
|
||||
DELIMITER $$;
|
||||
--error ER_WRONG_USAGE
|
||||
CREATE TRIGGER trg BEFORE INSERT ON t1
|
||||
FOR EACH ROW
|
||||
DECLARE
|
||||
r pkg.rec;
|
||||
BEGIN
|
||||
:NEW.val := CONCAT('r-', :NEW.id);
|
||||
END;
|
||||
$$
|
||||
--error ER_WRONG_USAGE
|
||||
CREATE TRIGGER trg BEFORE INSERT ON t1
|
||||
FOR EACH ROW
|
||||
DECLARE
|
||||
r db1.pkg.rec;
|
||||
BEGIN
|
||||
:NEW.val := CONCAT('r-', :NEW.id);
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
DROP DATABASE db1;
|
||||
USE test;
|
||||
|
||||
|
||||
# Package type in a REF CURSOR RETURN
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg AS
|
||||
TYPE rec IS RECORD (a INT);
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
CREATE TABLE t1 (a INT);
|
||||
|
||||
DELIMITER $$;
|
||||
--error ER_WRONG_USAGE
|
||||
CREATE TRIGGER trg BEFORE INSERT ON t1
|
||||
FOR EACH ROW
|
||||
DECLARE
|
||||
TYPE c IS REF CURSOR RETURN pkg.rec;
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
DELIMITER $$;
|
||||
--error ER_WRONG_USAGE
|
||||
CREATE TRIGGER trg BEFORE INSERT ON t1
|
||||
FOR EACH ROW
|
||||
DECLARE
|
||||
TYPE c IS REF CURSOR RETURN test.pkg.rec;
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
DROP TABLE t1;
|
||||
DROP PACKAGE pkg;
|
||||
|
||||
|
||||
# Package TYPE in a assoc array
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg AS
|
||||
TYPE rec IS RECORD (a INT);
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
CREATE TABLE t1 (a INT);
|
||||
|
||||
DELIMITER $$;
|
||||
--error ER_WRONG_USAGE
|
||||
CREATE TRIGGER trg BEFORE INSERT ON t1
|
||||
FOR EACH ROW
|
||||
DECLARE
|
||||
TYPE c IS TABLE OF pkg.rec INDEX BY int;
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
DELIMITER $$;
|
||||
--error ER_WRONG_USAGE
|
||||
CREATE TRIGGER trg BEFORE INSERT ON t1
|
||||
FOR EACH ROW
|
||||
DECLARE
|
||||
TYPE c IS TABLE OF test.pkg.rec INDEX BY int;
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
DROP TABLE t1;
|
||||
DROP PACKAGE pkg;
|
||||
205
mysql-test/suite/compat/oracle/t/sp-package-spec-type.test
Normal file
205
mysql-test/suite/compat/oracle/t/sp-package-spec-type.test
Normal file
@@ -0,0 +1,205 @@
|
||||
SET sql_mode=ORACLE;
|
||||
SET NAMES utf8mb3;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-39587 Package-wide TYPE for variable declarations
|
||||
--echo #
|
||||
|
||||
--echo # raise_unknown_data_type
|
||||
|
||||
DELIMITER $$;
|
||||
--error ER_UNKNOWN_DATA_TYPE
|
||||
CREATE PROCEDURE p1 AS
|
||||
a aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa;
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
|
||||
DELIMITER $$;
|
||||
--error ER_UNKNOWN_DATA_TYPE,
|
||||
CREATE PROCEDURE p1 AS
|
||||
a aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa;
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
|
||||
DELIMITER $$;
|
||||
--error ER_UNKNOWN_DATA_TYPE
|
||||
CREATE PROCEDURE p1 AS
|
||||
a åååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååå.
|
||||
åååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååå;
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
|
||||
DELIMITER $$;
|
||||
--error ER_UNKNOWN_DATA_TYPE,
|
||||
CREATE PROCEDURE p1 AS
|
||||
a åååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååå.
|
||||
åååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååå.
|
||||
åååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååååå;
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
|
||||
DELIMITER $$;
|
||||
--error ER_UNKNOWN_DATA_TYPE
|
||||
CREATE PROCEDURE p1 AS
|
||||
a €€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€.
|
||||
€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€;
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
|
||||
DELIMITER $$;
|
||||
--error ER_UNKNOWN_DATA_TYPE,
|
||||
CREATE PROCEDURE p1 AS
|
||||
a €€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€.
|
||||
€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€.
|
||||
€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€;
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
|
||||
--echo # PACKAGE gets dropped making an orphan type reference: 2-step
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE rec0_t IS RECORD(a INT, b VARCHAR(30));
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PROCEDURE p1 AS
|
||||
r0 pkg1.rec0_t;
|
||||
BEGIN
|
||||
r0.a:= 10;
|
||||
r0.b:= 'b';
|
||||
SELECT r0.a, r0.b;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
CALL p1;
|
||||
DROP PACKAGE pkg1;
|
||||
--error ER_SP_PROC_TABLE_CORRUPT
|
||||
CALL p1;
|
||||
SHOW WARNINGS;
|
||||
DROP PROCEDURE p1;
|
||||
|
||||
|
||||
--echo # PACKAGE gets dropped making an orphan type reference: 3-step
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE rec0_t IS RECORD(a INT, b VARCHAR(30));
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
CREATE DATABASE test1;
|
||||
USE test1;
|
||||
DELIMITER $$;
|
||||
CREATE PROCEDURE p1 AS
|
||||
r0 test.pkg1.rec0_t;
|
||||
BEGIN
|
||||
r0.a:= 10;
|
||||
r0.b:= 'b';
|
||||
SELECT r0.a, r0.b;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
CALL p1;
|
||||
DROP PACKAGE test.pkg1;
|
||||
--error ER_SP_PROC_TABLE_CORRUPT
|
||||
CALL p1;
|
||||
SHOW WARNINGS;
|
||||
DROP PROCEDURE p1;
|
||||
DROP DATABASE test1;
|
||||
USE test;
|
||||
|
||||
|
||||
--echo # Too long identifier chain
|
||||
|
||||
DELIMITER $$;
|
||||
--error ER_UNKNOWN_DATA_TYPE
|
||||
CREATE PROCEDURE p1 AS
|
||||
v1 cat1.db1.pkg1.type1;
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-40155 Weak REF CURSOR without RETURN is not opened using a dynamic SQL statement
|
||||
--echo #
|
||||
|
||||
CREATE TABLE t (id INT, name VARCHAR(100));
|
||||
INSERT INTO t VALUES (1,'Test');
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pc AS TYPE wc IS REF CURSOR; END;
|
||||
$$
|
||||
|
||||
CREATE PROCEDURE pdyn AS
|
||||
c pc.wc;
|
||||
vi INT;
|
||||
vn VARCHAR(100);
|
||||
BEGIN
|
||||
OPEN c FOR 'SELECT id, name FROM t';
|
||||
FETCH c INTO vi, vn;
|
||||
SELECT vi, vn;
|
||||
CLOSE c;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
CALL pdyn;
|
||||
|
||||
DROP PROCEDURE pdyn;
|
||||
DROP PACKAGE pc;
|
||||
DROP TABLE t;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-40153 Assertion `rec->field->head()->charset == nullptr' failed in virtual bool Type_handler_row::Column_definition_prepare_stage1(THD *, MEM_ROOT *, Column_definition *, column_definition_type_t, const Column_derived_attributes *) const
|
||||
--echo #
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pk_crash AS
|
||||
TYPE r IS RECORD (b BLOB);
|
||||
FUNCTION f RETURN r;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
DROP PACKAGE pk_crash;
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pk_crash AS
|
||||
TYPE rec0_t IS RECORD (b BLOB);
|
||||
FUNCTION f(r rec0_t) RETURN INT;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
DROP PACKAGE pk_crash;
|
||||
@@ -75,24 +75,24 @@ DROP TABLE t1;
|
||||
--echo #
|
||||
--echo # Qualified syntax is not supported yet in SP
|
||||
--echo # See MDEV-23353 Qualified data types in SP
|
||||
--echo # For now it's trying to parse as "RETURN mariadb_schema.DATE%ROWTYPE"
|
||||
--echo # For now it's trying to parse mariadb_schema as a package name
|
||||
--echo #
|
||||
|
||||
SET sql_mode=ORACLE;
|
||||
DELIMITER $$;
|
||||
--error ER_PARSE_ERROR
|
||||
--error ER_UNKNOWN_DATA_TYPE
|
||||
CREATE FUNCTION f1() RETURN mariadb_schema.DATE AS
|
||||
BEGIN
|
||||
RETURN CURRENT_DATE;
|
||||
END;
|
||||
$$
|
||||
--error ER_PARSE_ERROR
|
||||
--error ER_UNKNOWN_DATA_TYPE
|
||||
CREATE PROCEDURE p1(a mariadb_schema.DATE) AS
|
||||
BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
--error ER_PARSE_ERROR
|
||||
--error ER_UNKNOWN_DATA_TYPE
|
||||
CREATE PROCEDURE p1() AS
|
||||
a mariadb_schema.DATE;
|
||||
BEGIN
|
||||
|
||||
@@ -8,10 +8,7 @@ BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '.v0%ROWTYPE;
|
||||
BEGIN
|
||||
NULL;
|
||||
END' at line 2
|
||||
ERROR HY000: Unknown data type: '`cat1`.`db1`.`t1`'
|
||||
CREATE PROCEDURE p1 AS
|
||||
TYPE cur0_t IS REF CURSOR RETURN cat1.db1.t1%ROWTYPE;
|
||||
BEGIN
|
||||
|
||||
@@ -9,7 +9,7 @@ SET sql_mode=ORACLE;
|
||||
#
|
||||
|
||||
DELIMITER $$;
|
||||
--error ER_PARSE_ERROR
|
||||
--error ER_UNKNOWN_DATA_TYPE
|
||||
CREATE PROCEDURE p1 AS
|
||||
TYPE cur0_t IS REF CURSOR RETURN cat1.db1.t1.v0%ROWTYPE;
|
||||
BEGIN
|
||||
|
||||
@@ -11,10 +11,7 @@ BEGIN
|
||||
NULL;
|
||||
END;
|
||||
$$
|
||||
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '.v0%TYPE;
|
||||
BEGIN
|
||||
NULL;
|
||||
END' at line 2
|
||||
ERROR HY000: Unknown data type: '`cat1`.`db1`.`t1`'
|
||||
CREATE PROCEDURE p1 AS
|
||||
TYPE cur0_t IS REF CURSOR RETURN db1.t1.v0%TYPE;
|
||||
BEGIN
|
||||
|
||||
@@ -10,7 +10,7 @@ SET sql_mode=ORACLE;
|
||||
--echo #
|
||||
|
||||
DELIMITER $$;
|
||||
--error ER_PARSE_ERROR
|
||||
--error ER_UNKNOWN_DATA_TYPE
|
||||
CREATE PROCEDURE p1 AS
|
||||
TYPE cur0_t IS REF CURSOR RETURN cat1.db1.t1.v0%TYPE;
|
||||
BEGIN
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
template<size_t buff_sz>
|
||||
class CharBuffer
|
||||
{
|
||||
protected:
|
||||
char m_buff[buff_sz + 1 /* one extra byte for '\0' */];
|
||||
size_t m_length;
|
||||
bool is_sane() const
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
#include "lex_ident_cli.h"
|
||||
#include "sql_alloc.h"
|
||||
#include "char_buffer.h"
|
||||
|
||||
extern "C" MYSQL_PLUGIN_IMPORT CHARSET_INFO *system_charset_info;
|
||||
|
||||
@@ -60,9 +61,9 @@ public:
|
||||
LEX_CSTRING tmp= {name, length};
|
||||
set_valid_utf8(&tmp);
|
||||
}
|
||||
Lex_ident_sys(const THD *thd, const LEX_CSTRING *str)
|
||||
explicit Lex_ident_sys(const LEX_CSTRING &str)
|
||||
{
|
||||
set_valid_utf8(str);
|
||||
set_valid_utf8(&str);
|
||||
}
|
||||
Lex_ident_sys & operator=(const Lex_ident_sys_st &name)
|
||||
{
|
||||
@@ -72,4 +73,36 @@ public:
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
A buffer to print a qualified data type.
|
||||
It does not derive from ErrConv because it does not need lazy calculation yet.
|
||||
Also it's size is defined according to the error message in errmsg-utf8.txt:
|
||||
"Unknown data type: '%-.384s'" in errmsg-utf8.txt
|
||||
*/
|
||||
#define DATA_TYPE_FORMAT_LENGTH 384
|
||||
class QTypeErrBuffer: public CharBuffer<DATA_TYPE_FORMAT_LENGTH>
|
||||
{
|
||||
public:
|
||||
QTypeErrBuffer(const Lex_ident_sys_st &db, const Lex_ident_sys_st &package,
|
||||
const Lex_ident_sys_st &type)
|
||||
{
|
||||
DBUG_ASSERT(db.str);
|
||||
DBUG_ASSERT(package.str);
|
||||
DBUG_ASSERT(type.str);
|
||||
my_snprintf(m_buff, sizeof(m_buff), "%.*sQ.%.*sQ.%.*sQ",
|
||||
(int) db.length, db.str,
|
||||
(int) package.length, package.str,
|
||||
(int) type.length, type.str);
|
||||
}
|
||||
QTypeErrBuffer(const Lex_ident_sys_st &package, const Lex_ident_sys_st &type)
|
||||
{
|
||||
DBUG_ASSERT(package.str);
|
||||
DBUG_ASSERT(type.str);
|
||||
my_snprintf(m_buff, sizeof(m_buff), "%.*sQ.%.*sQ",
|
||||
(int) package.length, package.str,
|
||||
(int) type.length, type.str);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif // LEX_IDENT_SYS
|
||||
|
||||
@@ -12135,9 +12135,9 @@ ER_TOO_LONG_DATABASE_COMMENT
|
||||
spa "El comentario para la base de datos '%-.64s' es demasiado largo (máx = %u)"
|
||||
sw "Maoni kwa hifadhidata '%-.64s' ni ndefu sana (max = %u)"
|
||||
ER_UNKNOWN_DATA_TYPE
|
||||
eng "Unknown data type: '%-.64s'"
|
||||
spa "Tipo de datos desconocido: '%-.64s'"
|
||||
sw "Aina ya data isiyojulikana: '%-.64s'"
|
||||
eng "Unknown data type: '%-.384s'"
|
||||
spa "Tipo de datos desconocido: '%-.384s'"
|
||||
sw "Aina ya data isiyojulikana: '%-.384s'"
|
||||
ER_UNKNOWN_OPERATOR
|
||||
eng "Operator does not exist: '%-.128s'"
|
||||
spa "El operador no existe: '%-.128s'"
|
||||
|
||||
81
sql/sp.cc
81
sql/sp.cc
@@ -95,11 +95,19 @@ bool Sp_handler_procedure::add_instr_preturn(THD *thd, sp_head *sp,
|
||||
}
|
||||
|
||||
|
||||
bool Sp_handler_event::add_instr_preturn(THD *thd, sp_head *sp,
|
||||
sp_pcontext *spcont) const
|
||||
{
|
||||
return sp->add_instr_preturn(thd, spcont);
|
||||
}
|
||||
|
||||
|
||||
Sp_handler_procedure sp_handler_procedure;
|
||||
Sp_handler_function sp_handler_function;
|
||||
Sp_handler_package_spec sp_handler_package_spec;
|
||||
Sp_handler_package_body sp_handler_package_body;
|
||||
Sp_handler_trigger sp_handler_trigger;
|
||||
Sp_handler_event sp_handler_event;
|
||||
Sp_handler_package_procedure sp_handler_package_procedure;
|
||||
Sp_handler_package_function sp_handler_package_function;
|
||||
|
||||
@@ -878,7 +886,10 @@ static sp_head *sp_compile(THD *thd, String *defstr, sql_mode_t sql_mode,
|
||||
|
||||
LEX_STRING definition_string;
|
||||
|
||||
lex_start(thd);
|
||||
DBUG_ASSERT(thd->lex->stmt_lex);
|
||||
LEX *old_stmt_lex= thd->lex->stmt_lex;
|
||||
lex_start(thd); // This changes thd->lex->stmt_lex
|
||||
thd->lex->stmt_lex= old_stmt_lex;
|
||||
|
||||
init_sql_alloc(key_memory_sp_head_main_root, &thd->lex->sp_mem_root,
|
||||
MEM_ROOT_BLOCK_SIZE, MEM_ROOT_PREALLOC, MYF(0));
|
||||
@@ -980,6 +991,8 @@ Sp_handler::db_load_routine(THD *thd, const Database_qualified_name *name,
|
||||
Stored_program_creation_ctx *creation_ctx) const
|
||||
{
|
||||
LEX *old_lex= thd->lex, newlex;
|
||||
DBUG_ASSERT(thd->lex->stmt_lex);
|
||||
newlex.stmt_lex= thd->lex->stmt_lex;
|
||||
String defstr;
|
||||
char saved_cur_db_buf[SAFE_NAME_LEN+1];
|
||||
LEX_STRING saved_cur_db= { saved_cur_db_buf, sizeof(saved_cur_db_buf) };
|
||||
@@ -989,7 +1002,6 @@ Sp_handler::db_load_routine(THD *thd, const Database_qualified_name *name,
|
||||
int ret= 0;
|
||||
|
||||
thd->lex= &newlex;
|
||||
newlex.current_select= NULL;
|
||||
|
||||
defstr.set_charset(creation_ctx->get_client_cs());
|
||||
defstr.set_thread_specific();
|
||||
@@ -2527,6 +2539,43 @@ Sp_handler::sp_cache_routine_reentrant(THD *thd,
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Find and cache a routine in a parser safe mode and suppress all errors.
|
||||
*/
|
||||
int
|
||||
Sp_handler::sp_cache_routine_reentrant_suppress_errors(THD *thd,
|
||||
const Database_qualified_name *name,
|
||||
sp_head **sp) const
|
||||
{
|
||||
Dummy_error_handler err_handler;
|
||||
thd->push_internal_handler(&err_handler);
|
||||
int ret= sp_cache_routine_reentrant(thd, name, sp);
|
||||
thd->pop_internal_handler();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Find and cache a PACKAGE spec in a parser-safe reentrant mode.
|
||||
@param db - The database name
|
||||
@param package - The package name
|
||||
@retval - A null ptr if some error happened.
|
||||
Or a pointer to the PACKAGE spec.
|
||||
*/
|
||||
sp_package *Sp_handler::find_package_spec(THD *thd,
|
||||
const Lex_ident_db &db,
|
||||
const LEX_CSTRING &package)
|
||||
{
|
||||
DBUG_ASSERT(!thd->is_fatal_error);
|
||||
sp_head *sp= nullptr;
|
||||
Database_qualified_name tmp(db, package);
|
||||
bool ret= sp_handler_package_spec.
|
||||
sp_cache_routine_reentrant_suppress_errors(thd, &tmp, &sp);
|
||||
sp_package *spec= (!ret && sp) ? sp->get_package() : nullptr;
|
||||
return spec;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Check if a routine has a declaration in the CREATE PACKAGE statement,
|
||||
by looking up in thd->sp_package_spec_cache, and by loading from mysql.proc
|
||||
@@ -2560,15 +2609,7 @@ is_package_public_routine(THD *thd,
|
||||
const LEX_CSTRING &routine,
|
||||
enum_sp_type type)
|
||||
{
|
||||
sp_head *sp= NULL;
|
||||
Database_qualified_name tmp(db, package);
|
||||
|
||||
Dummy_error_handler err_handler;
|
||||
thd->push_internal_handler(&err_handler);
|
||||
bool ret= sp_handler_package_spec.sp_cache_routine_reentrant(thd, &tmp, &sp);
|
||||
thd->pop_internal_handler();
|
||||
|
||||
sp_package *spec= (!ret && sp) ? sp->get_package() : NULL;
|
||||
sp_package *spec= Sp_handler::find_package_spec(thd, db, package);
|
||||
return spec && spec->m_routine_declarations.find(routine, type);
|
||||
}
|
||||
|
||||
@@ -2994,8 +3035,22 @@ int Sp_handler::sp_cache_routine(THD *thd, const Database_qualified_name *name,
|
||||
Any error when loading an existing routine is either some problem
|
||||
with the mysql.proc table, or a parse error because the contents
|
||||
has been tampered with (in which case we clear that error).
|
||||
Other scenarios when we want to preserve the original error
|
||||
instead of ER_SP_PROC_TABLE_CORRUPT, for better readability:
|
||||
- A routine uses a TYPE from a PACKAGE specification
|
||||
but does not have EXECUTE privilege on the PACKAGE specification.
|
||||
Let's preserve the ER_PROCACCESS_DENIED_ERROR error,
|
||||
- Packages use types in a long cycle (MDEV-40597):
|
||||
* Package pkg1499 uses a type from pkg1500
|
||||
* Package pkg1498 uses a type from pkg1499
|
||||
* Package pkg1497 uses a type from pkg1488
|
||||
and so on. This can cause a thread stack overrun.
|
||||
Let's preserve the ER_STACK_OVERRUN_NEED_MORE error.
|
||||
*/
|
||||
if (ret == SP_PARSE_ERROR)
|
||||
if (ret == SP_PARSE_ERROR &&
|
||||
(!thd->is_error() ||
|
||||
(thd->get_stmt_da()->sql_errno() != ER_PROCACCESS_DENIED_ERROR &&
|
||||
thd->get_stmt_da()->sql_errno() != ER_STACK_OVERRUN_NEED_MORE)))
|
||||
thd->clear_error();
|
||||
/*
|
||||
If we cleared the parse error, or when db_find_routine() flagged
|
||||
@@ -3233,6 +3288,8 @@ Sp_handler::sp_load_for_information_schema(THD *thd, TABLE *proc_table,
|
||||
}
|
||||
|
||||
LEX *old_lex= thd->lex, newlex;
|
||||
DBUG_ASSERT(thd->lex->stmt_lex);
|
||||
newlex.stmt_lex= thd->lex->stmt_lex;
|
||||
Stored_program_creation_ctx *creation_ctx=
|
||||
Stored_routine_creation_ctx::load_from_db(thd, &sp_name_obj, proc_table);
|
||||
defstr.set_charset(creation_ctx->get_client_cs());
|
||||
|
||||
46
sql/sp.h
46
sql/sp.h
@@ -137,6 +137,9 @@ public:
|
||||
const Sp_handler *sph= handler(type);
|
||||
return sph ? sph->sp_handler_mysql_proc() : NULL;
|
||||
}
|
||||
static sp_package *find_package_spec(THD *thd,
|
||||
const Lex_ident_db &db,
|
||||
const LEX_CSTRING &package);
|
||||
|
||||
const char *type_str() const { return type_lex_cstring().str; }
|
||||
virtual const char *show_create_routine_col1_caption() const
|
||||
@@ -211,6 +214,10 @@ public:
|
||||
const Database_qualified_name *nm,
|
||||
sp_head **sp) const;
|
||||
|
||||
int sp_cache_routine_reentrant_suppress_errors(THD *thd,
|
||||
const Database_qualified_name *nm,
|
||||
sp_head **sp) const;
|
||||
|
||||
bool sp_exist_routines(THD *thd, TABLE_LIST *procs) const;
|
||||
bool sp_show_create_routine(THD *thd,
|
||||
const Database_qualified_name *name) const;
|
||||
@@ -249,6 +256,44 @@ public:
|
||||
};
|
||||
|
||||
|
||||
class Sp_handler_event: public Sp_handler
|
||||
{
|
||||
public:
|
||||
enum_sp_type type() const override { return SP_TYPE_EVENT; }
|
||||
LEX_CSTRING type_lex_cstring() const override
|
||||
{
|
||||
static LEX_CSTRING m_type_str= { STRING_WITH_LEN("EVENT")};
|
||||
return m_type_str;
|
||||
}
|
||||
enum_sql_command sqlcom_create() const override
|
||||
{
|
||||
DBUG_ASSERT(0);
|
||||
return SQLCOM_CREATE_EVENT;
|
||||
}
|
||||
enum_sql_command sqlcom_drop() const override
|
||||
{
|
||||
DBUG_ASSERT(0);
|
||||
return SQLCOM_DROP_EVENT;
|
||||
}
|
||||
const char *show_create_routine_col1_caption() const override
|
||||
{
|
||||
DBUG_ASSERT(0);
|
||||
return "Event";
|
||||
}
|
||||
const char *show_create_routine_col3_caption() const override
|
||||
{
|
||||
DBUG_ASSERT(0);
|
||||
return "Create Event";
|
||||
}
|
||||
MDL_key::enum_mdl_namespace get_mdl_type() const override
|
||||
{
|
||||
DBUG_ASSERT(0);
|
||||
return MDL_key::EVENT;
|
||||
}
|
||||
bool add_instr_preturn(THD *thd, sp_head *sp, sp_pcontext *spcont) const override;
|
||||
};
|
||||
|
||||
|
||||
class Sp_handler_procedure: public Sp_handler
|
||||
{
|
||||
public:
|
||||
@@ -499,6 +544,7 @@ extern MYSQL_PLUGIN_IMPORT Sp_handler_package_body sp_handler_package_body;
|
||||
extern MYSQL_PLUGIN_IMPORT Sp_handler_package_function sp_handler_package_function;
|
||||
extern MYSQL_PLUGIN_IMPORT Sp_handler_package_procedure sp_handler_package_procedure;
|
||||
extern MYSQL_PLUGIN_IMPORT Sp_handler_trigger sp_handler_trigger;
|
||||
extern MYSQL_PLUGIN_IMPORT Sp_handler_event sp_handler_event;
|
||||
|
||||
|
||||
inline const Sp_handler *Sp_handler::handler(enum_sql_command cmd)
|
||||
|
||||
349
sql/sp_head.cc
349
sql/sp_head.cc
@@ -570,6 +570,7 @@ sp_head::sp_head(MEM_ROOT *mem_root_arg, sp_package *parent,
|
||||
m_body(null_clex_str),
|
||||
m_body_utf8(null_clex_str),
|
||||
m_defstr(null_clex_str),
|
||||
m_definer{null_clex_str,null_clex_str},
|
||||
m_sp_cache_version(0),
|
||||
m_creation_ctx(0),
|
||||
unsafe_flags(0),
|
||||
@@ -4316,3 +4317,351 @@ ulong sp_head::sp_cache_version() const
|
||||
{
|
||||
return m_parent ? m_parent->sp_cache_version() : m_sp_cache_version;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Package data types are not allowed in triggers and events yet
|
||||
because of the dump/restore problems (MDEV-40436, MDEV-40686).
|
||||
Disallow qualified types.
|
||||
@param db - The database. Can be {nullptr,0}
|
||||
@param package - The package. Can be {nullptr,0}
|
||||
@param type - The type name. Cannot be {nullptr,0}
|
||||
*/
|
||||
bool sp_head::check_maybe_qualified_type_context(const Lex_ident_sys_st &db,
|
||||
const Lex_ident_sys_st &package,
|
||||
const Lex_ident_sys_st &type) const
|
||||
{
|
||||
DBUG_ASSERT(type.str);
|
||||
if ((m_handler == &sp_handler_trigger ||
|
||||
m_handler == &sp_handler_event) && package.str)
|
||||
{
|
||||
my_error(ER_WRONG_USAGE, MYF(0), m_handler->type_lex_cstring().str,
|
||||
db.str ? QTypeErrBuffer(db, package, type).ptr() :
|
||||
QTypeErrBuffer(package, type).ptr());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Check if the column definition "def" with type "type" can be used in "this".
|
||||
|
||||
These kind of declarations are not allowed in schema routines:
|
||||
PROCEDURE p1(a pkg1.type1) - a schema routine parameter type
|
||||
FUNCTION f1() RETURN pkg1.type1; - a schema function RETURN types
|
||||
because they show up in INFORMATION_SCHEMA.PARAMETERS.
|
||||
The code is not ready to handle this correctly.
|
||||
|
||||
Note, using them for package routines are OK, because package routines
|
||||
are not displayed in INFORMATION_SCHEMA.
|
||||
*/
|
||||
bool sp_head::check_maybe_foreign_type_context(THD *thd,
|
||||
const Lex_field_type_st &def,
|
||||
column_definition_type_t type)
|
||||
{
|
||||
if (def.foreign_module_type())
|
||||
{
|
||||
if ((m_handler == &sp_handler_procedure ||
|
||||
m_handler == &sp_handler_function)/*i.e. not a package routine*/ &&
|
||||
(type == COLUMN_DEFINITION_ROUTINE_PARAM ||
|
||||
type == COLUMN_DEFINITION_FUNCTION_RETURN))
|
||||
{
|
||||
my_error(ER_WRONG_USAGE, MYF(0),
|
||||
type == COLUMN_DEFINITION_ROUTINE_PARAM ?
|
||||
"parameter_declaration" : "RETURN",
|
||||
"package_name.type_name");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void sp_head::raise_unknown_data_type(const Lex_ident_db_normalized &db,
|
||||
const Lex_ident_sys_st &package,
|
||||
const Lex_ident_sys_st &type)
|
||||
{
|
||||
my_error(ER_UNKNOWN_DATA_TYPE, MYF(0),
|
||||
QTypeErrBuffer(Lex_ident_sys(db.str, db.length),
|
||||
package, type).ptr());
|
||||
}
|
||||
|
||||
|
||||
void sp_head::raise_unknown_data_type(const Lex_ident_sys_st &package,
|
||||
const Lex_ident_sys_st &type)
|
||||
{
|
||||
my_error(ER_UNKNOWN_DATA_TYPE, MYF(0), QTypeErrBuffer(package, type).ptr());
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Get the definition of the TYPE `dbn`.`package`.`type`.
|
||||
If the definition is not found, then an error message is raises.
|
||||
|
||||
@param thd - The thd
|
||||
@param OUT tdef - The pointer to the found TYPE definition
|
||||
@param spec - The package specification
|
||||
@param dbn - The nornamized database name (used for error messages)
|
||||
@param package - The package name (used for error messages)
|
||||
@param type - The data type name
|
||||
|
||||
@retval false - If the TYPE definition was found and written to "tdef"
|
||||
@retval true - If the data type was found found or some error happened.
|
||||
*/
|
||||
|
||||
bool sp_head::get_typedef_package_spec_or_error(THD *thd,
|
||||
const sp_type_def **tdef,
|
||||
sp_package *spec,
|
||||
const Lex_ident_db_normalized &dbn,
|
||||
const Lex_ident_sys_st &package,
|
||||
const Lex_ident_sys_st &type)
|
||||
{
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
Security_context *save_security_ctx= nullptr;
|
||||
if ((m_parent ? m_parent->suid() : suid()) != SP_IS_NOT_SUID &&
|
||||
m_definer.user.length/*Explicit DEFINER was given in CREATE*/)
|
||||
m_security_ctx.change_security_context(thd, &m_definer.user,
|
||||
&m_definer.host,
|
||||
&m_db,
|
||||
&save_security_ctx);
|
||||
#endif
|
||||
bool rc= check_routine_access(thd, EXECUTE_ACL,
|
||||
&spec->m_db, &spec->m_name,
|
||||
&sp_handler_package_spec, false);
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
if (save_security_ctx)
|
||||
m_security_ctx.restore_security_context(thd, save_security_ctx);
|
||||
#endif
|
||||
if (rc)
|
||||
return true;
|
||||
if (!(tdef[0]= spec->find_type_def(type)))
|
||||
{
|
||||
if (dbn.str)
|
||||
raise_unknown_data_type(dbn, package, type);
|
||||
else
|
||||
raise_unknown_data_type(package, type);
|
||||
return true;
|
||||
}
|
||||
m_flags|= spec->m_flags & HAS_COLUMN_TYPE_REFS;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Find a package-wide TYPE definition.
|
||||
No errors are raised on failure.
|
||||
*/
|
||||
sp_type_def *sp_package::find_type_def(const Lex_ident_sys_st &type)
|
||||
{
|
||||
if (!get_parse_context() || !get_parse_context()->child_context(0))
|
||||
return nullptr;
|
||||
return get_parse_context()->child_context(0)->find_type_def(type, false);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Get a 2-step qualified TYPE defined in a PACKAGE
|
||||
consisting by the package name and type name.
|
||||
Handles the following cases:
|
||||
- A PACKAGE refers to its own type using a qualified name
|
||||
- A routine refers to the PACKAGE in the database of the routine
|
||||
using a qualified type
|
||||
- Otherwise, the database which contains a package "package" with the type
|
||||
"type" is resolved using the @@PATH variable.
|
||||
|
||||
@param OUT tdef - The pointer to the TYPE definition
|
||||
@param package - The package name
|
||||
@param type - The data type name
|
||||
|
||||
@retval false - The package "package" with the data type "type" was found,
|
||||
and tdef[0] was set to the pointer of the found type.
|
||||
@retval true - The data type was not found, or some error happened
|
||||
during type resolution.
|
||||
*/
|
||||
bool sp_head::get_typedef_package_spec_or_error(THD *thd,
|
||||
const sp_type_def **tdef,
|
||||
const Lex_ident_sys_st &package,
|
||||
const Lex_ident_sys_st &type)
|
||||
{
|
||||
DBUG_ASSERT(!package.is_null());
|
||||
DBUG_ASSERT(!type.is_null());
|
||||
/*
|
||||
Catch a special case first: a reference to the current package spec.
|
||||
Note, cast to Lex_ident_routine is safe below because m_name gets
|
||||
to sp_head after Lex_ident_routine::check_name_with_error().
|
||||
*/
|
||||
if (m_handler == &sp_handler_package_spec &&
|
||||
Lex_ident_routine(m_name).streq(package))
|
||||
{
|
||||
/*
|
||||
The data type pkg1.type1 refers the current package specifications
|
||||
for the packge pkg1:
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE rec0_t IS RECORD (a INT, b VARCHAR(32));
|
||||
TYPE assoc0_t IS TABLE OF pkg1.rec0_t INDEX BY INTEGER;
|
||||
END;
|
||||
Avoid a recursive find_package_spec_type().
|
||||
*/
|
||||
sp_package *spec= get_package();
|
||||
DBUG_ASSERT(spec);
|
||||
if (!(tdef[0]= spec->find_type_def(type)))
|
||||
{
|
||||
raise_unknown_data_type(package, type);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/*
|
||||
Another special case: a reference to the current package specification
|
||||
from a package routine parameter or a package function RETURN:
|
||||
CREATE PACKAGE p2 AS
|
||||
TYPE r IS RECORD(x INT);
|
||||
PROCEDURE q(v p2.r); -- here
|
||||
FUNCTION f RETURN p2.r; -- here
|
||||
END;
|
||||
*/
|
||||
if ((m_handler == &sp_handler_package_function ||
|
||||
m_handler == &sp_handler_package_procedure))
|
||||
{
|
||||
DBUG_ASSERT(m_parent);
|
||||
if (m_parent->m_handler == &sp_handler_package_spec &&
|
||||
Lex_ident_routine(m_parent->m_name).streq(package))
|
||||
{
|
||||
if (!(tdef[0]= m_parent->find_type_def(type)))
|
||||
{
|
||||
raise_unknown_data_type(package, type);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Another special case - a two step reference to a type
|
||||
in the package of the db of the current routine (test1 in this example):
|
||||
CREATE OR REPLACE PROCEDURE test1.p1 AS
|
||||
r0 pkg1.rec0_t; -- A reference to test1.pkg1.rec0_t
|
||||
BEGIN ...
|
||||
*/
|
||||
if (m_db.str)
|
||||
{
|
||||
Lex_ident_db_normalized ndb;
|
||||
if (!(ndb= thd->to_ident_db_normalized_with_error(m_db)).str)
|
||||
return true;
|
||||
sp_package *spec;
|
||||
if ((spec= Sp_handler::find_package_spec(thd, ndb, package)))
|
||||
return get_typedef_package_spec_or_error(thd, tdef, spec,
|
||||
ndb, package, type);
|
||||
if (thd->is_fatal_error)
|
||||
return true; // E.g. ER_STACK_OVERRUN_NEED_MORE raised
|
||||
}
|
||||
|
||||
// Now go with the general case
|
||||
Lex_ident_db_normalized resolved_db;
|
||||
if (thd->variables.path.find_package_spec_type(thd, &resolved_db,
|
||||
package, type))
|
||||
return true; // An internal error
|
||||
if (!resolved_db.str)
|
||||
{
|
||||
raise_unknown_data_type(package, type);
|
||||
return true; // 2-step package spec was not found
|
||||
}
|
||||
return get_typedef_package_spec_or_error(thd, tdef,
|
||||
Lex_ident_sys(resolved_db.str,
|
||||
resolved_db.length),
|
||||
package, type);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Get a 3-step qualified TYPE defines in a PACKAGE
|
||||
|
||||
@param OUT tdef - The pointer to the TYPE definition
|
||||
@param db - The database name
|
||||
@param package - The package name
|
||||
@param type - The data type name
|
||||
|
||||
@retval false - The database "db" with the package "package"
|
||||
with the data type "type" was found,
|
||||
and tdef was set to the pointer of the found type.
|
||||
@retval true - The data type was not found, or some error happened
|
||||
during type resolution.
|
||||
*/
|
||||
bool sp_head::get_typedef_package_spec_or_error(THD *thd,
|
||||
const sp_type_def **tdef,
|
||||
const Lex_ident_sys_st &db,
|
||||
const Lex_ident_sys_st &package,
|
||||
const Lex_ident_sys_st &type)
|
||||
{
|
||||
DBUG_ASSERT(!db.is_null());
|
||||
DBUG_ASSERT(!package.is_null());
|
||||
DBUG_ASSERT(!type.is_null());
|
||||
|
||||
Lex_ident_db_normalized dbn= thd->to_ident_db_normalized_with_error(db);
|
||||
if (!dbn.str)
|
||||
return true;
|
||||
|
||||
/*
|
||||
Catch a special case first: a reference to the current package spec.
|
||||
Note, cast to Lex_ident_routine is safe below because m_name gets
|
||||
to sp_head after Lex_ident_routine::check_name_with_error().
|
||||
*/
|
||||
if (m_handler == &sp_handler_package_spec &&
|
||||
dbn.streq(m_db) &&
|
||||
Lex_ident_routine(m_name).streq(package))
|
||||
{
|
||||
/*
|
||||
The data type db1.pkg1.type1 refers the current package specifications
|
||||
for the packge pkg1:
|
||||
USE db1;
|
||||
CREATE PACKAGE pkg1 AS
|
||||
TYPE rec0_t IS RECORD (a INT, b VARCHAR(32));
|
||||
TYPE assoc0_t IS TABLE OF db1.pkg1.rec0_t INDEX BY INTEGER;
|
||||
END;
|
||||
Avoid a recursive find_package_spec_type().
|
||||
*/
|
||||
sp_package *spec= get_package();
|
||||
DBUG_ASSERT(spec);
|
||||
if (!(tdef[0]= spec->find_type_def(type)))
|
||||
{
|
||||
raise_unknown_data_type(dbn, package, type);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
Another special case: a reference to the current package specification
|
||||
from a package routine parameter or a package function RETURN:
|
||||
CREATE PACKAGE p2 AS
|
||||
TYPE r IS RECORD(x INT);
|
||||
PROCEDURE q(v test.p2.r); -- here
|
||||
FUNCTION f RETURN test.p2.r; -- here
|
||||
END;
|
||||
*/
|
||||
if ((m_handler == &sp_handler_package_function ||
|
||||
m_handler == &sp_handler_package_procedure))
|
||||
{
|
||||
DBUG_ASSERT(m_parent);
|
||||
if (m_parent->m_handler == &sp_handler_package_spec &&
|
||||
dbn.streq(m_parent->m_db) &&
|
||||
Lex_ident_routine(m_parent->m_name).streq(package))
|
||||
{
|
||||
if (!(tdef[0]= m_parent->find_type_def(type)))
|
||||
{
|
||||
raise_unknown_data_type(package, type);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
sp_package *spec= Sp_handler::find_package_spec(thd, dbn, package);
|
||||
if (!spec)
|
||||
{
|
||||
raise_unknown_data_type(dbn, package, type);
|
||||
return true; // 3-step package spec was not found
|
||||
}
|
||||
return get_typedef_package_spec_or_error(thd, tdef, spec, dbn, package, type);
|
||||
}
|
||||
|
||||
@@ -1021,6 +1021,32 @@ public:
|
||||
|
||||
virtual void init_psi_share();
|
||||
|
||||
static void raise_unknown_data_type(const Lex_ident_db_normalized &db,
|
||||
const Lex_ident_sys_st &package,
|
||||
const Lex_ident_sys_st &type);
|
||||
static void raise_unknown_data_type(const Lex_ident_sys_st &package,
|
||||
const Lex_ident_sys_st &type);
|
||||
bool check_maybe_qualified_type_context(const Lex_ident_sys_st &db,
|
||||
const Lex_ident_sys_st &package,
|
||||
const Lex_ident_sys_st &type) const;
|
||||
bool check_maybe_foreign_type_context(THD *thd, const Lex_field_type_st &def,
|
||||
column_definition_type_t type);
|
||||
bool get_typedef_package_spec_or_error(THD *thd,
|
||||
const sp_type_def **tdef,
|
||||
const Lex_ident_sys_st &package,
|
||||
const Lex_ident_sys_st &type);
|
||||
|
||||
bool get_typedef_package_spec_or_error(THD *thd,
|
||||
const sp_type_def **tdef,
|
||||
const Lex_ident_sys_st &db,
|
||||
const Lex_ident_sys_st &package,
|
||||
const Lex_ident_sys_st &type);
|
||||
bool get_typedef_package_spec_or_error(THD *thd,
|
||||
const sp_type_def **tdef,
|
||||
sp_package *spec,
|
||||
const Lex_ident_db_normalized &db,
|
||||
const Lex_ident_sys_st &package,
|
||||
const Lex_ident_sys_st &type);
|
||||
protected:
|
||||
|
||||
MEM_ROOT *m_thd_root; ///< Temp. store for thd's mem_root
|
||||
@@ -1204,6 +1230,8 @@ public:
|
||||
sp_pcontext *ctx= m_pcont->child_context(0);
|
||||
return ctx ? ctx->find_variable(name, true) : NULL;
|
||||
}
|
||||
sp_type_def *find_type_def(const Lex_ident_sys_st &type);
|
||||
|
||||
bool validate_after_parser(THD *thd);
|
||||
bool instantiate_if_needed(THD *thd);
|
||||
};
|
||||
|
||||
@@ -69,7 +69,7 @@ public:
|
||||
bool sp_cursor_stmt_finalize(THD *thd, const Lex_ident_sys_st &ps_name,
|
||||
const char *beg, const char *end)
|
||||
{
|
||||
m_ps_name= Lex_ident_sys(thd, &ps_name);
|
||||
m_ps_name= Lex_ident_sys(ps_name);
|
||||
pop_select(); //main select
|
||||
if (unlikely(stmt_finalize(thd)))
|
||||
return true;
|
||||
|
||||
@@ -445,6 +445,20 @@ sp_type_def *sp_pcontext::find_type_def(const LEX_CSTRING &name,
|
||||
}
|
||||
|
||||
|
||||
bool sp_pcontext::type_defs_add_ref_cursor(THD *thd,
|
||||
const Lex_ident_column &name,
|
||||
const Type_handler *th,
|
||||
const Spvar_definition &return_def,
|
||||
bool is_prepared)
|
||||
{
|
||||
sp_type_def_ref *tdef= new (thd->mem_root) sp_type_def_ref(name, th,
|
||||
return_def, is_prepared);
|
||||
if (unlikely(!tdef || type_defs_add(thd, tdef)))
|
||||
return true; // EOM
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
sp_condition_value *
|
||||
sp_pcontext::find_declared_or_predefined_condition(THD *thd,
|
||||
const LEX_CSTRING *name)
|
||||
|
||||
@@ -789,6 +789,25 @@ public:
|
||||
return sp_type_def_list::type_defs_add(def);
|
||||
}
|
||||
|
||||
/*
|
||||
Add a new TYPE for REF CURSOR, e.g.:
|
||||
TYPE type1 IS REF CURSOR;
|
||||
TYPE type1 IS REF CURSOR RETURN t1%ROWTYPE;
|
||||
TYPE type1 IS REF CURSOR RETURN pkg1.rec1;
|
||||
@param THD - The THD
|
||||
@param name - The name of the new data type
|
||||
@param th - The type handler of the new TYPE
|
||||
(usually &type_handler_sys_refcursor)
|
||||
@param return_def - The definition of the RETURN type
|
||||
@param is_prepared - If sp_prepare_create_field() has already
|
||||
been called for return_def.
|
||||
See details in class sp_type_def_ref.
|
||||
*/
|
||||
bool type_defs_add_ref_cursor(THD *thd, const Lex_ident_column &name,
|
||||
const Type_handler *th,
|
||||
const Spvar_definition &return_def,
|
||||
bool is_prepared);
|
||||
|
||||
private:
|
||||
/// Constructor for a tree node.
|
||||
/// @param prev the parent parsing context
|
||||
|
||||
281
sql/sql_lex.cc
281
sql/sql_lex.cc
@@ -6824,8 +6824,10 @@ sp_variable *LEX::sp_param_init(LEX_CSTRING *name)
|
||||
bool LEX::sp_param_fill_definition(sp_variable *spvar,
|
||||
const Lex_field_type_st &def)
|
||||
{
|
||||
constexpr column_definition_type_t dtype= COLUMN_DEFINITION_ROUTINE_PARAM;
|
||||
return
|
||||
last_field->set_attributes(thd, def, COLUMN_DEFINITION_ROUTINE_PARAM) ||
|
||||
sphead->check_maybe_foreign_type_context(thd, def, dtype) ||
|
||||
last_field->set_attributes(thd, def, dtype) ||
|
||||
sphead->fill_spvar_definition(thd, last_field, &spvar->name);
|
||||
}
|
||||
|
||||
@@ -6884,8 +6886,10 @@ bool LEX::sp_param_set_default_and_finalize(sp_variable *spvar,
|
||||
|
||||
bool LEX::sf_return_fill_definition(const Lex_field_type_st &def)
|
||||
{
|
||||
constexpr column_definition_type_t dtype= COLUMN_DEFINITION_FUNCTION_RETURN;
|
||||
return
|
||||
last_field->set_attributes(thd, def, COLUMN_DEFINITION_FUNCTION_RETURN) ||
|
||||
sphead->check_maybe_foreign_type_context(thd, def, dtype) ||
|
||||
last_field->set_attributes(thd, def, dtype) ||
|
||||
sphead->fill_field_definition(thd, last_field);
|
||||
}
|
||||
|
||||
@@ -6940,12 +6944,61 @@ void LEX::set_stmt_init()
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
Check if the current CREATE PACKAGE statement does not recursively depend on:
|
||||
CREATE PACKAGE db.name
|
||||
|
||||
This method is called to avoid cyclic dependencies:
|
||||
|
||||
CREATE PACKAGE a_pkg AS
|
||||
TYPE arec IS RECORD (x INT, y VARCHAR(10));
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE b_pkg AS
|
||||
TYPE brec IS RECORD (p INT, q VARCHAR(10));
|
||||
TYPE bcur IS REF CURSOR RETURN a_pkg.arec; -- b_pkg -> a_pkg
|
||||
END;
|
||||
$$
|
||||
-- The next statement would replace a_pkg and cause a cyclic dependency:
|
||||
CREATE OR REPLACE PACKAGE a_pkg AS
|
||||
TYPE arec IS RECORD (x INT, y VARCHAR(10));
|
||||
TYPE acur IS REF CURSOR RETURN b_pkg.brec; -- a_pkg -> b_pkg -> a_pkg
|
||||
END;
|
||||
$$
|
||||
*/
|
||||
bool LEX::check_create_package_cycle_dependency(const Lex_ident_sys_st &db,
|
||||
const Lex_ident_sys_st &name)
|
||||
const
|
||||
{
|
||||
if (this != stmt_lex &&
|
||||
stmt_lex->sql_command == SQLCOM_CREATE_PACKAGE &&
|
||||
stmt_lex->sphead &&
|
||||
stmt_lex->sphead->m_handler == &sp_handler_package_spec)
|
||||
{
|
||||
if (sphead->m_handler != &sp_handler_package_spec)
|
||||
return false; // e.g. a package routine inside a package specification
|
||||
if (stmt_lex->sphead->m_db.streq(db) &&
|
||||
Lex_ident_routine(stmt_lex->sphead->m_name).streq(name))
|
||||
{
|
||||
/*
|
||||
The exact raised error is not important here.
|
||||
It will be overriden to: Unknown data type: '`pkg`.`type`'
|
||||
*/
|
||||
DBUG_ASSERT(thd->get_internal_handler());
|
||||
my_error(ER_UNKNOWN_ERROR, MYF(0), "Cycle found in TYPE definition");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Find a local or a package body type declaration by name
|
||||
@param IN name - the data type name
|
||||
@retval - the data type (if found), or NULL otherwise.
|
||||
*/
|
||||
const sp_type_def *LEX::find_type_def(const LEX_CSTRING &name) const
|
||||
const sp_type_def *LEX::find_type_def(const Lex_ident_sys_st &name) const
|
||||
{
|
||||
DBUG_ASSERT(spcont);
|
||||
const sp_type_def *def= spcont->find_type_def(name, false);
|
||||
@@ -6954,8 +7007,7 @@ const sp_type_def *LEX::find_type_def(const LEX_CSTRING &name) const
|
||||
if (sphead->m_parent)
|
||||
{
|
||||
// Find a package body type definition
|
||||
return sphead->m_parent->get_parse_context()->
|
||||
child_context(0)->find_type_def(name, true);
|
||||
return sphead->m_parent->find_type_def(name);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
@@ -8272,7 +8324,8 @@ sp_lex_local *LEX::package_routine_start(THD *thd,
|
||||
|
||||
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)))
|
||||
if (unlikely(!sublex->make_sp_head_no_recursive(thd, spname, definer,
|
||||
sph, atype)))
|
||||
return NULL;
|
||||
sphead->get_package()->m_current_routine= sublex;
|
||||
return sublex;
|
||||
@@ -8312,6 +8365,7 @@ sp_head *LEX::make_sp_head(THD *thd, const sp_name *name,
|
||||
|
||||
|
||||
sp_head *LEX::make_sp_head_no_recursive(THD *thd, const sp_name *name,
|
||||
const LEX_USER *definer_arg,
|
||||
const Sp_handler *sph,
|
||||
enum_sp_aggregate_type agg_type)
|
||||
{
|
||||
@@ -8330,7 +8384,12 @@ sp_head *LEX::make_sp_head_no_recursive(THD *thd, const sp_name *name,
|
||||
if (!sphead || (package &&
|
||||
(sph == &sp_handler_package_procedure ||
|
||||
sph == &sp_handler_package_function)))
|
||||
return make_sp_head(thd, name, sph, agg_type);
|
||||
{
|
||||
sp_head *res= make_sp_head(thd, name, sph, agg_type);
|
||||
if (res && definer_arg)
|
||||
res->set_definer(&definer_arg->user, &definer_arg->host);
|
||||
return res;
|
||||
}
|
||||
my_error(ER_SP_NO_RECURSIVE_CREATE, MYF(0), sph->type_str());
|
||||
return NULL;
|
||||
}
|
||||
@@ -9676,8 +9735,7 @@ Item *LEX::create_item_ident_sp(THD *thd, Lex_ident_sys_st *name,
|
||||
*/
|
||||
bool got_error;
|
||||
Item *trigger_specific_item=
|
||||
create_item_ident_trigger_specific(thd,
|
||||
Lex_ident_sys(thd, name), &got_error);
|
||||
create_item_ident_trigger_specific(thd, Lex_ident_sys(*name), &got_error);
|
||||
if (trigger_specific_item)
|
||||
/*
|
||||
trigger_specific_item != nullptr if the argument 'name' equals one of
|
||||
@@ -12956,7 +13014,7 @@ bool st_select_lex::save_item_list_names(THD *thd)
|
||||
|
||||
while ((item= li++))
|
||||
{
|
||||
Lex_ident_sys *name= new (thd->mem_root) Lex_ident_sys(thd, &item->name);
|
||||
Lex_ident_sys *name= new (thd->mem_root) Lex_ident_sys(item->name);
|
||||
if (unlikely(!name ||
|
||||
orig_names_of_item_list_elems->push_back(name, thd->mem_root)))
|
||||
{
|
||||
@@ -13182,7 +13240,7 @@ bool LEX::stmt_create_stored_function_start(const DDL_options_st &options,
|
||||
const sp_name *spname)
|
||||
{
|
||||
if (stmt_create_function_start(options) ||
|
||||
unlikely(!make_sp_head_no_recursive(thd, spname,
|
||||
unlikely(!make_sp_head_no_recursive(thd, spname, definer,
|
||||
&sp_handler_function, agg_type)))
|
||||
return true;
|
||||
return false;
|
||||
@@ -13404,9 +13462,96 @@ bool LEX::declare_type_assoc_array(THD *thd,
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Declare a new REF CURSOR type with these semantics:
|
||||
TYPE t IS REF CURSOR RETURN db.package.type; -- a 3-step package spec type
|
||||
TYPE t IS REF CURSOR RETURN package.type; -- a 2-step package spec type
|
||||
TYPE t IS REF CURSOR RETURN type; -- a 1-step semantic
|
||||
I.e. the data type in RETURN refers to a previously defined TYPE.
|
||||
|
||||
@param thd - The thd
|
||||
@param type_name - The name of the new data type
|
||||
@param db - The database name. Can be a null identifier {0,0}.
|
||||
@param package - The package name. Can be a null identifier {0,0}.
|
||||
@param type - The type name.
|
||||
|
||||
@retval true - If could not create a new TYPE. Possible reasons:
|
||||
* the data type specified by [db.]package.type
|
||||
was not found
|
||||
* something went wrong during mysql.proc reading.
|
||||
* EOM happened
|
||||
@retval false - If the new TYPE was successfully created.
|
||||
*/
|
||||
bool LEX::declare_type_ref_cursor_return_typedef(THD *thd,
|
||||
const Lex_ident_sys_st &type_name,
|
||||
const Lex_ident_sys_st &db,
|
||||
const Lex_ident_sys_st &package,
|
||||
const Lex_ident_sys_st &type)
|
||||
{
|
||||
if (sphead->check_maybe_qualified_type_context(db, package, type))
|
||||
return true;
|
||||
|
||||
const Lex_ident_plugin sr= "sys_refcursor"_Lex_ident_plugin;
|
||||
const Type_handler *th= Type_handler::handler_by_name_or_error(thd, sr);
|
||||
if (unlikely(!th))
|
||||
return true;
|
||||
|
||||
const sp_type_def *rt= nullptr; // The typedef of the RETURN type
|
||||
if (db.str) // A 3-step RETURN
|
||||
{
|
||||
// TYPE c0 IS REF CURSOR RETURN db1.pkg1.rec1_t;
|
||||
if (check_create_package_cycle_dependency(db, package) ||
|
||||
sphead->get_typedef_package_spec_or_error(thd, &rt, db, package, type))
|
||||
return true;
|
||||
}
|
||||
else if (package.str) // A 2-step RETURN
|
||||
{
|
||||
// TYPE c0 IS REF CURSOR RETURN pkg1.rec1_t;
|
||||
if (check_create_package_cycle_dependency(Lex_ident_sys(sphead->m_db),
|
||||
package) ||
|
||||
sphead->get_typedef_package_spec_or_error(thd, &rt, package, type))
|
||||
return true;
|
||||
}
|
||||
else // A 1-step RETURN
|
||||
{
|
||||
// TYPE c0 IS REF CURSOR RETURN rec1_t;
|
||||
if (!(rt= find_type_def(type)))
|
||||
{
|
||||
my_error(ER_UNKNOWN_DATA_TYPE, MYF(0), type.str);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
const sp_type_def_record *type_def_rec=
|
||||
dynamic_cast<const sp_type_def_record*>(rt);
|
||||
if (!type_def_rec ||
|
||||
!dynamic_cast<const Type_handler_row*>(rt->type_handler()))
|
||||
{
|
||||
my_error(ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION, MYF(0),
|
||||
type.str, "REF CURSOR RETURN");
|
||||
return true;
|
||||
}
|
||||
Row_definition_list *row= type_def_rec->field->deep_copy(thd);
|
||||
if (!row)
|
||||
return true; // EOM
|
||||
|
||||
if (check_ref_cursor_components(row))
|
||||
return true;
|
||||
|
||||
const Spvar_definition return_def(&type_handler_row, row);
|
||||
return spcont->type_defs_add_ref_cursor(thd, Lex_ident_column(type_name), th,
|
||||
return_def, false/*is_prepared*/);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Declare a new REF CURSOR type with these semantics:
|
||||
TYPE t IS REF CURSOR;
|
||||
TYPE t IS REF CURSOR RETURN db1.t1%ROWTYPE;
|
||||
TYPE t IS REF CURSOR RETURN t1%ROWTYPE;
|
||||
TYPE t IS REF CURSOR RETURN rec_var%TYPE;
|
||||
*/
|
||||
bool LEX::declare_type_ref_cursor(THD *thd,
|
||||
const Lex_ident_sys_st &type_name,
|
||||
const Lex_ident_sys_st &return_type_name,
|
||||
const Qualified_column_ident *rowtype,
|
||||
const Qualified_column_ident *vartype,
|
||||
const Lex_ident_cli_st &syntax_error_token)
|
||||
@@ -13480,41 +13625,9 @@ bool LEX::declare_type_ref_cursor(THD *thd,
|
||||
return_def= Spvar_definition(ti, sp_rcontext_addr(nullptr, 0));
|
||||
}
|
||||
}
|
||||
else if (!return_type_name.is_null())
|
||||
{
|
||||
/*
|
||||
An explicit data type in the RETURN clause:
|
||||
TYPE c0 IS REF CURSOR RETURN rec0_t;
|
||||
*/
|
||||
const sp_type_def *rt= find_type_def(return_type_name);
|
||||
if (!rt)
|
||||
{
|
||||
my_error(ER_UNKNOWN_DATA_TYPE, MYF(0), return_type_name.str);
|
||||
return true;
|
||||
}
|
||||
if (!dynamic_cast<const Type_handler_row*>(rt->type_handler()))
|
||||
{
|
||||
my_error(ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION, MYF(0),
|
||||
return_type_name.str, "REF CURSOR RETURN");
|
||||
return true;
|
||||
}
|
||||
Row_definition_list *row= static_cast<const sp_type_def_record*>(rt)->
|
||||
field->deep_copy(thd);
|
||||
if (!row)
|
||||
return true; // EOM
|
||||
|
||||
if (check_ref_cursor_components(row))
|
||||
return true;
|
||||
|
||||
return_def= Spvar_definition(&type_handler_row, row);
|
||||
}
|
||||
sp_type_def_ref *tdef=
|
||||
new (thd->mem_root) sp_type_def_ref(Lex_ident_column(type_name), th,
|
||||
return_def, is_prepared);
|
||||
if (unlikely(!tdef || spcont->type_defs_add(thd, tdef)))
|
||||
return true; // EOM
|
||||
|
||||
return false;
|
||||
return spcont->type_defs_add_ref_cursor(thd, Lex_ident_column(type_name), th,
|
||||
return_def, is_prepared);
|
||||
}
|
||||
|
||||
|
||||
@@ -13537,7 +13650,7 @@ bool LEX::check_ref_cursor_components(Row_definition_list *row) const
|
||||
|
||||
|
||||
bool LEX::set_field_type_udt_or_typedef(Lex_field_type_st *type,
|
||||
const LEX_CSTRING &name,
|
||||
const Lex_ident_sys_st &name,
|
||||
const Lex_length_and_dec_st &attr,
|
||||
const Lex_column_charset_collation_attrs_st &coll)
|
||||
{
|
||||
@@ -13598,7 +13711,7 @@ bool LEX::set_cast_type_udt(Lex_cast_type_st *type,
|
||||
|
||||
|
||||
bool LEX::set_field_type_typedef(Lex_field_type_st *type,
|
||||
const LEX_CSTRING &name,
|
||||
const Lex_ident_sys_st &name,
|
||||
const Lex_length_and_dec_st &attr,
|
||||
const Lex_column_charset_collation_attrs_st &coll,
|
||||
bool *is_typedef)
|
||||
@@ -13625,6 +13738,78 @@ bool LEX::set_field_type_typedef(Lex_field_type_st *type,
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Set a PACKAGE data type to "res" for a 2-step qualified name,
|
||||
consisting by the package name and type name.
|
||||
Handles the following cases:
|
||||
- A PACKAGE refers to its own type using a qualified name
|
||||
- A routine refers to the PACKAGE in the same database with the routine
|
||||
using a qualified type
|
||||
- Otherwise, the database which contains a package "package" with the type
|
||||
"type" is resolved using the @@PATH variable.
|
||||
|
||||
@param OUT res - The data type to write to
|
||||
@param package - The package name
|
||||
@param type - The data type name
|
||||
|
||||
@retval false - The package "package" with the data type "type" was found,
|
||||
and res[0] was set to the found type.
|
||||
@retval true - The data type was not found, or some error happened
|
||||
during type resolution.
|
||||
*/
|
||||
bool LEX::set_field_type_typedef_package_spec(Lex_field_type_st *res,
|
||||
const Lex_ident_sys_st &package,
|
||||
const Lex_ident_sys_st &type)
|
||||
{
|
||||
const sp_type_def *tdef= nullptr;
|
||||
if (sphead->check_maybe_qualified_type_context(Lex_ident_sys(),
|
||||
package, type))
|
||||
return true;
|
||||
if (check_create_package_cycle_dependency(Lex_ident_sys(sphead->m_db),
|
||||
package))
|
||||
return true;
|
||||
if (sphead->get_typedef_package_spec_or_error(thd, &tdef, package, type))
|
||||
return true;
|
||||
res->set(tdef->type_handler(), nullptr/*CHARSET_INFO*/);
|
||||
res->set_foreign_module_type(true);
|
||||
last_field->set_attr_const_generic_ptr(0, tdef);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Set a PACKAGE data type to "res" by a 3-step qualified name,
|
||||
consisting by the database name, package name and type name.
|
||||
|
||||
@param OUT res - The data type to write to
|
||||
@param db - The database name
|
||||
@param package - The package name
|
||||
@param type - The data type name
|
||||
|
||||
@retval false - The package "package" with the data type "type" was found,
|
||||
and res[0] was set to the found type.
|
||||
@retval true - The data type was not found, or some error happened
|
||||
during type resolution.
|
||||
*/
|
||||
bool LEX::set_field_type_typedef_package_spec(Lex_field_type_st *res,
|
||||
const Lex_ident_sys_st &db,
|
||||
const Lex_ident_sys_st &package,
|
||||
const Lex_ident_sys_st &type)
|
||||
{
|
||||
const sp_type_def *tdef= nullptr;
|
||||
if (sphead->check_maybe_qualified_type_context(db, package, type))
|
||||
return true;
|
||||
if (check_create_package_cycle_dependency(db, package))
|
||||
return true;
|
||||
if (sphead->get_typedef_package_spec_or_error(thd, &tdef, db, package, type))
|
||||
return true;
|
||||
res->set(tdef->type_handler(), nullptr/*CHARSET_INFO*/);
|
||||
res->set_foreign_module_type(true);
|
||||
last_field->set_attr_const_generic_ptr(0, tdef);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool sp_expr_lex::sp_repeat_loop_finalize(THD *thd)
|
||||
{
|
||||
uint ip= sphead->instructions();
|
||||
|
||||
@@ -4111,6 +4111,7 @@ public:
|
||||
sp_head *make_sp_head(THD *thd, const sp_name *name, const Sp_handler *sph,
|
||||
enum_sp_aggregate_type agg_type);
|
||||
sp_head *make_sp_head_no_recursive(THD *thd, const sp_name *name,
|
||||
const LEX_USER *definer,
|
||||
const Sp_handler *sph,
|
||||
enum_sp_aggregate_type agg_type);
|
||||
bool sp_body_finalize_routine(THD *);
|
||||
@@ -4151,7 +4152,10 @@ public:
|
||||
bool direct_call(THD *thd, const Qualified_ident *ident, List<Item> *args);
|
||||
|
||||
bool assoc_assign_start(THD *thd, Qualified_ident *ident);
|
||||
const sp_type_def *find_type_def(const LEX_CSTRING &name) const;
|
||||
const sp_type_def *find_type_def(const Lex_ident_sys_st& name) const;
|
||||
bool check_create_package_cycle_dependency(const Lex_ident_sys_st &db,
|
||||
const Lex_ident_sys_st &name)
|
||||
const;
|
||||
sp_variable *find_variable(const LEX_CSTRING *name,
|
||||
sp_pcontext **ctx,
|
||||
const Sp_rcontext_handler **rh) const;
|
||||
@@ -5277,20 +5281,32 @@ public:
|
||||
Spvar_definition *value);
|
||||
bool declare_type_ref_cursor(THD *thd,
|
||||
const Lex_ident_sys_st &type_name,
|
||||
const Lex_ident_sys_st &return_type_name,
|
||||
const Qualified_column_ident *rowtype,
|
||||
const Qualified_column_ident *vartype,
|
||||
const Lex_ident_cli_st &syntax_error_token);
|
||||
bool declare_type_ref_cursor_return_typedef(THD *thd,
|
||||
const Lex_ident_sys_st &type_name,
|
||||
const Lex_ident_sys_st &db/*can be null ident*/,
|
||||
const Lex_ident_sys_st &package,
|
||||
const Lex_ident_sys_st &type);
|
||||
bool set_field_type_typedef(Lex_field_type_st *type,
|
||||
const LEX_CSTRING &name,
|
||||
const Lex_ident_sys_st &name,
|
||||
const Lex_length_and_dec_st &attr,
|
||||
const Lex_column_charset_collation_attrs_st &coll,
|
||||
bool *is_typedef);
|
||||
bool set_field_type_udt_or_typedef(Lex_field_type_st *type,
|
||||
const LEX_CSTRING &name,
|
||||
const Lex_ident_sys_st &name,
|
||||
const Lex_length_and_dec_st &attr,
|
||||
const Lex_column_charset_collation_attrs_st &coll);
|
||||
|
||||
bool set_field_type_typedef_package_spec(Lex_field_type_st *res,
|
||||
const Lex_ident_sys_st &package,
|
||||
const Lex_ident_sys_st &type);
|
||||
bool set_field_type_typedef_package_spec(Lex_field_type_st *res,
|
||||
const Lex_ident_sys_st &db,
|
||||
const Lex_ident_sys_st &package,
|
||||
const Lex_ident_sys_st &type);
|
||||
|
||||
bool map_data_type(const Lex_ident_sys_st &schema,
|
||||
Lex_field_type_st *type) const;
|
||||
|
||||
|
||||
@@ -172,6 +172,63 @@ bool Sql_path::resolve(THD *thd, sp_head *caller, sp_name *name,
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Iterate through all schemas in @@path and find a package "package" with the
|
||||
type "type"
|
||||
|
||||
@param thd - The THD
|
||||
@param OUT db - The found database which contains a type package.type
|
||||
If db->str is nullptr the nothing was found.
|
||||
@param package - The package to find.
|
||||
@param type - The type to find.
|
||||
@retval true - If error happened during resolution.
|
||||
@retval false - If no errors happened during resolution.
|
||||
Note, if nothing was found and no errors happened,
|
||||
the return value is false.
|
||||
*/
|
||||
bool Sql_path::find_package_spec_type(THD *thd,
|
||||
Lex_ident_db_normalized *db,
|
||||
const Lex_ident_sys_st &package,
|
||||
const Lex_ident_sys_st &type)
|
||||
{
|
||||
DBUG_ASSERT(!thd->is_fatal_error);
|
||||
*db= Lex_ident_db_normalized();
|
||||
for (size_t i= 0; i < m_count; i++)
|
||||
{
|
||||
sp_package *pkg;
|
||||
Lex_ident_db_normalized ncdb;
|
||||
if (is_cur_schema(i))
|
||||
{
|
||||
if (!thd->db.str)
|
||||
continue;
|
||||
if (!(ncdb= thd->copy_db_normalized()).str)
|
||||
return true; // EOM
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
Conversion to Lex_ident_db_normalized is safe because
|
||||
database names get into Sql_path in normalized form.
|
||||
*/
|
||||
ncdb= Lex_ident_db_normalized(m_schemas[i].str, m_schemas[i].length);
|
||||
}
|
||||
if (!(pkg= Sp_handler::find_package_spec(thd, ncdb, package)))
|
||||
{
|
||||
if (thd->is_fatal_error)
|
||||
return true; // E.g. ER_STACK_OVERRUN_NEED_MORE raised
|
||||
continue;
|
||||
}
|
||||
sp_type_def *tdef= pkg->find_type_def(type);
|
||||
if (tdef)
|
||||
{
|
||||
*db= ncdb;
|
||||
return false; // Found a TYPE declaration in a CREATE PACKAGE
|
||||
}
|
||||
}
|
||||
return false; // Nothing found
|
||||
}
|
||||
|
||||
|
||||
void Sql_path::free()
|
||||
{
|
||||
if (m_count)
|
||||
|
||||
@@ -38,6 +38,10 @@ public:
|
||||
|
||||
bool resolve(THD *thd, sp_head *caller, sp_name *name,
|
||||
const Sp_handler **sph, Database_qualified_name *pkgname) const;
|
||||
|
||||
bool find_package_spec_type(THD *thd, Lex_ident_db_normalized *db,
|
||||
const Lex_ident_sys_st &package,
|
||||
const Lex_ident_sys_st &type);
|
||||
/*
|
||||
Initialize the path variable with default values
|
||||
*/
|
||||
|
||||
@@ -1791,8 +1791,27 @@ bool Table_triggers_list::check_n_load(THD *thd, const LEX_CSTRING *db,
|
||||
|
||||
thd->lex= &lex;
|
||||
|
||||
save_db= thd->db;
|
||||
thd->reset_db(db);
|
||||
/*
|
||||
Let's set thd->db to a my_alloc-ed copy of "db".
|
||||
We cannot just call thd->reset_db(db) here for the following reasons:
|
||||
|
||||
In case if a trigger uses package TYPEs, e.g.:
|
||||
CREATE TRIGGER db2.trg BEFORE INSERT ON db2.t1 FOR EACH ROW
|
||||
DECLARE
|
||||
r db1.pkg.rec; -- package TYPE
|
||||
BEGIN
|
||||
...
|
||||
END;
|
||||
we'll call Sp_hadler::db_load_routine() for the PACKAGE db1.pkg when
|
||||
parsing the trigger body. It'll call mysql_change_db() which will:
|
||||
- set thd->db to a my_alloc'ed copy of "db1"
|
||||
(which is the database of the TYPE db1.pkg.rec)
|
||||
- on success, call my_free() to the previous value thd->db.str.
|
||||
So let's set thd->db to a copy of "db", which can be my_free'd.
|
||||
*/
|
||||
save_db= thd->db; // Make a thd->db backup
|
||||
thd->reset_db(&null_clex_str); // Reset thd->db without freeing it
|
||||
thd->set_db(db); // Set thd->db to a my_alloc copy of "db"
|
||||
while ((trg_create_str= it++))
|
||||
{
|
||||
sp_head *sp;
|
||||
@@ -2035,7 +2054,14 @@ bool Table_triggers_list::check_n_load(THD *thd, const LEX_CSTRING *db,
|
||||
sp->m_trg= trigger;
|
||||
lex_end(&lex);
|
||||
}
|
||||
thd->reset_db(&save_db);
|
||||
/*
|
||||
Now thd->db should point to a my_alloc-ed copy of "db",
|
||||
even if we loaded PACKAGEs during the parsing of the trigger.
|
||||
See comments about package TYPEs above. Let's my_free thd->db.str
|
||||
and restore the backed copy of thd->db.
|
||||
*/
|
||||
thd->set_db(&null_clex_str); // It'll call my_free() for thd->db.str
|
||||
thd->reset_db(&save_db); // Restore thd->db
|
||||
thd->lex= old_lex;
|
||||
thd->spcont= save_spcont;
|
||||
thd->variables.sql_mode= save_sql_mode;
|
||||
|
||||
@@ -1379,7 +1379,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
|
||||
sp_opt_label BIN_NUM TEXT_STRING_filesystem
|
||||
opt_constraint constraint opt_ident
|
||||
sp_block_label sp_control_label opt_place opt_db opt_nls_param
|
||||
udt_name
|
||||
|
||||
%ifdef ORACLE
|
||||
%type <lex_str>
|
||||
@@ -1398,6 +1397,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
|
||||
ident_for_loop_index
|
||||
select_or_ps_name
|
||||
fetch_statement_source
|
||||
udt_name
|
||||
|
||||
%type <lex_string_with_metadata>
|
||||
TEXT_STRING
|
||||
@@ -3336,7 +3336,7 @@ ev_sql_stmt:
|
||||
|
||||
if (unlikely(!lex->make_sp_head(thd,
|
||||
lex->event_parse_data->identifier,
|
||||
&sp_handler_procedure,
|
||||
&sp_handler_event,
|
||||
DEFAULT_AGGREGATE)))
|
||||
MYSQL_YYABORT;
|
||||
|
||||
@@ -6717,8 +6717,8 @@ qualified_field_type:
|
||||
|
||||
udt_name:
|
||||
IDENT_sys { $$= $1; }
|
||||
| reserved_keyword_udt { $$= $1; }
|
||||
| non_reserved_keyword_udt { $$= $1; }
|
||||
| reserved_keyword_udt { $$= Lex_ident_sys($1.str, $1.length); }
|
||||
| non_reserved_keyword_udt { $$= Lex_ident_sys($1.str, $1.length); }
|
||||
;
|
||||
|
||||
field_type_all_builtin:
|
||||
@@ -6748,6 +6748,16 @@ field_type_all_with_typedefs:
|
||||
if (unlikely(Lex->set_field_type_udt_or_typedef(&$$, $1, $2, $4)))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
| sp_decl_ident '.' ident
|
||||
{
|
||||
if (Lex->set_field_type_typedef_package_spec(&$$, $1, $3))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
| sp_decl_ident '.' ident '.' ident
|
||||
{
|
||||
if (Lex->set_field_type_typedef_package_spec(&$$, $1, $3, $5))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
;
|
||||
|
||||
field_type_numeric:
|
||||
@@ -13926,7 +13936,7 @@ select_outvar:
|
||||
}
|
||||
| ident_or_text
|
||||
{
|
||||
const Lex_ident_sys name(thd, &$1);
|
||||
const Lex_ident_sys name($1);
|
||||
if (unlikely(!($$= Lex->create_outvar(thd, name)) && Lex->result))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
@@ -19811,7 +19821,7 @@ sf_c_chistics_and_body_standalone:
|
||||
sp_tail_standalone:
|
||||
sp_name
|
||||
{
|
||||
if (unlikely(!Lex->make_sp_head_no_recursive(thd, $1,
|
||||
if (unlikely(!Lex->make_sp_head_no_recursive(thd, $1, Lex->definer,
|
||||
&sp_handler_procedure,
|
||||
DEFAULT_AGGREGATE)))
|
||||
MYSQL_YYABORT;
|
||||
@@ -20571,7 +20581,7 @@ package_implementation_routine_definition:
|
||||
pkg->m_current_routine= NULL;
|
||||
$$.init();
|
||||
}
|
||||
| package_specification_element { $$.init(); }
|
||||
| package_specification_routine { $$.init(); }
|
||||
;
|
||||
|
||||
|
||||
@@ -20624,7 +20634,7 @@ package_specification_element_list:
|
||||
| package_specification_element_list package_specification_element
|
||||
;
|
||||
|
||||
package_specification_element:
|
||||
package_specification_routine:
|
||||
FUNCTION_SYM package_specification_function ';'
|
||||
{
|
||||
sp_package *pkg= Lex->get_sp_package();
|
||||
@@ -20641,6 +20651,13 @@ package_specification_element:
|
||||
}
|
||||
;
|
||||
|
||||
package_specification_element:
|
||||
package_specification_routine
|
||||
%ifdef ORACLE
|
||||
| sp_decl_type ';'
|
||||
%endif
|
||||
;
|
||||
|
||||
|
||||
%ifdef ORACLE
|
||||
|
||||
@@ -20728,7 +20745,7 @@ sf_c_chistics_and_body_standalone:
|
||||
sp_tail_standalone:
|
||||
sp_name
|
||||
{
|
||||
if (unlikely(!Lex->make_sp_head_no_recursive(thd, $1,
|
||||
if (unlikely(!Lex->make_sp_head_no_recursive(thd, $1, Lex->definer,
|
||||
&sp_handler_procedure,
|
||||
DEFAULT_AGGREGATE)))
|
||||
MYSQL_YYABORT;
|
||||
@@ -21015,15 +21032,22 @@ sp_decl_type:
|
||||
}
|
||||
| typed_ident IS REF_SYM CURSOR_SYM
|
||||
{
|
||||
if (unlikely(Lex->declare_type_ref_cursor(thd, $1, Lex_ident_sys(),
|
||||
if (unlikely(Lex->declare_type_ref_cursor(thd, $1,
|
||||
nullptr, nullptr, $4)))
|
||||
MYSQL_YYABORT;
|
||||
$$.init();
|
||||
}
|
||||
| typed_ident IS REF_SYM CURSOR_SYM RETURN_ORACLE_SYM sp_decl_ident
|
||||
| typed_ident IS REF_SYM CURSOR_SYM RETURN_ORACLE_SYM
|
||||
optionally_qualified_column_ident
|
||||
{
|
||||
if (unlikely(Lex->declare_type_ref_cursor(thd, $1, $6,
|
||||
nullptr, nullptr, $5)))
|
||||
/*
|
||||
Conversion of $6 components to Lex_ident_sys is safe,
|
||||
according to the grammar.
|
||||
*/
|
||||
if (unlikely(Lex->declare_type_ref_cursor_return_typedef(thd, $1,
|
||||
Lex_ident_sys($6->db.str, $6->db.length),
|
||||
Lex_ident_sys($6->table.str, $6->table.length),
|
||||
Lex_ident_sys($6->m_column.str, $6->m_column.length))))
|
||||
MYSQL_YYABORT;
|
||||
$$.init();
|
||||
}
|
||||
@@ -21031,7 +21055,7 @@ sp_decl_type:
|
||||
optionally_qualified_column_ident
|
||||
PERCENT_ORACLE_SYM TYPE_SYM
|
||||
{
|
||||
if (unlikely(Lex->declare_type_ref_cursor(thd, $1, Lex_ident_sys(),
|
||||
if (unlikely(Lex->declare_type_ref_cursor(thd, $1,
|
||||
nullptr, $6, $8)))
|
||||
MYSQL_YYABORT;
|
||||
$$.init();
|
||||
@@ -21040,7 +21064,7 @@ sp_decl_type:
|
||||
optionally_qualified_column_ident
|
||||
PERCENT_ORACLE_SYM ROWTYPE_ORACLE_SYM
|
||||
{
|
||||
if (unlikely(Lex->declare_type_ref_cursor(thd, $1, Lex_ident_sys(),
|
||||
if (unlikely(Lex->declare_type_ref_cursor(thd, $1,
|
||||
$6, nullptr, $8)))
|
||||
MYSQL_YYABORT;
|
||||
$$.init();
|
||||
|
||||
@@ -665,6 +665,7 @@ protected:
|
||||
bool m_has_explicit_dec:1;
|
||||
bool m_length_overflowed:1;
|
||||
bool m_dec_overflowed:1;
|
||||
bool m_foreign_module_type:1; // Is a type from CREATE PACKAGE
|
||||
|
||||
static_assert(LEX_CHARSET_COLLATION_TYPE_BITS <= 8,
|
||||
"Lex_length_and_dec_st::m_collation_type bits check");
|
||||
@@ -685,6 +686,7 @@ public:
|
||||
m_has_explicit_dec= false;
|
||||
m_length_overflowed= false;
|
||||
m_dec_overflowed= false;
|
||||
m_foreign_module_type= false;
|
||||
}
|
||||
void set_length_only(uint32 length)
|
||||
{
|
||||
@@ -695,6 +697,7 @@ public:
|
||||
m_has_explicit_dec= false;
|
||||
m_length_overflowed= false;
|
||||
m_dec_overflowed= false;
|
||||
m_foreign_module_type= false;
|
||||
}
|
||||
void set_dec_only(uint8 dec)
|
||||
{
|
||||
@@ -705,6 +708,7 @@ public:
|
||||
m_has_explicit_dec= true;
|
||||
m_length_overflowed= false;
|
||||
m_dec_overflowed= false;
|
||||
m_foreign_module_type= false;
|
||||
}
|
||||
void set_length_and_dec(uint32 length, uint8 dec)
|
||||
{
|
||||
@@ -715,8 +719,13 @@ public:
|
||||
m_has_explicit_dec= true;
|
||||
m_length_overflowed= false;
|
||||
m_dec_overflowed= false;
|
||||
m_foreign_module_type= false;
|
||||
}
|
||||
void set(const char *length, const char *dec);
|
||||
void set_foreign_module_type(bool value)
|
||||
{
|
||||
m_foreign_module_type= value;
|
||||
}
|
||||
uint32 length() const
|
||||
{
|
||||
return m_length;
|
||||
@@ -741,6 +750,10 @@ public:
|
||||
{
|
||||
return m_dec_overflowed;
|
||||
}
|
||||
bool foreign_module_type() const
|
||||
{
|
||||
return m_foreign_module_type;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user