mirror of
https://github.com/MariaDB/server.git
synced 2025-01-27 01:04:19 +01:00
e1cd3c4033
Adding support for the ROW data type in the stored function RETURNS clause: - explicit ROW(..members...) for both sql_mode=DEFAULT and sql_mode=ORACLE CREATE FUNCTION f1() RETURNS ROW(a INT, b VARCHAR(32)) ... - anchored "ROW TYPE OF [db1.]table1" declarations for sql_mode=DEFAULT CREATE FUNCTION f1() RETURNS ROW TYPE OF test.t1 ... - anchored "[db1.]table1%ROWTYPE" declarations for sql_mode=ORACLE CREATE FUNCTION f1() RETURN test.t1%ROWTYPE ... Adding support for anchored scalar data types in RETURNS clause: - "TYPE OF [db1.]table1.column1" for sql_mode=DEFAULT CREATE FUNCTION f1() RETURNS TYPE OF test.t1.column1; - "[db1.]table1.column1" for sql_mode=ORACLE CREATE FUNCTION f1() RETURN test.t1.column1%TYPE; Details: - Adding a new sql_mode_t parameter to sp_head::create() sp_head::sp_head() sp_package::create() sp_package::sp_package() to guarantee early initialization of sp_head::m_sql_mode. Before this change, this member was not initialized at all during CREATE FUNCTION/PROCEDURE/PACKAGE statements, and was not used. Now it needs to be initialized to write properly the mysql.proc.returns column, according to the create time sql_mode. - Code refactoring to make the things simpler and functions smaller: * Adding a new method Field_row::row_create_fields(THD *thd, List<Spvar_definition> *list) to make a Virtual_tmp_table with Fields for ROW members from an explicit definition. * Adding a new method Field_row::row_create_fields(THD *thd, const Spvar_definition &def) to make a Virtual_tmp_table with Fields for ROW members from an explicit or a table anchored definition. * Adding a new method Item_args::add_array_of_item_field(THD *thd, const Virtual_tmp_table &vtable) to create and array of Item_field corresponding to all Field instances in a Virtual_tmp_table * Removing Item_field_row::row_create_items(). It was decomposed into the new methods described above. * Moving the code from the loop body in sp_rcontext::init_var_items() into a separate method Spvar_definition::make_item_field_row(), to make the code clearer (smaller functions). make_item_field_row() itself uses the new methods described above. - Changing the data type of sp_head::m_return_field_def from Column_definition to Spvar_definition. So now it supports not only SQL column field types, but also explicit ROW and anchored ROW data types, as well as anchored column types. - Adding a new Column_definition parameter to sp_head::create_result_field(). Before this patch, create_result_field() took the definition only from m_return_field_def. Now it's also called with a local Column_definition variable which contains the explicit definition resolved from an anchored defition. - Modifying sql_yacc.yy to support the new grammar. Adding new helper methods: * sf_return_fill_definition_row() * sf_return_fill_definition_rowtype_of() * sf_return_fill_definition_type_of() - Fixing tests in: * Virtual_tmp_table::setup_field_pointers() in sql_select.cc * Send_field::normalize() in field.h * store_column_type() to prevent calling Type_handler_row::field_type(), which is implemented a DBUG_ASSERT(0). Before this patch the affected methods and functions were called only for scalar data types. Now ROW is also possible. - Adding a new virtual method Field::cols() - Overriding methods: Item_func_sp::cols() Item_func_sp::element_index() Item_func_sp::check_cols() Item_func_sp::bring_value() to support the ROW data type. - Extending the rule sp_return_type to support * explicit ROW and anchored ROW data types * anchored scalar data types - Overriding Field_row::sql_type() to print the data type of an explicit ROW.
199 lines
4.1 KiB
Text
199 lines
4.1 KiB
Text
#
|
|
# Start of 11.4 tests
|
|
#
|
|
SET sql_mode='';
|
|
CREATE OR REPLACE PACKAGE pkg
|
|
PROCEDURE p1();
|
|
FUNCTION f1() RETURNS INT;
|
|
END;
|
|
$$
|
|
CREATE OR REPLACE PACKAGE BODY pkg
|
|
-- variable declarations
|
|
DECLARE a INT DEFAULT 11;
|
|
DECLARE b INT DEFAULT 10;
|
|
-- routine declarations
|
|
PROCEDURE p1()
|
|
BEGIN
|
|
SELECT CURRENT_USER;
|
|
END;
|
|
FUNCTION f1() RETURNS INT
|
|
BEGIN
|
|
RETURN a;
|
|
END;
|
|
-- initialization section
|
|
SET a=a-b;
|
|
END;
|
|
$$
|
|
SHOW CREATE PACKAGE pkg;
|
|
Package sql_mode Create Package character_set_client collation_connection Database Collation
|
|
pkg CREATE DEFINER=`root`@`localhost` PACKAGE `pkg` PROCEDURE p1();
|
|
FUNCTION f1() RETURNS INT;
|
|
END latin1 latin1_swedish_ci utf8mb4_uca1400_ai_ci
|
|
SHOW CREATE PACKAGE BODY pkg;
|
|
Package body sql_mode Create Package Body character_set_client collation_connection Database Collation
|
|
pkg CREATE DEFINER=`root`@`localhost` PACKAGE BODY `pkg` DECLARE a INT DEFAULT 11;
|
|
DECLARE b INT DEFAULT 10;
|
|
-- routine declarations
|
|
PROCEDURE p1()
|
|
BEGIN
|
|
SELECT CURRENT_USER;
|
|
END;
|
|
FUNCTION f1() RETURNS INT
|
|
BEGIN
|
|
RETURN a;
|
|
END;
|
|
-- initialization section
|
|
SET a=a-b;
|
|
END latin1 latin1_swedish_ci utf8mb4_uca1400_ai_ci
|
|
CALL pkg.p1();
|
|
CURRENT_USER
|
|
root@localhost
|
|
SELECT pkg.f1();
|
|
pkg.f1()
|
|
1
|
|
DROP PACKAGE pkg;
|
|
#
|
|
# MDEV-33428 Error messages ER_PACKAGE_ROUTINE_* are not good enough
|
|
#
|
|
#
|
|
# Routines declared in CREATE PACKAGE missing in CREATE PACKAGE BODY
|
|
#
|
|
CREATE PACKAGE test2
|
|
PROCEDURE p1();
|
|
END;
|
|
$$
|
|
CREATE PACKAGE BODY test2
|
|
PROCEDURE p2() BEGIN SELECT 0; END;
|
|
END;
|
|
$$
|
|
ERROR HY000: PROCEDURE `test.test2.p1` is declared in the package specification but is not defined in the package body
|
|
DROP PACKAGE test2;
|
|
CREATE PACKAGE test2
|
|
FUNCTION f1() RETURNS INT;
|
|
END;
|
|
$$
|
|
CREATE PACKAGE BODY test2
|
|
FUNCTION f2() RETURNS INT BEGIN RETURN 10; END;
|
|
END;
|
|
$$
|
|
ERROR HY000: FUNCTION `test.test2.f1` is declared in the package specification but is not defined in the package body
|
|
DROP PACKAGE test2;
|
|
CREATE PACKAGE test2
|
|
PROCEDURE p1();
|
|
END;
|
|
$$
|
|
CREATE PACKAGE BODY test2
|
|
FUNCTION p1() RETURNS INT BEGIN RETURN 10; END;
|
|
END;
|
|
$$
|
|
ERROR HY000: PROCEDURE `test.test2.p1` is declared in the package specification but is not defined in the package body
|
|
DROP PACKAGE test2;
|
|
CREATE PACKAGE test2
|
|
PROCEDURE p1();
|
|
END;
|
|
$$
|
|
CREATE PACKAGE BODY test2
|
|
PROCEDURE p1(a INT) BEGIN SELECT 0; END; -- Notice different prototype
|
|
END;
|
|
$$
|
|
ERROR HY000: PROCEDURE `test.test2.p1` is declared in the package specification but is not defined in the package body
|
|
DROP PACKAGE test2;
|
|
#
|
|
# Forward declarations in CREATE PACKAGE BODY with missing implementations
|
|
#
|
|
CREATE PACKAGE test2
|
|
PROCEDURE p1();
|
|
END;
|
|
$$
|
|
CREATE PACKAGE BODY test2
|
|
PROCEDURE p1() BEGIN SELECT 0; END;
|
|
PROCEDURE p2();
|
|
END;
|
|
$$
|
|
ERROR HY000: PROCEDURE `test.test2.p2` has a forward declaration but is not defined
|
|
CREATE PACKAGE BODY test2
|
|
FUNCTION f1() RETURNS INT;
|
|
PROCEDURE p1() BEGIN SELECT 0; END;
|
|
END;
|
|
$$
|
|
ERROR HY000: FUNCTION `test.test2.f1` has a forward declaration but is not defined
|
|
DROP PACKAGE test2;
|
|
#
|
|
# End of 11.4 tests
|
|
#
|
|
#
|
|
# Start of 11.7 tests
|
|
#
|
|
#
|
|
# MDEV-12252 ROW data type for stored function return values
|
|
#
|
|
#
|
|
# Testing fixed ROW type with package routines
|
|
#
|
|
CREATE PACKAGE pkg
|
|
FUNCTION f1() RETURNS ROW(a INT, b VARCHAR(32));
|
|
PROCEDURE p1(r ROW(a INT, b VARCHAR(32)));
|
|
PROCEDURE p2();
|
|
END;
|
|
$$
|
|
CREATE PACKAGE BODY pkg
|
|
FUNCTION f1() RETURNS ROW(a INT, b VARCHAR(32))
|
|
BEGIN
|
|
RETURN ROW(1,'b1');
|
|
END;
|
|
PROCEDURE p1(r ROW(a INT, b VARCHAR(32)))
|
|
BEGIN
|
|
SELECT r.a, r.b;
|
|
END;
|
|
PROCEDURE p2()
|
|
BEGIN
|
|
CALL p1(f1());
|
|
END;
|
|
END;
|
|
$$
|
|
CALL pkg.p1(pkg.f1());
|
|
r.a r.b
|
|
1 b1
|
|
CALL pkg.p2;
|
|
r.a r.b
|
|
1 b1
|
|
DROP PACKAGE pkg;
|
|
#
|
|
# Testing "ROW TYPE OF table" with package routines
|
|
#
|
|
CREATE TABLE t1 (a INT, b VARCHAR(32));
|
|
INSERT INTO t1 VALUES (1,'b1');
|
|
CREATE PACKAGE pkg
|
|
FUNCTION f1() RETURNS ROW TYPE OF t1;
|
|
PROCEDURE p1(r ROW TYPE OF t1);
|
|
PROCEDURE p2();
|
|
END;
|
|
/
|
|
CREATE PACKAGE BODY pkg
|
|
FUNCTION f1() RETURNS ROW TYPE OF t1
|
|
BEGIN
|
|
DECLARE r ROW TYPE OF t1;
|
|
SELECT * INTO r FROM t1;
|
|
RETURN r;
|
|
END;
|
|
PROCEDURE p1(r ROW TYPE OF t1)
|
|
BEGIN
|
|
SELECT CONCAT(r.a, ' ', r.b);
|
|
END;
|
|
PROCEDURE p2()
|
|
BEGIN
|
|
CALL p1(f1());
|
|
END;
|
|
END;
|
|
/
|
|
CALL pkg.p1(pkg.f1());
|
|
CONCAT(r.a, ' ', r.b)
|
|
1 b1
|
|
CALL pkg.p2;
|
|
CONCAT(r.a, ' ', r.b)
|
|
1 b1
|
|
DROP PACKAGE pkg;
|
|
DROP TABLE t1;
|
|
#
|
|
# End of 11.7 tests
|
|
#
|