From 6b2f13098a59d9ad520828dca4cb63da8c86b5e3 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 7 Dec 2005 17:01:17 +0300 Subject: [PATCH] Patch for WL#2894: Make stored routine variables work according to the standard. The idea is to use Field-classes to implement stored routines variables. Also, we should provide facade to Item-hierarchy by Item_field class (it is necessary, since SRVs take part in expressions). The patch fixes the following bugs: - BUG#8702: Stored Procedures: No Error/Warning shown for inappropriate data type matching; - BUG#8768: Functions: For any unsigned data type, -ve values can be passed and returned; - BUG#8769: Functions: For Int datatypes, out of range values can be passed and returned; - BUG#9078: STORED PROCDURE: Decimal digits are not displayed when we use DECIMAL datatype; - BUG#9572: Stored procedures: variable type declarations ignored; - BUG#12903: upper function does not work inside a function; - BUG#13705: parameters to stored procedures are not verified; - BUG#13808: ENUM type stored procedure parameter accepts non-enumerated data; - BUG#13909: Varchar Stored Procedure Parameter always BINARY string (ignores CHARACTER SET); - BUG#14161: Stored procedure cannot retrieve bigint unsigned; - BUG#14188: BINARY variables have no 0x00 padding; - BUG#15148: Stored procedure variables accept non-scalar values; mysql-test/r/ctype_ujis.result: Explicitly specify correct charset. mysql-test/r/schema.result: Drop our test database to not affect this test if some test left it cause of failure. mysql-test/r/show_check.result: Drop our test database to not affect this test if some test left it cause of failure. mysql-test/r/skip_name_resolve.result: Ignore columns with unpredictable values. mysql-test/r/sp-big.result: Add cleanup statement. mysql-test/r/sp-dynamic.result: Add cleanup statements. mysql-test/r/sp.result: Update result file. mysql-test/r/sum_distinct-big.result: Update result file. mysql-test/r/type_newdecimal-big.result: Update result file. mysql-test/t/ctype_ujis.test: Explicitly specify correct charset. mysql-test/t/schema.test: Drop our test database to not affect this test if some test left it cause of failure. mysql-test/t/show_check.test: Drop our test database to not affect this test if some test left it cause of failure. mysql-test/t/skip_name_resolve.test: Ignore columns with unpredictable values. mysql-test/t/sp-big.test: Add cleanup statement. mysql-test/t/sp-dynamic.test: Add cleanup statements. mysql-test/t/sp.test: Non-scalar values prohibited for assignment to SP-vars; polishing. mysql-test/t/type_newdecimal-big.test: Update type specification so that the variables can contain the large values used in the test. sql/field.cc: Extract create_field::init() to initialize an existing instance of create_field from new_create_field(). sql/field.h: Extract create_field::init() to initialize an existing instance of create_field from new_create_field(). sql/item.cc: - Introduce a new class: Item_sp_variable -- a base class of stored-routine-variables classes; - Introduce Item_case_expr -- an Item, which is used to access to the expression of CASE statement; sql/item.h: - Introduce a new class: Item_sp_variable -- a base class of stored-routine-variables classes; - Introduce Item_case_expr -- an Item, which is used to access to the expression of CASE statement; sql/item_func.cc: Pass the Field (instead of Item) for the return value of a function to the function execution routine. sql/item_func.h: Pass the Field (instead of Item) for the return value of a function to the function execution routine. sql/mysql_priv.h: Move create_virtual_tmp_table() out of sql_select.h. sql/sp.cc: Use create_result_field() instead of make_field(). sql/sp_head.cc: - Add a function to map enum_field_types to Item::Type; - Add sp_instr_push_case_expr instruction -- an instruction to push CASE expression into the active running context; - Add sp_instr_pop_case_expr instruction -- an instruction to pop CASE expression from the active running context; - Adapt the SP-execution code to using Fields instead of Items for SP-vars; - Use create_field structure for field description instead of a set of members. sql/sp_head.h: - Add a function to map enum_field_types to Item::Type; - Add sp_instr_push_case_expr instruction -- an instruction to push CASE expression into the active running context; - Add sp_instr_pop_case_expr instruction -- an instruction to pop CASE expression from the active running context; - Adapt the SP-execution code to using Fields instead of Items for SP-vars; - Use create_field structure for field description instead of a set of members. sql/sp_pcontext.cc: - Change rules to assign an index of SP-variable: use transparent index; - Add an operation to retrieve a list of defined SP-vars from the processing context recursively. sql/sp_pcontext.h: - Change rules to assign an index of SP-variable: use transparent index; - Add an operation to retrieve a list of defined SP-vars from the processing context recursively. sql/sp_rcontext.cc: - Change rules to assign an index of SP-variable: use transparent index; - Use a tmp virtual table to store SP-vars instead of Items; - Provide operations to work with CASE expresion. sql/sp_rcontext.h: - Change rules to assign an index of SP-variable: use transparent index; - Use a tmp virtual table to store SP-vars instead of Items; - Provide operations to work with CASE expresion. sql/sql_class.cc: - Reflect Item_splocal ctor changes; - Item_splocal::get_offset() has been renamed to get_var_idx(). sql/sql_class.h: Polishing. sql/sql_parse.cc: Extract create_field::init() to initialize an existing instance of create_field from new_create_field(). sql/sql_select.cc: Take care of BLOB columns in create_virtual_tmp_table(). sql/sql_select.h: Move create_virtual_tmp_table() out of sql_select.h. sql/sql_trigger.cc: Use boolean constants for boolean type instead of numerical ones. sql/sql_yacc.yy: Provide an instance of create_field for each SP-var. mysql-test/include/sp-vars.inc: The definitions of common-procedures, which are created under different circumstances. mysql-test/r/sp-vars.result: Result file for the SP-vars test. mysql-test/sp-vars.test: A new test for checking SP-vars functionality. --- mysql-test/include/sp-vars.inc | 122 +++ mysql-test/r/ctype_ujis.result | 2 +- mysql-test/r/schema.result | 1 + mysql-test/r/show_check.result | 1 + mysql-test/r/skip_name_resolve.result | 4 +- mysql-test/r/sp-big.result | 1 + mysql-test/r/sp-dynamic.result | 2 + mysql-test/r/sp-vars.result | 1077 +++++++++++++++++++ mysql-test/r/sp.result | 41 +- mysql-test/r/sum_distinct-big.result | 29 +- mysql-test/r/type_newdecimal-big.result | 31 +- mysql-test/sp-vars.test | 1273 +++++++++++++++++++++++ mysql-test/t/ctype_ujis.test | 2 +- mysql-test/t/schema.test | 6 + mysql-test/t/show_check.test | 1 + mysql-test/t/skip_name_resolve.test | 2 +- mysql-test/t/sp-big.test | 3 + mysql-test/t/sp-dynamic.test | 6 + mysql-test/t/sp.test | 9 +- mysql-test/t/type_newdecimal-big.test | 31 +- sql/field.cc | 347 ++++++ sql/field.h | 18 + sql/item.cc | 197 ++-- sql/item.h | 249 +++-- sql/item_func.cc | 51 +- sql/item_func.h | 4 +- sql/mysql_priv.h | 3 +- sql/sp.cc | 2 +- sql/sp_head.cc | 952 +++++++++-------- sql/sp_head.h | 61 +- sql/sp_pcontext.cc | 75 +- sql/sp_pcontext.h | 98 +- sql/sp_rcontext.cc | 304 +++++- sql/sp_rcontext.h | 148 +-- sql/sql_class.cc | 10 +- sql/sql_class.h | 2 +- sql/sql_parse.cc | 328 +----- sql/sql_select.cc | 13 + sql/sql_select.h | 1 - sql/sql_trigger.cc | 6 +- sql/sql_yacc.yy | 227 ++-- 41 files changed, 4486 insertions(+), 1254 deletions(-) create mode 100644 mysql-test/include/sp-vars.inc create mode 100644 mysql-test/r/sp-vars.result create mode 100644 mysql-test/sp-vars.test diff --git a/mysql-test/include/sp-vars.inc b/mysql-test/include/sp-vars.inc new file mode 100644 index 00000000000..3e02c9d1709 --- /dev/null +++ b/mysql-test/include/sp-vars.inc @@ -0,0 +1,122 @@ +delimiter |; + +--------------------------------------------------------------------------- + +CREATE PROCEDURE sp_vars_check_dflt() +BEGIN + DECLARE v1 TINYINT DEFAULT 1e200; + DECLARE v1u TINYINT UNSIGNED DEFAULT 1e200; + DECLARE v2 TINYINT DEFAULT -1e200; + DECLARE v2u TINYINT UNSIGNED DEFAULT -1e200; + DECLARE v3 TINYINT DEFAULT 300; + DECLARE v3u TINYINT UNSIGNED DEFAULT 300; + DECLARE v4 TINYINT DEFAULT -300; + DECLARE v4u TINYINT UNSIGNED DEFAULT -300; + + DECLARE v5 TINYINT DEFAULT 10 * 10 * 10; + DECLARE v5u TINYINT UNSIGNED DEFAULT 10 * 10 * 10; + DECLARE v6 TINYINT DEFAULT -10 * 10 * 10; + DECLARE v6u TINYINT UNSIGNED DEFAULT -10 * 10 * 10; + + DECLARE v7 TINYINT DEFAULT '10'; + DECLARE v8 TINYINT DEFAULT '10 '; + DECLARE v9 TINYINT DEFAULT ' 10 '; + DECLARE v10 TINYINT DEFAULT 'String 10 '; + DECLARE v11 TINYINT DEFAULT 'String10'; + DECLARE v12 TINYINT DEFAULT '10 String'; + DECLARE v13 TINYINT DEFAULT '10String'; + DECLARE v14 TINYINT DEFAULT concat('10', ' '); + DECLARE v15 TINYINT DEFAULT concat(' ', '10'); + DECLARE v16 TINYINT DEFAULT concat('Hello, ', 'world'); + + DECLARE v17 DECIMAL(64, 2) DEFAULT 12; + DECLARE v18 DECIMAL(64, 2) DEFAULT 12.123; + DECLARE v19 DECIMAL(64, 2) DEFAULT 11 + 1; + DECLARE v20 DECIMAL(64, 2) DEFAULT 12 + 0.123; + + SELECT v1, v1u, v2, v2u, v3, v3u, v4, v4u; + SELECT v5, v5u, v6, v6u; + SELECT v7, v8, v9, v10, v11, v12, v13, v14, v15, v16; + SELECT v17, v18, v19, v20; +END| + +--------------------------------------------------------------------------- + +CREATE PROCEDURE sp_vars_check_assignment() +BEGIN + DECLARE i1, i2, i3, i4 TINYINT; + DECLARE u1, u2, u3, u4 TINYINT UNSIGNED; + DECLARE d1, d2, d3 DECIMAL(64, 2); + + SET i1 = 1e200; + SET i2 = -1e200; + SET i3 = 300; + SET i4 = -300; + + SELECT i1, i2, i3, i4; + + SET i1 = 10 * 10 * 10; + SET i2 = -10 * 10 * 10; + SET i3 = sign(10 * 10) * 10 * 20; + SET i4 = sign(-10 * 10) * -10 * 20; + + SELECT i1, i2, i3, i4; + + SET u1 = 1e200; + SET u2 = -1e200; + SET u3 = 300; + SET u4 = -300; + + SELECT u1, u2, u3, u4; + + SET u1 = 10 * 10 * 10; + SET u2 = -10 * 10 * 10; + SET u3 = sign(10 * 10) * 10 * 20; + SET u4 = sign(-10 * 10) * -10 * 20; + + SELECT u1, u2, u3, u4; + + SET d1 = 1234; + SET d2 = 1234.12; + SET d3 = 1234.1234; + + SELECT d1, d2, d3; + + SET d1 = 12 * 100 + 34; + SET d2 = 12 * 100 + 34 + 0.12; + SET d3 = 12 * 100 + 34 + 0.1234; + + SELECT d1, d2, d3; +END| + +--------------------------------------------------------------------------- + +CREATE FUNCTION sp_vars_check_ret1() RETURNS TINYINT +BEGIN + RETURN 1e200; +END| + +--------------------------------------------------------------------------- + +CREATE FUNCTION sp_vars_check_ret2() RETURNS TINYINT +BEGIN + RETURN 10 * 10 * 10; +END| + +--------------------------------------------------------------------------- + +CREATE FUNCTION sp_vars_check_ret3() RETURNS TINYINT +BEGIN + RETURN 'Hello, world'; +END| + +--------------------------------------------------------------------------- + +CREATE FUNCTION sp_vars_check_ret4() RETURNS DECIMAL(64, 2) +BEGIN + RETURN 12 * 10 + 34 + 0.1234; +END| + +--------------------------------------------------------------------------- + +delimiter ;| diff --git a/mysql-test/r/ctype_ujis.result b/mysql-test/r/ctype_ujis.result index 15de93440fc..2e14fe34430 100644 --- a/mysql-test/r/ctype_ujis.result +++ b/mysql-test/r/ctype_ujis.result @@ -2317,7 +2317,7 @@ CREATE TABLE t2(c2 char(2)) default charset = ujis; INSERT INTO t1 VALUES(_ujis 0xA4A2); CREATE PROCEDURE sp1() BEGIN -DECLARE a CHAR(1); +DECLARE a CHAR(2) CHARSET ujis; DECLARE cur1 CURSOR FOR SELECT c1 FROM t1; OPEN cur1; FETCH cur1 INTO a; diff --git a/mysql-test/r/schema.result b/mysql-test/r/schema.result index 48e6ebcfad2..538abd8d039 100644 --- a/mysql-test/r/schema.result +++ b/mysql-test/r/schema.result @@ -1,3 +1,4 @@ +drop database if exists mysqltest1; create schema foo; show create schema foo; Database Create Database diff --git a/mysql-test/r/show_check.result b/mysql-test/r/show_check.result index fdb0db602ff..61a820b4469 100644 --- a/mysql-test/r/show_check.result +++ b/mysql-test/r/show_check.result @@ -1,6 +1,7 @@ drop table if exists t1,t2; drop table if exists t1aa,t2aa; drop database if exists mysqltest; +drop database if exists mysqltest1; delete from mysql.user where user='mysqltest_1' || user='mysqltest_2' || user='mysqltest_3'; delete from mysql.db where user='mysqltest_1' || user='mysqltest_2' || user='mysqltest_3'; flush privileges; diff --git a/mysql-test/r/skip_name_resolve.result b/mysql-test/r/skip_name_resolve.result index a969c5c9ae0..8ef52e75238 100644 --- a/mysql-test/r/skip_name_resolve.result +++ b/mysql-test/r/skip_name_resolve.result @@ -10,5 +10,5 @@ user() # show processlist; Id User Host db Command Time State Info -# root # test Sleep # NULL -# root # test Query # NULL show processlist + root test