From f748b69134c62cfd1767357b7f4adeb7e990ee2e Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 2 Aug 2006 22:18:49 -0700 Subject: Bug#8153 (Stored procedure with subquery and continue handler, wrong result) Before this fix, - a runtime error in a statement in a stored procedure with no error handlers was properly detected (as expected) - a runtime error in a statement with an error handler inherited from a non local runtime context (i.e., proc a with a handler, calling proc b) was properly detected (as expected) - a runtime error in a statement with a *local* error handler was executed as follows : a) the statement would succeed, regardless of the error condition, (bug) b) the error handler would be called (as expected). The root cause is that functions like my_messqge_sql would "forget" to set the thread flag thd->net.report_error to 1, because of the check involving sp_rcontext::found_handler_here(). Failure to set this flag would cause, later in the call stack, in Item_func::fix_fields() at line 190, the code to return FALSE and consider that executing the statement was successful. With this fix : - error handling code, that was duplicated in different places in the code, is now implemented in sp_rcontext::handle_error(), - handle_error() correctly sets thd->net.report_error when a handler is present, regardless of the handler location (local, or in the call stack). A test case, bug8153_subselect, has been written to demonstrate the change of behavior before and after the fix. Another test case, bug8153_function_a, as also been writen. This test has the same behavior before and after the fix. This test has been written to demonstrate that the previous expected result of procedure bug18787, was incorrect, since select no_such_function() should fail and therefore not produce a result. The incorrect result for bug18787 has the same root cause as Bug#8153, and the expected result has been adjusted. sql/mysqld.cc: Bug#8153, use sp_rcontext::handle_error() to handle errors. sql/sql_error.cc: Bug#8153, use sp_rcontext::handle_error() to handle errors. sql/protocol.cc: Bug#8153, use sp_rcontext::handle_error() to handle errors. sql/sp_rcontext.h: Bug#8153, created helper sp_rcontext::handle_error() to handle errors. sql/sp_rcontext.cc: Bug#8153, created helper sp_rcontext::handle_error() to handle errors. mysql-test/t/sp.test: Bug#8153, added test cases. mysql-test/r/sp.result: Bug#8153, added test cases, fixed expected result of bug18787. --- mysql-test/r/sp.result | 62 ++++++++++++++++++++++++++++++++++++++++++++++++-- mysql-test/t/sp.test | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 122 insertions(+), 2 deletions(-) (limited to 'mysql-test') diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index 70d8a99c7c2..7e74cfffa94 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -4872,8 +4872,6 @@ declare continue handler for sqlexception begin end; select no_such_function(); end| call bug18787()| -no_such_function() -NULL drop procedure bug18787| create database bug18344_012345678901| use bug18344_012345678901| @@ -5220,6 +5218,66 @@ CHARSET(p2) COLLATION(p2) cp1251 cp1251_general_ci CHARSET(p3) COLLATION(p3) greek greek_general_ci +drop table if exists t3, t4, t5| +drop procedure if exists bug8153_subselect| +drop procedure if exists bug8153_function| +create table t3 (a int)| +create table t4 (a int)| +insert into t3 values (1)| +insert into t4 values (1), (1)| +create procedure bug8153_subselect() +begin +declare continue handler for sqlexception +begin +select 'statement failed'; +end; +update t3 set a=a+1 where (select a from t4 where a=1) is null; +select 'statement after update'; +end| +call bug8153_subselect()| +statement failed +statement failed +statement after update +statement after update +select * from t3| +a +1 +call bug8153_subselect()| +statement failed +statement failed +statement after update +statement after update +select * from t3| +a +1 +drop procedure bug8153_subselect| +create procedure bug8153_function_a() +begin +declare continue handler for sqlexception +begin +select 'in continue handler'; +end; +select 'reachable code a1'; +call bug8153_function_b(); +select 'reachable code a2'; +end| +create procedure bug8153_function_b() +begin +select 'reachable code b1'; +select no_such_function(); +select 'unreachable code b2'; +end| +call bug8153_function_a()| +reachable code a1 +reachable code a1 +reachable code b1 +reachable code b1 +in continue handler +in continue handler +reachable code a2 +reachable code a2 +drop procedure bug8153_function_a| +drop procedure bug8153_function_b| use test| DROP DATABASE mysqltest1| drop table t1,t2; diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index 3f051f77954..6eadf06461b 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -6141,6 +6141,68 @@ SET @v3 = 'c'| CALL bug16676_p1('a', @v2, @v3)| CALL bug16676_p2('a', @v2, @v3)| +# +# BUG#8153: Stored procedure with subquery and continue handler, wrong result +# + +--disable_warnings +drop table if exists t3, t4, t5| +drop procedure if exists bug8153_subselect| +drop procedure if exists bug8153_function| +--enable_warnings + +create table t3 (a int)| +create table t4 (a int)| +insert into t3 values (1)| +insert into t4 values (1), (1)| + +## Testing the use case reported in Bug#8153 + +create procedure bug8153_subselect() +begin + declare continue handler for sqlexception + begin + select 'statement failed'; + end; + update t3 set a=a+1 where (select a from t4 where a=1) is null; + select 'statement after update'; +end| + +call bug8153_subselect()| +select * from t3| + +call bug8153_subselect()| +select * from t3| + +drop procedure bug8153_subselect| + +## Testing extra use cases, found while investigating +## This is related to BUG#18787, with a non local handler + +create procedure bug8153_function_a() +begin + declare continue handler for sqlexception + begin + select 'in continue handler'; + end; + + select 'reachable code a1'; + call bug8153_function_b(); + select 'reachable code a2'; +end| + +create procedure bug8153_function_b() +begin + select 'reachable code b1'; + select no_such_function(); + select 'unreachable code b2'; +end| + +call bug8153_function_a()| + +drop procedure bug8153_function_a| +drop procedure bug8153_function_b| + # Cleanup. use test| -- cgit v1.2.1 From 8daf4e8373b9fc3def33e2146445cd1600cbc084 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 21 Aug 2006 12:18:59 +0400 Subject: Fix for bug#21216 "Simultaneous DROP TABLE and SHOW OPEN TABLES causes server to crash". Crash caused by assertion failure happened when one ran SHOW OPEN TABLES while concurrently doing DROP TABLE (or RENAME TABLE, CREATE TABLE LIKE or any other command that takes name-lock) in other connection. For non-debug version of server problem exposed itself as wrong output of SHOW OPEN TABLES statement (it was missing name-locked tables). Finally in 5.1 both debug and non-debug versions simply crashed in this situation due to NULL-pointer dereference. This problem was caused by the fact that table placeholders which were added to table cache in order to obtain name-lock had TABLE_SHARE::table_name set to 0. Therefore they broke assumption that this member is non-0 for all tables in table cache which was checked by assert in list_open_tables() (in 5.1 this function simply relies on it). The fix simply sets this member for such placeholders to appropriate value making this assumption true again. This patch also includes test for similar bug 12212 "Crash that happens during removing of database name from cache" reappeared in 5.1 as bug 19403. mysql-test/r/drop.result: Added test for bug#21216 "Simultaneous DROP TABLE and SHOW OPEN TABLES causes server to crash" and bug#12212/19403 "Crash that happens during removing of database name from cache". mysql-test/t/drop.test: Added test for bug#21216 "Simultaneous DROP TABLE and SHOW OPEN TABLES causes server to crash" and bug#12212/19403 "Crash that happens during removing of database name from cache". sql/lock.cc: lock_table_name(): Our code assumes that TABLE_SHARE::table_name for objects in table cache is non-NULL (for example look at assertion in list_open_tables()). This was not true for table placeholders that were added to table cache for name-locking. So let us set this member for such placeholders. --- mysql-test/r/drop.result | 13 +++++++++++++ mysql-test/t/drop.test | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) (limited to 'mysql-test') diff --git a/mysql-test/r/drop.result b/mysql-test/r/drop.result index 979e5d48871..d122dabc4ec 100644 --- a/mysql-test/r/drop.result +++ b/mysql-test/r/drop.result @@ -72,3 +72,16 @@ show tables; Tables_in_test t1 drop table t1; +drop database if exists mysqltest; +drop table if exists t1; +create table t1 (i int); +lock tables t1 read; +create database mysqltest; + drop table t1; +show open tables; + drop database mysqltest; +select 1; +1 +1 +unlock tables; +End of 5.0 tests diff --git a/mysql-test/t/drop.test b/mysql-test/t/drop.test index 7cd943d46da..a1451773e90 100644 --- a/mysql-test/t/drop.test +++ b/mysql-test/t/drop.test @@ -81,3 +81,44 @@ show tables; drop table t1; # End of 4.1 tests + + +# +# Test for bug#21216 "Simultaneous DROP TABLE and SHOW OPEN TABLES causes +# server to crash". Crash (caused by failed assertion in 5.0 or by null +# pointer dereference in 5.1) happened when one ran SHOW OPEN TABLES +# while concurrently doing DROP TABLE (or RENAME TABLE, CREATE TABLE LIKE +# or any other command that takes name-lock) in other connection. +# +# Also includes test for similar bug#12212 "Crash that happens during +# removing of database name from cache" reappeared in 5.1 as bug#19403 +# In its case crash happened when one concurrently executed DROP DATABASE +# and one of name-locking command. +# +--disable_warnings +drop database if exists mysqltest; +drop table if exists t1; +--enable_warnings +create table t1 (i int); +lock tables t1 read; +create database mysqltest; +connect (addconroot1, localhost, root,,); +--send drop table t1 +connect (addconroot2, localhost, root,,); +# Server should not crash in any of the following statements +--disable_result_log +show open tables; +--enable_result_log +--send drop database mysqltest +connection default; +select 1; +unlock tables; +connection addconroot1; +--reap +connection addconroot2; +--reap +disconnect addconroot1; +disconnect addconroot2; +connection default; + +--echo End of 5.0 tests -- cgit v1.2.1 From 09e9b2f6cd92d7a75dfb6e46fadd9be2c326c8f5 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 22 Aug 2006 18:58:14 -0700 Subject: Bug#8153 (Stored procedure with subquery and continue handler, wrong result) Implemented code review comments Test cleanup sql/protocol.cc: Bug#8153 (Stored procedure with subquery and continue handler, wrong result) Implemented code review comments --- mysql-test/r/sp.result | 82 +++++++++++++++++++++++++++++++++++++++++++------- mysql-test/t/sp.test | 64 ++++++++++++++++++++++++++++++--------- 2 files changed, 121 insertions(+), 25 deletions(-) (limited to 'mysql-test') diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index daf99b0f469..7440ee16007 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -5218,12 +5218,18 @@ CHARSET(p2) COLLATION(p2) cp1251 cp1251_general_ci CHARSET(p3) COLLATION(p3) greek greek_general_ci -drop table if exists t3, t4, t5| +use test| +DROP DATABASE mysqltest1| +drop table if exists t3| +drop table if exists t4| drop procedure if exists bug8153_subselect| -drop procedure if exists bug8153_function| +drop procedure if exists bug8153_subselect_a| +drop procedure if exists bug8153_subselect_b| +drop procedure if exists bug8153_proc_a| +drop procedure if exists bug8153_proc_b| create table t3 (a int)| create table t4 (a int)| -insert into t3 values (1)| +insert into t3 values (1), (1), (2), (3)| insert into t4 values (1), (1)| create procedure bug8153_subselect() begin @@ -5242,6 +5248,9 @@ statement after update select * from t3| a 1 +1 +2 +3 call bug8153_subselect()| statement failed statement failed @@ -5250,24 +5259,75 @@ statement after update select * from t3| a 1 +1 +2 +3 drop procedure bug8153_subselect| -create procedure bug8153_function_a() +create procedure bug8153_subselect_a() +begin +declare continue handler for sqlexception +begin +select 'in continue handler'; +end; +select 'reachable code a1'; +call bug8153_subselect_b(); +select 'reachable code a2'; +end| +create procedure bug8153_subselect_b() +begin +select 'reachable code b1'; +update t3 set a=a+1 where (select a from t4 where a=1) is null; +select 'unreachable code b2'; +end| +call bug8153_subselect_a()| +reachable code a1 +reachable code a1 +reachable code b1 +reachable code b1 +in continue handler +in continue handler +reachable code a2 +reachable code a2 +select * from t3| +a +1 +1 +2 +3 +call bug8153_subselect_a()| +reachable code a1 +reachable code a1 +reachable code b1 +reachable code b1 +in continue handler +in continue handler +reachable code a2 +reachable code a2 +select * from t3| +a +1 +1 +2 +3 +drop procedure bug8153_subselect_a| +drop procedure bug8153_subselect_b| +create procedure bug8153_proc_a() begin declare continue handler for sqlexception begin select 'in continue handler'; end; select 'reachable code a1'; -call bug8153_function_b(); +call bug8153_proc_b(); select 'reachable code a2'; end| -create procedure bug8153_function_b() +create procedure bug8153_proc_b() begin select 'reachable code b1'; select no_such_function(); select 'unreachable code b2'; end| -call bug8153_function_a()| +call bug8153_proc_a()| reachable code a1 reachable code a1 reachable code b1 @@ -5276,10 +5336,10 @@ in continue handler in continue handler reachable code a2 reachable code a2 -drop procedure bug8153_function_a| -drop procedure bug8153_function_b| -use test| -DROP DATABASE mysqltest1| +drop procedure bug8153_proc_a| +drop procedure bug8153_proc_b| +drop table t3| +drop table t4| drop procedure if exists bug19862| CREATE TABLE t11 (a INT)| CREATE TABLE t12 (a INT)| diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index fa33e66a9d8..f48a210c7eb 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -6141,19 +6141,28 @@ SET @v3 = 'c'| CALL bug16676_p1('a', @v2, @v3)| CALL bug16676_p2('a', @v2, @v3)| +# Cleanup. + +use test| + +DROP DATABASE mysqltest1| # # BUG#8153: Stored procedure with subquery and continue handler, wrong result # --disable_warnings -drop table if exists t3, t4, t5| +drop table if exists t3| +drop table if exists t4| drop procedure if exists bug8153_subselect| -drop procedure if exists bug8153_function| +drop procedure if exists bug8153_subselect_a| +drop procedure if exists bug8153_subselect_b| +drop procedure if exists bug8153_proc_a| +drop procedure if exists bug8153_proc_b| --enable_warnings create table t3 (a int)| create table t4 (a int)| -insert into t3 values (1)| +insert into t3 values (1), (1), (2), (3)| insert into t4 values (1), (1)| ## Testing the use case reported in Bug#8153 @@ -6176,10 +6185,40 @@ select * from t3| drop procedure bug8153_subselect| +## Testing a subselect with a non local handler + +create procedure bug8153_subselect_a() +begin + declare continue handler for sqlexception + begin + select 'in continue handler'; + end; + + select 'reachable code a1'; + call bug8153_subselect_b(); + select 'reachable code a2'; +end| + +create procedure bug8153_subselect_b() +begin + select 'reachable code b1'; + update t3 set a=a+1 where (select a from t4 where a=1) is null; + select 'unreachable code b2'; +end| + +call bug8153_subselect_a()| +select * from t3| + +call bug8153_subselect_a()| +select * from t3| + +drop procedure bug8153_subselect_a| +drop procedure bug8153_subselect_b| + ## Testing extra use cases, found while investigating ## This is related to BUG#18787, with a non local handler -create procedure bug8153_function_a() +create procedure bug8153_proc_a() begin declare continue handler for sqlexception begin @@ -6187,27 +6226,24 @@ begin end; select 'reachable code a1'; - call bug8153_function_b(); + call bug8153_proc_b(); select 'reachable code a2'; end| -create procedure bug8153_function_b() +create procedure bug8153_proc_b() begin select 'reachable code b1'; select no_such_function(); select 'unreachable code b2'; end| -call bug8153_function_a()| - -drop procedure bug8153_function_a| -drop procedure bug8153_function_b| - -# Cleanup. +call bug8153_proc_a()| -use test| +drop procedure bug8153_proc_a| +drop procedure bug8153_proc_b| +drop table t3| +drop table t4| -DROP DATABASE mysqltest1| # # BUG#19862: Sort with filesort by function evaluates function twice # -- cgit v1.2.1 From f96ee72fb07961faf1ee950fcb66c2dfa0589694 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 23 Aug 2006 21:31:00 +0400 Subject: Fix for BUG#16899: Possible buffer overflow in handling of DEFINER-clause User name (host name) has limit on length. The server code relies on these limits when storing the names. The problem was that sometimes these limits were not checked properly, so that could lead to buffer overflow. The fix is to check length of user/host name in parser and if string is too long, throw an error. mysql-test/r/grant.result: Updated result file. mysql-test/r/sp.result: Updated result file. mysql-test/r/trigger.result: Updated result file. mysql-test/r/view.result: Updated result file. mysql-test/t/grant.test: Added test for BUG#16899. mysql-test/t/sp.test: Added test for BUG#16899. mysql-test/t/trigger.test: Added test for BUG#16899. mysql-test/t/view.test: Added test for BUG#16899. sql/mysql_priv.h: Added prototype for new function. sql/share/errmsg.txt: Added new resources. sql/sql_acl.cc: Remove outdated checks. sql/sql_parse.cc: Add a new function for checking string length. sql/sql_yacc.yy: Check length of user/host name. --- mysql-test/r/grant.result | 24 ++++++++++++++++++++++ mysql-test/r/sp.result | 13 ++++++++++++ mysql-test/r/trigger.result | 13 ++++++++++++ mysql-test/r/view.result | 11 ++++++++++ mysql-test/t/grant.test | 49 +++++++++++++++++++++++++++++++++++++++++++++ mysql-test/t/sp.test | 26 ++++++++++++++++++++++++ mysql-test/t/trigger.test | 30 +++++++++++++++++++++++++++ mysql-test/t/view.test | 27 +++++++++++++++++++++++++ 8 files changed, 193 insertions(+) (limited to 'mysql-test') diff --git a/mysql-test/r/grant.result b/mysql-test/r/grant.result index 3f3325354ee..e755822c490 100644 --- a/mysql-test/r/grant.result +++ b/mysql-test/r/grant.result @@ -867,3 +867,27 @@ insert into mysql.user select * from t2; flush privileges; drop table t2; drop table t1; +GRANT CREATE ON mysqltest.* TO 1234567890abcdefGHIKL@localhost; +ERROR HY000: String '1234567890abcdefGHIKL' is too long for user name (should be no longer than 16) +GRANT CREATE ON mysqltest.* TO some_user_name@1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY; +ERROR HY000: String '1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY' is too long for host name (should be no longer than 60) +REVOKE CREATE ON mysqltest.* FROM 1234567890abcdefGHIKL@localhost; +ERROR HY000: String '1234567890abcdefGHIKL' is too long for user name (should be no longer than 16) +REVOKE CREATE ON mysqltest.* FROM some_user_name@1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY; +ERROR HY000: String '1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY' is too long for host name (should be no longer than 60) +GRANT CREATE ON t1 TO 1234567890abcdefGHIKL@localhost; +ERROR HY000: String '1234567890abcdefGHIKL' is too long for user name (should be no longer than 16) +GRANT CREATE ON t1 TO some_user_name@1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY; +ERROR HY000: String '1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY' is too long for host name (should be no longer than 60) +REVOKE CREATE ON t1 FROM 1234567890abcdefGHIKL@localhost; +ERROR HY000: String '1234567890abcdefGHIKL' is too long for user name (should be no longer than 16) +REVOKE CREATE ON t1 FROM some_user_name@1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY; +ERROR HY000: String '1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY' is too long for host name (should be no longer than 60) +GRANT EXECUTE ON PROCEDURE p1 TO 1234567890abcdefGHIKL@localhost; +ERROR HY000: String '1234567890abcdefGHIKL' is too long for user name (should be no longer than 16) +GRANT EXECUTE ON PROCEDURE p1 TO some_user_name@1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY; +ERROR HY000: String '1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY' is too long for host name (should be no longer than 60) +REVOKE EXECUTE ON PROCEDURE p1 FROM 1234567890abcdefGHIKL@localhost; +ERROR HY000: String '1234567890abcdefGHIKL' is too long for user name (should be no longer than 16) +REVOKE EXECUTE ON PROCEDURE t1 FROM some_user_name@1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY; +ERROR HY000: String '1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY' is too long for host name (should be no longer than 60) diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index 7440ee16007..d4c77bc47e5 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -5374,4 +5374,17 @@ a 1 use test| drop table t3| +DROP PROCEDURE IF EXISTS bug16899_p1| +DROP FUNCTION IF EXISTS bug16899_f1| +CREATE DEFINER=1234567890abcdefGHIKL@localhost PROCEDURE bug16899_p1() +BEGIN +SET @a = 1; +END| +ERROR HY000: String '1234567890abcdefGHIKL' is too long for user name (should be no longer than 16) +CREATE DEFINER=some_user_name@1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY +FUNCTION bug16899_f1() RETURNS INT +BEGIN +RETURN 1; +END| +ERROR HY000: String '1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY' is too long for host name (should be no longer than 60) drop table t1,t2; diff --git a/mysql-test/r/trigger.result b/mysql-test/r/trigger.result index f3e797d2344..b41dd66c390 100644 --- a/mysql-test/r/trigger.result +++ b/mysql-test/r/trigger.result @@ -1089,4 +1089,17 @@ begin set @a:= 1; end| ERROR HY000: Triggers can not be created on system tables +use test| +DROP TABLE IF EXISTS t1; +DROP TABLE IF EXISTS t2; +CREATE TABLE t1(c INT); +CREATE TABLE t2(c INT); +CREATE DEFINER=1234567890abcdefGHIKL@localhost +TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW SET @a = 1; +ERROR HY000: String '1234567890abcdefGHIKL' is too long for user name (should be no longer than 16) +CREATE DEFINER=some_user_name@1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY +TRIGGER t2_bi BEFORE INSERT ON t2 FOR EACH ROW SET @a = 2; +ERROR HY000: String '1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY' is too long for host name (should be no longer than 60) +DROP TABLE t1; +DROP TABLE t2; End of 5.0 tests diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 534065a33b6..c10f7d49157 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -2850,3 +2850,14 @@ Tables_in_test t1 DROP TABLE t1; DROP VIEW IF EXISTS v1; +DROP TABLE IF EXISTS t1; +DROP VIEW IF EXISTS v1; +DROP VIEW IF EXISTS v2; +CREATE TABLE t1(a INT, b INT); +CREATE DEFINER=1234567890abcdefGHIKL@localhost +VIEW v1 AS SELECT a FROM t1; +ERROR HY000: String '1234567890abcdefGHIKL' is too long for user name (should be no longer than 16) +CREATE DEFINER=some_user_name@1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY +VIEW v2 AS SELECT b FROM t1; +ERROR HY000: String '1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY' is too long for host name (should be no longer than 60) +DROP TABLE t1; diff --git a/mysql-test/t/grant.test b/mysql-test/t/grant.test index a9d52f559ca..94b63389771 100644 --- a/mysql-test/t/grant.test +++ b/mysql-test/t/grant.test @@ -681,3 +681,52 @@ drop table t2; drop table t1; +# +# Test for BUG#16899: Possible buffer overflow in handling of DEFINER-clause. +# +# These checks are intended to ensure that appropriate errors are risen when +# illegal user name or hostname is specified in user-clause of GRANT/REVOKE +# statements. +# + +# Working with database-level privileges. + +--error ER_WRONG_STRING_LENGTH +GRANT CREATE ON mysqltest.* TO 1234567890abcdefGHIKL@localhost; + +--error ER_WRONG_STRING_LENGTH +GRANT CREATE ON mysqltest.* TO some_user_name@1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY; + +--error ER_WRONG_STRING_LENGTH +REVOKE CREATE ON mysqltest.* FROM 1234567890abcdefGHIKL@localhost; + +--error ER_WRONG_STRING_LENGTH +REVOKE CREATE ON mysqltest.* FROM some_user_name@1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY; + +# Working with table-level privileges. + +--error ER_WRONG_STRING_LENGTH +GRANT CREATE ON t1 TO 1234567890abcdefGHIKL@localhost; + +--error ER_WRONG_STRING_LENGTH +GRANT CREATE ON t1 TO some_user_name@1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY; + +--error ER_WRONG_STRING_LENGTH +REVOKE CREATE ON t1 FROM 1234567890abcdefGHIKL@localhost; + +--error ER_WRONG_STRING_LENGTH +REVOKE CREATE ON t1 FROM some_user_name@1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY; + +# Working with routine-level privileges. + +--error ER_WRONG_STRING_LENGTH +GRANT EXECUTE ON PROCEDURE p1 TO 1234567890abcdefGHIKL@localhost; + +--error ER_WRONG_STRING_LENGTH +GRANT EXECUTE ON PROCEDURE p1 TO some_user_name@1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY; + +--error ER_WRONG_STRING_LENGTH +REVOKE EXECUTE ON PROCEDURE p1 FROM 1234567890abcdefGHIKL@localhost; + +--error ER_WRONG_STRING_LENGTH +REVOKE EXECUTE ON PROCEDURE t1 FROM some_user_name@1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY; diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index f48a210c7eb..bf255bf631a 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -6286,6 +6286,32 @@ select * from (select 1 as a) as t1 natural join (select * from test.t3) as t2| use test| drop table t3| + +# +# Test for BUG#16899: Possible buffer overflow in handling of DEFINER-clause. +# + +# Prepare. + +--disable_warnings +DROP PROCEDURE IF EXISTS bug16899_p1| +DROP FUNCTION IF EXISTS bug16899_f1| +--enable_warnings + +--error ER_WRONG_STRING_LENGTH +CREATE DEFINER=1234567890abcdefGHIKL@localhost PROCEDURE bug16899_p1() +BEGIN + SET @a = 1; +END| + +--error ER_WRONG_STRING_LENGTH +CREATE DEFINER=some_user_name@1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY + FUNCTION bug16899_f1() RETURNS INT +BEGIN + RETURN 1; +END| + + # # BUG#NNNN: New bug synopsis # diff --git a/mysql-test/t/trigger.test b/mysql-test/t/trigger.test index 95e8eaae83e..7e20b61c1e4 100644 --- a/mysql-test/t/trigger.test +++ b/mysql-test/t/trigger.test @@ -1301,6 +1301,36 @@ create trigger wont_work after update on event for each row begin set @a:= 1; end| +use test| delimiter ;| + +# +# Test for BUG#16899: Possible buffer overflow in handling of DEFINER-clause. +# + +# Prepare. + +--disable_warnings +DROP TABLE IF EXISTS t1; +DROP TABLE IF EXISTS t2; +--enable_warnings + +CREATE TABLE t1(c INT); +CREATE TABLE t2(c INT); + +--error ER_WRONG_STRING_LENGTH +CREATE DEFINER=1234567890abcdefGHIKL@localhost + TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW SET @a = 1; + +--error ER_WRONG_STRING_LENGTH +CREATE DEFINER=some_user_name@1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY + TRIGGER t2_bi BEFORE INSERT ON t2 FOR EACH ROW SET @a = 2; + +# Cleanup. + +DROP TABLE t1; +DROP TABLE t2; + + --echo End of 5.0 tests diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index 5cb85ca6c9b..3e0129dcb7d 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -2718,3 +2718,30 @@ DROP TABLE t1; --disable_warnings DROP VIEW IF EXISTS v1; --enable_warnings + + +# +# Test for BUG#16899: Possible buffer overflow in handling of DEFINER-clause. +# + +# Prepare. + +--disable_warnings +DROP TABLE IF EXISTS t1; +DROP VIEW IF EXISTS v1; +DROP VIEW IF EXISTS v2; +--enable_warnings + +CREATE TABLE t1(a INT, b INT); + +--error ER_WRONG_STRING_LENGTH +CREATE DEFINER=1234567890abcdefGHIKL@localhost + VIEW v1 AS SELECT a FROM t1; + +--error ER_WRONG_STRING_LENGTH +CREATE DEFINER=some_user_name@1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY + VIEW v2 AS SELECT b FROM t1; + +# Cleanup. + +DROP TABLE t1; -- cgit v1.2.1 From 965a3970c91dc4554a8ccbd3e358b1b2c20a0cfb Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 24 Aug 2006 15:49:12 +0400 Subject: BUG#21166: Prepared statement causes signal 11 on second execution Changes in an item tree done by optimizer weren't properly registered and went unnoticed, which resulted in preliminary freeing of used memory. mysql-test/r/ps.result: Add result for bug#21166: Prepared statement causes signal 11 on second execution. mysql-test/t/ps.test: Add test case for bug#21166: Prepared statement causes signal 11 on second execution. sql/item.cc: Move Item::transform() and Item_default_value::transform() from item.h here and use THD::change_item_tree() instead of plain assignment. Change Item_field::set_no_const_sub() to be used with Item::walk() instead of Item::transform(). sql/item.h: Move definition of Item::transform() and Item_default_value::transform() to item.cc. Change Item::set_no_const_sub() to be used with Item::walk() instead of Item::transform(). sql/item_cmpfunc.cc: Use Item::walk() to execute Item::set_no_const_sub(). Use THD::change_item_tree() instead of plain assignment. sql/item_func.cc: Add assert and comment to Item_func::traverse_cond(). sql/item_row.cc: Use THD::change_item_tree() instead of plain assignment. sql/item_strfunc.cc: Move Item_func_make_set::transform() from item_strfunc.h here and use THD::change_item_tree() instead of plain assignment. sql/item_strfunc.h: Move definition of Item_func_make_set::transform() to item_strfunc.cc. --- mysql-test/r/ps.result | 15 +++++++++++++++ mysql-test/t/ps.test | 31 ++++++++++++++++++++++++++++++- 2 files changed, 45 insertions(+), 1 deletion(-) (limited to 'mysql-test') diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index d73dd03fc57..080187cfa7b 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -1297,3 +1297,18 @@ ERROR 3D000: No database selected create temporary table t1 (i int); ERROR 3D000: No database selected use test; +DROP TABLE IF EXISTS t1, t2, t3; +CREATE TABLE t1 (i BIGINT, j BIGINT); +CREATE TABLE t2 (i BIGINT); +CREATE TABLE t3 (i BIGINT, j BIGINT); +PREPARE stmt FROM "SELECT * FROM t1 JOIN t2 ON (t2.i = t1.i) + LEFT JOIN t3 ON ((t3.i, t3.j) = (t1.i, t1.j)) + WHERE t1.i = ?"; +SET @a= 1; +EXECUTE stmt USING @a; +i j i i j +EXECUTE stmt USING @a; +i j i i j +DEALLOCATE PREPARE stmt; +DROP TABLE IF EXISTS t1, t2, t3; +End of 5.0 tests. diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test index d0f31087c8f..5b2e37ecc94 100644 --- a/mysql-test/t/ps.test +++ b/mysql-test/t/ps.test @@ -1329,4 +1329,33 @@ create temporary table t1 (i int); # Restore the old environemnt # use test; -# End of 5.0 tests + + +# +# BUG#21166: Prepared statement causes signal 11 on second execution +# +# Changes in an item tree done by optimizer weren't properly +# registered and went unnoticed, which resulted in preliminary freeing +# of used memory. +# +--disable_warnings +DROP TABLE IF EXISTS t1, t2, t3; +--enable_warnings + +CREATE TABLE t1 (i BIGINT, j BIGINT); +CREATE TABLE t2 (i BIGINT); +CREATE TABLE t3 (i BIGINT, j BIGINT); + +PREPARE stmt FROM "SELECT * FROM t1 JOIN t2 ON (t2.i = t1.i) + LEFT JOIN t3 ON ((t3.i, t3.j) = (t1.i, t1.j)) + WHERE t1.i = ?"; + +SET @a= 1; +EXECUTE stmt USING @a; +EXECUTE stmt USING @a; + +DEALLOCATE PREPARE stmt; +DROP TABLE IF EXISTS t1, t2, t3; + + +--echo End of 5.0 tests. -- cgit v1.2.1 From 807ecdf43ae2c5f35c2f350e67242580618ff9a8 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 24 Aug 2006 19:36:26 +0200 Subject: Fix for bug#21416 SP: Recursion level higher than zero needed for non-recursive call The following procedure was not possible if max_sp_recursion_depth is 0 create procedure show_proc() show create procedure show_proc; Actually there is no recursive call but the limit is checked. Solved by temporarily increasing the thread's limit just before the fetch from cache and decreasing after that. mysql-test/r/sp.result: update result mysql-test/t/sp.test: Test for bug #21416 SP: Recursion level higher than zero needed for non-recursive call sql/sp.cc: Increase the max_sp_recursion_depth temporarily for SHOW CREATE PROCEDURE call. This call is in fact not recursive but is counted as such. Outcome, it will work always but if max_sp_recursion_depth is reached we are going to cache one more sp_head instance. --- mysql-test/r/sp.result | 7 +++++++ mysql-test/t/sp.test | 10 ++++++++++ 2 files changed, 17 insertions(+) (limited to 'mysql-test') diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index d4c77bc47e5..854935b071b 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -5387,4 +5387,11 @@ BEGIN RETURN 1; END| ERROR HY000: String '1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY' is too long for host name (should be no longer than 60) +drop procedure if exists bug21416| +create procedure bug21416() show create procedure bug21416| +call bug21416()| +Procedure sql_mode Create Procedure +bug21416 CREATE DEFINER=`root`@`localhost` PROCEDURE `bug21416`() +show create procedure bug21416 +drop procedure bug21416| drop table t1,t2; diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index bf255bf631a..4b0f463a9e3 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -6312,6 +6312,16 @@ BEGIN END| +# +# BUG#21416: SP: Recursion level higher than zero needed for non-recursive call +# +--disable_warnings +drop procedure if exists bug21416| +--enable_warnings +create procedure bug21416() show create procedure bug21416| +call bug21416()| +drop procedure bug21416| + # # BUG#NNNN: New bug synopsis # -- cgit v1.2.1 From 133d2aa599a65637b28e1d0634274015c49dc4e2 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 25 Aug 2006 15:51:29 +0200 Subject: Fix for bug#21795: SP: sp_head::is_not_allowed_in_function() contains erroneous check Problem: Actually there were two problems in the server code. The check for SQLCOM_FLUSH in SF/Triggers were not according to the existing architecture which uses sp_get_flags_for_command() from sp_head.cc . This function was also missing a check for SQLCOM_FLUSH which has a problem combined with prelocking. This changeset fixes both of these deficiencies as well as the erroneous check in sp_head::is_not_allowed_in_function() which was a copy&paste error. mysql-test/r/sp-error.result: update result mysql-test/r/trigger.result: update result mysql-test/t/sp-error.test: FLUSH can create a problem with prelocking, hence it's disabled. There is a better way to check this than a check in the parser. Now we use sp_get_flags_for_command() and the error returned is different. mysql-test/t/trigger.test: FLUSH can create a problem with prelocking, hence it's disabled. There is a better way to check this than a check in the parser. Now we use sp_get_flags_for_command() and the error returned is different. sql/sp_head.cc: FLUSH and RESET are not allowed inside a SF/Trigger. Because they don't imply a COMMIT sp_head::HAS_COMMIT_OR_ROLLBACK cannot be used. Two new flags were introduced for that reason. sql/sp_head.h: Don't check m_type as this check is erroneous. This is probably a copy and paste error when moving code from somewhere else. Another fact which supports this was prefixing the enum value with the name of class sp_head. Adding two new flags HAS_SQLCOM_RESET and HAS_SQLCOM_FLUSH. The values are 2048 and 4096 because in the 5.1 branch there are already new flags which are with values up-to 1024. sql/sql_parse.cc: FLUSH can cause a problem with prelocking in SF/Trigger and therefore is already disabled. RESET is also disabled because is handled by the same code as FLUSH. We won't allow RESET inside SF/Trigger at that stage without thorough analysis. The check for them is already done in the parser by calling is_not_allowed_in_function() sql/sql_yacc.yy: By listing SQLCOM_FLUSH as command which implies COMMIT in sp_get_flags_for_command() the check in sql_yacc.yy is obsolete. --- mysql-test/r/sp-error.result | 39 +++++++++++++++++++ mysql-test/r/trigger.result | 73 ++++++++++++++++++++++++++++++++++- mysql-test/t/sp-error.test | 39 +++++++++++++++++++ mysql-test/t/trigger.test | 90 +++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 239 insertions(+), 2 deletions(-) (limited to 'mysql-test') diff --git a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result index da1fc58db57..85ea624ce2f 100644 --- a/mysql-test/r/sp-error.result +++ b/mysql-test/r/sp-error.result @@ -634,6 +634,45 @@ flush tables; return 5; end| ERROR 0A000: FLUSH is not allowed in stored function or trigger +create function bug8409() returns int begin reset query cache; +return 1; end| +ERROR 0A000: RESET is not allowed in stored function or trigger +create function bug8409() returns int begin reset master; +return 1; end| +ERROR 0A000: RESET is not allowed in stored function or trigger +create function bug8409() returns int begin reset slave; +return 1; end| +ERROR 0A000: RESET is not allowed in stored function or trigger +create function bug8409() returns int begin flush hosts; +return 1; end| +ERROR 0A000: FLUSH is not allowed in stored function or trigger +create function bug8409() returns int begin flush privileges; +return 1; end| +ERROR 0A000: FLUSH is not allowed in stored function or trigger +create function bug8409() returns int begin flush tables with read lock; +return 1; end| +ERROR 0A000: FLUSH is not allowed in stored function or trigger +create function bug8409() returns int begin flush tables; +return 1; end| +ERROR 0A000: FLUSH is not allowed in stored function or trigger +create function bug8409() returns int begin flush logs; +return 1; end| +ERROR 0A000: FLUSH is not allowed in stored function or trigger +create function bug8409() returns int begin flush status; +return 1; end| +ERROR 0A000: FLUSH is not allowed in stored function or trigger +create function bug8409() returns int begin flush slave; +return 1; end| +ERROR 0A000: FLUSH is not allowed in stored function or trigger +create function bug8409() returns int begin flush master; +return 1; end| +ERROR 0A000: FLUSH is not allowed in stored function or trigger +create function bug8409() returns int begin flush des_key_file; +return 1; end| +ERROR 0A000: FLUSH is not allowed in stored function or trigger +create function bug8409() returns int begin flush user_resources; +return 1; end| +ERROR 0A000: FLUSH is not allowed in stored function or trigger create procedure bug9529_901234567890123456789012345678901234567890123456789012345() begin end| diff --git a/mysql-test/r/trigger.result b/mysql-test/r/trigger.result index b41dd66c390..c687d4c49c8 100644 --- a/mysql-test/r/trigger.result +++ b/mysql-test/r/trigger.result @@ -626,12 +626,51 @@ Trigger Event Table Statement Timing Created sql_mode Definer t1_bi INSERT t1 set new.a = '2004-01-00' BEFORE # root@localhost drop table t1; create table t1 (id int); +create trigger t1_ai after insert on t1 for each row reset query cache; +ERROR 0A000: RESET is not allowed in stored function or trigger +create trigger t1_ai after insert on t1 for each row reset master; +ERROR 0A000: RESET is not allowed in stored function or trigger +create trigger t1_ai after insert on t1 for each row reset slave; +ERROR 0A000: RESET is not allowed in stored function or trigger +create trigger t1_ai after insert on t1 for each row flush hosts; +ERROR 0A000: FLUSH is not allowed in stored function or trigger +create trigger t1_ai after insert on t1 for each row flush tables with read lock; +ERROR 0A000: FLUSH is not allowed in stored function or trigger +create trigger t1_ai after insert on t1 for each row flush logs; +ERROR 0A000: FLUSH is not allowed in stored function or trigger +create trigger t1_ai after insert on t1 for each row flush status; +ERROR 0A000: FLUSH is not allowed in stored function or trigger +create trigger t1_ai after insert on t1 for each row flush slave; +ERROR 0A000: FLUSH is not allowed in stored function or trigger +create trigger t1_ai after insert on t1 for each row flush master; +ERROR 0A000: FLUSH is not allowed in stored function or trigger +create trigger t1_ai after insert on t1 for each row flush des_key_file; +ERROR 0A000: FLUSH is not allowed in stored function or trigger +create trigger t1_ai after insert on t1 for each row flush user_resources; +ERROR 0A000: FLUSH is not allowed in stored function or trigger create trigger t1_ai after insert on t1 for each row flush tables; ERROR 0A000: FLUSH is not allowed in stored function or trigger create trigger t1_ai after insert on t1 for each row flush privileges; ERROR 0A000: FLUSH is not allowed in stored function or trigger -create procedure p1() flush tables; +drop procedure if exists p1; create trigger t1_ai after insert on t1 for each row call p1(); +create procedure p1() flush tables; +insert into t1 values (0); +ERROR 0A000: FLUSH is not allowed in stored function or trigger +drop procedure p1; +create procedure p1() reset query cache; +insert into t1 values (0); +ERROR 0A000: RESET is not allowed in stored function or trigger +drop procedure p1; +create procedure p1() reset master; +insert into t1 values (0); +ERROR 0A000: RESET is not allowed in stored function or trigger +drop procedure p1; +create procedure p1() reset slave; +insert into t1 values (0); +ERROR 0A000: RESET is not allowed in stored function or trigger +drop procedure p1; +create procedure p1() flush hosts; insert into t1 values (0); ERROR 0A000: FLUSH is not allowed in stored function or trigger drop procedure p1; @@ -639,6 +678,38 @@ create procedure p1() flush privileges; insert into t1 values (0); ERROR 0A000: FLUSH is not allowed in stored function or trigger drop procedure p1; +create procedure p1() flush tables with read lock; +insert into t1 values (0); +ERROR 0A000: FLUSH is not allowed in stored function or trigger +drop procedure p1; +create procedure p1() flush tables; +insert into t1 values (0); +ERROR 0A000: FLUSH is not allowed in stored function or trigger +drop procedure p1; +create procedure p1() flush logs; +insert into t1 values (0); +ERROR 0A000: FLUSH is not allowed in stored function or trigger +drop procedure p1; +create procedure p1() flush status; +insert into t1 values (0); +ERROR 0A000: FLUSH is not allowed in stored function or trigger +drop procedure p1; +create procedure p1() flush slave; +insert into t1 values (0); +ERROR 0A000: FLUSH is not allowed in stored function or trigger +drop procedure p1; +create procedure p1() flush master; +insert into t1 values (0); +ERROR 0A000: FLUSH is not allowed in stored function or trigger +drop procedure p1; +create procedure p1() flush des_key_file; +insert into t1 values (0); +ERROR 0A000: FLUSH is not allowed in stored function or trigger +drop procedure p1; +create procedure p1() flush user_resources; +insert into t1 values (0); +ERROR 0A000: FLUSH is not allowed in stored function or trigger +drop procedure p1; drop table t1; create table t1 (id int, data int, username varchar(16)); insert into t1 (id, data) values (1, 0); diff --git a/mysql-test/t/sp-error.test b/mysql-test/t/sp-error.test index 2abb923efbb..abb36f040d2 100644 --- a/mysql-test/t/sp-error.test +++ b/mysql-test/t/sp-error.test @@ -899,6 +899,45 @@ begin flush tables; return 5; end| +--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG +create function bug8409() returns int begin reset query cache; +return 1; end| +--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG +create function bug8409() returns int begin reset master; +return 1; end| +--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG +create function bug8409() returns int begin reset slave; +return 1; end| +--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG +create function bug8409() returns int begin flush hosts; +return 1; end| +--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG +create function bug8409() returns int begin flush privileges; +return 1; end| +--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG +create function bug8409() returns int begin flush tables with read lock; +return 1; end| +--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG +create function bug8409() returns int begin flush tables; +return 1; end| +--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG +create function bug8409() returns int begin flush logs; +return 1; end| +--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG +create function bug8409() returns int begin flush status; +return 1; end| +--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG +create function bug8409() returns int begin flush slave; +return 1; end| +--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG +create function bug8409() returns int begin flush master; +return 1; end| +--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG +create function bug8409() returns int begin flush des_key_file; +return 1; end| +--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG +create function bug8409() returns int begin flush user_resources; +return 1; end| # diff --git a/mysql-test/t/trigger.test b/mysql-test/t/trigger.test index 7e20b61c1e4..2a145e1eeaa 100644 --- a/mysql-test/t/trigger.test +++ b/mysql-test/t/trigger.test @@ -651,17 +651,105 @@ drop table t1; # of functions and triggers. create table t1 (id int); --error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG +create trigger t1_ai after insert on t1 for each row reset query cache; +--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG +create trigger t1_ai after insert on t1 for each row reset master; +--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG +create trigger t1_ai after insert on t1 for each row reset slave; +--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG +create trigger t1_ai after insert on t1 for each row flush hosts; +--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG +create trigger t1_ai after insert on t1 for each row flush tables with read lock; +--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG +create trigger t1_ai after insert on t1 for each row flush logs; +--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG +create trigger t1_ai after insert on t1 for each row flush status; +--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG +create trigger t1_ai after insert on t1 for each row flush slave; +--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG +create trigger t1_ai after insert on t1 for each row flush master; +--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG +create trigger t1_ai after insert on t1 for each row flush des_key_file; +--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG +create trigger t1_ai after insert on t1 for each row flush user_resources; +--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG create trigger t1_ai after insert on t1 for each row flush tables; --error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG create trigger t1_ai after insert on t1 for each row flush privileges; -create procedure p1() flush tables; +--disable_warnings +drop procedure if exists p1; +--enable_warnings + create trigger t1_ai after insert on t1 for each row call p1(); +create procedure p1() flush tables; --error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG insert into t1 values (0); + +drop procedure p1; +create procedure p1() reset query cache; +--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG +insert into t1 values (0); + +drop procedure p1; +create procedure p1() reset master; +--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG +insert into t1 values (0); + +drop procedure p1; +create procedure p1() reset slave; +--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG +insert into t1 values (0); + +drop procedure p1; +create procedure p1() flush hosts; +--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG +insert into t1 values (0); + drop procedure p1; create procedure p1() flush privileges; --error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG insert into t1 values (0); + +drop procedure p1; +create procedure p1() flush tables with read lock; +--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG +insert into t1 values (0); + +drop procedure p1; +create procedure p1() flush tables; +--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG +insert into t1 values (0); + +drop procedure p1; +create procedure p1() flush logs; +--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG +insert into t1 values (0); + +drop procedure p1; +create procedure p1() flush status; +--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG +insert into t1 values (0); + +drop procedure p1; +create procedure p1() flush slave; +--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG +insert into t1 values (0); + +drop procedure p1; +create procedure p1() flush master; +--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG +insert into t1 values (0); + +drop procedure p1; +create procedure p1() flush des_key_file; +--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG +insert into t1 values (0); + +drop procedure p1; +create procedure p1() flush user_resources; +--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG +insert into t1 values (0); + drop procedure p1; drop table t1; -- cgit v1.2.1 From 7a5a2544bf1e1b1abb910968340ad4b9d6162065 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 29 Aug 2006 14:32:59 +0400 Subject: BUG#17591: Updatable view not possible with trigger or stored function When a view was used inside a trigger or a function, lock type for tables used in a view was always set to READ (thus making the view non-updatable), even if we were trying to update the view. The solution is to set lock type properly. mysql-test/r/view.result: Add result for bug#17591: Updatable view not possible with trigger or stored function. mysql-test/t/view.test: Add test case for bug#17591: Updatable view not possible with trigger or stored function. sql/sql_view.cc: Move the code that sets requested lock type before the point where we exit from mysql_make_view() when we process a placeholder for prelocked table. --- mysql-test/r/view.result | 28 ++++++++++++++++++++++++++- mysql-test/t/view.test | 49 +++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 75 insertions(+), 2 deletions(-) (limited to 'mysql-test') diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 534065a33b6..d506eb69048 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -2849,4 +2849,30 @@ SHOW TABLES; Tables_in_test t1 DROP TABLE t1; -DROP VIEW IF EXISTS v1; +DROP FUNCTION IF EXISTS f1; +DROP FUNCTION IF EXISTS f2; +DROP VIEW IF EXISTS v1, v2; +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 (i INT); +CREATE VIEW v1 AS SELECT * FROM t1; +CREATE FUNCTION f1() RETURNS INT +BEGIN +INSERT INTO v1 VALUES (0); +RETURN 0; +END | +SELECT f1(); +f1() +0 +CREATE ALGORITHM=TEMPTABLE VIEW v2 AS SELECT * FROM t1; +CREATE FUNCTION f2() RETURNS INT +BEGIN +INSERT INTO v2 VALUES (0); +RETURN 0; +END | +SELECT f2(); +ERROR HY000: The target table v2 of the INSERT is not updatable +DROP FUNCTION f1; +DROP FUNCTION f2; +DROP VIEW v1, v2; +DROP TABLE t1; +End of 5.0 tests. diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index 5cb85ca6c9b..9360ccc1521 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -2715,6 +2715,53 @@ DROP VIEW t1,v1; SHOW TABLES; DROP TABLE t1; + + +# +# BUG#17591: Updatable view not possible with trigger or stored +# function +# +# During prelocking phase we didn't update lock type of view tables, +# hence READ lock was always requested. +# --disable_warnings -DROP VIEW IF EXISTS v1; +DROP FUNCTION IF EXISTS f1; +DROP FUNCTION IF EXISTS f2; +DROP VIEW IF EXISTS v1, v2; +DROP TABLE IF EXISTS t1; --enable_warnings + +CREATE TABLE t1 (i INT); + +CREATE VIEW v1 AS SELECT * FROM t1; + +delimiter |; +CREATE FUNCTION f1() RETURNS INT +BEGIN + INSERT INTO v1 VALUES (0); + RETURN 0; +END | +delimiter ;| + +SELECT f1(); + +CREATE ALGORITHM=TEMPTABLE VIEW v2 AS SELECT * FROM t1; + +delimiter |; +CREATE FUNCTION f2() RETURNS INT +BEGIN + INSERT INTO v2 VALUES (0); + RETURN 0; +END | +delimiter ;| + +--error ER_NON_UPDATABLE_TABLE +SELECT f2(); + +DROP FUNCTION f1; +DROP FUNCTION f2; +DROP VIEW v1, v2; +DROP TABLE t1; + + +--echo End of 5.0 tests. -- cgit v1.2.1 From 33294b1b50eb20e09db5f1462a12fe5668f4f097 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 29 Aug 2006 15:46:40 +0400 Subject: Preliminary patch for the following bugs: - BUG#15934: Instance manager fails to work; - BUG#18020: IM connect problem; - BUG#18027: IM: Server_ID differs; - BUG#18033: IM: Server_ID not reported; - BUG#21331: Instance Manager: Connect problems in tests; The only test suite has been changed (server codebase has not been modified). BitKeeper/deleted/.del-im_check_os.inc: Rename: mysql-test/include/im_check_os.inc -> BitKeeper/deleted/.del-im_check_os.inc mysql-test/include/im_check_env.inc: Include only this file from all IM-tests. mysql-test/lib/mtr_io.pl: Update mtr_get_pid_from_file() to workaround race, described in BUG#21884. mysql-test/lib/mtr_process.pl: Refactor im_start()/im_stop() so that they will be more reliable. There are the following user-visible changes: - if one of these functions fails, the test suite is aborted; - mtr_im_stop() now determines whether the component is alive or not not only by checking PID, but also by trying to connect to the component; - after starting IM, the test suite waits for it to start accepting client connections and to start all its guarded mysqld instances; - a lot of debug-logs have been added in order to simplify investigation of future failures. mysql-test/mysql-test-run.pl: 1. Get rid of kill_and_cleanup(); 2. Move im_start()/im_stop() to mtr_process.pl; 3. Change default IM port to 9311 so that it does not interfere with default slave port; mysql-test/r/im_daemon_life_cycle.result: Updated result file. mysql-test/r/im_life_cycle.result: Updated result file. mysql-test/r/im_options_set.result: Updated result file. mysql-test/r/im_options_unset.result: Updated result file. mysql-test/r/im_utils.result: Updated result file. mysql-test/t/im_daemon_life_cycle.imtest: Updated IM-test. mysql-test/t/im_life_cycle.imtest: Updated IM-test. mysql-test/t/im_options_set.imtest: Updated IM-test. mysql-test/t/im_options_unset.imtest: Updated IM-test. mysql-test/t/im_utils.imtest: Updated IM-test. --- mysql-test/include/im_check_env.inc | 6 +- mysql-test/include/im_check_os.inc | 7 - mysql-test/lib/mtr_io.pl | 38 +- mysql-test/lib/mtr_process.pl | 836 +++++++++++++++++++++++++++++-- mysql-test/mysql-test-run.pl | 259 +--------- mysql-test/r/im_daemon_life_cycle.result | 1 - mysql-test/r/im_life_cycle.result | 1 - mysql-test/r/im_options_set.result | 1 - mysql-test/r/im_options_unset.result | 1 - mysql-test/r/im_utils.result | 1 - mysql-test/t/im_daemon_life_cycle.imtest | 1 - mysql-test/t/im_life_cycle.imtest | 1 - mysql-test/t/im_options_set.imtest | 1 - mysql-test/t/im_options_unset.imtest | 1 - mysql-test/t/im_utils.imtest | 1 - 15 files changed, 829 insertions(+), 327 deletions(-) delete mode 100644 mysql-test/include/im_check_os.inc (limited to 'mysql-test') diff --git a/mysql-test/include/im_check_env.inc b/mysql-test/include/im_check_env.inc index 169edbac6b3..019e0984614 100644 --- a/mysql-test/include/im_check_env.inc +++ b/mysql-test/include/im_check_env.inc @@ -2,10 +2,6 @@ # that ensure that starting conditions (environment) for the IM-test are as # expected. -# Wait for mysqld1 (guarded instance) to start. - ---exec $MYSQL_TEST_DIR/t/wait_for_process.sh $IM_MYSQLD1_PATH_PID 30 started - # Check the running instances. --connect (mysql1_con,localhost,root,,mysql,$IM_MYSQLD1_PORT,$IM_MYSQLD1_SOCK) @@ -14,6 +10,8 @@ SHOW VARIABLES LIKE 'server_id'; +--source include/not_windows.inc + --connection default # Let IM detect that mysqld1 is online. This delay should be longer than diff --git a/mysql-test/include/im_check_os.inc b/mysql-test/include/im_check_os.inc deleted file mode 100644 index 9465115feb5..00000000000 --- a/mysql-test/include/im_check_os.inc +++ /dev/null @@ -1,7 +0,0 @@ ---connect (dflt_server_con,localhost,root,,mysql,$IM_MYSQLD1_PORT,$IM_MYSQLD1_SOCK) ---connection dflt_server_con - ---source include/not_windows.inc - ---connection default ---disconnect dflt_server_con diff --git a/mysql-test/lib/mtr_io.pl b/mysql-test/lib/mtr_io.pl index b3da6d97664..bdf91212b59 100644 --- a/mysql-test/lib/mtr_io.pl +++ b/mysql-test/lib/mtr_io.pl @@ -19,13 +19,39 @@ sub mtr_tonewfile($@); ############################################################################## sub mtr_get_pid_from_file ($) { - my $file= shift; + my $pid_file_path= shift; + my $TOTAL_ATTEMPTS= 30; + my $timeout= 1; - open(FILE,"<",$file) or mtr_error("can't open file \"$file\": $!"); - my $pid= ; - chomp($pid); - close FILE; - return $pid; + # We should read from the file until we get correct pid. As it is + # stated in BUG#21884, pid file can be empty at some moment. So, we should + # read it until we get valid data. + + for (my $cur_attempt= 1; $cur_attempt <= $TOTAL_ATTEMPTS; ++$cur_attempt) + { + mtr_debug("Reading pid file '$pid_file_path' " . + "($cur_attempt of $TOTAL_ATTEMPTS)..."); + + open(FILE, '<', $pid_file_path) + or mtr_error("can't open file \"$pid_file_path\": $!"); + + my $pid= ; + + chomp($pid) if defined $pid; + + close FILE; + + return $pid if defined $pid && $pid ne ''; + + mtr_debug("Pid file '$pid_file_path' is empty. " . + "Sleeping $timeout second(s)..."); + + sleep(1); + } + + mtr_error("Pid file '$pid_file_path' is corrupted. " . + "Can not retrieve PID in " . + ($timeout * $TOTAL_ATTEMPTS) . " seconds."); } sub mtr_get_opts_from_file ($) { diff --git a/mysql-test/lib/mtr_process.pl b/mysql-test/lib/mtr_process.pl index 0ca16b61fc2..9a558f91822 100644 --- a/mysql-test/lib/mtr_process.pl +++ b/mysql-test/lib/mtr_process.pl @@ -20,7 +20,29 @@ sub mtr_record_dead_children (); sub mtr_exit ($); sub sleep_until_file_created ($$$); sub mtr_kill_processes ($); -sub mtr_kill_process ($$$$); +sub mtr_ping_mysqld_server ($); + +# Private IM-related operations. + +sub mtr_im_kill_process ($$$$); +sub mtr_im_load_pids ($); +sub mtr_im_terminate ($); +sub mtr_im_check_alive ($); +sub mtr_im_check_main_alive ($); +sub mtr_im_check_angel_alive ($); +sub mtr_im_check_mysqlds_alive ($); +sub mtr_im_check_mysqld_alive ($$); +sub mtr_im_cleanup ($); +sub mtr_im_rm_file ($); +sub mtr_im_errlog ($); +sub mtr_im_kill ($); +sub mtr_im_wait_for_connection ($$$); +sub mtr_im_wait_for_mysqld($$$); + +# Public IM-related operations. + +sub mtr_im_start ($$); +sub mtr_im_stop ($); # static in C sub spawn_impl ($$$$$$$$); @@ -359,40 +381,51 @@ sub mtr_process_exit_status { sub mtr_kill_leftovers () { - # First, kill all masters and slaves that would conflict with - # this run. Make sure to remove the PID file, if any. - # FIXME kill IM manager first, else it will restart the servers, how?! + mtr_debug("mtr_kill_leftovers(): started."); + + mtr_im_stop($::instance_manager); + + # Kill mysqld servers (masters and slaves) that would conflict with this + # run. Make sure to remove the PID file, if any. + # Don't touch IM-managed mysqld instances -- they should be stopped by + # mtr_im_stop(). + + mtr_debug("Collecting mysqld-instances to shutdown..."); my @args; - for ( my $idx; $idx < 2; $idx++ ) + for ( my $idx= 0; $idx < 2; $idx++ ) { - push(@args,{ - pid => 0, # We don't know the PID - pidfile => $::instance_manager->{'instances'}->[$idx]->{'path_pid'}, - sockfile => $::instance_manager->{'instances'}->[$idx]->{'path_sock'}, - port => $::instance_manager->{'instances'}->[$idx]->{'port'}, - }); - } + my $pidfile= $::master->[$idx]->{'path_mypid'}; + my $sockfile= $::master->[$idx]->{'path_mysock'}; + my $port= $::master->[$idx]->{'path_myport'}; - for ( my $idx; $idx < 2; $idx++ ) - { push(@args,{ pid => 0, # We don't know the PID - pidfile => $::master->[$idx]->{'path_mypid'}, - sockfile => $::master->[$idx]->{'path_mysock'}, - port => $::master->[$idx]->{'path_myport'}, + pidfile => $pidfile, + sockfile => $sockfile, + port => $port, }); + + mtr_debug(" - Master mysqld " . + "(idx: $idx; pid: '$pidfile'; socket: '$sockfile'; port: $port)"); } - for ( my $idx; $idx < 3; $idx++ ) + for ( my $idx= 0; $idx < 3; $idx++ ) { + my $pidfile= $::slave->[$idx]->{'path_mypid'}; + my $sockfile= $::slave->[$idx]->{'path_mysock'}; + my $port= $::slave->[$idx]->{'path_myport'}; + push(@args,{ pid => 0, # We don't know the PID - pidfile => $::slave->[$idx]->{'path_mypid'}, - sockfile => $::slave->[$idx]->{'path_mysock'}, - port => $::slave->[$idx]->{'path_myport'}, + pidfile => $pidfile, + sockfile => $sockfile, + port => $port, }); + + mtr_debug(" - Slave mysqld " . + "(idx: $idx; pid: '$pidfile'; socket: '$sockfile'; port: $port)"); } mtr_mysqladmin_shutdown(\@args, 20); @@ -413,6 +446,8 @@ sub mtr_kill_leftovers () { # FIXME $path_run_dir or something my $rundir= "$::opt_vardir/run"; + mtr_debug("Processing PID files in directory '$rundir'..."); + if ( -d $rundir ) { opendir(RUNDIR, $rundir) @@ -426,8 +461,12 @@ sub mtr_kill_leftovers () { if ( -f $pidfile ) { + mtr_debug("Processing PID file: '$pidfile'..."); + my $pid= mtr_get_pid_from_file($pidfile); + mtr_debug("Got pid: $pid from file '$pidfile'"); + # Race, could have been removed between I tested with -f # and the unlink() below, so I better check again with -f @@ -438,14 +477,24 @@ sub mtr_kill_leftovers () { if ( $::glob_cygwin_perl or kill(0, $pid) ) { + mtr_debug("There is process with pid $pid -- scheduling for kill."); push(@pids, $pid); # We know (cygwin guess) it exists } + else + { + mtr_debug("There is no process with pid $pid -- skipping."); + } } } closedir(RUNDIR); if ( @pids ) { + mtr_debug("Killing the following processes with PID files: " . + join(' ', @pids) . "..."); + + start_reap_all(); + if ( $::glob_cygwin_perl ) { # We have no (easy) way of knowing the Cygwin controlling @@ -459,6 +508,7 @@ sub mtr_kill_leftovers () { my $retries= 10; # 10 seconds do { + mtr_debug("Sending SIGKILL to pids: " . join(' ', @pids)); kill(9, @pids); mtr_debug("Sleep 1 second waiting for processes to die"); sleep(1) # Wait one second @@ -469,19 +519,29 @@ sub mtr_kill_leftovers () { mtr_warning("can't kill process(es) " . join(" ", @pids)); } } + + stop_reap_all(); } } + else + { + mtr_debug("Directory for PID files ($rundir) does not exist."); + } # We may have failed everything, bug we now check again if we have # the listen ports free to use, and if they are free, just go for it. + mtr_debug("Checking known mysqld servers..."); + foreach my $srv ( @args ) { - if ( mtr_ping_mysqld_server($srv->{'port'}, $srv->{'sockfile'}) ) + if ( mtr_ping_mysqld_server($srv->{'port'}) ) { mtr_warning("can't kill old mysqld holding port $srv->{'port'}"); } } + + mtr_debug("mtr_kill_leftovers(): finished."); } ############################################################################## @@ -653,10 +713,15 @@ sub mtr_mysqladmin_shutdown { my %mysql_admin_pids; my @to_kill_specs; + mtr_debug("mtr_mysqladmin_shutdown(): starting..."); + mtr_debug("Collecting mysqld-instances to shutdown..."); + foreach my $srv ( @$spec ) { - if ( mtr_ping_mysqld_server($srv->{'port'}, $srv->{'sockfile'}) ) + if ( mtr_ping_mysqld_server($srv->{'port'}) ) { + mtr_debug("Mysqld (port: $srv->{port}) needs to be stopped."); + push(@to_kill_specs, $srv); } } @@ -688,6 +753,9 @@ sub mtr_mysqladmin_shutdown { mtr_add_arg($args, "--shutdown_timeout=$adm_shutdown_tmo"); mtr_add_arg($args, "shutdown"); + mtr_debug("Shutting down mysqld " . + "(port: $srv->{port}; socket: '$srv->{sockfile}')..."); + my $path_mysqladmin_log= "$::opt_vardir/log/mysqladmin.log"; my $pid= mtr_spawn($::exe_mysqladmin, $args, "", $path_mysqladmin_log, $path_mysqladmin_log, "", @@ -719,14 +787,18 @@ sub mtr_mysqladmin_shutdown { my $res= 1; # If we just fall through, we are done # in the sense that the servers don't # listen to their ports any longer + + mtr_debug("Waiting for mysqld servers to stop..."); + TIME: while ( $timeout-- ) { foreach my $srv ( @to_kill_specs ) { $res= 1; # We are optimistic - if ( mtr_ping_mysqld_server($srv->{'port'}, $srv->{'sockfile'}) ) + if ( mtr_ping_mysqld_server($srv->{'port'}) ) { + mtr_debug("Mysqld (port: $srv->{port}) is still alive."); mtr_debug("Sleep 1 second waiting for processes to stop using port"); sleep(1); # One second $res= 0; @@ -736,7 +808,14 @@ sub mtr_mysqladmin_shutdown { last; # If we got here, we are done } - $timeout or mtr_debug("At least one server is still listening to its port"); + if ($res) + { + mtr_debug("mtr_mysqladmin_shutdown(): All mysqld instances are down."); + } + else + { + mtr_debug("mtr_mysqladmin_shutdown(): At least one server is alive."); + } return $res; } @@ -795,7 +874,7 @@ sub stop_reap_all { $SIG{CHLD}= 'DEFAULT'; } -sub mtr_ping_mysqld_server () { +sub mtr_ping_mysqld_server ($) { my $port= shift; my $remote= "localhost"; @@ -810,13 +889,18 @@ sub mtr_ping_mysqld_server () { { mtr_error("can't create socket: $!"); } + + mtr_debug("Pinging server (port: $port)..."); + if ( connect(SOCK, $paddr) ) { + mtr_debug("Server (port: $port) is alive."); close(SOCK); # FIXME check error? return 1; } else { + mtr_debug("Server (port: $port) is dead."); return 0; } } @@ -886,34 +970,6 @@ sub mtr_kill_processes ($) { } } - -sub mtr_kill_process ($$$$) { - my $pid= shift; - my $signal= shift; - my $total_retries= shift; - my $timeout= shift; - - for (my $cur_attempt= 1; $cur_attempt <= $total_retries; ++$cur_attempt) - { - mtr_debug("Sending $signal to $pid..."); - - kill($signal, $pid); - - unless (kill (0, $pid)) - { - mtr_debug("Process $pid died."); - return; - } - - mtr_debug("Sleeping $timeout second(s) waiting for processes to die..."); - - sleep($timeout); - } - - mtr_debug("Process $pid is still alive after $total_retries " . - "of sending signal $signal."); -} - ############################################################################## # # When we exit, we kill off all children @@ -943,4 +999,676 @@ sub mtr_exit ($) { exit($code); } +############################################################################## +# +# Instance Manager management routines. +# +############################################################################## + +sub mtr_im_kill_process ($$$$) { + my $pid_lst= shift; + my $signal= shift; + my $total_retries= shift; + my $timeout= shift; + + my %pids; + + foreach my $pid (@{$pid_lst}) + { + $pids{$pid}= 1; + } + + for (my $cur_attempt= 1; $cur_attempt <= $total_retries; ++$cur_attempt) + { + foreach my $pid (keys %pids) + { + mtr_debug("Sending $signal to $pid..."); + + kill($signal, $pid); + + unless (kill (0, $pid)) + { + mtr_debug("Process $pid died."); + delete $pids{$pid}; + } + } + + return if scalar keys %pids == 0; + + mtr_debug("Sleeping $timeout second(s) waiting for processes to die..."); + + sleep($timeout); + } + + mtr_debug("Process(es) " . + join(' ', keys %pids) . + " is still alive after $total_retries " . + "of sending signal $signal."); +} + +########################################################################### + +sub mtr_im_load_pids($) { + my $instance_manager= shift; + + mtr_debug("Loading PID files..."); + + # Obtain mysqld-process pids. + + my $instances = $instance_manager->{'instances'}; + + for (my $idx= 0; $idx < 2; ++$idx) + { + mtr_debug("IM-guarded mysqld[$idx] PID file: '" . + $instances->[$idx]->{'path_pid'} . "'."); + + my $mysqld_pid; + + if (-r $instances->[$idx]->{'path_pid'}) + { + $mysqld_pid= mtr_get_pid_from_file($instances->[$idx]->{'path_pid'}); + mtr_debug("IM-guarded mysqld[$idx] PID: $mysqld_pid."); + } + else + { + $mysqld_pid= undef; + mtr_debug("IM-guarded mysqld[$idx]: no PID file."); + } + + $instances->[$idx]->{'pid'}= $mysqld_pid; + } + + # Re-read Instance Manager PIDs from the file, since during tests Instance + # Manager could have been restarted, so its PIDs could have been changed. + + # - IM-main + + mtr_debug("IM-main PID file: '$instance_manager->{path_pid}'."); + + if (-f $instance_manager->{'path_pid'}) + { + $instance_manager->{'pid'} = + mtr_get_pid_from_file($instance_manager->{'path_pid'}); + + mtr_debug("IM-main PID: $instance_manager->{pid}."); + } + else + { + mtr_debug("IM-main: no PID file."); + $instance_manager->{'pid'}= undef; + } + + # - IM-angel + + mtr_debug("IM-angel PID file: '$instance_manager->{path_angel_pid}'."); + + if (-f $instance_manager->{'path_angel_pid'}) + { + $instance_manager->{'angel_pid'} = + mtr_get_pid_from_file($instance_manager->{'path_angel_pid'}); + + mtr_debug("IM-angel PID: $instance_manager->{'angel_pid'}."); + } + else + { + mtr_debug("IM-angel: no PID file."); + $instance_manager->{'angel_pid'} = undef; + } +} + +########################################################################### + +sub mtr_im_terminate($) { + my $instance_manager= shift; + + # Load pids from pid-files. We should do it first of all, because IM deletes + # them on shutdown. + + mtr_im_load_pids($instance_manager); + + mtr_debug("Shutting Instance Manager down..."); + + # Ignoring SIGCHLD so that all children could rest in peace. + + start_reap_all(); + + # Send SIGTERM to IM-main. + + if (defined $instance_manager->{'pid'}) + { + mtr_debug("IM-main pid: $instance_manager->{pid}."); + mtr_debug("Stopping IM-main..."); + + mtr_im_kill_process([ $instance_manager->{'pid'} ], 'TERM', 10, 1); + } + else + { + mtr_debug("IM-main pid: n/a."); + } + + # If IM-angel was alive, wait for it to die. + + if (defined $instance_manager->{'angel_pid'}) + { + mtr_debug("IM-angel pid: $instance_manager->{'angel_pid'}."); + mtr_debug("Waiting for IM-angel to die..."); + + my $total_attempts= 10; + + for (my $cur_attempt=1; $cur_attempt <= $total_attempts; ++$cur_attempt) + { + unless (kill (0, $instance_manager->{'angel_pid'})) + { + mtr_debug("IM-angel died."); + last; + } + + sleep(1); + } + } + else + { + mtr_debug("IM-angel pid: n/a."); + } + + stop_reap_all(); + + # Re-load PIDs. + + mtr_im_load_pids($instance_manager); +} + +########################################################################### + +sub mtr_im_check_alive($) { + my $instance_manager= shift; + + mtr_debug("Checking whether IM-components are alive..."); + + return 1 if mtr_im_check_main_alive($instance_manager); + + return 1 if mtr_im_check_angel_alive($instance_manager); + + return 1 if mtr_im_check_mysqlds_alive($instance_manager); + + return 0; +} + +########################################################################### + +sub mtr_im_check_main_alive($) { + my $instance_manager= shift; + + # Check that the process, that we know to be IM's, is dead. + + if (defined $instance_manager->{'pid'}) + { + if (kill (0, $instance_manager->{'pid'})) + { + mtr_debug("IM-main (PID: $instance_manager->{pid}) is alive."); + return 1; + } + else + { + mtr_debug("IM-main (PID: $instance_manager->{pid}) is dead."); + } + } + else + { + mtr_debug("No PID file for IM-main."); + } + + # Check that IM does not accept client connections. + + if (mtr_ping_mysqld_server($instance_manager->{'port'})) + { + mtr_debug("IM-main (port: $instance_manager->{port}) " . + "is accepting connections."); + + mtr_im_errlog("IM-main is accepting connections on port " . + "$instance_manager->{port}, but there is no " . + "process information."); + return 1; + } + else + { + mtr_debug("IM-main (port: $instance_manager->{port}) " . + "does not accept connections."); + return 0; + } +} + +########################################################################### + +sub mtr_im_check_angel_alive($) { + my $instance_manager= shift; + + # Check that the process, that we know to be the Angel, is dead. + + if (defined $instance_manager->{'angel_pid'}) + { + if (kill (0, $instance_manager->{'angel_pid'})) + { + mtr_debug("IM-angel (PID: $instance_manager->{angel_pid}) is alive."); + return 1; + } + else + { + mtr_debug("IM-angel (PID: $instance_manager->{angel_pid}) is dead."); + return 0; + } + } + else + { + mtr_debug("No PID file for IM-angel."); + return 0; + } +} + +########################################################################### + +sub mtr_im_check_mysqlds_alive($) { + my $instance_manager= shift; + + mtr_debug("Checking for IM-guarded mysqld instances..."); + + my $instances = $instance_manager->{'instances'}; + + for (my $idx= 0; $idx < 2; ++$idx) + { + mtr_debug("Checking mysqld[$idx]..."); + + return 1 + if mtr_im_check_mysqld_alive($instance_manager, $instances->[$idx]); + } +} + +########################################################################### + +sub mtr_im_check_mysqld_alive($$) { + my $instance_manager= shift; + my $mysqld_instance= shift; + + # Check that the process is dead. + + if (defined $instance_manager->{'pid'}) + { + if (kill (0, $instance_manager->{'pid'})) + { + mtr_debug("Mysqld instance (PID: $mysqld_instance->{pid}) is alive."); + return 1; + } + else + { + mtr_debug("Mysqld instance (PID: $mysqld_instance->{pid}) is dead."); + } + } + else + { + mtr_debug("No PID file for mysqld instance."); + } + + # Check that mysqld does not accept client connections. + + if (mtr_ping_mysqld_server($mysqld_instance->{'port'})) + { + mtr_debug("Mysqld instance (port: $mysqld_instance->{port}) " . + "is accepting connections."); + + mtr_im_errlog("Mysqld is accepting connections on port " . + "$mysqld_instance->{port}, but there is no " . + "process information."); + return 1; + } + else + { + mtr_debug("Mysqld instance (port: $mysqld_instance->{port}) " . + "does not accept connections."); + return 0; + } +} + +########################################################################### + +sub mtr_im_cleanup($) { + my $instance_manager= shift; + + mtr_im_rm_file($instance_manager->{'path_pid'}); + mtr_im_rm_file($instance_manager->{'path_sock'}); + + mtr_im_rm_file($instance_manager->{'path_angel_pid'}); + + for (my $idx= 0; $idx < 2; ++$idx) + { + mtr_im_rm_file($instance_manager->{'instances'}->[$idx]->{'path_pid'}); + mtr_im_rm_file($instance_manager->{'instances'}->[$idx]->{'path_sock'}); + } +} + +########################################################################### + +sub mtr_im_rm_file($) +{ + my $file_path= shift; + + if (-f $file_path) + { + mtr_debug("Removing '$file_path'..."); + + mtr_warning("Can not remove '$file_path'.") + unless unlink($file_path); + } + else + { + mtr_debug("File '$file_path' does not exist already."); + } +} + +########################################################################### + +sub mtr_im_errlog($) { + my $msg= shift; + + # Complain in error log so that a warning will be shown. + # + # TODO: unless BUG#20761 is fixed, we will print the warning to stdout, so + # that it can be seen on console and does not produce pushbuild error. + + # my $errlog= "$opt_vardir/log/mysql-test-run.pl.err"; + # + # open (ERRLOG, ">>$errlog") || + # mtr_error("Can not open error log ($errlog)"); + # + # my $ts= localtime(); + # print ERRLOG + # "Warning: [$ts] $msg\n"; + # + # close ERRLOG; + + my $ts= localtime(); + print "Warning: [$ts] $msg\n"; +} + +########################################################################### + +sub mtr_im_kill($) { + my $instance_manager= shift; + + # Re-load PIDs. That can be useful because some processes could have been + # restarted. + + mtr_im_load_pids($instance_manager); + + # Ignoring SIGCHLD so that all children could rest in peace. + + start_reap_all(); + + # Kill IM-angel first of all. + + if (defined $instance_manager->{'angel_pid'}) + { + mtr_debug("Killing IM-angel (PID: $instance_manager->{angel_pid})..."); + mtr_im_kill_process([ $instance_manager->{'angel_pid'} ], 'KILL', 10, 1) + } + else + { + mtr_debug("IM-angel is dead."); + } + + # Re-load PIDs again. + + mtr_im_load_pids($instance_manager); + + # Kill IM-main. + + if (defined $instance_manager->{'pid'}) + { + mtr_debug("Killing IM-main (PID: $instance_manager->pid})..."); + mtr_im_kill_process([ $instance_manager->{'pid'} ], 'KILL', 10, 1); + } + else + { + mtr_debug("IM-main is dead."); + } + + # Re-load PIDs again. + + mtr_im_load_pids($instance_manager); + + # Kill guarded mysqld instances. + + my @mysqld_pids; + + mtr_debug("Collecting PIDs of mysqld instances to kill..."); + + for (my $idx= 0; $idx < 2; ++$idx) + { + my $pid= $instance_manager->{'instances'}->[$idx]->{'pid'}; + + next unless defined $pid; + + mtr_debug(" - IM-guarded mysqld[$idx] PID: $pid."); + + push (@mysqld_pids, $pid); + } + + if (scalar @mysqld_pids > 0) + { + mtr_debug("Killing IM-guarded mysqld instances..."); + mtr_im_kill_process(\@mysqld_pids, 'KILL', 10, 1); + } + + # That's all. + + stop_reap_all(); +} + +############################################################################## + +sub mtr_im_wait_for_connection($$$) { + my $instance_manager= shift; + my $total_attempts= shift; + my $connect_timeout= shift; + + mtr_debug("Waiting for IM on port $instance_manager->{port} " . + "to start accepting connections..."); + + for (my $cur_attempt= 1; $cur_attempt <= $total_attempts; ++$cur_attempt) + { + mtr_debug("Trying to connect to IM ($cur_attempt of $total_attempts)..."); + + if (mtr_ping_mysqld_server($instance_manager->{'port'})) + { + mtr_debug("IM is accepting connections " . + "on port $instance_manager->{port}."); + return 1; + } + + mtr_debug("Sleeping $connect_timeout..."); + sleep($connect_timeout); + } + + mtr_debug("IM does not accept connections " . + "on port $instance_manager->{port} after " . + ($total_attempts * $connect_timeout) . " seconds."); + + return 0; +} + +############################################################################## + +sub mtr_im_wait_for_mysqld($$$) { + my $mysqld= shift; + my $total_attempts= shift; + my $connect_timeout= shift; + + mtr_debug("Waiting for IM-guarded mysqld on port $mysqld->{port} " . + "to start accepting connections..."); + + for (my $cur_attempt= 1; $cur_attempt <= $total_attempts; ++$cur_attempt) + { + mtr_debug("Trying to connect to mysqld " . + "($cur_attempt of $total_attempts)..."); + + if (mtr_ping_mysqld_server($mysqld->{'port'})) + { + mtr_debug("Mysqld is accepting connections " . + "on port $mysqld->{port}."); + return 1; + } + + mtr_debug("Sleeping $connect_timeout..."); + sleep($connect_timeout); + } + + mtr_debug("Mysqld does not accept connections " . + "on port $mysqld->{port} after " . + ($total_attempts * $connect_timeout) . " seconds."); + + return 0; +} + +############################################################################## + +sub mtr_im_start($$) { + my $instance_manager = shift; + my $opts = shift; + + mtr_debug("Starting Instance Manager..."); + + my $args; + mtr_init_args(\$args); + mtr_add_arg($args, "--defaults-file=%s", + $instance_manager->{'defaults_file'}); + + foreach my $opt (@{$opts}) + { + mtr_add_arg($args, $opt); + } + + $instance_manager->{'pid'} = + mtr_spawn( + $::exe_im, # path to the executable + $args, # cmd-line args + '', # stdin + $instance_manager->{'path_log'}, # stdout + $instance_manager->{'path_err'}, # stderr + '', # pid file path (not used) + { append_log_file => 1 } # append log files + ); + + if ( ! $instance_manager->{'pid'} ) + { + mtr_report('Could not start Instance Manager'); + return; + } + + # Instance Manager can be run in daemon mode. In this case, it creates + # several processes and the parent process, created by mtr_spawn(), exits just + # after start. So, we have to obtain Instance Manager PID from the PID file. + + if ( ! sleep_until_file_created( + $instance_manager->{'path_pid'}, + $instance_manager->{'start_timeout'}, + -1)) # real PID is still unknown + { + mtr_report("Instance Manager PID file is missing"); + return; + } + + $instance_manager->{'pid'} = + mtr_get_pid_from_file($instance_manager->{'path_pid'}); + + mtr_debug("Instance Manager started. PID: $instance_manager->{pid}."); + + # Wait until we can connect to IM. + + my $IM_CONNECT_TIMEOUT= 30; + + unless (mtr_im_wait_for_connection($instance_manager, + $IM_CONNECT_TIMEOUT, 1)) + { + mtr_debug("Can not connect to Instance Manager " . + "in $IM_CONNECT_TIMEOUT seconds after start."); + mtr_debug("Aborting test suite..."); + + mtr_kill_leftovers(); + + mtr_error("Can not connect to Instance Manager " . + "in $IM_CONNECT_TIMEOUT seconds after start."); + } + + # Wait until we can connect to guarded mysqld-instances + # (in other words -- wait for IM to start guarded instances). + + for (my $idx= 0; $idx < 2; ++$idx) + { + my $mysqld= $instance_manager->{'instances'}->[$idx]; + + next if exists $mysqld->{'nonguarded'}; + + mtr_debug("Waiting for mysqld[$idx] to start..."); + + unless (mtr_im_wait_for_mysqld($mysqld, 30, 1)) + { + mtr_debug("Can not connect to mysqld[$idx] " . + "in $IM_CONNECT_TIMEOUT seconds after start."); + mtr_debug("Aborting test suite..."); + + mtr_kill_leftovers(); + + mtr_error("Can not connect to mysqld[$idx] " . + "in $IM_CONNECT_TIMEOUT seconds after start."); + } + + mtr_debug("mysqld[$idx] started."); + } + + mtr_debug("Instance Manager started."); +} + +############################################################################## + +sub mtr_im_stop($) { + my $instance_manager= shift; + + mtr_debug("Stopping Instance Manager..."); + + # Try graceful shutdown. + + mtr_im_terminate($instance_manager); + + # Check that all processes died. + + unless (mtr_im_check_alive($instance_manager)) + { + mtr_debug("Instance Manager has been stopped successfully."); + mtr_im_cleanup($instance_manager); + return 1; + } + + # Instance Manager don't want to die. We should kill it. + + mtr_im_errlog("Instance Manager did not shutdown gracefully."); + + mtr_im_kill($instance_manager); + + # Check again that all IM-related processes have been killed. + + my $im_is_alive= mtr_im_check_alive($instance_manager); + + mtr_im_cleanup($instance_manager); + + if ($im_is_alive) + { + mtr_error("Can not kill Instance Manager or its children."); + return 0; + } + + mtr_debug("Instance Manager has been killed successfully."); + return 1; +} + +########################################################################### + 1; diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index a5d857845ba..21669c0b4f9 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -335,7 +335,7 @@ sub snapshot_setup (); sub executable_setup (); sub environment_setup (); sub kill_running_server (); -sub kill_and_cleanup (); +sub cleanup_stale_files (); sub check_ssl_support (); sub check_running_as_root(); sub check_ndbcluster_support (); @@ -355,8 +355,6 @@ sub mysqld_arguments ($$$$$$); sub stop_masters_slaves (); sub stop_masters (); sub stop_slaves (); -sub im_start ($$); -sub im_stop ($); sub run_mysqltest ($); sub usage ($); @@ -498,7 +496,7 @@ sub command_line_setup () { my $opt_master_myport= 9306; my $opt_slave_myport= 9308; $opt_ndbcluster_port= 9350; - my $im_port= 9310; + my $im_port= 9311; my $im_mysqld1_port= 9312; my $im_mysqld2_port= 9314; @@ -1284,6 +1282,7 @@ sub kill_running_server () { mtr_report("Killing Possible Leftover Processes"); mkpath("$opt_vardir/log"); # Needed for mysqladmin log + mtr_kill_leftovers(); $using_ndbcluster_master= $opt_with_ndbcluster; @@ -1292,9 +1291,7 @@ sub kill_running_server () { } } -sub kill_and_cleanup () { - - kill_running_server (); +sub cleanup_stale_files () { mtr_report("Removing Stale Files"); @@ -1673,13 +1670,11 @@ sub run_suite () { sub initialize_servers () { if ( ! $glob_use_running_server ) { - if ( $opt_start_dirty ) - { - kill_running_server(); - } - else + kill_running_server(); + + unless ( $opt_start_dirty ) { - kill_and_cleanup(); + cleanup_stale_files(); mysql_install_db(); if ( $opt_force ) { @@ -2081,7 +2076,7 @@ sub run_testcase ($) { im_create_defaults_file($instance_manager); - im_start($instance_manager, $tinfo->{im_opts}); + mtr_im_start($instance_manager, $tinfo->{im_opts}); } # ---------------------------------------------------------------------- @@ -2176,10 +2171,9 @@ sub run_testcase ($) { # Stop Instance Manager if we are processing an IM-test case. # ---------------------------------------------------------------------- - if ( ! $glob_use_running_server and $tinfo->{'component_id'} eq 'im' and - $instance_manager->{'pid'} ) + if ( ! $glob_use_running_server and $tinfo->{'component_id'} eq 'im' ) { - im_stop($instance_manager); + mtr_im_stop($instance_manager); } } @@ -2707,11 +2701,8 @@ sub stop_masters_slaves () { print "Ending Tests\n"; - if ( $instance_manager->{'pid'} ) - { - print "Shutting-down Instance Manager\n"; - im_stop($instance_manager); - } + print "Shutting-down Instance Manager\n"; + mtr_im_stop($instance_manager); print "Shutting-down MySQL daemon\n\n"; stop_masters(); @@ -2773,230 +2764,6 @@ sub stop_slaves () { mtr_stop_mysqld_servers(\@args); } -############################################################################## -# -# Instance Manager management routines. -# -############################################################################## - -sub im_start($$) { - my $instance_manager = shift; - my $opts = shift; - - my $args; - mtr_init_args(\$args); - mtr_add_arg($args, "--defaults-file=%s", - $instance_manager->{'defaults_file'}); - - foreach my $opt (@{$opts}) - { - mtr_add_arg($args, $opt); - } - - $instance_manager->{'pid'} = - mtr_spawn( - $exe_im, # path to the executable - $args, # cmd-line args - '', # stdin - $instance_manager->{'path_log'}, # stdout - $instance_manager->{'path_err'}, # stderr - '', # pid file path (not used) - { append_log_file => 1 } # append log files - ); - - if ( ! $instance_manager->{'pid'} ) - { - mtr_report('Could not start Instance Manager'); - return; - } - - # Instance Manager can be run in daemon mode. In this case, it creates - # several processes and the parent process, created by mtr_spawn(), exits just - # after start. So, we have to obtain Instance Manager PID from the PID file. - - if ( ! sleep_until_file_created( - $instance_manager->{'path_pid'}, - $instance_manager->{'start_timeout'}, - -1)) # real PID is still unknown - { - mtr_report("Instance Manager PID file is missing"); - return; - } - - $instance_manager->{'pid'} = - mtr_get_pid_from_file($instance_manager->{'path_pid'}); -} - - -sub im_stop($) { - my $instance_manager = shift; - - # Obtain mysqld-process pids before we start stopping IM (it can delete pid - # files). - - my @mysqld_pids = (); - my $instances = $instance_manager->{'instances'}; - - push(@mysqld_pids, mtr_get_pid_from_file($instances->[0]->{'path_pid'})) - if -r $instances->[0]->{'path_pid'}; - - push(@mysqld_pids, mtr_get_pid_from_file($instances->[1]->{'path_pid'})) - if -r $instances->[1]->{'path_pid'}; - - # Re-read pid from the file, since during tests Instance Manager could have - # been restarted, so its pid could have been changed. - - $instance_manager->{'pid'} = - mtr_get_pid_from_file($instance_manager->{'path_pid'}) - if -f $instance_manager->{'path_pid'}; - - if (-f $instance_manager->{'path_angel_pid'}) - { - $instance_manager->{'angel_pid'} = - mtr_get_pid_from_file($instance_manager->{'path_angel_pid'}) - } - else - { - $instance_manager->{'angel_pid'} = undef; - } - - # Inspired from mtr_stop_mysqld_servers(). - - start_reap_all(); - - # Try graceful shutdown. - - mtr_debug("IM-main pid: $instance_manager->{'pid'}"); - mtr_debug("Stopping IM-main..."); - - mtr_kill_process($instance_manager->{'pid'}, 'TERM', 10, 1); - - # If necessary, wait for angel process to die. - - if (defined $instance_manager->{'angel_pid'}) - { - mtr_debug("IM-angel pid: $instance_manager->{'angel_pid'}"); - mtr_debug("Waiting for IM-angel to die..."); - - my $total_attempts= 10; - - for (my $cur_attempt=1; $cur_attempt <= $total_attempts; ++$cur_attempt) - { - unless (kill (0, $instance_manager->{'angel_pid'})) - { - mtr_debug("IM-angel died."); - last; - } - - sleep(1); - } - } - - # Check that all processes died. - - my $clean_shutdown= 0; - - while (1) - { - # Check that IM-main died. - - if (kill (0, $instance_manager->{'pid'})) - { - mtr_debug("IM-main is still alive."); - last; - } - - # Check that IM-angel died. - - if (defined $instance_manager->{'angel_pid'} && - kill (0, $instance_manager->{'angel_pid'})) - { - mtr_debug("IM-angel is still alive."); - last; - } - - # Check that all guarded mysqld-instances died. - - my $guarded_mysqlds_dead= 1; - - foreach my $pid (@mysqld_pids) - { - if (kill (0, $pid)) - { - mtr_debug("Guarded mysqld ($pid) is still alive."); - $guarded_mysqlds_dead= 0; - last; - } - } - - last unless $guarded_mysqlds_dead; - - # Ok, all necessary processes are dead. - - $clean_shutdown= 1; - last; - } - - # Kill leftovers (the order is important). - - if ($clean_shutdown) - { - mtr_debug("IM-shutdown was clean -- all processed died."); - } - else - { - mtr_debug("IM failed to shutdown gracefully. We have to clean the mess..."); - } - - unless ($clean_shutdown) - { - - if (defined $instance_manager->{'angel_pid'}) - { - mtr_debug("Killing IM-angel..."); - mtr_kill_process($instance_manager->{'angel_pid'}, 'KILL', 10, 1) - } - - mtr_debug("Killing IM-main..."); - mtr_kill_process($instance_manager->{'pid'}, 'KILL', 10, 1); - - # Shutdown managed mysqld-processes. Some of them may be nonguarded, so IM - # will not stop them on shutdown. So, we should firstly try to end them - # legally. - - mtr_debug("Killing guarded mysqld(s)..."); - mtr_kill_processes(\@mysqld_pids); - - # Complain in error log so that a warning will be shown. - # - # TODO: unless BUG#20761 is fixed, we will print the warning - # to stdout, so that it can be seen on console and does not - # produce pushbuild error. - - # my $errlog= "$opt_vardir/log/mysql-test-run.pl.err"; - # - # open (ERRLOG, ">>$errlog") || - # mtr_error("Can not open error log ($errlog)"); - # - # my $ts= localtime(); - # print ERRLOG - # "Warning: [$ts] Instance Manager did not shutdown gracefully.\n"; - # - # close ERRLOG; - - my $ts= localtime(); - print "Warning: [$ts] Instance Manager did not shutdown gracefully.\n"; - } - - # That's all. - - stop_reap_all(); - - $instance_manager->{'pid'} = undef; - $instance_manager->{'angel_pid'} = undef; -} - - # # Run include/check-testcase.test # Before a testcase, run in record mode, save result file to var diff --git a/mysql-test/r/im_daemon_life_cycle.result b/mysql-test/r/im_daemon_life_cycle.result index 4f7dd77a88f..b805bdc9166 100644 --- a/mysql-test/r/im_daemon_life_cycle.result +++ b/mysql-test/r/im_daemon_life_cycle.result @@ -1,4 +1,3 @@ -Success: the process has been started. SHOW VARIABLES LIKE 'server_id'; Variable_name Value server_id 1 diff --git a/mysql-test/r/im_life_cycle.result b/mysql-test/r/im_life_cycle.result index 8394ec491e5..1ef978375c8 100644 --- a/mysql-test/r/im_life_cycle.result +++ b/mysql-test/r/im_life_cycle.result @@ -1,4 +1,3 @@ -Success: the process has been started. SHOW VARIABLES LIKE 'server_id'; Variable_name Value server_id 1 diff --git a/mysql-test/r/im_options_set.result b/mysql-test/r/im_options_set.result index c3035079b39..f7b7e8eaef7 100644 --- a/mysql-test/r/im_options_set.result +++ b/mysql-test/r/im_options_set.result @@ -1,4 +1,3 @@ -Success: the process has been started. SHOW VARIABLES LIKE 'server_id'; Variable_name Value server_id 1 diff --git a/mysql-test/r/im_options_unset.result b/mysql-test/r/im_options_unset.result index ba468c78a5b..2ab775e611a 100644 --- a/mysql-test/r/im_options_unset.result +++ b/mysql-test/r/im_options_unset.result @@ -1,4 +1,3 @@ -Success: the process has been started. SHOW VARIABLES LIKE 'server_id'; Variable_name Value server_id 1 diff --git a/mysql-test/r/im_utils.result b/mysql-test/r/im_utils.result index be696921812..f671089d31d 100644 --- a/mysql-test/r/im_utils.result +++ b/mysql-test/r/im_utils.result @@ -1,4 +1,3 @@ -Success: the process has been started. SHOW VARIABLES LIKE 'server_id'; Variable_name Value server_id 1 diff --git a/mysql-test/t/im_daemon_life_cycle.imtest b/mysql-test/t/im_daemon_life_cycle.imtest index fe2345a9987..a07da161279 100644 --- a/mysql-test/t/im_daemon_life_cycle.imtest +++ b/mysql-test/t/im_daemon_life_cycle.imtest @@ -6,7 +6,6 @@ # ########################################################################### ---source include/im_check_os.inc --source include/im_check_env.inc ########################################################################### diff --git a/mysql-test/t/im_life_cycle.imtest b/mysql-test/t/im_life_cycle.imtest index 35258396415..c6a9569cec2 100644 --- a/mysql-test/t/im_life_cycle.imtest +++ b/mysql-test/t/im_life_cycle.imtest @@ -6,7 +6,6 @@ # ########################################################################### ---source include/im_check_os.inc --source include/im_check_env.inc ########################################################################### diff --git a/mysql-test/t/im_options_set.imtest b/mysql-test/t/im_options_set.imtest index 76e209b6a66..6a70c31c0a4 100644 --- a/mysql-test/t/im_options_set.imtest +++ b/mysql-test/t/im_options_set.imtest @@ -38,7 +38,6 @@ ########################################################################### ---source include/im_check_os.inc --source include/im_check_env.inc ########################################################################### diff --git a/mysql-test/t/im_options_unset.imtest b/mysql-test/t/im_options_unset.imtest index 06f59e79ffe..074c9a3b869 100644 --- a/mysql-test/t/im_options_unset.imtest +++ b/mysql-test/t/im_options_unset.imtest @@ -45,7 +45,6 @@ ########################################################################### ---source include/im_check_os.inc --source include/im_check_env.inc ########################################################################### diff --git a/mysql-test/t/im_utils.imtest b/mysql-test/t/im_utils.imtest index 4c05b342af5..52878f6c2b5 100644 --- a/mysql-test/t/im_utils.imtest +++ b/mysql-test/t/im_utils.imtest @@ -6,7 +6,6 @@ # ########################################################################### ---source include/im_check_os.inc --source include/im_check_env.inc ########################################################################### -- cgit v1.2.1 From 4355ea5a38c819cf1e98089b3d85fc628c48da46 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 30 Aug 2006 00:38:58 +0400 Subject: A fix for Bug#14897 "ResultSet.getString("table.column") sometimes doesn't find the column" When a user was using 4.1 tables with VARCHAR column and 5.0 server and a query that used a temporary table to resolve itself, the table metadata for the varchar column sent to client was incorrect: MYSQL_FIELD::table member was empty. The bug was caused by implicit "upgrade" from old VARCHAR to new VARCHAR hard-coded in Field::new_field, which did not preserve the information about the original table. Thus, the field metadata of the "upgraded" field pointed to an auxiliary temporary table created for query execution. The fix is to copy the pointer to the original table to the new field. mysql-test/r/type_varchar.result: Update test results (Bug#14897) mysql-test/t/type_varchar.test: Add a test case for Bug#14897 "ResultSet.getString("table.column") sometimes doesn't find the column" sql/field.cc: Preserve the original table name when converting fields from old VARCHAR to new VARCHAR. mysql-test/std_data/14897.frm: New BitKeeper file ``mysql-test/std_data/14897.frm'' --- mysql-test/r/type_varchar.result | 31 +++++++++++++++++++++++++++++ mysql-test/std_data/14897.frm | Bin 0 -> 8608 bytes mysql-test/t/type_varchar.test | 41 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 72 insertions(+) create mode 100644 mysql-test/std_data/14897.frm (limited to 'mysql-test') diff --git a/mysql-test/r/type_varchar.result b/mysql-test/r/type_varchar.result index e74850bba33..1d707b83a4d 100644 --- a/mysql-test/r/type_varchar.result +++ b/mysql-test/r/type_varchar.result @@ -422,3 +422,34 @@ DROP TABLE IF EXISTS t1; CREATE TABLE t1(f1 CHAR(100) DEFAULT 'test'); INSERT INTO t1 VALUES(SUBSTR(f1, 1, 3)); DROP TABLE IF EXISTS t1; +drop table if exists t1, t2, t3; +create table t3 ( +id int(11), +en varchar(255) character set utf8, +cz varchar(255) character set utf8 +); +truncate table t3; +insert into t3 (id, en, cz) values +(1,'en string 1','cz string 1'), +(2,'en string 2','cz string 2'), +(3,'en string 3','cz string 3'); +create table t1 ( +id int(11), +name_id int(11) +); +insert into t1 (id, name_id) values (1,1), (2,3), (3,3); +create table t2 (id int(11)); +insert into t2 (id) values (1), (2), (3); +select t1.*, t2.id, t3.en, t3.cz from t1 left join t2 on t1.id=t2.id +left join t3 on t1.id=t3.id order by t3.id; +Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr +def test t1 t1 id id 3 11 1 Y 32768 0 63 +def test t1 t1 name_id name_id 3 11 1 Y 32768 0 63 +def test t2 t2 id id 3 11 1 Y 32768 0 63 +def test t3 t3 en en 253 255 11 Y 0 0 8 +def test t3 t3 cz cz 253 255 11 Y 0 0 8 +id name_id id en cz +1 1 1 en string 1 cz string 1 +2 3 2 en string 2 cz string 2 +3 3 3 en string 3 cz string 3 +drop table t1, t2, t3; diff --git a/mysql-test/std_data/14897.frm b/mysql-test/std_data/14897.frm new file mode 100644 index 00000000000..aff11b467b0 Binary files /dev/null and b/mysql-test/std_data/14897.frm differ diff --git a/mysql-test/t/type_varchar.test b/mysql-test/t/type_varchar.test index e5614afe4f6..439e98471b2 100644 --- a/mysql-test/t/type_varchar.test +++ b/mysql-test/t/type_varchar.test @@ -146,3 +146,44 @@ DROP TABLE IF EXISTS t1; CREATE TABLE t1(f1 CHAR(100) DEFAULT 'test'); INSERT INTO t1 VALUES(SUBSTR(f1, 1, 3)); DROP TABLE IF EXISTS t1; + +# +# Bug#14897 "ResultSet.getString("table.column") sometimes doesn't find the +# column" +# Test that after upgrading an old 4.1 VARCHAR column to 5.0 VARCHAR we preserve +# the original column metadata. +# +--disable_warnings +drop table if exists t1, t2, t3; +--enable_warnings + +create table t3 ( + id int(11), + en varchar(255) character set utf8, + cz varchar(255) character set utf8 +); +system cp $MYSQL_TEST_DIR/std_data/14897.frm $MYSQLTEST_VARDIR/master-data/test/t3.frm; +truncate table t3; +insert into t3 (id, en, cz) values +(1,'en string 1','cz string 1'), +(2,'en string 2','cz string 2'), +(3,'en string 3','cz string 3'); + +create table t1 ( + id int(11), + name_id int(11) +); +insert into t1 (id, name_id) values (1,1), (2,3), (3,3); + +create table t2 (id int(11)); +insert into t2 (id) values (1), (2), (3); + +# max_length is different for varchar fields in ps-protocol and we can't +# replace a single metadata column, disable PS protocol +--disable_ps_protocol +--enable_metadata +select t1.*, t2.id, t3.en, t3.cz from t1 left join t2 on t1.id=t2.id +left join t3 on t1.id=t3.id order by t3.id; +--disable_metadata +--enable_ps_protocol +drop table t1, t2, t3; -- cgit v1.2.1