From 3aa6d3f51a06145c7aa50af993623758ea7ef482 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 13 Jun 2007 10:35:20 +0200 Subject: [PATCH 1/9] Bug#29065 mysql-test-run.pl aborts execution on missing log file from test tool - Make tesingt continue even if test log file does not exists mysql-test/mysql-test-run.pl: Allow execution to continue even if no log file has been generated by the test tool - it's not a critical error --- mysql-test/mysql-test-run.pl | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index e3d4c33cba9..783d48b9f48 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -3106,9 +3106,12 @@ sub find_testcase_skipped_reason($) { my ($tinfo)= @_; + # Set default message + $tinfo->{'comment'}= "Detected by testcase(no log file)"; + # Open mysqltest.log - my $F= IO::File->new($path_timefile) or - mtr_error("can't open file \"$path_timefile\": $!"); + my $F= IO::File->new($path_timefile) + or return; my $reason; while ( my $line= <$F> ) @@ -3161,8 +3164,8 @@ sub analyze_testcase_failure($) my ($tinfo)= @_; # Open mysqltest.log - my $F= IO::File->new($path_timefile) or - mtr_error("can't open file \"$path_timefile\": $!"); + my $F= IO::File->new($path_timefile) + or return; while ( my $line= <$F> ) { From d2f858aba3a9414d9bc247fccb13bc85f8799af0 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 15 Jun 2007 16:09:28 +0500 Subject: [PATCH 2/9] Fix for bug #28144: "Slave_IO_Running" differs in replication tests Problem: show slave status may return different Slave_IO_Running values running some tests. Fix: wait for a certain slave state if needed to get tests more predictable. mysql-test/r/rpl_log_pos.result: Fix for bug #28144: "Slave_IO_Running" differs in replication tests - test result adjusted. mysql-test/r/rpl_ssl.result: Fix for bug #28144: "Slave_IO_Running" differs in replication tests - test result adjusted. mysql-test/t/rpl_log_pos.test: Fix for bug #28144: "Slave_IO_Running" differs in replication tests - test has been rewritten to get certain slave state, now we use wait_for_slave_param.inc to ensure we get proper IO/SQL slave's threads states. mysql-test/t/rpl_ssl.test: Fix for bug #28144: "Slave_IO_Running" differs in replication tests - wait_for_slave_to_start.inc used to get certain slave states in order to be more predictable. mysql-test/include/wait_for_slave_param.inc: New BitKeeper file ``mysql-test/include/wait_for_slave_param.inc'' allow to wait until SHOW SLAVE STATUS has returned a spicified value. --- mysql-test/include/wait_for_slave_param.inc | 26 +++++++ mysql-test/r/rpl_log_pos.result | 83 +++++++++++++++++---- mysql-test/r/rpl_ssl.result | 1 + mysql-test/t/rpl_log_pos.test | 33 ++++---- mysql-test/t/rpl_ssl.test | 3 + 5 files changed, 112 insertions(+), 34 deletions(-) create mode 100644 mysql-test/include/wait_for_slave_param.inc diff --git a/mysql-test/include/wait_for_slave_param.inc b/mysql-test/include/wait_for_slave_param.inc new file mode 100644 index 00000000000..fed97195aba --- /dev/null +++ b/mysql-test/include/wait_for_slave_param.inc @@ -0,0 +1,26 @@ +# include/wait_for_slave_param.inc +# +# SUMMARY +# +# Waits until SHOW SLAVE STATUS has returned a spicified value. +# +# USAGE +# +# let $slave_param= Slave_SQL_Running; +# let $slave_param_value= No; +# --source include/slave_wait_param.inc + +let $slave_wait_param_counter= 300; +let $slave_value= query_get_value("SHOW SLAVE STATUS", $slave_param, 1); +while (`select "$slave_value" != "$slave_param_value"`) +{ + dec $slave_wait_param_counter; + if (!$slave_wait_param_counter) + { + --echo ERROR: failed while waiting for slave parameter $slave_param: $slave_param_value + query_vertical show slave status; + exit; + } + sleep 0.1; + let $slave_value= query_get_value("SHOW SLAVE STATUS", $slave_param, 1); +} diff --git a/mysql-test/r/rpl_log_pos.result b/mysql-test/r/rpl_log_pos.result index cf13756966e..b55326415bf 100644 --- a/mysql-test/r/rpl_log_pos.result +++ b/mysql-test/r/rpl_log_pos.result @@ -7,27 +7,78 @@ start slave; show master status; File Position Binlog_Do_DB Binlog_Ignore_DB master-bin.000001 98 -show slave status; -Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master -# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 98 # # master-bin.000001 Yes Yes 0 0 98 # None 0 No # -stop slave; -change master to master_log_pos=73; -start slave; stop slave; change master to master_log_pos=73; show slave status; -Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master -# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 73 # # master-bin.000001 No No 0 0 73 # None 0 No # +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port MASTER_PORT +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos 73 +Relay_Log_File # +Relay_Log_Pos # +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running No +Slave_SQL_Running No +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 0 +Last_Error +Skip_Counter 0 +Exec_Master_Log_Pos 73 +Relay_Log_Space # +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # start slave; -show slave status; -Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master -# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 73 # # master-bin.000001 No Yes 0 0 73 # None 0 No # stop slave; -change master to master_log_pos=173; -start slave; show slave status; -Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master -# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 173 # # master-bin.000001 No Yes 0 0 173 # None 0 No # +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port MASTER_PORT +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos 73 +Relay_Log_File # +Relay_Log_Pos # +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running No +Slave_SQL_Running No +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 0 +Last_Error +Skip_Counter 0 +Exec_Master_Log_Pos 73 +Relay_Log_Space # +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # show master status; File Position Binlog_Do_DB Binlog_Ignore_DB master-bin.000001 98 @@ -35,7 +86,6 @@ create table if not exists t1 (n int); drop table if exists t1; create table t1 (n int); insert into t1 values (1),(2),(3); -stop slave; change master to master_log_pos=98; start slave; select * from t1; @@ -44,3 +94,4 @@ n 2 3 drop table t1; +End of 5.0 tests diff --git a/mysql-test/r/rpl_ssl.result b/mysql-test/r/rpl_ssl.result index 6bc1e996965..1d3f4762693 100644 --- a/mysql-test/r/rpl_ssl.result +++ b/mysql-test/r/rpl_ssl.result @@ -92,3 +92,4 @@ Master_SSL_Cert MYSQL_TEST_DIR/std_data/client-cert.pem Master_SSL_Cipher Master_SSL_Key MYSQL_TEST_DIR/std_data/client-key.pem Seconds_Behind_Master # +End of 5.0 tests diff --git a/mysql-test/t/rpl_log_pos.test b/mysql-test/t/rpl_log_pos.test index 979b146bb22..ee8da494f86 100644 --- a/mysql-test/t/rpl_log_pos.test +++ b/mysql-test/t/rpl_log_pos.test @@ -4,31 +4,29 @@ source include/master-slave.inc; show master status; sync_slave_with_master; ---replace_result $MASTER_MYPORT MASTER_PORT ---replace_column 1 # 8 # 9 # 23 # 33 # -show slave status; -stop slave; -change master to master_log_pos=73; -start slave; -sleep 5; + stop slave; +--source include/wait_for_slave_to_stop.inc change master to master_log_pos=73; --replace_result $MASTER_MYPORT MASTER_PORT --replace_column 1 # 8 # 9 # 23 # 33 # -show slave status; +query_vertical show slave status; + start slave; -sleep 5; ---replace_result $MASTER_MYPORT MASTER_PORT ---replace_column 1 # 8 # 9 # 23 # 33 # -show slave status; +let $slave_param= Slave_SQL_Running; +let $slave_param_value= Yes; +--source include/wait_for_slave_param.inc +let $slave_param= Slave_IO_Running; +let $slave_param_value= No; +--source include/wait_for_slave_param.inc stop slave; -change master to master_log_pos=173; -start slave; -sleep 2; +--source include/wait_for_slave_to_stop.inc + --replace_result $MASTER_MYPORT MASTER_PORT --replace_column 1 # 8 # 9 # 23 # 33 # -show slave status; +query_vertical show slave status; + connection master; show master status; create table if not exists t1 (n int); @@ -37,7 +35,6 @@ create table t1 (n int); insert into t1 values (1),(2),(3); save_master_pos; connection slave; -stop slave; change master to master_log_pos=98; start slave; sync_with_master; @@ -46,4 +43,4 @@ connection master; drop table t1; sync_slave_with_master; -# End of 4.1 tests +--echo End of 5.0 tests diff --git a/mysql-test/t/rpl_ssl.test b/mysql-test/t/rpl_ssl.test index f83f8b983b2..d08004cb00b 100644 --- a/mysql-test/t/rpl_ssl.test +++ b/mysql-test/t/rpl_ssl.test @@ -56,6 +56,9 @@ enable_query_log; connection master; insert into t1 values (NULL); sync_slave_with_master; +--source include/wait_for_slave_to_start.inc --replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR $MASTER_MYPORT MASTER_MYPORT --replace_column 1 # 7 # 8 # 9 # 22 # 23 # 33 # query_vertical show slave status; + +--echo End of 5.0 tests From 2a9bb274244a71155382ccce9485db0453ff4a70 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 18 Jun 2007 17:16:20 -0400 Subject: [PATCH 3/9] Bug #29053 SQL_CACHE in UNION causes non-deterministic functions to be cached Changed code to enforce that SQL_CACHE only in the first SELECT is used to turn on caching(as documented), but any SQL_NO_CACHE will turn off caching (not documented, but a useful behaviour, especially for machine generated queries). Added test cases to explicitly test the documented caching behaviour and test cases for the reported bug. mysql-test/r/query_cache.result: Added non-bug specific tests that ensure that only SQL_CACHE in the first SELECT is respected when encountered by the parser. These tests validate what is already documented, that only the outer most SELECTS can use the SQL_CACHE option to turn on caching. Because it would break existing SQL applications, we do not return an error if the SQL_CACHE expression is found in nested SELECTs. Also added test to validate nested SELECT can contain SQL_NO_CACHE and it will always turn off caching for the whole query. Also added a bug specific test case to validate that the buggy behavior as reported has been fixed. mysql-test/t/query_cache.test: Added non-bug specific tests that ensure that only SQL_CACHE in the first SELECT is respected when encountered by the parser. These tests validate what is already documented, that only the outer most SELECTS can use the SQL_CACHE option to turn on caching. Because it would break existing SQL applications, we do not return an error if the SQL_CACHE expression is found in nested SELECTs. Also added test to validate nested SELECT can contain SQL_NO_CACHE and it will always turn off caching for the whole query. Also added a bug specific test case to validate that the buggy behavior as reported has been fixed. sql/sql_yacc.yy: Added an explicit check to make sure "SELECT SQL_CACHE" only works on the first select in a query. The parser will always hit the outermost SELECT first, and if the SQL_CACHE option is found it sets the safe_to_query flag in the lex. Then, if there are subseqent "uncachable" subqueries or functions, as it parses those elements it sets the safe_to_query to 0. However, this cause problems if nested SELECTs also used the SQL_CACHE option, because then it would set back safe_to_query to 1, even though there are uncacheable expressions previously parsed. By adding the check to ensure only the first SELECT can turn caching on, it means a subsequent SQL_CACHE option can't turn caching back on after a uncacheable subsequery was already encountered. --- mysql-test/r/query_cache.result | 53 ++++++++++++++++++++++++++++++++- mysql-test/t/query_cache.test | 34 +++++++++++++++++++++ sql/sql_yacc.yy | 8 +++-- 3 files changed, 92 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/query_cache.result b/mysql-test/r/query_cache.result index 53a0977a16a..b0f3fb77c0e 100644 --- a/mysql-test/r/query_cache.result +++ b/mysql-test/r/query_cache.result @@ -179,12 +179,22 @@ a 1 2 3 +select * from t1 where a IN (select sql_cache a from t1); +a +1 +2 +3 +select * from t1 where a IN (select a from t1 union select sql_cache a from t1); +a +1 +2 +3 show status like "Qcache_hits"; Variable_name Value Qcache_hits 4 show status like "Qcache_queries_in_cache"; Variable_name Value -Qcache_queries_in_cache 2 +Qcache_queries_in_cache 1 set query_cache_type=on; reset query cache; show status like "Qcache_queries_in_cache"; @@ -195,6 +205,41 @@ a 1 2 3 +select * from t1 union select sql_no_cache * from t1; +a +1 +2 +3 +select * from t1 where a IN (select sql_no_cache a from t1); +a +1 +2 +3 +select * from t1 where a IN (select a from t1 union select sql_no_cache a from t1); +a +1 +2 +3 +select sql_cache sql_no_cache * from t1; +a +1 +2 +3 +select sql_cache * from t1 union select sql_no_cache * from t1; +a +1 +2 +3 +select sql_cache * from t1 where a IN (select sql_no_cache a from t1); +a +1 +2 +3 +select sql_cache * from t1 where a IN (select a from t1 union select sql_no_cache a from t1); +a +1 +2 +3 show status like "Qcache_queries_in_cache"; Variable_name Value Qcache_queries_in_cache 0 @@ -1416,3 +1461,9 @@ insert into t1 values ('c'); a drop table t1; set GLOBAL query_cache_size= default; +set GLOBAL query_cache_size=1000000; +create table t1 (a char); +insert into t1 values ('c'); +a +drop table t1; +set GLOBAL query_cache_size= default; diff --git a/mysql-test/t/query_cache.test b/mysql-test/t/query_cache.test index 342ef5b6990..965ebf5df62 100644 --- a/mysql-test/t/query_cache.test +++ b/mysql-test/t/query_cache.test @@ -89,7 +89,11 @@ show status like "Qcache_queries_in_cache"; select sql_cache * from t1 union select * from t1; set query_cache_type=2; select sql_cache * from t1 union select * from t1; + +# all sql_cache statements, except for the first select, are ignored. select * from t1 union select sql_cache * from t1; +select * from t1 where a IN (select sql_cache a from t1); +select * from t1 where a IN (select a from t1 union select sql_cache a from t1); show status like "Qcache_hits"; show status like "Qcache_queries_in_cache"; set query_cache_type=on; @@ -102,6 +106,15 @@ show status like "Qcache_queries_in_cache"; # SELECT SQL_NO_CACHE # select sql_no_cache * from t1; +# sql_no_cache can occur in any nested select to turn on cacheing for the whole +# expression and it will always override a sql_cache statement. +select * from t1 union select sql_no_cache * from t1; +select * from t1 where a IN (select sql_no_cache a from t1); +select * from t1 where a IN (select a from t1 union select sql_no_cache a from t1); +select sql_cache sql_no_cache * from t1; +select sql_cache * from t1 union select sql_no_cache * from t1; +select sql_cache * from t1 where a IN (select sql_no_cache a from t1); +select sql_cache * from t1 where a IN (select a from t1 union select sql_no_cache a from t1); show status like "Qcache_queries_in_cache"; drop table t1; # @@ -994,4 +1007,25 @@ drop table t1; set GLOBAL query_cache_size= default; +# +# Bug #29053 SQL_CACHE in UNION causes non-deterministic functions to be cached +# + +set GLOBAL query_cache_size=1000000; + +create table t1 (a char); +insert into t1 values ('c'); + +let $q1= `select RAND() from t1 union select sql_cache 1 from t1;`; +let $q2= `select RAND() from t1 union select sql_cache 1 from t1;`; + +# disabling the logging of the query because the times are different each run. +--disable_query_log +eval select a from t1 where "$q1" = "$q2"; +--enable_query_log + +drop table t1; + +set GLOBAL query_cache_size= default; + # End of 5.0 tests diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index d1da36dfa5b..9c75c08c62a 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -4363,8 +4363,12 @@ select_option: } | SQL_CACHE_SYM { - /* Honor this flag only if SQL_NO_CACHE wasn't specified. */ - if (Lex->select_lex.sql_cache != SELECT_LEX::SQL_NO_CACHE) + /* + Honor this flag only if SQL_NO_CACHE wasn't specified AND + we are parsing the outermost SELECT in the query. + */ + if (Lex->select_lex.sql_cache != SELECT_LEX::SQL_NO_CACHE && + Lex->current_select == &Lex->select_lex) { Lex->safe_to_cache_query=1; Lex->select_lex.options|= OPTION_TO_QUERY_CACHE; From 5941479ee3f540a7dc6ce6ecb9246ee8edf5eb88 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 18 Jun 2007 17:55:12 -0400 Subject: [PATCH 4/9] Bug #28921 Queries containing UDF functions are cached Fixed runtime to no longer allow the caching of queries with UDF calls. mysql-test/r/udf.result: Added a test that turns on caching and checks that querys calling UDFs don't get cached. mysql-test/t/udf.test: Added a test that turns on caching and checks that querys calling UDFs don't get cached. sql/sql_yacc.yy: Fixed code to set safe_to_cache_query=0 regardless if the function call is a UDF or SP. Where it was placed previously -- at the very end of the else testing for UDFs -- it only executed the statement if the function call was a stored procedure call. --- mysql-test/r/udf.result | 23 +++++++++++++++++++++++ mysql-test/t/udf.test | 24 ++++++++++++++++++++++++ sql/sql_yacc.yy | 4 ++-- 3 files changed, 49 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/udf.result b/mysql-test/r/udf.result index 7c52e7da496..2e9cf217ed6 100644 --- a/mysql-test/r/udf.result +++ b/mysql-test/r/udf.result @@ -273,4 +273,27 @@ drop function f3; drop function metaphon; drop function myfunc_double; drop function myfunc_int; +CREATE FUNCTION metaphon RETURNS STRING SONAME "UDF_EXAMPLE_LIB"; +create table t1 (a char); +set GLOBAL query_cache_size=1355776; +reset query cache; +select metaphon('MySQL') from t1; +metaphon('MySQL') +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 0 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +select metaphon('MySQL') from t1; +metaphon('MySQL') +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 0 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +drop table t1; +drop function metaphon; +set GLOBAL query_cache_size=default; End of 5.0 tests. diff --git a/mysql-test/t/udf.test b/mysql-test/t/udf.test index 0b582dc61b6..75af1f4be4b 100644 --- a/mysql-test/t/udf.test +++ b/mysql-test/t/udf.test @@ -288,4 +288,28 @@ drop function metaphon; drop function myfunc_double; drop function myfunc_int; +# +# Bug #28921: Queries containing UDF functions are cached +# + +--replace_result $UDF_EXAMPLE_LIB UDF_EXAMPLE_LIB +eval CREATE FUNCTION metaphon RETURNS STRING SONAME "$UDF_EXAMPLE_LIB"; +create table t1 (a char); + +set GLOBAL query_cache_size=1355776; +reset query cache; + +select metaphon('MySQL') from t1; +show status like "Qcache_hits"; +show status like "Qcache_queries_in_cache"; + +select metaphon('MySQL') from t1; +show status like "Qcache_hits"; +show status like "Qcache_queries_in_cache"; + +drop table t1; +drop function metaphon; +set GLOBAL query_cache_size=default; + + --echo End of 5.0 tests. diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 924a8bd6d7d..22ec7b31248 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -5150,8 +5150,8 @@ simple_expr: $$= new Item_func_sp(Lex->current_context(), name, *$4); else $$= new Item_func_sp(Lex->current_context(), name); - lex->safe_to_cache_query=0; - } + } + lex->safe_to_cache_query=0; } | UNIQUE_USERS '(' text_literal ',' NUM ',' NUM ',' expr_list ')' { From b269713c10212138685fc7a9f2dcdc2feb015e92 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 19 Jun 2007 09:56:19 +0200 Subject: [PATCH 5/9] Bug#28769 Test case "innodb" fails with --skip-log-bin - Move binlog related tests to binlog_innodb.test - Remove "source include/have_log_bin.inc" from innodb.test mysql-test/r/innodb.result: Move binlog related tests to binlog_innodb.test mysql-test/t/innodb.test: Move binlog related tests to binlog_innodb.test mysql-test/r/binlog_innodb.result: Move binlog related tests to binlog_innodb.test mysql-test/t/binlog_innodb.test: Move binlog related tests to binlog_innodb.test --- mysql-test/r/binlog_innodb.result | 23 ++++++++++++++++++ mysql-test/r/innodb.result | 27 ++------------------- mysql-test/t/binlog_innodb.test | 39 +++++++++++++++++++++++++++++++ mysql-test/t/innodb.test | 35 --------------------------- 4 files changed, 64 insertions(+), 60 deletions(-) create mode 100644 mysql-test/r/binlog_innodb.result create mode 100644 mysql-test/t/binlog_innodb.test diff --git a/mysql-test/r/binlog_innodb.result b/mysql-test/r/binlog_innodb.result new file mode 100644 index 00000000000..93414a13ba1 --- /dev/null +++ b/mysql-test/r/binlog_innodb.result @@ -0,0 +1,23 @@ +show status like "binlog_cache_use"; +Variable_name Value +Binlog_cache_use 0 +show status like "binlog_cache_disk_use"; +Variable_name Value +Binlog_cache_disk_use 0 +create table t1 (a int) engine=innodb; +show status like "binlog_cache_use"; +Variable_name Value +Binlog_cache_use 1 +show status like "binlog_cache_disk_use"; +Variable_name Value +Binlog_cache_disk_use 1 +begin; +delete from t1; +commit; +show status like "binlog_cache_use"; +Variable_name Value +Binlog_cache_use 2 +show status like "binlog_cache_disk_use"; +Variable_name Value +Binlog_cache_disk_use 1 +drop table t1; diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result index 9f327ca1901..b16ada85f8f 100644 --- a/mysql-test/r/innodb.result +++ b/mysql-test/r/innodb.result @@ -1640,29 +1640,6 @@ t2 CREATE TABLE `t2` ( CONSTRAINT `t2_ibfk_2` FOREIGN KEY (`b`) REFERENCES `t1` (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 drop table t2, t1; -show status like "binlog_cache_use"; -Variable_name Value -Binlog_cache_use 155 -show status like "binlog_cache_disk_use"; -Variable_name Value -Binlog_cache_disk_use 0 -create table t1 (a int) engine=innodb; -show status like "binlog_cache_use"; -Variable_name Value -Binlog_cache_use 156 -show status like "binlog_cache_disk_use"; -Variable_name Value -Binlog_cache_disk_use 1 -begin; -delete from t1; -commit; -show status like "binlog_cache_use"; -Variable_name Value -Binlog_cache_use 157 -show status like "binlog_cache_disk_use"; -Variable_name Value -Binlog_cache_disk_use 1 -drop table t1; create table t1 (c char(10), index (c,c)) engine=innodb; ERROR 42S21: Duplicate column name 'c' create table t1 (c1 char(10), c2 char(10), index (c1,c2,c1)) engine=innodb; @@ -1782,10 +1759,10 @@ Variable_name Value Innodb_page_size 16384 show status like "Innodb_rows_deleted"; Variable_name Value -Innodb_rows_deleted 2070 +Innodb_rows_deleted 70 show status like "Innodb_rows_inserted"; Variable_name Value -Innodb_rows_inserted 31727 +Innodb_rows_inserted 29727 show status like "Innodb_rows_updated"; Variable_name Value Innodb_rows_updated 29530 diff --git a/mysql-test/t/binlog_innodb.test b/mysql-test/t/binlog_innodb.test new file mode 100644 index 00000000000..2da7b2b0895 --- /dev/null +++ b/mysql-test/t/binlog_innodb.test @@ -0,0 +1,39 @@ +-- source include/have_innodb.inc +-- source include/have_log_bin.inc + + +# +# Let us test binlog_cache_use and binlog_cache_disk_use status vars. +# Actually this test has nothing to do with innodb per se, it just requires +# transactional table. +# +show status like "binlog_cache_use"; +show status like "binlog_cache_disk_use"; + +create table t1 (a int) engine=innodb; + +# Now we are going to create transaction which is long enough so its +# transaction binlog will be flushed to disk... +let $1=2000; +disable_query_log; +begin; +while ($1) +{ + eval insert into t1 values( $1 ); + dec $1; +} +commit; +enable_query_log; +show status like "binlog_cache_use"; +show status like "binlog_cache_disk_use"; + +# Transaction which should not be flushed to disk and so should not +# increase binlog_cache_disk_use. +begin; +delete from t1; +commit; +show status like "binlog_cache_use"; +show status like "binlog_cache_disk_use"; +drop table t1; + + diff --git a/mysql-test/t/innodb.test b/mysql-test/t/innodb.test index b7f264578f2..9e8aa050e7d 100644 --- a/mysql-test/t/innodb.test +++ b/mysql-test/t/innodb.test @@ -12,7 +12,6 @@ ####################################################################### -- source include/have_innodb.inc --- source include/have_log_bin.inc # # Small basic test with ignore @@ -1155,40 +1154,6 @@ show create table t2; drop table t2, t1; -# -# Let us test binlog_cache_use and binlog_cache_disk_use status vars. -# Actually this test has nothing to do with innodb per se, it just requires -# transactional table. -# -show status like "binlog_cache_use"; -show status like "binlog_cache_disk_use"; - -create table t1 (a int) engine=innodb; - -# Now we are going to create transaction which is long enough so its -# transaction binlog will be flushed to disk... -let $1=2000; -disable_query_log; -begin; -while ($1) -{ - eval insert into t1 values( $1 ); - dec $1; -} -commit; -enable_query_log; -show status like "binlog_cache_use"; -show status like "binlog_cache_disk_use"; - -# Transaction which should not be flushed to disk and so should not -# increase binlog_cache_disk_use. -begin; -delete from t1; -commit; -show status like "binlog_cache_use"; -show status like "binlog_cache_disk_use"; -drop table t1; - # # Bug #6126: Duplicate columns in keys gives misleading error message # From 9aac6fd7bd5be2e77694bc4e438ff12e862067f0 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 19 Jun 2007 11:06:02 +0200 Subject: [PATCH 6/9] WL#3232 mysqltest, enable --source $variables/ - Add test case for this already existing feature mysql-test/r/mysqltest.result: Update result file mysql-test/t/mysqltest.test: Add test case for this feature --- mysql-test/r/mysqltest.result | 1 + mysql-test/t/mysqltest.test | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/mysql-test/r/mysqltest.result b/mysql-test/r/mysqltest.result index 92265c94c4b..c71fbc4f5e0 100644 --- a/mysql-test/r/mysqltest.result +++ b/mysql-test/r/mysqltest.result @@ -330,6 +330,7 @@ here is the sourced script In loop here is the sourced script +here is the sourced script mysqltest: At line 1: Missing argument to sleep mysqltest: At line 1: Missing argument to real_sleep mysqltest: At line 1: Invalid argument to sleep "abc" diff --git a/mysql-test/t/mysqltest.test b/mysql-test/t/mysqltest.test index 8dae94e271e..5bc004125c4 100644 --- a/mysql-test/t/mysqltest.test +++ b/mysql-test/t/mysqltest.test @@ -807,6 +807,10 @@ while ($num) } --enable_abort_on_error --enable_query_log + +# Test source $variable/ +--source $MYSQLTEST_VARDIR/tmp/sourced.inc + --remove_file $MYSQLTEST_VARDIR/tmp/sourced.inc # ---------------------------------------------------------------------------- From c5fb4b243a06fc097b390d867e042f00809b326d Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 20 Jun 2007 11:47:55 +0200 Subject: [PATCH 7/9] Bug#28742 mysql-test-run is very slow on "Stopping All Servers" step - Improve shutdown algorithm - Wait up to 5 seconds for processes to exit after their port is free mysql-test/lib/mtr_process.pl: Improve shutdown algorithm, shutdown the server hard if it hasn't responded to "mysqladmin shutdown" and it's port is free. Print error to servers error log indicating "hard shutdown" Give processes up to 5 seconds to exit after their port is free mysql-test/lib/mtr_report.pl: Indicate in what file the warning was found mysql-test/mysql-test-run.pl: Pass path of process error log to 'mtr_check_stop_servers' --- mysql-test/lib/mtr_process.pl | 169 ++++++++++++++++------------------ mysql-test/lib/mtr_report.pl | 2 +- mysql-test/mysql-test-run.pl | 3 + 3 files changed, 85 insertions(+), 89 deletions(-) diff --git a/mysql-test/lib/mtr_process.pl b/mysql-test/lib/mtr_process.pl index ac2e049a67c..e4fd3390c5f 100644 --- a/mysql-test/lib/mtr_process.pl +++ b/mysql-test/lib/mtr_process.pl @@ -547,72 +547,87 @@ sub mtr_kill_leftovers () { } -# Check that all processes in list are killed -# The argument is a list of 'ports', 'pids', 'pidfiles' and 'socketfiles' -# for which shutdown has been started. Make sure they all get killed -# in one way or the other. # -# FIXME On Cygwin, and maybe some other platforms, $srv->{'pid'} and -# the pid in $srv->{'pidfile'} will not be the same PID. We need to try to kill -# both I think. - +# Check that all processes in "spec" are shutdown gracefully +# else kill them off hard +# sub mtr_check_stop_servers ($) { my $spec= shift; # Return if no processes are defined return if ! @$spec; - #mtr_report("mtr_check_stop_servers"); + mtr_verbose("mtr_check_stop_servers"); + # ---------------------------------------------------------------------- + # Wait until servers in "spec" has stopped listening + # to their ports or timeout occurs + # ---------------------------------------------------------------------- mtr_ping_with_timeout(\@$spec); # ---------------------------------------------------------------------- - # We loop with waitpid() nonblocking to see how many of the ones we - # are to kill, actually got killed by mysqladmin or ndb_mgm - # - # Note that we don't rely on this, the mysqld server might have stopped - # listening to the port, but still be alive. But it is a start. + # Use waitpid() nonblocking for a little while, to see how + # many process's will exit sucessfully. + # This is the normal case. # ---------------------------------------------------------------------- - + my $wait_counter= 50; # Max number of times to redo the loop foreach my $srv ( @$spec ) { + my $pid= $srv->{'pid'}; my $ret_pid; - if ( $srv->{'pid'} ) + if ( $pid ) { - $ret_pid= waitpid($srv->{'pid'},&WNOHANG); - if ($ret_pid == $srv->{'pid'}) + $ret_pid= waitpid($pid,&WNOHANG); + if ($ret_pid == $pid) { mtr_verbose("Caught exit of process $ret_pid"); $srv->{'pid'}= 0; } + elsif ($ret_pid == 0) + { + mtr_verbose("Process $pid is still alive"); + if ($wait_counter-- > 0) + { + # Give the processes more time to exit + select(undef, undef, undef, (0.1)); + redo; + } + } else { - # mtr_warning("caught exit of unknown child $ret_pid"); + mtr_warning("caught exit of unknown child $ret_pid"); } } } # ---------------------------------------------------------------------- - # We know the process was started from this file, so there is a PID - # saved, or else we have nothing to do. - # Might be that is is recorded to be missing, but we failed to - # take away the PID file earlier, then we do it now. + # The processes that haven't yet exited need to + # be killed hard, put them in "kill_pids" hash # ---------------------------------------------------------------------- - - my %mysqld_pids; - + my %kill_pids; foreach my $srv ( @$spec ) { - if ( $srv->{'pid'} ) + my $pid= $srv->{'pid'}; + if ( $pid ) { - $mysqld_pids{$srv->{'pid'}}= 1; + # Server is still alive, put it in list to be hard killed + $kill_pids{$pid}= 1; + + # Write a message to the process's error log (if it has one) + # that it's being killed hard. + if ( defined $srv->{'errfile'} ) + { + mtr_tofile($srv->{'errfile'}, "Note: Forcing kill of process $pid\n"); + } + mtr_warning("Forcing kill of process $pid"); + } else { - # Server is dead, we remove the pidfile if any - # Race, could have been removed between I tested with -f - # and the unlink() below, so I better check again with -f - + # Server is dead, remove the pidfile if it exists + # + # Race, could have been removed between test with -f + # and the unlink() below, so better check again with -f if ( -f $srv->{'pidfile'} and ! unlink($srv->{'pidfile'}) and -f $srv->{'pidfile'} ) { @@ -621,69 +636,35 @@ sub mtr_check_stop_servers ($) { } } - # ---------------------------------------------------------------------- - # If all the processes in list already have been killed, - # then we don't have to do anything. - # ---------------------------------------------------------------------- - - if ( ! keys %mysqld_pids ) + if ( ! keys %kill_pids ) { + # All processes has exited gracefully return; } - # ---------------------------------------------------------------------- - # In mtr_mysqladmin_shutdown() we only waited for the mysqld servers - # not to listen to the port. But we are not sure we got them all - # killed. If we suspect it lives, try nice kill with SIG_TERM. Note - # that for true Win32 processes, kill(0,$pid) will not return 1. - # ---------------------------------------------------------------------- - - start_reap_all(); # Avoid zombies - - my @mysqld_pids= keys %mysqld_pids; - mtr_kill_processes(\@mysqld_pids); - - stop_reap_all(); # Get into control again + mtr_kill_processes(\%kill_pids); # ---------------------------------------------------------------------- - # Now, we check if all we can find using kill(0,$pid) are dead, - # and just assume the rest are. We cleanup socket and PID files. + # All processes are killed, cleanup leftover files # ---------------------------------------------------------------------- - { my $errors= 0; foreach my $srv ( @$spec ) { if ( $srv->{'pid'} ) { - if ( kill(0,$srv->{'pid'}) ) + # Server has been hard killed, clean it's resources + foreach my $file ($srv->{'pidfile'}, $srv->{'sockfile'}) { - # FIXME In Cygwin there seem to be some fast reuse - # of PIDs, so dying may not be the right thing to do. - $errors++; - mtr_warning("can't kill process $srv->{'pid'}"); - } - else - { - # We managed to kill it at last - # FIXME In Cygwin, we will get here even if the process lives. - - # Not needed as we know the process is dead, but to be safe - # we unlink and check success in two steps. We first unlink - # without checking the error code, and then check if the - # file still exists. - - foreach my $file ($srv->{'pidfile'}, $srv->{'sockfile'}) + # Know it is dead so should be no race, careful anyway + if ( defined $file and -f $file and ! unlink($file) and -f $file ) { - # Know it is dead so should be no race, careful anyway - if ( defined $file and -f $file and ! unlink($file) and -f $file ) - { - $errors++; - mtr_warning("couldn't delete $file"); - } - } - $srv->{'pid'}= 0; - } + $errors++; + mtr_warning("couldn't delete $file"); + } + } + + $srv->{'pid'}= 0; } } if ( $errors ) @@ -701,12 +682,9 @@ sub mtr_check_stop_servers ($) { } } } - - # FIXME We just assume they are all dead, for Cygwin we are not - # really sure - } + # Wait for all the process in the list to terminate sub mtr_wait_blocking($) { my $admin_pids= shift; @@ -1095,9 +1073,9 @@ sub sleep_until_file_created ($$$) { sub mtr_kill_processes ($) { my $pids = shift; - mtr_verbose("mtr_kill_processes " . join(" ", @$pids)); + mtr_verbose("mtr_kill_processes (" . join(" ", keys %{$pids}) . ")"); - foreach my $pid (@$pids) + foreach my $pid (keys %{$pids}) { if ($pid <= 0) @@ -1106,11 +1084,26 @@ sub mtr_kill_processes ($) { next; } - foreach my $sig (15, 9) + my $signaled_procs= kill(9, $pid); + if ($signaled_procs == 0) { - last if mtr_im_kill_process([ $pid ], $sig, 10, 1); + # No such process existed, assume it's killed + mtr_verbose("killed $pid(no such process)"); + } + else + { + my $ret_pid= waitpid($pid,0); + if ($ret_pid == $pid) + { + mtr_verbose("killed $pid(got the pid)"); + } + elsif ($ret_pid == -1) + { + mtr_verbose("killed $pid(got -1)"); + } } } + mtr_verbose("done killing processes"); } diff --git a/mysql-test/lib/mtr_report.pl b/mysql-test/lib/mtr_report.pl index d08208d37a6..4b1dd2f3d6b 100644 --- a/mysql-test/lib/mtr_report.pl +++ b/mysql-test/lib/mtr_report.pl @@ -290,7 +290,7 @@ sub mtr_report_stats ($) { if ( /$pattern/ ) { $found_problems= 1; - print WARN $_; + print WARN basename($errlog) . ": $_"; } } } diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 2d665564034..103f7b309de 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -4097,6 +4097,7 @@ sub stop_all_servers () { pidfile => $mysqld->{'path_pid'}, sockfile => $mysqld->{'path_sock'}, port => $mysqld->{'port'}, + errfile => $mysqld->{'path_myerr'}, }); $mysqld->{'pid'}= 0; # Assume we are done with it @@ -4303,6 +4304,7 @@ sub run_testcase_stop_servers($$$) { pidfile => $mysqld->{'path_pid'}, sockfile => $mysqld->{'path_sock'}, port => $mysqld->{'port'}, + errfile => $mysqld->{'path_myerr'}, }); $mysqld->{'pid'}= 0; # Assume we are done with it @@ -4353,6 +4355,7 @@ sub run_testcase_stop_servers($$$) { pidfile => $mysqld->{'path_pid'}, sockfile => $mysqld->{'path_sock'}, port => $mysqld->{'port'}, + errfile => $mysqld->{'path_myerr'}, }); From 4d9cc3db77a89e9c8117ae28e8d4474bcb51fac6 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 21 Jun 2007 04:30:10 +0200 Subject: [PATCH 8/9] Bug#24924: shared-memory-base-name that is too long causes buffer overflow long shared-memory-base-names could overflow a static internal buffer and thus crash mysqld and various clients. change both to dynamic buffers, show everything but overflowing those buffers still works. The test case for this would pretty much amount to mysqld --shared-memory-base-name=HeyMrBaseNameXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX --shared-memory=1 & mysqladmin --no-defaults --shared-memory-base-name=HeyMrBaseNameXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX shutdown Unfortunately, we can't just use an .opt file for the server. The .opt file is used at start-up, before any include in the actual test can tell mysqltest to skip this one on non-Windows. As a result, such a test would break on unices. Fixing mysql-test-run.pl to export full path for master and slave would enable us to start a server from within the test which is ugly and, what's more, doesn't work as the server blocks (mysqltest offers no fire-and-forget fork-and-exec), and mysqladmin never gets run. Making the test rpl_windows_shm or some such so we can is beyond ugly. As is introducing another file-name based special case (run "win*.test" only when on Windows). As is (yuck) coding half the test into mtr (as in, having it hand out a customized environment conductive to the shm- thing on Win only). Situation is exacerbated by the fact that .sh is not necessary run as expected on Win. In short, it's just not worth it. No test-case until we have a new-and-improved test framework. sql-common/client.c: Bug#24924: shared-memory-base-name that is too long causes buffer overflow compose shared memory name in dynamic rather than static buffer to prevent overflows (clients) sql/mysqld.cc: Bug#24924: shared-memory-base-name that is too long causes buffer overflow compose shared memory name in dynamic rather than static buffer to prevent overflows (server) --- sql-common/client.c | 10 +++++++++- sql/mysqld.cc | 11 ++++++++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/sql-common/client.c b/sql-common/client.c index 3e5ceb1a738..f8d52e02196 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -402,13 +402,19 @@ HANDLE create_shared_memory(MYSQL *mysql,NET *net, uint connect_timeout) HANDLE handle_file_map = NULL; ulong connect_number; char connect_number_char[22], *p; - char tmp[64]; + char *tmp= NULL; char *suffix_pos; DWORD error_allow = 0; DWORD error_code = 0; DWORD event_access_rights= SYNCHRONIZE | EVENT_MODIFY_STATE; char *shared_memory_base_name = mysql->options.shared_memory_base_name; + /* + get enough space base-name + '_' + longest suffix we might ever send + */ + if (!(tmp= (char *)my_malloc(strlen(shared_memory_base_name) + 32L, MYF(MY_FAE)))) + goto err; + /* The name of event and file-mapping events create agree next rule: shared_memory_base_name+unique_part @@ -551,6 +557,8 @@ err2: CloseHandle(handle_file_map); } err: + if (tmp) + my_free(tmp, MYF(0)); if (error_allow) error_code = GetLastError(); if (event_connect_request) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 49d997f391e..afeb3b82a01 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -4420,7 +4420,7 @@ pthread_handler_t handle_connections_shared_memory(void *arg) HANDLE event_connect_answer= 0; ulong smem_buffer_length= shared_memory_buffer_length + 4; ulong connect_number= 1; - char tmp[63]; + char *tmp= NULL; char *suffix_pos; char connect_number_char[22], *p; const char *errmsg= 0; @@ -4429,6 +4429,12 @@ pthread_handler_t handle_connections_shared_memory(void *arg) DBUG_ENTER("handle_connections_shared_memorys"); DBUG_PRINT("general",("Waiting for allocated shared memory.")); + /* + get enough space base-name + '_' + longest suffix we might ever send + */ + if (!(tmp= (char *)my_malloc(strlen(shared_memory_base_name) + 32L, MYF(MY_FAE)))) + goto error; + if (my_security_attr_create(&sa_event, &errmsg, GENERIC_ALL, SYNCHRONIZE | EVENT_MODIFY_STATE)) goto error; @@ -4616,6 +4622,9 @@ errorconn: /* End shared memory handling */ error: + if (tmp) + my_free(tmp, MYF(0)); + if (errmsg) { char buff[180]; From e0e739b628588d5856ab634654347edae21880dd Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 21 Jun 2007 16:37:13 +0200 Subject: [PATCH 9/9] Add name of test that generated the warning to "warnings" file --- mysql-test/lib/mtr_report.pl | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/mysql-test/lib/mtr_report.pl b/mysql-test/lib/mtr_report.pl index 4b1dd2f3d6b..1abfc6b6b57 100644 --- a/mysql-test/lib/mtr_report.pl +++ b/mysql-test/lib/mtr_report.pl @@ -272,6 +272,7 @@ sub mtr_report_stats ($) { { foreach my $errlog ( sort glob("$::opt_vardir/log/*.err") ) { + my $testname= ""; unless ( open(ERR, $errlog) ) { mtr_warning("can't read $errlog"); @@ -287,10 +288,14 @@ sub mtr_report_stats ($) { { next; # Skip these lines } + if ( /CURRENT_TEST: (.*)/ ) + { + $testname= $1; + } if ( /$pattern/ ) { $found_problems= 1; - print WARN basename($errlog) . ": $_"; + print WARN basename($errlog) . ": $testname: $_"; } } }