Commit 92c7521f authored by John H. Embretsen's avatar John H. Embretsen

Merge fix for bug 52060 into tip of 5.1-bugteam.

parents 3d89b669 2758847b
...@@ -3,26 +3,53 @@ ...@@ -3,26 +3,53 @@
# The common part of the "rpl_get_master_version_and_clock" test. # The common part of the "rpl_get_master_version_and_clock" test.
# Restart slave under network disconnection between slave and master # Restart slave under network disconnection between slave and master
# following the steps: # following the steps:
# 1 - Got DBUG_SYNC_POINT lock # 0 - Set DEBUG_SYNC_ACTION to wait
# 2 - Set DBUG_SYNC_POINT before call mysql_real_query(...) function in get_master_version_and_clock(...) function and hang here # before call mysql_real_query(...) function in get_master_version_and_clock(...)
# 3 - shutdown master server for simulating network disconnection # function and hang here
# 4 - Release DBUG_SYNC_POINT lock # 1 - activate a sync-point through the $dbug_sync_point argument of the test
# 5 - Check if the slave I/O thread tries to reconnect to master. # 2 - shutdown master server for simulating network disconnection
# 3 - signal to the IO thread through $debug_sync_action to unhold from the sync-point
# 4 - check if the slave I/O thread tries to reconnect to master.
# #
# Note: Please make sure initialize the $debug_lock when call the test script. # Note: make sure to initialize the $debug_sync_action and $dbug_sync_point
# before calling the test script.
# #
# Pattern of usage:
#
# The caller test supplies the DBUG_EXECUTE_IF name
#
# let $dbug_sync_point = 'dbug_execute_if_name';
#
# as well as the action list for DEBUG_SYNC
#
# let $debug_sync_action= 'now signal signal_name';
#
# The $dbug_sync_point becomes the value of @@global.debug generating
# a newly started IO-slave thread's session value.
# Notice incremental operations to add and remove dbug_execute_if_name
# from the global variable allows propagation more dbug arguments
# out of mtr.
# The action list is to fire at proper time according to test logics
# (see pp 0-4 above).
#
connection slave; connection slave;
if (`SELECT '$debug_lock' = ''`) if (`SELECT $debug_sync_action = ''`)
{ {
--die Cannot continue. Please set value for $debug_lock. --die Cannot continue. Please set value for debug_sync_action.
} }
# Restart slave # Restart slave
--disable_warnings --disable_warnings
stop slave; stop slave;
source include/wait_for_slave_to_stop.inc; source include/wait_for_slave_to_stop.inc;
eval SET @@global.debug= "+d,$dbug_sync_point";
start slave; start slave;
source include/wait_for_slave_to_start.inc; source include/wait_for_slave_to_start.inc;
--echo slave is going to hang in get_master_version_and_clock
connection master; connection master;
# Write file to make mysql-test-run.pl expect the "crash", but don't start # Write file to make mysql-test-run.pl expect the "crash", but don't start
# it until it's told to # it until it's told to
...@@ -35,7 +62,9 @@ EOF ...@@ -35,7 +62,9 @@ EOF
shutdown_server 10; shutdown_server 10;
connection slave; connection slave;
eval SELECT RELEASE_LOCK($debug_lock); --echo slave is unblocked
eval SET DEBUG_SYNC=$debug_sync_action;
# Show slave last IO errno # Show slave last IO errno
connection slave; connection slave;
...@@ -53,6 +82,12 @@ if (`SELECT '$last_io_errno' = '2013' || # CR_SERVER_LOST ...@@ -53,6 +82,12 @@ if (`SELECT '$last_io_errno' = '2013' || # CR_SERVER_LOST
--echo NETWORK ERROR --echo NETWORK ERROR
} }
# deactivate the sync point of get_master_version_and_clock()
# now to avoid restarting IO-thread to re-enter it.
# There will be a new IO thread forked out with its @@session.debug
# unset.
eval set @@global.debug = "-d,$dbug_sync_point";
# Write file to make mysql-test-run.pl start up the server again # Write file to make mysql-test-run.pl start up the server again
--append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect --append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
restart restart
......
...@@ -18,11 +18,13 @@ EXPLAIN ...@@ -18,11 +18,13 @@ EXPLAIN
SELECT MIN( a ) FROM t1 WHERE a < NULL; SELECT MIN( a ) FROM t1 WHERE a < NULL;
SELECT MIN( a ) FROM t1 WHERE a < NULL; SELECT MIN( a ) FROM t1 WHERE a < NULL;
if (!$skip_null_safe_test)
{
--replace_column 1 x 2 x 3 x 4 x 5 x 6 x 7 x 8 x 9 x --replace_column 1 x 2 x 3 x 4 x 5 x 6 x 7 x 8 x 9 x
EXPLAIN EXPLAIN
SELECT MIN( a ) FROM t1 WHERE a <=> NULL; SELECT MIN( a ) FROM t1 WHERE a <=> NULL;
SELECT MIN( a ) FROM t1 WHERE a <=> NULL; SELECT MIN( a ) FROM t1 WHERE a <=> NULL;
}
--replace_column 1 x 2 x 3 x 4 x 5 x 6 x 7 x 8 x 9 x --replace_column 1 x 2 x 3 x 4 x 5 x 6 x 7 x 8 x 9 x
EXPLAIN EXPLAIN
SELECT MIN( a ) FROM t1 WHERE a BETWEEN NULL AND 10; SELECT MIN( a ) FROM t1 WHERE a BETWEEN NULL AND 10;
......
...@@ -2691,6 +2691,17 @@ DROP TABLE t1; ...@@ -2691,6 +2691,17 @@ DROP TABLE t1;
## Test for NOT NULLs ## Test for NOT NULLs
CREATE TABLE t1 ( a INT NOT NULL PRIMARY KEY); CREATE TABLE t1 ( a INT NOT NULL PRIMARY KEY);
INSERT INTO t1 VALUES (1), (2), (3); INSERT INTO t1 VALUES (1), (2), (3);
#
# NULL-safe operator test disabled for non-NULL indexed columns.
#
# See bugs
#
# - Bug#52173: Reading NULL value from non-NULL index gives
# wrong result in embedded server
#
# - Bug#52174: Sometimes wrong plan when reading a MAX value from
# non-NULL index
#
EXPLAIN EXPLAIN
SELECT MIN( a ) FROM t1 WHERE a = NULL; SELECT MIN( a ) FROM t1 WHERE a = NULL;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
...@@ -2720,13 +2731,6 @@ SELECT MIN( a ) FROM t1 WHERE a < NULL; ...@@ -2720,13 +2731,6 @@ SELECT MIN( a ) FROM t1 WHERE a < NULL;
MIN( a ) MIN( a )
NULL NULL
EXPLAIN EXPLAIN
SELECT MIN( a ) FROM t1 WHERE a <=> NULL;
id select_type table type possible_keys key key_len ref rows Extra
x x x x x x x x x No matching min/max row
SELECT MIN( a ) FROM t1 WHERE a <=> NULL;
MIN( a )
NULL
EXPLAIN
SELECT MIN( a ) FROM t1 WHERE a BETWEEN NULL AND 10; SELECT MIN( a ) FROM t1 WHERE a BETWEEN NULL AND 10;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
x x x x x x x x x Impossible WHERE noticed after reading const tables x x x x x x x x x Impossible WHERE noticed after reading const tables
......
...@@ -450,4 +450,39 @@ HAVING amount > 0 ...@@ -450,4 +450,39 @@ HAVING amount > 0
ORDER BY t1.id1; ORDER BY t1.id1;
id1 amount id1 amount
DROP TABLE t1; DROP TABLE t1;
#
# Bug#48916 Server incorrectly processing HAVING clauses with an ORDER BY clause
#
CREATE TABLE t1 (f1 INT PRIMARY KEY, f2 INT, f3 INT);
INSERT INTO t1 VALUES (2,7,9), (4,7,9), (6,2,9), (17,0,9);
SELECT table1.f1, table2.f2
FROM t1 AS table1
JOIN t1 AS table2 ON table1.f3 = table2.f3
WHERE table2.f1 = 2
GROUP BY table1.f1, table2.f2
HAVING (table2.f2 = 8 AND table1.f1 >= 6);
f1 f2
EXPLAIN EXTENDED
SELECT table1.f1, table2.f2
FROM t1 AS table1
JOIN t1 AS table2 ON table1.f3 = table2.f3
WHERE table2.f1 = 2
GROUP BY table1.f1, table2.f2
HAVING (table2.f2 = 8 AND table1.f1 >= 6);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible HAVING noticed after reading const tables
Warnings:
Note 1003 select `test`.`table1`.`f1` AS `f1`,'7' AS `f2` from `test`.`t1` `table1` join `test`.`t1` `table2` where ((`test`.`table1`.`f3` = '9')) group by `test`.`table1`.`f1`,'7' having (('7' = 8) and (`test`.`table1`.`f1` >= 6))
EXPLAIN EXTENDED
SELECT table1.f1, table2.f2
FROM t1 AS table1
JOIN t1 AS table2 ON table1.f3 = table2.f3
WHERE table2.f1 = 2
GROUP BY table1.f1, table2.f2
HAVING (table2.f2 = 8);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible HAVING noticed after reading const tables
Warnings:
Note 1003 select `test`.`table1`.`f1` AS `f1`,'7' AS `f2` from `test`.`t1` `table1` join `test`.`t1` `table2` where ((`test`.`table1`.`f3` = '9')) group by `test`.`table1`.`f1`,'7' having ('7' = 8)
DROP TABLE t1;
End of 5.0 tests End of 5.0 tests
...@@ -1289,3 +1289,23 @@ a COUNT( t2.b ) SUM( t2.b ) MAX( t2.b ) ...@@ -1289,3 +1289,23 @@ a COUNT( t2.b ) SUM( t2.b ) MAX( t2.b )
1 3 6 3 1 3 6 3
NULL 3 6 3 NULL 3 6 3
DROP TABLE t1, t2; DROP TABLE t1, t2;
#
# Bug#51598 Inconsistent behaviour with a COALESCE statement inside an IN comparison
#
CREATE TABLE t1(f1 INT, f2 INT, f3 INT);
INSERT INTO t1 VALUES (1, NULL, 3);
CREATE TABLE t2(f1 INT, f2 INT);
INSERT INTO t2 VALUES (2, 1);
EXPLAIN EXTENDED SELECT * FROM t1 LEFT JOIN t2 ON t1.f2 = t2.f2
WHERE (COALESCE(t1.f1, t2.f1), f3) IN ((1, 3), (2, 2));
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 system NULL NULL NULL NULL 1 100.00
1 SIMPLE t2 system NULL NULL NULL NULL 1 100.00
Warnings:
Note 1003 select '1' AS `f1`,NULL AS `f2`,'3' AS `f3`,NULL AS `f1`,NULL AS `f2` from `test`.`t1` left join `test`.`t2` on(multiple equal(NULL)) where ((coalesce('1',NULL),'3') in ((1,3),(2,2)))
SELECT * FROM t1 LEFT JOIN t2 ON t1.f2 = t2.f2
WHERE (COALESCE(t1.f1, t2.f1), f3) IN ((1, 3), (2, 2));
f1 f2 f3 f1 f2
1 NULL 3 NULL NULL
DROP TABLE t1, t2;
End of 5.1 tests
...@@ -2286,4 +2286,16 @@ m1 CREATE TABLE `m1` ( ...@@ -2286,4 +2286,16 @@ m1 CREATE TABLE `m1` (
DROP TABLE m1; DROP TABLE m1;
DROP TABLE `test@1`.`t@1`; DROP TABLE `test@1`.`t@1`;
DROP DATABASE `test@1`; DROP DATABASE `test@1`;
#
# Bug#51494c rash with join, explain and 'sounds like' operator
#
CREATE TABLE t1 (a INT) ENGINE=MYISAM;
INSERT INTO t1 VALUES(1);
CREATE TABLE t2 (b INT NOT NULL,c INT,d INT,e BLOB NOT NULL,
KEY idx0 (d, c)) ENGINE=MERGE;
EXPLAIN SELECT * FROM t1 NATURAL RIGHT JOIN
t2 WHERE b SOUNDS LIKE e AND d = 1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
DROP TABLE t2, t1;
End of 5.1 tests End of 5.1 tests
...@@ -309,4 +309,36 @@ yyyy c4 ...@@ -309,4 +309,36 @@ yyyy c4
2069 2069 2069 2069
DROP TABLE t2, t4; DROP TABLE t2, t4;
# #
# Bug #49910: Behavioural change in SELECT/WHERE on YEAR(4) data type
#
CREATE TABLE t1 (y YEAR NOT NULL, s VARCHAR(4));
INSERT INTO t1 (s) VALUES ('bad');
Warnings:
Warning 1364 Field 'y' doesn't have a default value
INSERT INTO t1 (y, s) VALUES (0, 0), (2000, 2000), (2001, 2001);
SELECT * FROM t1 ta, t1 tb WHERE ta.y = tb.y;
y s y s
0000 bad 0000 bad
0000 0 0000 bad
0000 bad 0000 0
0000 0 0000 0
2000 2000 2000 2000
2001 2001 2001 2001
SELECT * FROM t1 WHERE t1.y = 0;
y s
0000 bad
0000 0
SELECT * FROM t1 WHERE t1.y = 2000;
y s
2000 2000
SELECT ta.y AS ta_y, ta.s, tb.y AS tb_y, tb.s FROM t1 ta, t1 tb HAVING ta_y = tb_y;
ta_y s tb_y s
0000 bad 0000 bad
0000 0 0000 bad
0000 bad 0000 0
0000 0 0000 0
2000 2000 2000 2000
2001 2001 2001 2001
DROP TABLE t1;
#
End of 5.1 tests End of 5.1 tests
...@@ -7,34 +7,24 @@ start slave; ...@@ -7,34 +7,24 @@ start slave;
call mtr.add_suppression("Slave I/O: Master command COM_REGISTER_SLAVE failed: .*"); call mtr.add_suppression("Slave I/O: Master command COM_REGISTER_SLAVE failed: .*");
call mtr.add_suppression("Fatal error: The slave I/O thread stops because master and slave have equal MySQL server ids; .*"); call mtr.add_suppression("Fatal error: The slave I/O thread stops because master and slave have equal MySQL server ids; .*");
call mtr.add_suppression("Slave I/O thread .* register on master"); call mtr.add_suppression("Slave I/O thread .* register on master");
SELECT IS_FREE_LOCK("debug_lock.before_get_UNIX_TIMESTAMP");
IS_FREE_LOCK("debug_lock.before_get_UNIX_TIMESTAMP")
1
SELECT GET_LOCK("debug_lock.before_get_UNIX_TIMESTAMP", 1000);
GET_LOCK("debug_lock.before_get_UNIX_TIMESTAMP", 1000)
1
set global debug= 'd,debug_lock.before_get_UNIX_TIMESTAMP';
stop slave; stop slave;
SET @@global.debug= "+d,'debug_lock.before_get_UNIX_TIMESTAMP'";
start slave; start slave;
SELECT RELEASE_LOCK("debug_lock.before_get_UNIX_TIMESTAMP"); slave is going to hang in get_master_version_and_clock
RELEASE_LOCK("debug_lock.before_get_UNIX_TIMESTAMP") slave is unblocked
1 SET DEBUG_SYNC='now SIGNAL signal.get_unix_timestamp';
Check network error happened here Check network error happened here
NETWORK ERROR NETWORK ERROR
SELECT IS_FREE_LOCK("debug_lock.before_get_SERVER_ID"); set @@global.debug = "-d,'debug_lock.before_get_UNIX_TIMESTAMP'";
IS_FREE_LOCK("debug_lock.before_get_SERVER_ID")
1
SELECT GET_LOCK("debug_lock.before_get_SERVER_ID", 1000);
GET_LOCK("debug_lock.before_get_SERVER_ID", 1000)
1
set global debug= 'd,debug_lock.before_get_SERVER_ID';
stop slave; stop slave;
SET @@global.debug= "+d,'debug_lock.before_get_SERVER_ID'";
start slave; start slave;
SELECT RELEASE_LOCK("debug_lock.before_get_SERVER_ID"); slave is going to hang in get_master_version_and_clock
RELEASE_LOCK("debug_lock.before_get_SERVER_ID") slave is unblocked
1 SET DEBUG_SYNC='now SIGNAL signal.get_server_id';
Check network error happened here Check network error happened here
NETWORK ERROR NETWORK ERROR
set @@global.debug = "-d,'debug_lock.before_get_SERVER_ID'";
set global debug= ''; set global debug= '';
reset master; reset master;
include/stop_slave.inc include/stop_slave.inc
...@@ -43,3 +33,4 @@ start slave; ...@@ -43,3 +33,4 @@ start slave;
*** must be having the replicate-same-server-id IO thread error *** *** must be having the replicate-same-server-id IO thread error ***
Slave_IO_Errno= 1593 Slave_IO_Errno= 1593
Slave_IO_Error= Fatal error: The slave I/O thread stops because master and slave have equal MySQL server ids; these ids must be different for replication to work (or the --replicate-same-server-id option must be used on slave but this does not always make sense; please check the manual before using it). Slave_IO_Error= Fatal error: The slave I/O thread stops because master and slave have equal MySQL server ids; these ids must be different for replication to work (or the --replicate-same-server-id option must be used on slave but this does not always make sense; please check the manual before using it).
SET DEBUG_SYNC= 'RESET';
...@@ -4,11 +4,9 @@ reset master; ...@@ -4,11 +4,9 @@ reset master;
reset slave; reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
start slave; start slave;
SET DEBUG_SYNC= 'RESET';
include/stop_slave.inc include/stop_slave.inc
SELECT GET_LOCK("debug_lock.before_get_running_status_yes", 1000); set global debug= 'd,dbug.before_get_running_status_yes';
GET_LOCK("debug_lock.before_get_running_status_yes", 1000)
1
set global debug= 'd,debug_lock.before_get_running_status_yes';
Slave_running, Slave_IO_Running, Slave_SQL_Running, must be OFF, NO, NO in three following queries Slave_running, Slave_IO_Running, Slave_SQL_Running, must be OFF, NO, NO in three following queries
SHOW STATUS LIKE 'Slave_running'; SHOW STATUS LIKE 'Slave_running';
Variable_name Value Variable_name Value
...@@ -22,9 +20,7 @@ Variable_name Value ...@@ -22,9 +20,7 @@ Variable_name Value
Slave_running OFF Slave_running OFF
Slave_IO_Running= No Slave_IO_Running= No
Slave_SQL_Running= No Slave_SQL_Running= No
SELECT RELEASE_LOCK("debug_lock.before_get_running_status_yes"); SET DEBUG_SYNC='now SIGNAL signal.io_thread_let_running';
RELEASE_LOCK("debug_lock.before_get_running_status_yes")
1
Slave_running, Slave_IO_Running, Slave_SQL_Running must be OFF YES NO in three following queries Slave_running, Slave_IO_Running, Slave_SQL_Running must be OFF YES NO in three following queries
SHOW STATUS LIKE 'Slave_running'; SHOW STATUS LIKE 'Slave_running';
Variable_name Value Variable_name Value
...@@ -39,4 +35,5 @@ Slave_running ON ...@@ -39,4 +35,5 @@ Slave_running ON
Slave_IO_Running= Yes Slave_IO_Running= Yes
Slave_SQL_Running= Yes Slave_SQL_Running= Yes
set global debug= ''; set global debug= '';
SET DEBUG_SYNC= 'RESET';
End of tests End of tests
...@@ -16,8 +16,16 @@ ...@@ -16,8 +16,16 @@
source include/master-slave.inc; source include/master-slave.inc;
source include/have_debug.inc; source include/have_debug.inc;
source include/have_debug_sync.inc;
#
# The test is not supposed to have any binglog affairs.
# Hence it's enough it to run only with one binlog format
#
source include/have_binlog_format_mixed.inc;
connection slave; connection slave;
call mtr.add_suppression("Slave I/O: Master command COM_REGISTER_SLAVE failed: .*"); call mtr.add_suppression("Slave I/O: Master command COM_REGISTER_SLAVE failed: .*");
call mtr.add_suppression("Fatal error: The slave I/O thread stops because master and slave have equal MySQL server ids; .*"); call mtr.add_suppression("Fatal error: The slave I/O thread stops because master and slave have equal MySQL server ids; .*");
call mtr.add_suppression("Slave I/O thread .* register on master"); call mtr.add_suppression("Slave I/O thread .* register on master");
...@@ -25,20 +33,16 @@ call mtr.add_suppression("Slave I/O thread .* register on master"); ...@@ -25,20 +33,16 @@ call mtr.add_suppression("Slave I/O thread .* register on master");
#Test case 1: Try to get the value of the UNIX_TIMESTAMP from master under network disconnection #Test case 1: Try to get the value of the UNIX_TIMESTAMP from master under network disconnection
let $debug_saved= `select @@global.debug`; let $debug_saved= `select @@global.debug`;
let $debug_lock= "debug_lock.before_get_UNIX_TIMESTAMP"; # set up two parameters to pass into extra/rpl_tests/rpl_get_master_version_and_clock
eval SELECT IS_FREE_LOCK($debug_lock); let $dbug_sync_point= 'debug_lock.before_get_UNIX_TIMESTAMP';
eval SELECT GET_LOCK($debug_lock, 1000); let $debug_sync_action= 'now SIGNAL signal.get_unix_timestamp';
set global debug= 'd,debug_lock.before_get_UNIX_TIMESTAMP';
source extra/rpl_tests/rpl_get_master_version_and_clock.test; source extra/rpl_tests/rpl_get_master_version_and_clock.test;
#Test case 2: Try to get the value of the SERVER_ID from master under network disconnection #Test case 2: Try to get the value of the SERVER_ID from master under network disconnection
connection slave; connection slave;
let $debug_lock= "debug_lock.before_get_SERVER_ID";
eval SELECT IS_FREE_LOCK($debug_lock);
eval SELECT GET_LOCK($debug_lock, 1000);
set global debug= 'd,debug_lock.before_get_SERVER_ID'; let $dbug_sync_point= 'debug_lock.before_get_SERVER_ID';
let $debug_sync_action= 'now SIGNAL signal.get_server_id';
source extra/rpl_tests/rpl_get_master_version_and_clock.test; source extra/rpl_tests/rpl_get_master_version_and_clock.test;
eval set global debug= '$debug_saved'; eval set global debug= '$debug_saved';
...@@ -62,4 +66,9 @@ let $last_io_error= query_get_value("show slave status", Last_IO_Error, 1); ...@@ -62,4 +66,9 @@ let $last_io_error= query_get_value("show slave status", Last_IO_Error, 1);
echo Slave_IO_Errno= $last_io_errno; echo Slave_IO_Errno= $last_io_errno;
echo Slave_IO_Error= $last_io_error; echo Slave_IO_Error= $last_io_error;
# cleanup
# is not really necessary but avoids mtr post-run env check warnings
SET DEBUG_SYNC= 'RESET';
# End of tests # End of tests
...@@ -5,14 +5,14 @@ ...@@ -5,14 +5,14 @@
# #
source include/master-slave.inc; source include/master-slave.inc;
source include/have_debug.inc; source include/have_debug.inc;
source include/have_debug_sync.inc;
connection slave; connection slave;
SET DEBUG_SYNC= 'RESET';
source include/stop_slave.inc; source include/stop_slave.inc;
let $debug_saved= `select @@global.debug`; let $debug_saved= `select @@global.debug`;
let $debug_lock= "debug_lock.before_get_running_status_yes"; set global debug= 'd,dbug.before_get_running_status_yes'; # to block due-started IO
eval SELECT GET_LOCK($debug_lock, 1000);
set global debug= 'd,debug_lock.before_get_running_status_yes';
# Test 1. Slave is stopped # Test 1. Slave is stopped
...@@ -29,6 +29,12 @@ echo Slave_SQL_Running= $status; ...@@ -29,6 +29,12 @@ echo Slave_SQL_Running= $status;
start slave io_thread; start slave io_thread;
#
# Notice a difference between versions in showing p.2:
# 5.1 has two OFF,ON IO-thread state running state whereas later versions
# have three: OFF,Connecting,ON.
# Hence, 5.1 must display OFF NO NO where as 5.1+ OFF Connecting NO
#
--echo Slave_running, Slave_IO_Running, Slave_SQL_Running must be OFF NO NO in three following queries --echo Slave_running, Slave_IO_Running, Slave_SQL_Running must be OFF NO NO in three following queries
SHOW STATUS LIKE 'Slave_running'; SHOW STATUS LIKE 'Slave_running';
...@@ -40,7 +46,7 @@ echo Slave_SQL_Running= $status; ...@@ -40,7 +46,7 @@ echo Slave_SQL_Running= $status;
# Test 3. The slave IO thread is started and got connected to master # Test 3. The slave IO thread is started and got connected to master
# and SQL thread is still not started # and SQL thread is still not started
eval SELECT RELEASE_LOCK($debug_lock); SET DEBUG_SYNC='now SIGNAL signal.io_thread_let_running'; # unblock IO thread now
let $slave_param= Slave_IO_Running; let $slave_param= Slave_IO_Running;
let $slave_param_value= YES; let $slave_param_value= YES;
source include/wait_for_slave_param.inc; source include/wait_for_slave_param.inc;
...@@ -72,5 +78,5 @@ echo Slave_SQL_Running= $status; ...@@ -72,5 +78,5 @@ echo Slave_SQL_Running= $status;
connection slave; connection slave;
eval set global debug= '$debug_saved'; eval set global debug= '$debug_saved';
SET DEBUG_SYNC= 'RESET';
--echo End of tests --echo End of tests
...@@ -1070,6 +1070,18 @@ DROP TABLE t1; ...@@ -1070,6 +1070,18 @@ DROP TABLE t1;
--echo ## Test for NOT NULLs --echo ## Test for NOT NULLs
CREATE TABLE t1 ( a INT NOT NULL PRIMARY KEY); CREATE TABLE t1 ( a INT NOT NULL PRIMARY KEY);
INSERT INTO t1 VALUES (1), (2), (3); INSERT INTO t1 VALUES (1), (2), (3);
--echo #
--echo # NULL-safe operator test disabled for non-NULL indexed columns.
--echo #
--echo # See bugs
--echo #
--echo # - Bug#52173: Reading NULL value from non-NULL index gives
--echo # wrong result in embedded server
--echo #
--echo # - Bug#52174: Sometimes wrong plan when reading a MAX value from
--echo # non-NULL index
--echo #
--let $skip_null_safe_test= 1
--source include/min_null_cond.inc --source include/min_null_cond.inc
DROP TABLE t1; DROP TABLE t1;
......
...@@ -467,5 +467,35 @@ ORDER BY t1.id1; ...@@ -467,5 +467,35 @@ ORDER BY t1.id1;
DROP TABLE t1; DROP TABLE t1;
--echo #
--echo # Bug#48916 Server incorrectly processing HAVING clauses with an ORDER BY clause
--echo #
CREATE TABLE t1 (f1 INT PRIMARY KEY, f2 INT, f3 INT);
INSERT INTO t1 VALUES (2,7,9), (4,7,9), (6,2,9), (17,0,9);
SELECT table1.f1, table2.f2
FROM t1 AS table1
JOIN t1 AS table2 ON table1.f3 = table2.f3
WHERE table2.f1 = 2
GROUP BY table1.f1, table2.f2
HAVING (table2.f2 = 8 AND table1.f1 >= 6);
EXPLAIN EXTENDED
SELECT table1.f1, table2.f2
FROM t1 AS table1
JOIN t1 AS table2 ON table1.f3 = table2.f3
WHERE table2.f1 = 2
GROUP BY table1.f1, table2.f2
HAVING (table2.f2 = 8 AND table1.f1 >= 6);
EXPLAIN EXTENDED
SELECT table1.f1, table2.f2
FROM t1 AS table1
JOIN t1 AS table2 ON table1.f3 = table2.f3
WHERE table2.f1 = 2
GROUP BY table1.f1, table2.f2
HAVING (table2.f2 = 8);
DROP TABLE t1;
--echo End of 5.0 tests --echo End of 5.0 tests
...@@ -896,3 +896,21 @@ FROM t1 JOIN t2 USING( a ) ...@@ -896,3 +896,21 @@ FROM t1 JOIN t2 USING( a )
GROUP BY t1.a WITH ROLLUP; GROUP BY t1.a WITH ROLLUP;
DROP TABLE t1, t2; DROP TABLE t1, t2;
--echo #
--echo # Bug#51598 Inconsistent behaviour with a COALESCE statement inside an IN comparison
--echo #
CREATE TABLE t1(f1 INT, f2 INT, f3 INT);
INSERT INTO t1 VALUES (1, NULL, 3);
CREATE TABLE t2(f1 INT, f2 INT);
INSERT INTO t2 VALUES (2, 1);
EXPLAIN EXTENDED SELECT * FROM t1 LEFT JOIN t2 ON t1.f2 = t2.f2
WHERE (COALESCE(t1.f1, t2.f1), f3) IN ((1, 3), (2, 2));
SELECT * FROM t1 LEFT JOIN t2 ON t1.f2 = t2.f2
WHERE (COALESCE(t1.f1, t2.f1), f3) IN ((1, 3), (2, 2));
DROP TABLE t1, t2;
--echo End of 5.1 tests
...@@ -1690,4 +1690,19 @@ DROP TABLE m1; ...@@ -1690,4 +1690,19 @@ DROP TABLE m1;
DROP TABLE `test@1`.`t@1`; DROP TABLE `test@1`.`t@1`;
DROP DATABASE `test@1`; DROP DATABASE `test@1`;
--echo #
--echo # Bug#51494c rash with join, explain and 'sounds like' operator
--echo #
CREATE TABLE t1 (a INT) ENGINE=MYISAM;
INSERT INTO t1 VALUES(1);
CREATE TABLE t2 (b INT NOT NULL,c INT,d INT,e BLOB NOT NULL,
KEY idx0 (d, c)) ENGINE=MERGE;
EXPLAIN SELECT * FROM t1 NATURAL RIGHT JOIN
t2 WHERE b SOUNDS LIKE e AND d = 1;
DROP TABLE t2, t1;
--echo End of 5.1 tests --echo End of 5.1 tests
...@@ -133,6 +133,22 @@ SELECT * FROM t4 WHERE yyyy > 123; ...@@ -133,6 +133,22 @@ SELECT * FROM t4 WHERE yyyy > 123;
DROP TABLE t2, t4; DROP TABLE t2, t4;
--echo #
--echo # Bug #49910: Behavioural change in SELECT/WHERE on YEAR(4) data type
--echo #
CREATE TABLE t1 (y YEAR NOT NULL, s VARCHAR(4));
INSERT INTO t1 (s) VALUES ('bad');
INSERT INTO t1 (y, s) VALUES (0, 0), (2000, 2000), (2001, 2001);
SELECT * FROM t1 ta, t1 tb WHERE ta.y = tb.y;
SELECT * FROM t1 WHERE t1.y = 0;
SELECT * FROM t1 WHERE t1.y = 2000;
SELECT ta.y AS ta_y, ta.s, tb.y AS tb_y, tb.s FROM t1 ta, t1 tb HAVING ta_y = tb_y;
DROP TABLE t1;
--echo # --echo #
--echo End of 5.1 tests --echo End of 5.1 tests
...@@ -1903,4 +1903,42 @@ void debug_sync(THD *thd, const char *sync_point_name, size_t name_len) ...@@ -1903,4 +1903,42 @@ void debug_sync(THD *thd, const char *sync_point_name, size_t name_len)
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
/**
Define debug sync action.
@param[in] thd thread handle
@param[in] action_str action string
@return status
@retval FALSE ok
@retval TRUE error
@description
The function is similar to @c debug_sync_eval_action but is
to be called immediately from the server code rather than
to be triggered by setting a value to DEBUG_SYNC system variable.
@note
The input string is copied prior to be fed to
@c debug_sync_eval_action to let the latter modify it.
Caution.
The function allocates in THD::mem_root and therefore
is not recommended to be deployed inside big loops.
*/
bool debug_sync_set_action(THD *thd, const char *action_str, size_t len)
{
bool rc;
char *value;
DBUG_ENTER("debug_sync_set_action");
DBUG_ASSERT(thd);
DBUG_ASSERT(action_str);
value= strmake_root(thd->mem_root, action_str, len);
rc= debug_sync_eval_action(thd, value);
DBUG_RETURN(rc);
}
#endif /* defined(ENABLED_DEBUG_SYNC) */ #endif /* defined(ENABLED_DEBUG_SYNC) */
...@@ -50,6 +50,7 @@ extern void debug_sync_end(void); ...@@ -50,6 +50,7 @@ extern void debug_sync_end(void);
extern void debug_sync_init_thread(THD *thd); extern void debug_sync_init_thread(THD *thd);
extern void debug_sync_end_thread(THD *thd); extern void debug_sync_end_thread(THD *thd);
extern void debug_sync(THD *thd, const char *sync_point_name, size_t name_len); extern void debug_sync(THD *thd, const char *sync_point_name, size_t name_len);
extern bool debug_sync_set_action(THD *thd, const char *action_str, size_t len);
#else /* defined(ENABLED_DEBUG_SYNC) */ #else /* defined(ENABLED_DEBUG_SYNC) */
......
...@@ -1190,12 +1190,21 @@ get_year_value(THD *thd, Item ***item_arg, Item **cache_arg, ...@@ -1190,12 +1190,21 @@ get_year_value(THD *thd, Item ***item_arg, Item **cache_arg,
/* /*
Coerce value to the 19XX form in order to correctly compare Coerce value to the 19XX form in order to correctly compare
YEAR(2) & YEAR(4) types. YEAR(2) & YEAR(4) types.
Here we are converting all item values but YEAR(4) fields since
1) YEAR(4) already has a regular YYYY form and
2) we don't want to convert zero/bad YEAR(4) values to the
value of 2000.
*/ */
if (value < 70) Item *real_item= item->real_item();
value+= 100; if (!(real_item->type() == Item::FIELD_ITEM &&
if (value <= 1900) ((Item_field *)real_item)->field->type() == MYSQL_TYPE_YEAR &&
value+= 1900; ((Item_field *)real_item)->field->field_length == 4))
{
if (value < 70)
value+= 100;
if (value <= 1900)
value+= 1900;
}
/* Convert year to DATETIME of form YYYY-00-00 00:00:00 (YYYY0000000000). */ /* Convert year to DATETIME of form YYYY-00-00 00:00:00 (YYYY0000000000). */
value*= 10000000000LL; value*= 10000000000LL;
......
...@@ -3362,80 +3362,6 @@ longlong Item_master_pos_wait::val_int() ...@@ -3362,80 +3362,6 @@ longlong Item_master_pos_wait::val_int()
return event_count; return event_count;
} }
#ifdef EXTRA_DEBUG
void debug_sync_point(const char* lock_name, uint lock_timeout)
{
THD* thd=current_thd;
User_level_lock* ull;
struct timespec abstime;
size_t lock_name_len;
lock_name_len= strlen(lock_name);
pthread_mutex_lock(&LOCK_user_locks);
if (thd->ull)
{
item_user_lock_release(thd->ull);
thd->ull=0;
}
/*
If the lock has not been aquired by some client, we do not want to
create an entry for it, since we immediately release the lock. In
this case, we will not be waiting, but rather, just waste CPU and
memory on the whole deal
*/
if (!(ull= ((User_level_lock*) hash_search(&hash_user_locks,
(uchar*) lock_name,
lock_name_len))))
{
pthread_mutex_unlock(&LOCK_user_locks);
return;
}
ull->count++;
/*
Structure is now initialized. Try to get the lock.
Set up control struct to allow others to abort locks
*/
thd_proc_info(thd, "User lock");
thd->mysys_var->current_mutex= &LOCK_user_locks;
thd->mysys_var->current_cond= &ull->cond;
set_timespec(abstime,lock_timeout);
while (ull->locked && !thd->killed)
{
int error= pthread_cond_timedwait(&ull->cond, &LOCK_user_locks, &abstime);
if (error == ETIMEDOUT || error == ETIME)
break;
}
if (ull->locked)
{
if (!--ull->count)
delete ull; // Should never happen
}
else
{
ull->locked=1;
ull->set_thread(thd);
thd->ull=ull;
}
pthread_mutex_unlock(&LOCK_user_locks);
pthread_mutex_lock(&thd->mysys_var->mutex);
thd_proc_info(thd, 0);
thd->mysys_var->current_mutex= 0;
thd->mysys_var->current_cond= 0;
pthread_mutex_unlock(&thd->mysys_var->mutex);
pthread_mutex_lock(&LOCK_user_locks);
if (thd->ull)
{
item_user_lock_release(thd->ull);
thd->ull=0;
}
pthread_mutex_unlock(&LOCK_user_locks);
}
#endif
/** /**
Get a user level lock. If the thread has an old lock this is first released. Get a user level lock. If the thread has an old lock this is first released.
......
...@@ -30,7 +30,8 @@ ...@@ -30,7 +30,8 @@
*/ */
Item_row::Item_row(List<Item> &arg): Item_row::Item_row(List<Item> &arg):
Item(), used_tables_cache(0), const_item_cache(1), with_null(0) Item(), used_tables_cache(0), not_null_tables_cache(0),
const_item_cache(1), with_null(0)
{ {
//TODO: think placing 2-3 component items in item (as it done for function) //TODO: think placing 2-3 component items in item (as it done for function)
...@@ -71,6 +72,7 @@ bool Item_row::fix_fields(THD *thd, Item **ref) ...@@ -71,6 +72,7 @@ bool Item_row::fix_fields(THD *thd, Item **ref)
Item *item= *arg; Item *item= *arg;
used_tables_cache |= item->used_tables(); used_tables_cache |= item->used_tables();
const_item_cache&= item->const_item() && !with_null; const_item_cache&= item->const_item() && !with_null;
not_null_tables_cache|= item->not_null_tables();
/* /*
Some subqueries transformations aren't done in the view_prepare_mode thus Some subqueries transformations aren't done in the view_prepare_mode thus
is_null() will fail. So we skip is_null() calculation for CREATE VIEW as is_null() will fail. So we skip is_null() calculation for CREATE VIEW as
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
class Item_row: public Item class Item_row: public Item
{ {
Item **items; Item **items;
table_map used_tables_cache; table_map used_tables_cache, not_null_tables_cache;
uint arg_count; uint arg_count;
bool const_item_cache; bool const_item_cache;
bool with_null; bool with_null;
...@@ -26,6 +26,7 @@ public: ...@@ -26,6 +26,7 @@ public:
Item(), Item(),
items(item->items), items(item->items),
used_tables_cache(item->used_tables_cache), used_tables_cache(item->used_tables_cache),
not_null_tables_cache(0),
arg_count(item->arg_count), arg_count(item->arg_count),
const_item_cache(item->const_item_cache), const_item_cache(item->const_item_cache),
with_null(0) with_null(0)
...@@ -65,6 +66,7 @@ public: ...@@ -65,6 +66,7 @@ public:
bool const_item() const { return const_item_cache; }; bool const_item() const { return const_item_cache; };
enum Item_result result_type() const { return ROW_RESULT; } enum Item_result result_type() const { return ROW_RESULT; }
void update_used_tables(); void update_used_tables();
table_map not_null_tables() const { return not_null_tables_cache; }
virtual void print(String *str, enum_query_type query_type); virtual void print(String *str, enum_query_type query_type);
bool walk(Item_processor processor, bool walk_subquery, uchar *arg); bool walk(Item_processor processor, bool walk_subquery, uchar *arg);
......
...@@ -580,20 +580,6 @@ protected: ...@@ -580,20 +580,6 @@ protected:
/* Used to check GROUP BY list in the MODE_ONLY_FULL_GROUP_BY mode */ /* Used to check GROUP BY list in the MODE_ONLY_FULL_GROUP_BY mode */
#define UNDEF_POS (-1) #define UNDEF_POS (-1)
#ifdef EXTRA_DEBUG
/**
Sync points allow us to force the server to reach a certain line of code
and block there until the client tells the server it is ok to go on.
The client tells the server to block with SELECT GET_LOCK()
and unblocks it with SELECT RELEASE_LOCK(). Used for debugging difficult
concurrency problems
*/
#define DBUG_SYNC_POINT(lock_name,lock_timeout) \
debug_sync_point(lock_name,lock_timeout)
void debug_sync_point(const char* lock_name, uint lock_timeout);
#else
#define DBUG_SYNC_POINT(lock_name,lock_timeout)
#endif /* EXTRA_DEBUG */
/* BINLOG_DUMP options */ /* BINLOG_DUMP options */
......
...@@ -44,6 +44,7 @@ ...@@ -44,6 +44,7 @@
#ifdef HAVE_REPLICATION #ifdef HAVE_REPLICATION
#include "rpl_tblmap.h" #include "rpl_tblmap.h"
#include "debug_sync.h"
#define FLAGSTR(V,F) ((V)&(F)?#F" ":"") #define FLAGSTR(V,F) ((V)&(F)?#F" ":"")
...@@ -981,7 +982,16 @@ static int get_master_version_and_clock(MYSQL* mysql, Master_info* mi) ...@@ -981,7 +982,16 @@ static int get_master_version_and_clock(MYSQL* mysql, Master_info* mi)
unavailable (very old master not supporting UNIX_TIMESTAMP()?). unavailable (very old master not supporting UNIX_TIMESTAMP()?).
*/ */
DBUG_SYNC_POINT("debug_lock.before_get_UNIX_TIMESTAMP", 10); DBUG_EXECUTE_IF("dbug.before_get_UNIX_TIMESTAMP",
{
const char act[]=
"now "
"wait_for signal.get_unix_timestamp";
DBUG_ASSERT(opt_debug_sync_timeout > 0);
DBUG_ASSERT(!debug_sync_set_action(current_thd,
STRING_WITH_LEN(act)));
};);
master_res= NULL; master_res= NULL;
if (!mysql_real_query(mysql, STRING_WITH_LEN("SELECT UNIX_TIMESTAMP()")) && if (!mysql_real_query(mysql, STRING_WITH_LEN("SELECT UNIX_TIMESTAMP()")) &&
(master_res= mysql_store_result(mysql)) && (master_res= mysql_store_result(mysql)) &&
...@@ -1020,7 +1030,15 @@ static int get_master_version_and_clock(MYSQL* mysql, Master_info* mi) ...@@ -1020,7 +1030,15 @@ static int get_master_version_and_clock(MYSQL* mysql, Master_info* mi)
Note: we could have put a @@SERVER_ID in the previous SELECT Note: we could have put a @@SERVER_ID in the previous SELECT
UNIX_TIMESTAMP() instead, but this would not have worked on 3.23 masters. UNIX_TIMESTAMP() instead, but this would not have worked on 3.23 masters.
*/ */
DBUG_SYNC_POINT("debug_lock.before_get_SERVER_ID", 10); DBUG_EXECUTE_IF("dbug.before_get_SERVER_ID",
{
const char act[]=
"now "
"wait_for signal.get_server_id";
DBUG_ASSERT(opt_debug_sync_timeout > 0);
DBUG_ASSERT(!debug_sync_set_action(current_thd,
STRING_WITH_LEN(act)));
};);
master_res= NULL; master_res= NULL;
master_row= NULL; master_row= NULL;
if (!mysql_real_query(mysql, if (!mysql_real_query(mysql,
...@@ -2557,7 +2575,16 @@ pthread_handler_t handle_slave_io(void *arg) ...@@ -2557,7 +2575,16 @@ pthread_handler_t handle_slave_io(void *arg)
connected: connected:
DBUG_SYNC_POINT("debug_lock.before_get_running_status_yes", 10); DBUG_EXECUTE_IF("dbug.before_get_running_status_yes",
{
const char act[]=
"now "
"wait_for signal.io_thread_let_running";
DBUG_ASSERT(opt_debug_sync_timeout > 0);
DBUG_ASSERT(!debug_sync_set_action(thd,
STRING_WITH_LEN(act)));
};);
// TODO: the assignment below should be under mutex (5.0) // TODO: the assignment below should be under mutex (5.0)
mi->slave_running= MYSQL_SLAVE_RUN_CONNECT; mi->slave_running= MYSQL_SLAVE_RUN_CONNECT;
thd->slave_net = &mysql->net; thd->slave_net = &mysql->net;
......
...@@ -1711,7 +1711,6 @@ int log_loaded_block(IO_CACHE* file) ...@@ -1711,7 +1711,6 @@ int log_loaded_block(IO_CACHE* file)
if (mysql_bin_log.write(&b)) if (mysql_bin_log.write(&b))
DBUG_RETURN(1); DBUG_RETURN(1);
lf_info->wrote_create_file= 1; lf_info->wrote_create_file= 1;
DBUG_SYNC_POINT("debug_lock.created_file_event",10);
} }
} }
DBUG_RETURN(0); DBUG_RETURN(0);
......
...@@ -1112,6 +1112,31 @@ JOIN::optimize() ...@@ -1112,6 +1112,31 @@ JOIN::optimize()
{ {
conds=new Item_int((longlong) 0,1); // Always false conds=new Item_int((longlong) 0,1); // Always false
} }
/*
It's necessary to check const part of HAVING cond as
there is a chance that some cond parts may become
const items after make_join_statisctics(for example
when Item is a reference to cost table field from
outer join).
This check is performed only for those conditions
which do not use aggregate functions. In such case
temporary table may not be used and const condition
elements may be lost during further having
condition transformation in JOIN::exec.
*/
if (having && !having->with_sum_func)
{
COND *const_cond= make_cond_for_table(having, const_table_map, 0);
DBUG_EXECUTE("where", print_where(const_cond, "const_having_cond",
QT_ORDINARY););
if (const_cond && !const_cond->val_int())
{
zero_result_cause= "Impossible HAVING noticed after reading const tables";
DBUG_RETURN(0);
}
}
if (make_join_select(this, select, conds)) if (make_join_select(this, select, conds))
{ {
zero_result_cause= zero_result_cause=
...@@ -2943,7 +2968,8 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables_arg, COND *conds, ...@@ -2943,7 +2968,8 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables_arg, COND *conds,
s->quick=select->quick; s->quick=select->quick;
s->needed_reg=select->needed_reg; s->needed_reg=select->needed_reg;
select->quick=0; select->quick=0;
if (records == 0 && s->table->reginfo.impossible_range) if (records == 0 && s->table->reginfo.impossible_range &&
(s->table->file->ha_table_flags() & HA_STATS_RECORDS_IS_EXACT))
{ {
/* /*
Impossible WHERE or ON expression Impossible WHERE or ON expression
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment