mirror of
https://github.com/MariaDB/server.git
synced 2025-01-19 05:22:25 +01:00
7e5cf52c3e
Backporting BUG#43789 to mysql-5.1-bugteam The replication was generating corrupted data, warning messages on Valgrind and aborting on debug mode while replicating a "null" to "not null" field. Specifically the unpack_row routine, was considering the slave's table definition and trying to retrieve a field value, where there was nothing to be retrieved, ignoring the fact that the value was defined as "null" by the master. To fix the problem, we proceed as follows: 1 - If it is not STRICT sql_mode, implicit default values are used, regardless if it is multi-row or single-row statement. 2 - However, if it is STRICT mode, then a we do what follows: 2.1 If it is a transactional engine, we do a rollback on the first NULL that is to be set into a NOT NULL column and return an error. 2.2 If it is a non-transactional engine and it is the first row to be inserted with multi-row, we also return the error. Otherwise, we proceed with the execution, use implicit default values and print out warning messages. Unfortunately, the current patch cannot mimic the behavior showed by the master for updates on multi-tables and multi-row inserts. This happens because such statements are unfolded in different row events. For instance, considering the following updates and strict mode: (master) create table t1 (a int); create table t2 (a int not null); insert into t1 values (1); insert into t2 values (2); update t1, t2 SET t1.a=10, t2.a=NULL; t1 would have (10) and t2 would have (0) as this would be handled as a multi-row update. On the other hand, if we had the following updates: (master) create table t1 (a int); create table t2 (a int); (slave) create table t1 (a int); create table t2 (a int not null); (master) insert into t1 values (1); insert into t2 values (2); update t1, t2 SET t1.a=10, t2.a=NULL; On the master t1 would have (10) and t2 would have (NULL). On the slave, t1 would have (10) but the update on t1 would fail.
364 lines
10 KiB
Text
364 lines
10 KiB
Text
#################################################################################
|
|
# This test checks if the replication between "null" fields to either "null"
|
|
# fields or "not null" fields works properly. In the first case, the execution
|
|
# should work fine. In the second case, it may fail according to the sql_mode
|
|
# being used.
|
|
#
|
|
# The test is devided in three main parts:
|
|
#
|
|
# 1 - NULL --> NULL (no failures)
|
|
# 2 - NULL --> NOT NULL ( sql-mode = STRICT and failures)
|
|
# 3 - NULL --> NOT NULL ( sql-mode != STRICT and no failures)
|
|
#
|
|
#################################################################################
|
|
connection master;
|
|
|
|
SET SQL_LOG_BIN= 0;
|
|
eval CREATE TABLE t1(`a` INT, `b` DATE DEFAULT NULL,
|
|
`c` INT DEFAULT NULL,
|
|
PRIMARY KEY(`a`)) ENGINE=$engine DEFAULT CHARSET=LATIN1;
|
|
|
|
eval CREATE TABLE t2(`a` INT, `b` DATE DEFAULT NULL,
|
|
PRIMARY KEY(`a`)) ENGINE=$engine DEFAULT CHARSET=LATIN1;
|
|
|
|
eval CREATE TABLE t3(`a` INT, `b` DATE DEFAULT NULL,
|
|
PRIMARY KEY(`a`)) ENGINE=$engine DEFAULT CHARSET=LATIN1;
|
|
|
|
eval CREATE TABLE t4(`a` INT, `b` DATE DEFAULT NULL,
|
|
`c` INT DEFAULT NULL,
|
|
PRIMARY KEY(`a`)) ENGINE=$engine DEFAULT CHARSET=LATIN1;
|
|
SET SQL_LOG_BIN= 1;
|
|
|
|
connection slave;
|
|
|
|
eval CREATE TABLE t1(`a` INT, `b` DATE DEFAULT NULL,
|
|
`c` INT DEFAULT NULL,
|
|
PRIMARY KEY(`a`)) ENGINE=$engine DEFAULT CHARSET=LATIN1;
|
|
|
|
eval CREATE TABLE t2(`a` INT, `b` DATE DEFAULT NULL,
|
|
PRIMARY KEY(`a`)) ENGINE=$engine DEFAULT CHARSET=LATIN1;
|
|
|
|
eval CREATE TABLE t3(`a` INT, `b` DATE DEFAULT '0000-00-00',
|
|
`c` INT DEFAULT 500,
|
|
PRIMARY KEY(`a`)) ENGINE=$engine DEFAULT CHARSET=LATIN1;
|
|
|
|
eval CREATE TABLE t4(`a` INT, `b` DATE DEFAULT '0000-00-00',
|
|
PRIMARY KEY(`a`)) ENGINE=$engine DEFAULT CHARSET=LATIN1;
|
|
|
|
--echo ************* EXECUTION WITH INSERTS *************
|
|
connection master;
|
|
INSERT INTO t1(a,b,c) VALUES (1, null, 1);
|
|
INSERT INTO t1(a,b,c) VALUES (2,'1111-11-11', 2);
|
|
INSERT INTO t1(a,b) VALUES (3, null);
|
|
INSERT INTO t1(a,c) VALUES (4, 4);
|
|
INSERT INTO t1(a) VALUES (5);
|
|
|
|
INSERT INTO t2(a,b) VALUES (1, null);
|
|
INSERT INTO t2(a,b) VALUES (2,'1111-11-11');
|
|
INSERT INTO t2(a) VALUES (3);
|
|
|
|
INSERT INTO t3(a,b) VALUES (1, null);
|
|
INSERT INTO t3(a,b) VALUES (2,'1111-11-11');
|
|
INSERT INTO t3(a) VALUES (3);
|
|
|
|
INSERT INTO t4(a,b,c) VALUES (1, null, 1);
|
|
INSERT INTO t4(a,b,c) VALUES (2,'1111-11-11', 2);
|
|
INSERT INTO t4(a,b) VALUES (3, null);
|
|
INSERT INTO t4(a,c) VALUES (4, 4);
|
|
INSERT INTO t4(a) VALUES (5);
|
|
|
|
--echo ************* SHOWING THE RESULT SETS WITH INSERTS *************
|
|
sync_slave_with_master;
|
|
|
|
--echo TABLES t1 and t2 must be equal otherwise an error will be thrown.
|
|
let $diff_table_1=master:test.t1;
|
|
let $diff_table_2=slave:test.t1;
|
|
source include/diff_tables.inc;
|
|
|
|
let $diff_table_1=master:test.t2;
|
|
let $diff_table_2=slave:test.t2;
|
|
source include/diff_tables.inc;
|
|
|
|
--echo TABLES t2 and t3 must be different.
|
|
connection master;
|
|
SELECT * FROM t3;
|
|
connection slave;
|
|
SELECT * FROM t3;
|
|
connection master;
|
|
SELECT * FROM t4;
|
|
connection slave;
|
|
SELECT * FROM t4;
|
|
|
|
--echo ************* EXECUTION WITH UPDATES and REPLACES *************
|
|
connection master;
|
|
DELETE FROM t1;
|
|
INSERT INTO t1(a,b,c) VALUES (1,'1111-11-11', 1);
|
|
REPLACE INTO t1(a,b,c) VALUES (2,'1111-11-11', 2);
|
|
UPDATE t1 set b= NULL, c= 300 where a= 1;
|
|
REPLACE INTO t1(a,b,c) VALUES (2, NULL, 300);
|
|
|
|
--echo ************* SHOWING THE RESULT SETS WITH UPDATES and REPLACES *************
|
|
sync_slave_with_master;
|
|
|
|
--echo TABLES t1 and t2 must be equal otherwise an error will be thrown.
|
|
let $diff_table_1=master:test.t1;
|
|
let $diff_table_2=slave:test.t1;
|
|
source include/diff_tables.inc;
|
|
|
|
--echo ************* CLEANING *************
|
|
connection master;
|
|
|
|
DROP TABLE t1;
|
|
DROP TABLE t2;
|
|
DROP TABLE t3;
|
|
DROP TABLE t4;
|
|
|
|
sync_slave_with_master;
|
|
|
|
connection master;
|
|
|
|
SET SQL_LOG_BIN= 0;
|
|
eval CREATE TABLE t1 (`a` INT, `b` BIT DEFAULT NULL, `c` BIT DEFAULT NULL,
|
|
PRIMARY KEY (`a`)) ENGINE= $engine;
|
|
SET SQL_LOG_BIN= 1;
|
|
|
|
connection slave;
|
|
|
|
eval CREATE TABLE t1 (`a` INT, `b` BIT DEFAULT b'01', `c` BIT DEFAULT NULL,
|
|
PRIMARY KEY (`a`)) ENGINE= $engine;
|
|
|
|
--echo ************* EXECUTION WITH INSERTS *************
|
|
connection master;
|
|
INSERT INTO t1(a,b,c) VALUES (1, null, b'01');
|
|
INSERT INTO t1(a,b,c) VALUES (2,b'00', b'01');
|
|
INSERT INTO t1(a,b) VALUES (3, null);
|
|
INSERT INTO t1(a,c) VALUES (4, b'01');
|
|
INSERT INTO t1(a) VALUES (5);
|
|
|
|
--echo ************* SHOWING THE RESULT SETS WITH INSERTS *************
|
|
--echo TABLES t1 and t2 must be different.
|
|
sync_slave_with_master;
|
|
connection master;
|
|
SELECT a,b+0,c+0 FROM t1;
|
|
connection slave;
|
|
SELECT a,b+0,c+0 FROM t1;
|
|
|
|
--echo ************* EXECUTION WITH UPDATES and REPLACES *************
|
|
connection master;
|
|
DELETE FROM t1;
|
|
INSERT INTO t1(a,b,c) VALUES (1,b'00', b'01');
|
|
REPLACE INTO t1(a,b,c) VALUES (2,b'00',b'01');
|
|
UPDATE t1 set b= NULL, c= b'00' where a= 1;
|
|
REPLACE INTO t1(a,b,c) VALUES (2, NULL, b'00');
|
|
|
|
--echo ************* SHOWING THE RESULT SETS WITH UPDATES and REPLACES *************
|
|
--echo TABLES t1 and t2 must be equal otherwise an error will be thrown.
|
|
sync_slave_with_master;
|
|
let $diff_table_1=master:test.t1;
|
|
let $diff_table_2=slave:test.t1;
|
|
source include/diff_tables.inc;
|
|
|
|
connection master;
|
|
|
|
DROP TABLE t1;
|
|
|
|
sync_slave_with_master;
|
|
|
|
--echo ################################################################################
|
|
--echo # NULL ---> NOT NULL (STRICT MODE)
|
|
--echo # UNCOMMENT THIS AFTER FIXING BUG#43992
|
|
--echo ################################################################################
|
|
#connection slave;
|
|
#SET GLOBAL sql_mode="TRADITIONAL";
|
|
#
|
|
#STOP SLAVE;
|
|
#--source include/wait_for_slave_to_stop.inc
|
|
#START SLAVE;
|
|
#--source include/wait_for_slave_to_start.inc
|
|
#
|
|
#let $y=0;
|
|
#while (`select $y < 6`)
|
|
#{
|
|
# connection master;
|
|
#
|
|
# SET SQL_LOG_BIN= 0;
|
|
# eval CREATE TABLE t1(`a` INT NOT NULL, `b` INT,
|
|
# PRIMARY KEY(`a`)) ENGINE=$engine DEFAULT CHARSET=LATIN1;
|
|
# eval CREATE TABLE t2(`a` INT NOT NULL, `b` INT,
|
|
# PRIMARY KEY(`a`)) ENGINE=$engine DEFAULT CHARSET=LATIN1;
|
|
# eval CREATE TABLE t3(`a` INT NOT NULL, `b` INT,
|
|
# PRIMARY KEY(`a`)) ENGINE=$engine DEFAULT CHARSET=LATIN1;
|
|
# SET SQL_LOG_BIN= 1;
|
|
#
|
|
# connection slave;
|
|
#
|
|
# eval CREATE TABLE t1(`a` INT NOT NULL, `b` INT NOT NULL,
|
|
# `c` INT NOT NULL,
|
|
# PRIMARY KEY(`a`)) ENGINE=$engine DEFAULT CHARSET=LATIN1;
|
|
# eval CREATE TABLE t2(`a` INT NOT NULL, `b` INT NOT NULL,
|
|
# `c` INT,
|
|
# PRIMARY KEY(`a`)) ENGINE=$engine DEFAULT CHARSET=LATIN1;
|
|
# eval CREATE TABLE t3(`a` INT NOT NULL, `b` INT NOT NULL,
|
|
# `c` INT DEFAULT 500,
|
|
# PRIMARY KEY(`a`)) ENGINE=$engine DEFAULT CHARSET=LATIN1;
|
|
#
|
|
# if (`select $y=0`)
|
|
# {
|
|
# --echo ************* EXECUTION WITH INSERTS *************
|
|
# connection master;
|
|
# INSERT INTO t1(a) VALUES (1);
|
|
# }
|
|
#
|
|
# if (`select $y=1`)
|
|
# {
|
|
# --echo ************* EXECUTION WITH INSERTS *************
|
|
# connection master;
|
|
# INSERT INTO t1(a, b) VALUES (1, NULL);
|
|
# }
|
|
#
|
|
# if (`select $y=2`)
|
|
# {
|
|
# --echo ************* EXECUTION WITH UPDATES *************
|
|
# connection master;
|
|
# INSERT INTO t3(a, b) VALUES (1, 1);
|
|
# INSERT INTO t3(a, b) VALUES (2, 1);
|
|
# UPDATE t3 SET b = NULL where a= 1;
|
|
# }
|
|
#
|
|
# if (`select $y=3`)
|
|
# {
|
|
# --echo ************* EXECUTION WITH INSERTS/REPLACES *************
|
|
# connection master;
|
|
# REPLACE INTO t3(a, b) VALUES (1, null);
|
|
# }
|
|
#
|
|
# if (`select $y=4`)
|
|
# {
|
|
# --echo ************* EXECUTION WITH UPDATES/REPLACES *************
|
|
# connection master;
|
|
# INSERT INTO t3(a, b) VALUES (1, 1);
|
|
# REPLACE INTO t3(a, b) VALUES (1, null);
|
|
# }
|
|
#
|
|
# if (`select $y=5`)
|
|
# {
|
|
# --echo ************* EXECUTION WITH MULTI-ROW INSERTS *************
|
|
# connection master;
|
|
#
|
|
# SET SQL_LOG_BIN= 0;
|
|
# INSERT INTO t2(a, b) VALUES (1, 1);
|
|
# INSERT INTO t2(a, b) VALUES (2, 1);
|
|
# INSERT INTO t2(a, b) VALUES (3, null);
|
|
# INSERT INTO t2(a, b) VALUES (4, 1);
|
|
# INSERT INTO t2(a, b) VALUES (5, 1);
|
|
# SET SQL_LOG_BIN= 1;
|
|
#
|
|
# INSERT INTO t2 SELECT a + 10, b from t2;
|
|
# --echo The statement below is just executed to stop processing
|
|
# INSERT INTO t1(a) VALUES (1);
|
|
# }
|
|
#
|
|
# --echo ************* SHOWING THE RESULT SETS *************
|
|
# connection slave;
|
|
# --source include/wait_for_slave_sql_to_stop.inc
|
|
# connection master;
|
|
# SELECT * FROM t1;
|
|
# connection slave;
|
|
# SELECT * FROM t1;
|
|
# connection master;
|
|
# SELECT * FROM t2;
|
|
# connection slave;
|
|
# SELECT * FROM t2;
|
|
# connection master;
|
|
# SELECT * FROM t3;
|
|
# connection slave;
|
|
# SELECT * FROM t3;
|
|
# --source include/reset_master_and_slave.inc
|
|
#
|
|
# connection master;
|
|
#
|
|
# DROP TABLE t1;
|
|
# DROP TABLE t2;
|
|
# DROP TABLE t3;
|
|
#
|
|
# sync_slave_with_master;
|
|
#
|
|
# inc $y;
|
|
#}
|
|
#connection slave;
|
|
#SET GLOBAL sql_mode="";
|
|
#
|
|
#STOP SLAVE;
|
|
#source include/wait_for_slave_to_stop.inc;
|
|
#START SLAVE;
|
|
#--source include/wait_for_slave_to_start.inc
|
|
|
|
--echo ################################################################################
|
|
--echo # NULL ---> NOT NULL (NON-STRICT MODE)
|
|
--echo ################################################################################
|
|
connection master;
|
|
|
|
SET SQL_LOG_BIN= 0;
|
|
eval CREATE TABLE t1(`a` INT NOT NULL, `b` INT,
|
|
PRIMARY KEY(`a`)) ENGINE=$engine DEFAULT CHARSET=LATIN1;
|
|
eval CREATE TABLE t2(`a` INT NOT NULL, `b` INT,
|
|
PRIMARY KEY(`a`)) ENGINE=$engine DEFAULT CHARSET=LATIN1;
|
|
eval CREATE TABLE t3(`a` INT NOT NULL, `b` INT,
|
|
PRIMARY KEY(`a`)) ENGINE=$engine DEFAULT CHARSET=LATIN1;
|
|
SET SQL_LOG_BIN= 1;
|
|
|
|
connection slave;
|
|
|
|
eval CREATE TABLE t1(`a` INT NOT NULL, `b` INT NOT NULL,
|
|
`c` INT NOT NULL,
|
|
PRIMARY KEY(`a`)) ENGINE=$engine DEFAULT CHARSET=LATIN1;
|
|
eval CREATE TABLE t2(`a` INT NOT NULL, `b` INT NOT NULL,
|
|
`c` INT,
|
|
PRIMARY KEY(`a`)) ENGINE=$engine DEFAULT CHARSET=LATIN1;
|
|
eval CREATE TABLE t3(`a` INT NOT NULL, `b` INT NOT NULL,
|
|
`c` INT DEFAULT 500,
|
|
PRIMARY KEY(`a`)) ENGINE=$engine DEFAULT CHARSET=LATIN1;
|
|
|
|
--echo ************* EXECUTION WITH INSERTS *************
|
|
connection master;
|
|
INSERT INTO t1(a) VALUES (1);
|
|
INSERT INTO t1(a, b) VALUES (2, NULL);
|
|
INSERT INTO t1(a, b) VALUES (3, 1);
|
|
|
|
INSERT INTO t2(a) VALUES (1);
|
|
INSERT INTO t2(a, b) VALUES (2, NULL);
|
|
INSERT INTO t2(a, b) VALUES (3, 1);
|
|
|
|
INSERT INTO t3(a) VALUES (1);
|
|
INSERT INTO t3(a, b) VALUES (2, NULL);
|
|
INSERT INTO t3(a, b) VALUES (3, 1);
|
|
INSERT INTO t3(a, b) VALUES (4, 1);
|
|
REPLACE INTO t3(a, b) VALUES (5, null);
|
|
|
|
REPLACE INTO t3(a, b) VALUES (3, null);
|
|
UPDATE t3 SET b = NULL where a = 4;
|
|
|
|
--echo ************* SHOWING THE RESULT SETS *************
|
|
connection master;
|
|
sync_slave_with_master;
|
|
|
|
connection master;
|
|
SELECT * FROM t1;
|
|
connection slave;
|
|
SELECT * FROM t1;
|
|
connection master;
|
|
SELECT * FROM t2;
|
|
connection slave;
|
|
SELECT * FROM t2;
|
|
connection master;
|
|
SELECT * FROM t3;
|
|
connection slave;
|
|
SELECT * FROM t3;
|
|
|
|
connection master;
|
|
|
|
DROP TABLE t1;
|
|
DROP TABLE t2;
|
|
DROP TABLE t3;
|
|
|
|
sync_slave_with_master;
|