Merge 10.3 into 10.4

This commit is contained in:
Marko Mäkelä 2021-01-11 10:35:06 +02:00
commit fd5e103aa4
33 changed files with 1240 additions and 180 deletions

View File

@ -181,7 +181,7 @@ IF(WIN32)
MARK_AS_ADVANCED(SIGNCODE)
IF(SIGNCODE)
SET(SIGNTOOL_PARAMETERS
/a /t http://timestamp.verisign.com/scripts/timstamp.dll
/a /t http://timestamp.globalsign.com/scripts/timstamp.dll
CACHE STRING "parameters for signtool (list)")
FIND_PROGRAM(SIGNTOOL_EXECUTABLE signtool
PATHS "$ENV{ProgramFiles}/Microsoft SDKs/Windows/v7.0A/bin"

View File

@ -9,6 +9,9 @@ CREATE TABLE t1 (f1 INTEGER) Engine=InnoDB;
INSERT INTO t1 VALUES (1), (1);
--connection node_2
--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE NAME LIKE 'test/t1';
--source include/wait_condition.inc
SET SESSION wsrep_OSU_method = "RSU";
--error ER_DUP_ENTRY
ALTER TABLE t1 ADD PRIMARY KEY (f1);

View File

@ -9,6 +9,9 @@ CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1);
--connection node_2
--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE NAME LIKE 'test/t1';
--source include/wait_condition.inc
ALTER TABLE t1 ADD COLUMN f2 INTEGER;
INSERT INTO t1 VALUES (2, 3);

View File

@ -10,6 +10,9 @@ CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1);
--connection node_2
--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE NAME LIKE 'test/t1';
--source include/wait_condition.inc
ALTER TABLE t1 ADD COLUMN f2 INTEGER, LOCK=SHARED;
--connection node_1

View File

@ -14,6 +14,9 @@ CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) Engine=InnoDB;
INSERT INTO t1 VALUES (1);
--connection node_2
--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE NAME LIKE 'test/t1';
--source include/wait_condition.inc
TRUNCATE TABLE t1;
SELECT COUNT(*) = 0 FROM t1;

View File

@ -67,6 +67,9 @@ CREATE TEMPORARY TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
INSERT INTO t1 VALUES (2);
--connection node_2
--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE NAME LIKE 'test/t1';
--source include/wait_condition.inc
TRUNCATE TABLE t1;
SELECT COUNT(*) = 0 FROM t1;

View File

@ -62,3 +62,28 @@ INSERT INTO t1 (i) VALUES (1),(2);
SELECT * FROM t1 WHERE y BETWEEN 2012 AND 2016 FOR UPDATE;
y i b vi
DROP TABLE t1;
#
# MDEV-23632 ALTER TABLE...ADD KEY creates corrupted index on virtual column
#
CREATE TABLE t1(a INT PRIMARY KEY, b INT, g INT GENERATED ALWAYS AS(b)VIRTUAL) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1,1,default);
ALTER TABLE t1 ADD COLUMN c INT;
ALTER TABLE t1 ADD KEY(g);
CHECK TABLE t1;
Table Op Msg_type Msg_text
test.t1 check status OK
SELECT g FROM t1 FORCE INDEX (g);
g
1
DROP TABLE t1;
CREATE TABLE t1(a INT, b INT, g INT GENERATED ALWAYS AS(b)VIRTUAL) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1,1,default);
ALTER TABLE t1 ADD COLUMN c INT PRIMARY KEY;
ALTER TABLE t1 ADD KEY(g);
CHECK TABLE t1;
Table Op Msg_type Msg_text
test.t1 check status OK
SELECT g FROM t1 FORCE INDEX (g);
g
1
DROP TABLE t1;

View File

@ -52,3 +52,23 @@ SELECT * FROM t1 WHERE y BETWEEN 2012 AND 2016 FOR UPDATE;
INSERT INTO t1 (i) VALUES (1),(2);
SELECT * FROM t1 WHERE y BETWEEN 2012 AND 2016 FOR UPDATE;
DROP TABLE t1;
--echo #
--echo # MDEV-23632 ALTER TABLE...ADD KEY creates corrupted index on virtual column
--echo #
CREATE TABLE t1(a INT PRIMARY KEY, b INT, g INT GENERATED ALWAYS AS(b)VIRTUAL) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1,1,default);
ALTER TABLE t1 ADD COLUMN c INT;
ALTER TABLE t1 ADD KEY(g);
CHECK TABLE t1;
SELECT g FROM t1 FORCE INDEX (g);
DROP TABLE t1;
CREATE TABLE t1(a INT, b INT, g INT GENERATED ALWAYS AS(b)VIRTUAL) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1,1,default);
ALTER TABLE t1 ADD COLUMN c INT PRIMARY KEY; # Triggers `new_clustered`
ALTER TABLE t1 ADD KEY(g);
CHECK TABLE t1;
SELECT g FROM t1 FORCE INDEX (g);
DROP TABLE t1;

View File

@ -227,6 +227,7 @@ set global server_audit_logging= on;
disconnect cn1;
drop user user1@localhost;
set global server_audit_events='';
set global server_audit_incl_users='root, plug_dest';
CREATE USER plug IDENTIFIED WITH 'test_plugin_server' AS 'plug_dest';
CREATE USER plug_dest IDENTIFIED BY 'plug_dest_passwd';
connect(localhost,plug,plug_dest,test,MYSQL_PORT,MYSQL_SOCK);
@ -277,7 +278,7 @@ server_audit_file_path
server_audit_file_rotate_now OFF
server_audit_file_rotate_size 1000000
server_audit_file_rotations 9
server_audit_incl_users root
server_audit_incl_users root, plug_dest
server_audit_logging ON
server_audit_mode 1
server_audit_output_type file
@ -431,6 +432,7 @@ TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,proxies_priv,
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,roles_mapping,
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,global_priv,
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'set global server_audit_events=\'\'',0
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'set global server_audit_incl_users=\'root, plug_dest\'',0
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,db,
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,tables_priv,
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,columns_priv,
@ -454,6 +456,7 @@ TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,global_priv,
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'GRANT PROXY ON plug_dest TO plug',0
TIME,HOSTNAME,plug,localhost,ID,0,CONNECT,test,,0
TIME,HOSTNAME,plug,localhost,ID,0,PROXY_CONNECT,test,`plug_dest`@`%`,0
TIME,HOSTNAME,plug,localhost,ID,ID,QUERY,test,'select USER(),CURRENT_USER()',0
TIME,HOSTNAME,plug,localhost,ID,0,DISCONNECT,test,,0
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,db,
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,tables_priv,

View File

@ -173,6 +173,7 @@ source include/wait_until_count_sessions.inc;
drop user user1@localhost;
set global server_audit_events='';
set global server_audit_incl_users='root, plug_dest';
CREATE USER plug IDENTIFIED WITH 'test_plugin_server' AS 'plug_dest';
CREATE USER plug_dest IDENTIFIED BY 'plug_dest_passwd';

View File

@ -0,0 +1,380 @@
include/master-slave.inc
[connection master]
#
# Test case 1: KEY on a virtual column with ON DELETE CASCADE
#
CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1),(2),(3);
CREATE TABLE t2 (id INT NOT NULL PRIMARY KEY,
t1_id INT NOT NULL,
v_col INT AS (t1_id+1) VIRTUAL, KEY (v_col), KEY (t1_id),
CONSTRAINT a FOREIGN KEY (t1_id) REFERENCES t1 (id) ON DELETE CASCADE
) ENGINE=InnoDB;
INSERT INTO t2 VALUES (90,1,NULL);
INSERT INTO t2 VALUES (91,2,default);
DELETE FROM t1 WHERE id=1;
connection slave;
#
# Verify data consistency on slave
#
include/diff_tables.inc [master:test.t1, slave:test.t1]
include/diff_tables.inc [master:test.t2, slave:test.t2]
connection master;
DROP TABLE t2,t1;
connection slave;
#
# Test case 2: Verify "ON DELETE CASCADE" for parent->child->child scenario
# Parent table: users
# Child tables: matchmaking_groups, matchmaking_group_users
# Parent table: matchmaking_groups
# Child tables: matchmaking_group_users, matchmaking_group_maps
#
# Deleting a row from parent table should be reflected in
# child tables.
# matchmaking_groups->matchmaking_group_users->matchmaking_group_maps
# users->matchmaking_group_users->matchmaking_group_maps
#
connection master;
CREATE TABLE users (id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(32) NOT NULL DEFAULT ''
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE matchmaking_groups (
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
host_user_id INT UNSIGNED NOT NULL UNIQUE,
v_col INT AS (host_user_id+1) VIRTUAL, KEY (v_col),
CONSTRAINT FOREIGN KEY (host_user_id) REFERENCES users (id)
ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE matchmaking_group_users (
matchmaking_group_id BIGINT UNSIGNED NOT NULL,
user_id INT UNSIGNED NOT NULL,
v_col1 int as (user_id+1) virtual, KEY (v_col1),
PRIMARY KEY (matchmaking_group_id,user_id),
UNIQUE KEY user_id (user_id),
CONSTRAINT FOREIGN KEY (matchmaking_group_id)
REFERENCES matchmaking_groups (id) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT FOREIGN KEY (user_id)
REFERENCES users (id) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE matchmaking_group_maps (
matchmaking_group_id BIGINT UNSIGNED NOT NULL,
map_id TINYINT UNSIGNED NOT NULL,
v_col2 INT AS (map_id+1) VIRTUAL, KEY (v_col2),
PRIMARY KEY (matchmaking_group_id,map_id),
CONSTRAINT FOREIGN KEY (matchmaking_group_id)
REFERENCES matchmaking_groups (id) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
connection slave;
connection master;
INSERT INTO users VALUES (NULL,'foo'),(NULL,'bar');
INSERT INTO matchmaking_groups VALUES (10,1,default),(11,2,default);
INSERT INTO matchmaking_group_users VALUES (10,1,default),(11,2,default);
INSERT INTO matchmaking_group_maps VALUES (10,55,default),(11,66,default);
DELETE FROM matchmaking_groups WHERE id = 10;
connection slave;
#
# No rows should be returned as ON DELETE CASCASE should have removed
# corresponding rows from child tables. There should not any mismatch
# of 'id' field between parent->child.
#
SELECT * FROM matchmaking_group_users WHERE matchmaking_group_id NOT IN (SELECT id FROM matchmaking_groups);
matchmaking_group_id user_id v_col1
SELECT * FROM matchmaking_group_maps WHERE matchmaking_group_id NOT IN (SELECT id FROM matchmaking_groups);
matchmaking_group_id map_id v_col2
#
# Rows with id=11 should be present
#
SELECT * FROM matchmaking_group_users;
matchmaking_group_id user_id v_col1
11 2 3
SELECT * FROM matchmaking_group_maps;
matchmaking_group_id map_id v_col2
11 66 67
connection master;
DELETE FROM users WHERE id = 2;
connection slave;
#
# No rows should be present in both the child tables
#
SELECT * FROM matchmaking_group_users;
matchmaking_group_id user_id v_col1
SELECT * FROM matchmaking_group_maps;
matchmaking_group_id map_id v_col2
connection master;
DROP TABLE matchmaking_group_maps, matchmaking_group_users, matchmaking_groups, users;
connection slave;
#
# Test case 3: KEY on a virtual column with ON UPDATE CASCADE
#
connection master;
CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY, b INT NOT NULL) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1, 80);
CREATE TABLE t2 (a INT KEY, b INT,
v_col int as (b+1) virtual, KEY (v_col),
CONSTRAINT b FOREIGN KEY (b) REFERENCES t1(a) ON UPDATE CASCADE
) ENGINE=InnoDB;
INSERT INTO t2 VALUES (51, 1, default);
connection slave;
connection master;
UPDATE t1 SET a = 50 WHERE a = 1;
#
# Master: Verify that ON UPDATE CASCADE works fine
# old_row: (51, 1, 2) ON UPDATE New_row: (51, 50, 51)
#
SELECT * FROM t2 WHERE b=50;
a b v_col
51 50 51
connection slave;
#
# Slave: Verify that ON UPDATE CASCADE works fine
# old_row: (51, 1, 2) ON UPDATE New_row: (51, 50, 51)
#
SELECT * FROM t2 WHERE b=50;
a b v_col
51 50 51
connection master;
DROP TABLE t2, t1;
connection slave;
#
# Test case 4: Define triggers on master, their results should be
# replicated as part of row events and they should be
# applied on slave with the default
# slave_run_triggers_for_rbr=NO
#
connection master;
CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY) ENGINE=InnoDB;
CREATE TABLE t2 (count INT NOT NULL) ENGINE=InnoDB;
CREATE TRIGGER trg AFTER INSERT ON t1 FOR EACH ROW INSERT INTO t2 VALUES (1);
INSERT INTO t1 VALUES (2),(3);
connection slave;
SHOW GLOBAL VARIABLES LIKE 'slave_run_triggers_for_rbr';
Variable_name Value
slave_run_triggers_for_rbr NO
#
# As two rows are inserted in table 't1', two rows should get inserted
# into table 't2' as part of trigger.
#
include/assert.inc [Table t2 should have two rows.]
connection master;
DROP TABLE t1,t2;
connection slave;
#
# Test case 5: Define triggers + Foreign Keys on master, their results
# should be replicated as part of row events and master
# and slave should be in sync.
#
connection master;
CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY) ENGINE=InnoDB;
CREATE TABLE t2 (t1_id INT NOT NULL,
v_col INT AS (t1_id+1) VIRTUAL, KEY (v_col), KEY (t1_id),
CONSTRAINT a FOREIGN KEY (t1_id) REFERENCES t1 (id) ON DELETE CASCADE
) ENGINE=InnoDB;
CREATE TABLE t3 (count INT NOT NULL) ENGINE=InnoDB;
CREATE TRIGGER trg AFTER INSERT ON t1 FOR EACH ROW INSERT INTO t3 VALUES (1);
INSERT INTO t1 VALUES (2),(3);
INSERT INTO t2 VALUES (2, default), (3, default);
connection slave;
#
# As two rows are inserted in table 't1', two rows should get inserted
# into table 't3' as part of trigger.
#
include/assert.inc [Table t3 should have two rows.]
#
# Verify ON DELETE CASCASE correctness
#
connection master;
DELETE FROM t1 WHERE id=2;
connection slave;
connection master;
include/diff_tables.inc [master:test.t1, slave:test.t1]
include/diff_tables.inc [master:test.t2, slave:test.t2]
include/diff_tables.inc [master:test.t3, slave:test.t3]
DROP TABLE t3,t2,t1;
connection slave;
#
# Test case 6: Triggers are present only on slave and
# 'slave_run_triggers_for_rbr=NO'
#
connection slave;
SET @save_slave_run_triggers_for_rbr= @@GLOBAL.slave_run_triggers_for_rbr;
SET GLOBAL slave_run_triggers_for_rbr= NO;;
SHOW GLOBAL VARIABLES LIKE '%slave_run_triggers_for_rbr%';
Variable_name Value
slave_run_triggers_for_rbr NO
connection master;
CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY) ENGINE=InnoDB;
CREATE TABLE t2 (t1_id INT NOT NULL,
v_col INT AS (t1_id+1) VIRTUAL, KEY (v_col),
KEY (t1_id), CONSTRAINT a FOREIGN KEY (t1_id) REFERENCES t1 (id) ON DELETE CASCADE
) ENGINE=InnoDB;
CREATE TABLE t3 (count INT NOT NULL) ENGINE=InnoDB;
connection slave;
CREATE TRIGGER trg AFTER INSERT ON t2 FOR EACH ROW INSERT INTO t3 VALUES (1);
connection master;
INSERT INTO t1 VALUES (2),(3);
INSERT INTO t2 VALUES (2, default), (3, default);
connection slave;
#
# Count must be 0
#
include/assert.inc [Table t3 should have zero rows.]
connection master;
DELETE FROM t1 WHERE id=2;
connection slave;
SET GLOBAL slave_run_triggers_for_rbr= @save_slave_run_triggers_for_rbr;
#
# Verify t1, t2 are consistent on slave.
#
include/diff_tables.inc [master:test.t1, slave:test.t1]
include/diff_tables.inc [master:test.t2, slave:test.t2]
connection master;
DROP TABLE t3,t2,t1;
connection slave;
#
# Test case 7: Triggers are present only on slave and
# 'slave_run_triggers_for_rbr=YES'
#
connection slave;
SET @save_slave_run_triggers_for_rbr= @@GLOBAL.slave_run_triggers_for_rbr;
SET GLOBAL slave_run_triggers_for_rbr= YES;;
SHOW GLOBAL VARIABLES LIKE '%slave_run_triggers_for_rbr%';
Variable_name Value
slave_run_triggers_for_rbr YES
connection master;
CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY) ENGINE=InnoDB;
CREATE TABLE t2 (t1_id INT NOT NULL,
v_col INT AS (t1_id+1) VIRTUAL, KEY (v_col),
KEY (t1_id), CONSTRAINT a FOREIGN KEY (t1_id) REFERENCES t1 (id) ON DELETE CASCADE
) ENGINE=InnoDB;
CREATE TABLE t3 (count INT NOT NULL) ENGINE=InnoDB;
connection slave;
CREATE TRIGGER trg AFTER INSERT ON t2 FOR EACH ROW INSERT INTO t3 VALUES (1);
connection master;
INSERT INTO t1 VALUES (2),(3);
INSERT INTO t2 VALUES (2, default), (3, default);
connection slave;
#
# Count must be 2
#
include/assert.inc [Table t3 should have two rows.]
connection master;
DELETE FROM t1 WHERE id=2;
connection slave;
SET GLOBAL slave_run_triggers_for_rbr= @save_slave_run_triggers_for_rbr;
#
# Verify t1, t2 are consistent on slave.
#
include/diff_tables.inc [master:test.t1, slave:test.t1]
include/diff_tables.inc [master:test.t2, slave:test.t2]
connection master;
DROP TABLE t3,t2,t1;
connection slave;
#
# Test case 8: Triggers and Foreign Keys are present only on slave and
# 'slave_run_triggers_for_rbr=NO'
#
connection slave;
SET @save_slave_run_triggers_for_rbr= @@GLOBAL.slave_run_triggers_for_rbr;
SET GLOBAL slave_run_triggers_for_rbr= NO;;
SHOW GLOBAL VARIABLES LIKE '%slave_run_triggers_for_rbr%';
Variable_name Value
slave_run_triggers_for_rbr NO
connection master;
CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY) ENGINE=InnoDB;
SET sql_log_bin=0;
CREATE TABLE t2 (t1_id INT NOT NULL,v_col INT AS (t1_id+1) VIRTUAL) ENGINE=INNODB;
SET sql_log_bin=1;
CREATE TABLE t3 (count INT NOT NULL) ENGINE=InnoDB;
connection slave;
CREATE TABLE t2 (t1_id INT NOT NULL,
v_col INT AS (t1_id+1) VIRTUAL, KEY (v_col), KEY (t1_id),
CONSTRAINT a FOREIGN KEY (t1_id) REFERENCES t1 (id) ON DELETE CASCADE
) ENGINE=InnoDB;
CREATE TRIGGER trg AFTER INSERT ON t2 FOR EACH ROW INSERT INTO t3 VALUES (1);
connection master;
INSERT INTO t1 VALUES (2),(3);
INSERT INTO t2 VALUES (2, default), (3, default);
connection slave;
#
# Count must be 0
#
include/assert.inc [Table t3 should have zero rows.]
connection master;
DELETE FROM t1 WHERE id=2;
# t1: Should have one row
SELECT * FROM t1;
id
3
# t2: Should have two rows
SELECT * FROM t2;
t1_id v_col
2 3
3 4
connection slave;
# t1: Should have one row
SELECT * FROM t1;
id
3
# t2: Should have one row on slave due to ON DELETE CASCASE
SELECT * FROM t2;
t1_id v_col
3 4
SET GLOBAL slave_run_triggers_for_rbr= @save_slave_run_triggers_for_rbr;
connection master;
DROP TABLE t3,t2,t1;
connection slave;
#
# Test case 9: Triggers are Foreign Keys are present only on slave and
# 'slave_run_triggers_for_rbr=YES'
#
connection slave;
SET @save_slave_run_triggers_for_rbr= @@GLOBAL.slave_run_triggers_for_rbr;
SET GLOBAL slave_run_triggers_for_rbr= YES;;
SHOW GLOBAL VARIABLES LIKE '%slave_run_triggers_for_rbr%';
Variable_name Value
slave_run_triggers_for_rbr YES
connection master;
CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY) ENGINE=InnoDB;
SET sql_log_bin=0;
CREATE TABLE t2 (t1_id INT NOT NULL,v_col INT AS (t1_id+1) VIRTUAL) ENGINE=INNODB;
SET sql_log_bin=1;
CREATE TABLE t3 (count INT NOT NULL) ENGINE=InnoDB;
connection slave;
CREATE TABLE t2 (t1_id INT NOT NULL,
v_col INT AS (t1_id+1) VIRTUAL, KEY (v_col), KEY (t1_id),
CONSTRAINT a FOREIGN KEY (t1_id) REFERENCES t1 (id) ON DELETE CASCADE
) ENGINE=InnoDB;
CREATE TRIGGER trg AFTER INSERT ON t2 FOR EACH ROW INSERT INTO t3 VALUES (1);
connection master;
INSERT INTO t1 VALUES (2),(3);
INSERT INTO t2 VALUES (2, default), (3, default);
connection slave;
#
# Count must be 2
#
include/assert.inc [Table t3 should have two rows.]
connection master;
DELETE FROM t1 WHERE id=2;
# t1: Should have one row
SELECT * FROM t1;
id
3
# t2: Should have two rows
SELECT * FROM t2;
t1_id v_col
2 3
3 4
connection slave;
# t1: Should have one row
SELECT * FROM t1;
id
3
# t2: Should have one row on slave due to ON DELETE CASCASE
SELECT * FROM t2;
t1_id v_col
3 4
SET GLOBAL slave_run_triggers_for_rbr= @save_slave_run_triggers_for_rbr;
connection master;
DROP TABLE t3,t2,t1;
connection slave;
include/rpl_end.inc

View File

@ -0,0 +1,425 @@
# ==== Purpose ====
#
# Test verifies that, slave doesn't report any assert on UPDATE or DELETE of
# row which tries to update the virtual columns with associated KEYs.
#
# Test scenarios are listed below.
# 1) KEY on a virtual column with ON DELETE CASCADE
# 2) Verify "ON DELETE CASCADE" for parent->child->child scenario
# 3) KEY on a virtual column with ON UPDATE CASCADE
# 4) Define triggers on master, their results should be replicated
# as part of row events and they should be applied on slave with
# the default slave_run_triggers_for_rbr=NO
# 5) Define triggers + Foreign Keys on master, their results should be
# replicated as part of row events and master and slave should be in sync.
# 6) Triggers are present only on slave and 'slave_run_triggers_for_rbr=NO'
# 7) Triggers are present only on slave and 'slave_run_triggers_for_rbr=YES'
# 8) Triggers and Foreign Keys are present only on slave and
# 'slave_run_triggers_for_rbr=NO'
# 9) Triggers are Foreign Keys are present only on slave and
# 'slave_run_triggers_for_rbr=YES'
#
# ==== References ====
#
# MDEV-23033: All slaves crash once in ~24 hours and loop restart with signal 11
#
--source include/have_binlog_format_row.inc
--source include/have_innodb.inc
--source include/master-slave.inc
--echo #
--echo # Test case 1: KEY on a virtual column with ON DELETE CASCADE
--echo #
CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1),(2),(3);
CREATE TABLE t2 (id INT NOT NULL PRIMARY KEY,
t1_id INT NOT NULL,
v_col INT AS (t1_id+1) VIRTUAL, KEY (v_col), KEY (t1_id),
CONSTRAINT a FOREIGN KEY (t1_id) REFERENCES t1 (id) ON DELETE CASCADE
) ENGINE=InnoDB;
INSERT INTO t2 VALUES (90,1,NULL);
INSERT INTO t2 VALUES (91,2,default);
# Following query results in an assert on slave
DELETE FROM t1 WHERE id=1;
--sync_slave_with_master
--echo #
--echo # Verify data consistency on slave
--echo #
--let $diff_tables= master:test.t1, slave:test.t1
--source include/diff_tables.inc
--let $diff_tables= master:test.t2, slave:test.t2
--source include/diff_tables.inc
--connection master
DROP TABLE t2,t1;
--sync_slave_with_master
--echo #
--echo # Test case 2: Verify "ON DELETE CASCADE" for parent->child->child scenario
--echo # Parent table: users
--echo # Child tables: matchmaking_groups, matchmaking_group_users
--echo # Parent table: matchmaking_groups
--echo # Child tables: matchmaking_group_users, matchmaking_group_maps
--echo #
--echo # Deleting a row from parent table should be reflected in
--echo # child tables.
--echo # matchmaking_groups->matchmaking_group_users->matchmaking_group_maps
--echo # users->matchmaking_group_users->matchmaking_group_maps
--echo #
--connection master
CREATE TABLE users (id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(32) NOT NULL DEFAULT ''
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE matchmaking_groups (
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
host_user_id INT UNSIGNED NOT NULL UNIQUE,
v_col INT AS (host_user_id+1) VIRTUAL, KEY (v_col),
CONSTRAINT FOREIGN KEY (host_user_id) REFERENCES users (id)
ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE matchmaking_group_users (
matchmaking_group_id BIGINT UNSIGNED NOT NULL,
user_id INT UNSIGNED NOT NULL,
v_col1 int as (user_id+1) virtual, KEY (v_col1),
PRIMARY KEY (matchmaking_group_id,user_id),
UNIQUE KEY user_id (user_id),
CONSTRAINT FOREIGN KEY (matchmaking_group_id)
REFERENCES matchmaking_groups (id) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT FOREIGN KEY (user_id)
REFERENCES users (id) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE matchmaking_group_maps (
matchmaking_group_id BIGINT UNSIGNED NOT NULL,
map_id TINYINT UNSIGNED NOT NULL,
v_col2 INT AS (map_id+1) VIRTUAL, KEY (v_col2),
PRIMARY KEY (matchmaking_group_id,map_id),
CONSTRAINT FOREIGN KEY (matchmaking_group_id)
REFERENCES matchmaking_groups (id) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--sync_slave_with_master
--connection master
INSERT INTO users VALUES (NULL,'foo'),(NULL,'bar');
INSERT INTO matchmaking_groups VALUES (10,1,default),(11,2,default);
INSERT INTO matchmaking_group_users VALUES (10,1,default),(11,2,default);
INSERT INTO matchmaking_group_maps VALUES (10,55,default),(11,66,default);
DELETE FROM matchmaking_groups WHERE id = 10;
--sync_slave_with_master
--echo #
--echo # No rows should be returned as ON DELETE CASCASE should have removed
--echo # corresponding rows from child tables. There should not any mismatch
--echo # of 'id' field between parent->child.
--echo #
SELECT * FROM matchmaking_group_users WHERE matchmaking_group_id NOT IN (SELECT id FROM matchmaking_groups);
SELECT * FROM matchmaking_group_maps WHERE matchmaking_group_id NOT IN (SELECT id FROM matchmaking_groups);
--echo #
--echo # Rows with id=11 should be present
--echo #
SELECT * FROM matchmaking_group_users;
SELECT * FROM matchmaking_group_maps;
--connection master
DELETE FROM users WHERE id = 2;
--sync_slave_with_master
--echo #
--echo # No rows should be present in both the child tables
--echo #
SELECT * FROM matchmaking_group_users;
SELECT * FROM matchmaking_group_maps;
--connection master
DROP TABLE matchmaking_group_maps, matchmaking_group_users, matchmaking_groups, users;
--sync_slave_with_master
--echo #
--echo # Test case 3: KEY on a virtual column with ON UPDATE CASCADE
--echo #
--connection master
CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY, b INT NOT NULL) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1, 80);
CREATE TABLE t2 (a INT KEY, b INT,
v_col int as (b+1) virtual, KEY (v_col),
CONSTRAINT b FOREIGN KEY (b) REFERENCES t1(a) ON UPDATE CASCADE
) ENGINE=InnoDB;
INSERT INTO t2 VALUES (51, 1, default);
--sync_slave_with_master
--connection master
UPDATE t1 SET a = 50 WHERE a = 1;
--echo #
--echo # Master: Verify that ON UPDATE CASCADE works fine
--echo # old_row: (51, 1, 2) ON UPDATE New_row: (51, 50, 51)
--echo #
SELECT * FROM t2 WHERE b=50;
--sync_slave_with_master
--echo #
--echo # Slave: Verify that ON UPDATE CASCADE works fine
--echo # old_row: (51, 1, 2) ON UPDATE New_row: (51, 50, 51)
--echo #
SELECT * FROM t2 WHERE b=50;
--connection master
DROP TABLE t2, t1;
--sync_slave_with_master
--echo #
--echo # Test case 4: Define triggers on master, their results should be
--echo # replicated as part of row events and they should be
--echo # applied on slave with the default
--echo # slave_run_triggers_for_rbr=NO
--echo #
# In row-based replication, the binary log contains row changes. It will have
# both the changes made by the statement itself, and the changes made by the
# triggers that were invoked by the statement. Slave server(s) do not need to
# run triggers for row changes they are applying. Hence verify that this
# property remains the same and data should be available as if trigger was
# executed. Please note by default slave_run_triggers_for_rbr=NO.
--connection master
CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY) ENGINE=InnoDB;
CREATE TABLE t2 (count INT NOT NULL) ENGINE=InnoDB;
CREATE TRIGGER trg AFTER INSERT ON t1 FOR EACH ROW INSERT INTO t2 VALUES (1);
INSERT INTO t1 VALUES (2),(3);
--sync_slave_with_master
SHOW GLOBAL VARIABLES LIKE 'slave_run_triggers_for_rbr';
--echo #
--echo # As two rows are inserted in table 't1', two rows should get inserted
--echo # into table 't2' as part of trigger.
--echo #
--let $assert_cond= COUNT(*) = 2 FROM t2
--let $assert_text= Table t2 should have two rows.
--source include/assert.inc
--connection master
DROP TABLE t1,t2;
--sync_slave_with_master
--echo #
--echo # Test case 5: Define triggers + Foreign Keys on master, their results
--echo # should be replicated as part of row events and master
--echo # and slave should be in sync.
--echo #
--connection master
CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY) ENGINE=InnoDB;
CREATE TABLE t2 (t1_id INT NOT NULL,
v_col INT AS (t1_id+1) VIRTUAL, KEY (v_col), KEY (t1_id),
CONSTRAINT a FOREIGN KEY (t1_id) REFERENCES t1 (id) ON DELETE CASCADE
) ENGINE=InnoDB;
CREATE TABLE t3 (count INT NOT NULL) ENGINE=InnoDB;
CREATE TRIGGER trg AFTER INSERT ON t1 FOR EACH ROW INSERT INTO t3 VALUES (1);
INSERT INTO t1 VALUES (2),(3);
INSERT INTO t2 VALUES (2, default), (3, default);
--sync_slave_with_master
--echo #
--echo # As two rows are inserted in table 't1', two rows should get inserted
--echo # into table 't3' as part of trigger.
--echo #
--let $assert_cond= COUNT(*) = 2 FROM t3
--let $assert_text= Table t3 should have two rows.
--source include/assert.inc
--echo #
--echo # Verify ON DELETE CASCASE correctness
--echo #
--connection master
DELETE FROM t1 WHERE id=2;
--sync_slave_with_master
--connection master
--let $diff_tables= master:test.t1, slave:test.t1
--source include/diff_tables.inc
--let $diff_tables= master:test.t2, slave:test.t2
--source include/diff_tables.inc
--let $diff_tables= master:test.t3, slave:test.t3
--source include/diff_tables.inc
DROP TABLE t3,t2,t1;
--sync_slave_with_master
#
# Test case: Triggers only on slave
#
--write_file $MYSQLTEST_VARDIR/tmp/trig_on_slave.inc PROCEDURE
if ($slave_run_triggers_for_rbr == '') {
--die !!!ERROR IN TEST: you must set $slave_run_triggers_for_rbr
}
--connection slave
SET @save_slave_run_triggers_for_rbr= @@GLOBAL.slave_run_triggers_for_rbr;
--eval SET GLOBAL slave_run_triggers_for_rbr= $slave_run_triggers_for_rbr;
SHOW GLOBAL VARIABLES LIKE '%slave_run_triggers_for_rbr%';
--connection master
CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY) ENGINE=InnoDB;
CREATE TABLE t2 (t1_id INT NOT NULL,
v_col INT AS (t1_id+1) VIRTUAL, KEY (v_col),
KEY (t1_id), CONSTRAINT a FOREIGN KEY (t1_id) REFERENCES t1 (id) ON DELETE CASCADE
) ENGINE=InnoDB;
CREATE TABLE t3 (count INT NOT NULL) ENGINE=InnoDB;
--sync_slave_with_master
CREATE TRIGGER trg AFTER INSERT ON t2 FOR EACH ROW INSERT INTO t3 VALUES (1);
--connection master
INSERT INTO t1 VALUES (2),(3);
INSERT INTO t2 VALUES (2, default), (3, default);
--sync_slave_with_master
if ($slave_run_triggers_for_rbr == 'NO') {
--echo #
--echo # Count must be 0
--echo #
--let $assert_cond= COUNT(*) = 0 FROM t3
--let $assert_text= Table t3 should have zero rows.
--source include/assert.inc
}
if ($slave_run_triggers_for_rbr == 'YES') {
--echo #
--echo # Count must be 2
--echo #
--let $assert_cond= COUNT(*) = 2 FROM t3
--let $assert_text= Table t3 should have two rows.
--source include/assert.inc
}
--connection master
DELETE FROM t1 WHERE id=2;
--sync_slave_with_master
SET GLOBAL slave_run_triggers_for_rbr= @save_slave_run_triggers_for_rbr;
--echo #
--echo # Verify t1, t2 are consistent on slave.
--echo #
--let $diff_tables= master:test.t1, slave:test.t1
--source include/diff_tables.inc
--let $diff_tables= master:test.t2, slave:test.t2
--source include/diff_tables.inc
--connection master
DROP TABLE t3,t2,t1;
--sync_slave_with_master
#END OF
PROCEDURE
--echo #
--echo # Test case 6: Triggers are present only on slave and
--echo # 'slave_run_triggers_for_rbr=NO'
--echo #
--let $slave_run_triggers_for_rbr=NO
--source $MYSQLTEST_VARDIR/tmp/trig_on_slave.inc
--echo #
--echo # Test case 7: Triggers are present only on slave and
--echo # 'slave_run_triggers_for_rbr=YES'
--echo #
--let $slave_run_triggers_for_rbr=YES
--source $MYSQLTEST_VARDIR/tmp/trig_on_slave.inc
--remove_file $MYSQLTEST_VARDIR/tmp/trig_on_slave.inc
#
# Test case: Trigger and Foreign Key are present only on slave
#
--write_file $MYSQLTEST_VARDIR/tmp/trig_fk_on_slave.inc PROCEDURE
if ($slave_run_triggers_for_rbr == '') {
--die !!!ERROR IN TEST: you must set $slave_run_triggers_for_rbr
}
--connection slave
SET @save_slave_run_triggers_for_rbr= @@GLOBAL.slave_run_triggers_for_rbr;
--eval SET GLOBAL slave_run_triggers_for_rbr= $slave_run_triggers_for_rbr;
SHOW GLOBAL VARIABLES LIKE '%slave_run_triggers_for_rbr%';
--connection master
CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY) ENGINE=InnoDB;
SET sql_log_bin=0;
CREATE TABLE t2 (t1_id INT NOT NULL,v_col INT AS (t1_id+1) VIRTUAL) ENGINE=INNODB;
SET sql_log_bin=1;
CREATE TABLE t3 (count INT NOT NULL) ENGINE=InnoDB;
--sync_slave_with_master
# Have foreign key and trigger on slave.
CREATE TABLE t2 (t1_id INT NOT NULL,
v_col INT AS (t1_id+1) VIRTUAL, KEY (v_col), KEY (t1_id),
CONSTRAINT a FOREIGN KEY (t1_id) REFERENCES t1 (id) ON DELETE CASCADE
) ENGINE=InnoDB;
CREATE TRIGGER trg AFTER INSERT ON t2 FOR EACH ROW INSERT INTO t3 VALUES (1);
--connection master
INSERT INTO t1 VALUES (2),(3);
INSERT INTO t2 VALUES (2, default), (3, default);
--sync_slave_with_master
if ($slave_run_triggers_for_rbr == 'NO') {
--echo #
--echo # Count must be 0
--echo #
--let $assert_cond= COUNT(*) = 0 FROM t3
--let $assert_text= Table t3 should have zero rows.
--source include/assert.inc
}
if ($slave_run_triggers_for_rbr == 'YES') {
--echo #
--echo # Count must be 2
--echo #
--let $assert_cond= COUNT(*) = 2 FROM t3
--let $assert_text= Table t3 should have two rows.
--source include/assert.inc
}
--connection master
DELETE FROM t1 WHERE id=2;
--echo # t1: Should have one row
SELECT * FROM t1;
--echo # t2: Should have two rows
SELECT * FROM t2;
--sync_slave_with_master
--echo # t1: Should have one row
SELECT * FROM t1;
--echo # t2: Should have one row on slave due to ON DELETE CASCASE
SELECT * FROM t2;
SET GLOBAL slave_run_triggers_for_rbr= @save_slave_run_triggers_for_rbr;
--connection master
DROP TABLE t3,t2,t1;
--sync_slave_with_master
#END OF
PROCEDURE
--echo #
--echo # Test case 8: Triggers and Foreign Keys are present only on slave and
--echo # 'slave_run_triggers_for_rbr=NO'
--echo #
--let $slave_run_triggers_for_rbr=NO
--source $MYSQLTEST_VARDIR/tmp/trig_fk_on_slave.inc
--echo #
--echo # Test case 9: Triggers are Foreign Keys are present only on slave and
--echo # 'slave_run_triggers_for_rbr=YES'
--echo #
--let $slave_run_triggers_for_rbr=YES
--source $MYSQLTEST_VARDIR/tmp/trig_fk_on_slave.inc
--remove_file $MYSQLTEST_VARDIR/tmp/trig_fk_on_slave.inc
--source include/rpl_end.inc

View File

@ -31,8 +31,12 @@ echo [ enable semi-sync on slave ];
stop slave;
set global rpl_semi_sync_slave_enabled = 1;
start slave;
let $status_var= rpl_semi_sync_slave_status;
let $status_var_value= ON;
source include/wait_for_status_var.inc;
show status like 'rpl_semi_sync_slave%';
connection master;
CREATE TABLE t1(a INT) ENGINE=InnoDB;
sync_slave_with_master;
@ -190,6 +194,12 @@ connection con1;
INSERT INTO t1 values (2);
sync_slave_with_master;
connection con1;
let $status_var= Rpl_semi_sync_master_clients;
let $status_var_value= 1;
source include/wait_for_status_var.inc;
let $status_var= Rpl_semi_sync_master_status;
let $status_var_value= ON;
source include/wait_for_status_var.inc;
show status like 'Rpl_semi_sync_master_clients';
show status like 'Rpl_semi_sync_master_status';
@ -259,7 +269,12 @@ START SLAVE IO_THREAD;
--echo #########################################################
connection con1;
SET GLOBAL rpl_semi_sync_master_enabled = 0;
let $status_var= Rpl_semi_sync_master_clients;
let $status_var_value= 1;
source include/wait_for_status_var.inc;
show status like 'Rpl_semi_sync_master_clients';
INSERT INTO t1 VALUES (1);
SET GLOBAL rpl_semi_sync_master_enabled = 1;
INSERT INTO t1 VALUES (2);

View File

@ -538,6 +538,7 @@ set timestamp=1523466002.799571;
insert into t1 values (11),(12);
set timestamp=1523466004.169435;
delete from t1 where pk in (11, 12);
set timestamp= default;
#
# MDEV-18136 Server crashes in Item_func_dyncol_create::prepare_arguments
#
@ -690,6 +691,41 @@ create table t1 (a int) with system versioning partition by system_time
(partition p1 history, partition pn current);
alter table t1 add partition (partition p2);
ERROR HY000: Wrong partitioning type, expected type: `SYSTEM_TIME`
# MDEV-17891 Assertion failures in select_insert::abort_result_set and
# mysql_load upon attempt to replace into a full table
set @@max_heap_table_size= 1024*1024;
create or replace table t1 (
pk integer auto_increment,
primary key (pk),
f varchar(45000)
) with system versioning engine=memory
partition by system_time interval 1 year (partition p1 history,
partition pn current);
# fill the table until full
insert into t1 () values (),(),(),(),(),(),(),(),(),(),(),(),(),(),(),();
insert into t1 (f) select f from t1;
ERROR HY000: The table 't1' is full
# leave space for exactly one record in current partition
delete from t1 where pk = 1;
# copy all data into history partition
replace into t1 select * from t1;
replace into t1 select * from t1;
ERROR HY000: The table 't1' is full
create or replace table t1 (
pk integer auto_increment,
primary key (pk),
f varchar(45000)
) with system versioning engine=memory
partition by system_time interval 1 year (partition p1 history,
partition pn current);
insert into t1 () values (),(),(),(),(),(),(),(),(),(),(),(),(),(),(),();
select * into outfile 'load.data' from t1;
load data infile 'load.data' replace into table t1;
load data infile 'load.data' replace into table t1;
ERROR HY000: The table 't1' is full
load data infile 'load.data' replace into table t1;
ERROR HY000: The table 't1' is full
set @@max_heap_table_size= 1048576;
drop table t1;
#
# MDEV-22178 Assertion `info->alias.str' failed in partition_info::check_partition_info instead of ER_VERS_WRONG_PARTS

View File

@ -48,3 +48,16 @@ INSERT INTO t1 () VALUES (),(),(),(),(),();
UPDATE IGNORE t1 SET f = 1;
REPLACE t1 SELECT * FROM t1;
DROP TABLE t1;
# MDEV-22540 ER_DUP_ENTRY upon REPLACE or Assertion failed
set timestamp=1589245268.41934;
create table t1 (a int primary key) with system versioning;
insert into t1 values (1),(2);
connect con1,localhost,root,,test;
set timestamp=1589245268.52093;
replace into t1 values (1),(2);
connection default;
replace into t1 values (1),(2);
connection con1;
replace into t1 values (1),(2);
ERROR 23000: Duplicate entry '1' for key 'PRIMARY'
drop table t1;

View File

@ -473,6 +473,7 @@ set timestamp=1523466002.799571;
insert into t1 values (11),(12);
set timestamp=1523466004.169435;
delete from t1 where pk in (11, 12);
set timestamp= default;
--echo #
--echo # MDEV-18136 Server crashes in Item_func_dyncol_create::prepare_arguments
@ -640,7 +641,51 @@ create table t1 (a int) with system versioning partition by system_time
--error ER_PARTITION_WRONG_TYPE
alter table t1 add partition (partition p2);
--echo # MDEV-17891 Assertion failures in select_insert::abort_result_set and
--echo # mysql_load upon attempt to replace into a full table
--let $max_heap_table_size_orig= `select @@max_heap_table_size;`
set @@max_heap_table_size= 1024*1024;
create or replace table t1 (
pk integer auto_increment,
primary key (pk),
f varchar(45000)
) with system versioning engine=memory
partition by system_time interval 1 year (partition p1 history,
partition pn current);
--echo # fill the table until full
insert into t1 () values (),(),(),(),(),(),(),(),(),(),(),(),(),(),(),();
--error ER_RECORD_FILE_FULL
insert into t1 (f) select f from t1;
--echo # leave space for exactly one record in current partition
delete from t1 where pk = 1;
--echo # copy all data into history partition
replace into t1 select * from t1;
--error ER_RECORD_FILE_FULL
replace into t1 select * from t1;
create or replace table t1 (
pk integer auto_increment,
primary key (pk),
f varchar(45000)
) with system versioning engine=memory
partition by system_time interval 1 year (partition p1 history,
partition pn current);
insert into t1 () values (),(),(),(),(),(),(),(),(),(),(),(),(),(),(),();
select * into outfile 'load.data' from t1;
load data infile 'load.data' replace into table t1;
--error ER_RECORD_FILE_FULL
load data infile 'load.data' replace into table t1;
--error ER_RECORD_FILE_FULL
load data infile 'load.data' replace into table t1;
# Cleanup
--let $datadir= `select @@datadir`
--remove_file $datadir/test/load.data
eval set @@max_heap_table_size= $max_heap_table_size_orig;
drop table t1;
--echo #

View File

@ -59,4 +59,22 @@ UPDATE IGNORE t1 SET f = 1;
REPLACE t1 SELECT * FROM t1;
DROP TABLE t1;
--echo # MDEV-22540 ER_DUP_ENTRY upon REPLACE or Assertion failed
set timestamp=1589245268.41934;
create table t1 (a int primary key) with system versioning;
insert into t1 values (1),(2);
--connect (con1,localhost,root,,test)
set timestamp=1589245268.52093;
replace into t1 values (1),(2);
--connection default
replace into t1 values (1),(2);
--connection con1
--error ER_DUP_ENTRY
replace into t1 values (1),(2);
drop table t1;
--source suite/versioning/common_finish.inc

View File

@ -1581,22 +1581,27 @@ no_password:
static int do_log_user(const char *name, int take_lock)
static int do_log_user(const char *name, int len,
const char *proxy, int proxy_len, int take_lock)
{
size_t len;
int result;
if (!name)
return 0;
len= strlen(name);
if (take_lock)
flogger_mutex_lock(&lock_operations);
if (incl_user_coll.n_users)
result= coll_search(&incl_user_coll, name, len) != 0;
{
result= coll_search(&incl_user_coll, name, len) != 0 ||
(proxy && coll_search(&incl_user_coll, proxy, proxy_len) != 0);
}
else if (excl_user_coll.n_users)
result= coll_search(&excl_user_coll, name, len) == 0;
{
result= coll_search(&excl_user_coll, name, len) == 0 &&
(proxy && coll_search(&excl_user_coll, proxy, proxy_len) == 0);
}
else
result= 1;
@ -2137,7 +2142,9 @@ void auditing(MYSQL_THD thd, unsigned int event_class, const void *ev)
}
if (event_class == MYSQL_AUDIT_GENERAL_CLASS && FILTER(EVENT_QUERY) &&
cn && (cn->log_always || do_log_user(cn->user, 1)))
cn && (cn->log_always || do_log_user(cn->user, cn->user_length,
cn->proxy, cn->proxy_length,
1)))
{
const struct mysql_event_general *event =
(const struct mysql_event_general *) ev;
@ -2157,7 +2164,8 @@ void auditing(MYSQL_THD thd, unsigned int event_class, const void *ev)
{
const struct mysql_event_table *event =
(const struct mysql_event_table *) ev;
if (do_log_user(event->user, 1))
if (do_log_user(event->user, (int) SAFE_STRLEN(event->user),
cn->proxy, cn->proxy_length, 1))
{
switch (event->event_subclass)
{

View File

@ -11267,7 +11267,7 @@ int Rows_log_event::do_add_row_data(uchar *row_data, size_t length)
There was the same problem with MERGE MYISAM tables and so here we try to
go the same way.
*/
static void restore_empty_query_table_list(LEX *lex)
inline void restore_empty_query_table_list(LEX *lex)
{
if (lex->first_not_own_table())
(*lex->first_not_own_table()->prev_global)= NULL;
@ -11282,6 +11282,8 @@ int Rows_log_event::do_apply_event(rpl_group_info *rgi)
TABLE* table;
DBUG_ENTER("Rows_log_event::do_apply_event(Relay_log_info*)");
int error= 0;
LEX *lex= thd->lex;
uint8 new_trg_event_map= get_trg_event_map();
/*
If m_table_id == ~0ULL, then we have a dummy event that does not
contain any data. In that case, we just remove all tables in the
@ -11372,27 +11374,29 @@ int Rows_log_event::do_apply_event(rpl_group_info *rgi)
DBUG_ASSERT(!debug_sync_set_action(thd, STRING_WITH_LEN(action)));
};);
if (slave_run_triggers_for_rbr)
/*
Trigger's procedures work with global table list. So we have to add
rgi->tables_to_lock content there to get trigger's in the list.
Then restore_empty_query_table_list() restore the list as it was
*/
DBUG_ASSERT(lex->query_tables == NULL);
if ((lex->query_tables= rgi->tables_to_lock))
rgi->tables_to_lock->prev_global= &lex->query_tables;
for (TABLE_LIST *tables= rgi->tables_to_lock; tables;
tables= tables->next_global)
{
LEX *lex= thd->lex;
uint8 new_trg_event_map= get_trg_event_map();
/*
Trigger's procedures work with global table list. So we have to add
rgi->tables_to_lock content there to get trigger's in the list.
Then restore_empty_query_table_list() restore the list as it was
*/
DBUG_ASSERT(lex->query_tables == NULL);
if ((lex->query_tables= rgi->tables_to_lock))
rgi->tables_to_lock->prev_global= &lex->query_tables;
for (TABLE_LIST *tables= rgi->tables_to_lock; tables;
tables= tables->next_global)
if (slave_run_triggers_for_rbr)
{
tables->trg_event_map= new_trg_event_map;
lex->query_tables_last= &tables->next_global;
}
else if (!WSREP_ON)
{
tables->slave_fk_event_map= new_trg_event_map;
lex->query_tables_last= &tables->next_global;
}
}
if (unlikely(open_and_lock_tables(thd, rgi->tables_to_lock, FALSE, 0)))
{
@ -11749,8 +11753,7 @@ int Rows_log_event::do_apply_event(rpl_group_info *rgi)
}
/* remove trigger's tables */
if (slave_run_triggers_for_rbr)
restore_empty_query_table_list(thd->lex);
restore_empty_query_table_list(thd->lex);
#if defined(WITH_WSREP) && defined(HAVE_QUERY_CACHE)
if (WSREP(thd) && wsrep_thd_is_applying(thd))
@ -11769,8 +11772,7 @@ int Rows_log_event::do_apply_event(rpl_group_info *rgi)
DBUG_RETURN(error);
err:
if (slave_run_triggers_for_rbr)
restore_empty_query_table_list(thd->lex);
restore_empty_query_table_list(thd->lex);
rgi->slave_close_thread_tables(thd);
DBUG_RETURN(error);
}

View File

@ -4693,7 +4693,72 @@ add_internal_tables(THD *thd, Query_tables_list *prelocking_ctx,
DBUG_RETURN(FALSE);
}
/**
Extend the table_list to include foreign tables for prelocking.
@param[in] thd Thread context.
@param[in] prelocking_ctx Prelocking context of the statement.
@param[in] table_list Table list element for table.
@param[in] sp Routine body.
@param[out] need_prelocking Set to TRUE if method detects that prelocking
required, not changed otherwise.
@retval FALSE Success.
@retval TRUE Failure (OOM).
*/
inline bool
prepare_fk_prelocking_list(THD *thd, Query_tables_list *prelocking_ctx,
TABLE_LIST *table_list, bool *need_prelocking,
uint8 op)
{
DBUG_ENTER("prepare_fk_prelocking_list");
List <FOREIGN_KEY_INFO> fk_list;
List_iterator<FOREIGN_KEY_INFO> fk_list_it(fk_list);
FOREIGN_KEY_INFO *fk;
Query_arena *arena, backup;
TABLE *table= table_list->table;
arena= thd->activate_stmt_arena_if_needed(&backup);
table->file->get_parent_foreign_key_list(thd, &fk_list);
if (unlikely(thd->is_error()))
{
if (arena)
thd->restore_active_arena(arena, &backup);
return TRUE;
}
*need_prelocking= TRUE;
while ((fk= fk_list_it++))
{
// FK_OPTION_RESTRICT and FK_OPTION_NO_ACTION only need read access
thr_lock_type lock_type;
if ((op & (1 << TRG_EVENT_DELETE) && fk_modifies_child(fk->delete_method))
|| (op & (1 << TRG_EVENT_UPDATE) && fk_modifies_child(fk->update_method)))
lock_type= TL_WRITE_ALLOW_WRITE;
else
lock_type= TL_READ;
if (table_already_fk_prelocked(prelocking_ctx->query_tables,
fk->foreign_db, fk->foreign_table,
lock_type))
continue;
TABLE_LIST *tl= (TABLE_LIST *) thd->alloc(sizeof(TABLE_LIST));
tl->init_one_table_for_prelocking(fk->foreign_db,
fk->foreign_table,
NULL, lock_type,
TABLE_LIST::PRELOCK_FK,
table_list->belong_to_view, op,
&prelocking_ctx->query_tables_last,
table_list->for_insert_data);
}
if (arena)
thd->restore_active_arena(arena, &backup);
DBUG_RETURN(FALSE);
}
/**
Defines how prelocking algorithm for DML statements should handle table list
@ -4740,53 +4805,20 @@ handle_table(THD *thd, Query_tables_list *prelocking_ctx,
if (table->file->referenced_by_foreign_key())
{
List <FOREIGN_KEY_INFO> fk_list;
List_iterator<FOREIGN_KEY_INFO> fk_list_it(fk_list);
FOREIGN_KEY_INFO *fk;
Query_arena *arena, backup;
arena= thd->activate_stmt_arena_if_needed(&backup);
table->file->get_parent_foreign_key_list(thd, &fk_list);
if (unlikely(thd->is_error()))
{
if (arena)
thd->restore_active_arena(arena, &backup);
DBUG_RETURN(TRUE);
}
*need_prelocking= TRUE;
while ((fk= fk_list_it++))
{
// FK_OPTION_RESTRICT and FK_OPTION_NO_ACTION only need read access
uint8 op= table_list->trg_event_map;
thr_lock_type lock_type;
if ((op & (1 << TRG_EVENT_DELETE) && fk_modifies_child(fk->delete_method))
|| (op & (1 << TRG_EVENT_UPDATE) && fk_modifies_child(fk->update_method)))
lock_type= TL_WRITE_ALLOW_WRITE;
else
lock_type= TL_READ;
if (table_already_fk_prelocked(prelocking_ctx->query_tables,
fk->foreign_db, fk->foreign_table,
lock_type))
continue;
TABLE_LIST *tl= (TABLE_LIST *) thd->alloc(sizeof(TABLE_LIST));
tl->init_one_table_for_prelocking(fk->foreign_db,
fk->foreign_table,
NULL, lock_type,
TABLE_LIST::PRELOCK_FK,
table_list->belong_to_view, op,
&prelocking_ctx->query_tables_last,
table_list->for_insert_data);
}
if (arena)
thd->restore_active_arena(arena, &backup);
if (prepare_fk_prelocking_list(thd, prelocking_ctx, table_list,
need_prelocking,
table_list->trg_event_map))
return TRUE;
}
}
else if (table_list->slave_fk_event_map &&
table->file->referenced_by_foreign_key())
{
if (prepare_fk_prelocking_list(thd, prelocking_ctx, table_list,
need_prelocking,
table_list->slave_fk_event_map))
return TRUE;
}
/* Open any tables used by DEFAULT (like sequence tables) */
DBUG_PRINT("info", ("table: %p name: %s db: %s flags: %u",

View File

@ -1,6 +1,6 @@
/*
Copyright (c) 2000, 2015, Oracle and/or its affiliates.
Copyright (c) 2008, 2020, MariaDB Corporation.
Copyright (c) 2008, 2021, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -1512,16 +1512,29 @@ void THD::reset_db(const LEX_CSTRING *new_db)
/* Do operations that may take a long time */
void THD::cleanup(void)
void THD::cleanup(bool have_mutex)
{
DBUG_ENTER("THD::cleanup");
DBUG_ASSERT(cleanup_done == 0);
set_killed(KILL_CONNECTION);
if (have_mutex)
set_killed_no_mutex(KILL_CONNECTION,0,0);
else
set_killed(KILL_CONNECTION);
#ifdef WITH_WSREP
if (wsrep_cs().state() != wsrep::client_state::s_none)
{
wsrep_cs().cleanup();
if (have_mutex)
{
mysql_mutex_assert_owner(static_cast<mysql_mutex_t*>
(m_wsrep_mutex.native()));
// Below wsrep-lib function will not acquire any mutexes
wsrep::unique_lock<wsrep::mutex> lock(m_wsrep_mutex, std::adopt_lock);
wsrep_cs().cleanup(lock);
lock.release();
}
else
wsrep_cs().cleanup();
}
wsrep_client_thread= false;
#endif /* WITH_WSREP */
@ -1598,16 +1611,38 @@ void THD::cleanup(void)
void THD::free_connection()
{
DBUG_ASSERT(free_connection_done == 0);
my_free((char*) db.str);
/* Make sure threads are not available via server_threads. */
assert_not_linked();
/*
Other threads may have a lock on THD::LOCK_thd_data or
THD::LOCK_thd_kill to ensure that this THD is not deleted
while they access it. The following mutex_lock ensures
that no one else is using this THD and it's now safe to
continue.
For example consider KILL-statement execution on
sql_parse.cc kill_one_thread() that will use
THD::LOCK_thd_data to protect victim thread during
THD::awake().
*/
mysql_mutex_lock(&LOCK_thd_data);
mysql_mutex_lock(&LOCK_thd_kill);
#ifdef WITH_WSREP
delete wsrep_rgi;
wsrep_rgi= nullptr;
#endif /* WITH_WSREP */
my_free(const_cast<char*>(db.str));
db= null_clex_str;
#ifndef EMBEDDED_LIBRARY
if (net.vio)
vio_delete(net.vio);
net.vio= 0;
net.vio= nullptr;
net_end(&net);
#endif
if (!cleanup_done)
cleanup();
if (!cleanup_done)
cleanup(true); // We have locked THD::LOCK_thd_kill
ha_close_connection(this);
plugin_thdvar_cleanup(this);
mysql_audit_free_thd(this);
@ -1618,6 +1653,8 @@ void THD::free_connection()
#if defined(ENABLED_PROFILING)
profiling.restart(); // Reset profiling
#endif
mysql_mutex_unlock(&LOCK_thd_kill);
mysql_mutex_unlock(&LOCK_thd_data);
}
/*
@ -1671,24 +1708,10 @@ THD::~THD()
if (!status_in_global)
add_status_to_global();
/*
Other threads may have a lock on LOCK_thd_kill to ensure that this
THD is not deleted while they access it. The following mutex_lock
ensures that no one else is using this THD and it's now safe to delete
*/
if (WSREP_NNULL(this)) mysql_mutex_lock(&LOCK_thd_data);
mysql_mutex_lock(&LOCK_thd_kill);
mysql_mutex_unlock(&LOCK_thd_kill);
if (WSREP_NNULL(this)) mysql_mutex_unlock(&LOCK_thd_data);
if (!free_connection_done)
free_connection();
#ifdef WITH_WSREP
if (wsrep_rgi != NULL) {
delete wsrep_rgi;
wsrep_rgi = NULL;
}
mysql_cond_destroy(&COND_wsrep_thd);
#endif
mdl_context.destroy();
@ -3142,12 +3165,12 @@ static File create_file(THD *thd, char *path, sql_exchange *exchange,
}
/* Create the file world readable */
if ((file= mysql_file_create(key_select_to_file,
path, 0666, O_WRONLY|O_EXCL, MYF(MY_WME))) < 0)
path, 0644, O_WRONLY|O_EXCL, MYF(MY_WME))) < 0)
return file;
#ifdef HAVE_FCHMOD
(void) fchmod(file, 0666); // Because of umask()
(void) fchmod(file, 0644); // Because of umask()
#else
(void) chmod(path, 0666);
(void) chmod(path, 0644);
#endif
if (init_io_cache(cache, file, 0L, WRITE_CACHE, 0L, 1, MYF(MY_WME)))
{

View File

@ -3281,7 +3281,7 @@ public:
void update_all_stats();
void update_stats(void);
void change_user(void);
void cleanup(void);
void cleanup(bool have_mutex=false);
void cleanup_after_query();
void free_connection();
void reset_for_reuse();

View File

@ -1981,6 +1981,8 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
if (likely(!error))
{
info->deleted++;
if (!table->file->has_transactions())
thd->transaction.stmt.modified_non_trans_table= TRUE;
if (table->versioned(VERS_TIMESTAMP))
{
store_record(table, record[2]);

View File

@ -1,5 +1,5 @@
/* Copyright (c) 2002, 2015, Oracle and/or its affiliates.
Copyright (c) 2008, 2019, MariaDB
Copyright (c) 2008, 2021, MariaDB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -118,6 +118,8 @@ When one supplies long data for a placeholder:
#include <mysql.h>
#else
#include <mysql_com.h>
/* Constants defining bits in parameter type flags. Flags are read from high byte of short value */
static const uint PARAMETER_FLAG_UNSIGNED= 128U << 8;
#endif
#include "lock.h" // MYSQL_OPEN_FORCE_SHARED_MDL
#include "sql_handler.h"
@ -127,9 +129,6 @@ When one supplies long data for a placeholder:
#include "wsrep_trans_observer.h"
#endif /* WITH_WSREP */
/* Constants defining bits in parameter type flags. Flags are read from high byte of short value */
static const uint PARAMETER_FLAG_UNSIGNED = 128U << 8;
/**
A result class used to send cursor rows using the binary protocol.
*/

View File

@ -2485,6 +2485,7 @@ int multi_update::send_data(List<Item> &not_used_values)
{
TABLE_LIST *cur_table;
DBUG_ENTER("multi_update::send_data");
int error= 0;
for (cur_table= update_tables; cur_table; cur_table= cur_table->next_local)
{
@ -2531,7 +2532,6 @@ int multi_update::send_data(List<Item> &not_used_values)
found++;
if (!can_compare_record || compare_record(table))
{
int error;
if ((error= cur_table->view_check_option(thd, ignore)) !=
VIEW_CHECK_OK)
@ -2614,7 +2614,6 @@ error:
}
else
{
int error;
TABLE *tmp_table= tmp_tables[offset];
if (copy_funcs(tmp_table_param[offset].items_to_copy, thd))
DBUG_RETURN(1);

View File

@ -2577,8 +2577,12 @@ struct TABLE_LIST
Indicates what triggers we need to pre-load for this TABLE_LIST
when opening an associated TABLE. This is filled after
the parsed tree is created.
slave_fk_event_map is filled on the slave side with bitmaps value
representing row-based event operation to help find and prelock
possible FK constrain-related child tables.
*/
uint8 trg_event_map;
uint8 trg_event_map, slave_fk_event_map;
/* TRUE <=> this table is a const one and was optimized away. */
bool optimized_away;

View File

@ -4,7 +4,7 @@ Copyright (c) 2000, 2020, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, 2009 Google Inc.
Copyright (c) 2009, Percona Inc.
Copyright (c) 2012, Facebook Inc.
Copyright (c) 2013, 2020, MariaDB Corporation.
Copyright (c) 2013, 2021, MariaDB Corporation.
Portions of this file contain modifications contributed and copyrighted by
Google, Inc. Those modifications are gratefully acknowledged and are described
@ -5066,7 +5066,7 @@ rollback_and_free:
DBUG_RETURN(0);
}
UNIV_INTERN void lock_cancel_waiting_and_release(lock_t* lock);
void lock_cancel_waiting_and_release(lock_t *lock);
/** Cancel any pending lock request associated with the current THD.
@sa THD::awake() @sa ha_kill_query() */
@ -5076,6 +5076,7 @@ static void innobase_kill_query(handlerton*, THD *thd, enum thd_kill_levels)
if (trx_t* trx= thd_to_trx(thd))
{
ut_ad(trx->mysql_thd == thd);
#ifdef WITH_WSREP
if (trx->is_wsrep() && wsrep_thd_is_aborting(thd))
/* if victim has been signaled by BF thread and/or aborting is already
@ -5084,28 +5085,13 @@ static void innobase_kill_query(handlerton*, THD *thd, enum thd_kill_levels)
DBUG_VOID_RETURN;
#endif /* WITH_WSREP */
lock_mutex_enter();
mutex_enter(&trx_sys.mutex);
trx_mutex_enter(trx);
/* It is possible that innobase_close_connection() is concurrently
being executed on our victim. Even if the trx object is later
reused for another client connection or a background transaction,
its trx->mysql_thd will differ from our thd.
trx_t::state changes are protected by trx_t::mutex, and
trx_sys.trx_list is protected by trx_sys.mutex, in
both trx_create() and trx_t::free().
At this point, trx may have been reallocated for another client
connection, or for a background operation. In that case, either
trx_t::state or trx_t::mysql_thd should not match our expectations. */
bool cancel= trx->mysql_thd == thd && trx->state == TRX_STATE_ACTIVE &&
!trx->lock.was_chosen_as_deadlock_victim;
mutex_exit(&trx_sys.mutex);
if (!cancel);
else if (lock_t *lock= trx->lock.wait_lock)
if (lock_t *lock= trx->lock.wait_lock)
{
trx_mutex_enter(trx);
lock_cancel_waiting_and_release(lock);
trx_mutex_exit(trx);
}
lock_mutex_exit();
trx_mutex_exit(trx);
}
DBUG_VOID_RETURN;

View File

@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 2005, 2019, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2013, 2020, MariaDB Corporation.
Copyright (c) 2013, 2021, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@ -10150,6 +10150,44 @@ innobase_page_compression_try(
DBUG_RETURN(false);
}
static
void
dict_stats_try_drop_table(THD *thd, const table_name_t &name,
const LEX_CSTRING &table_name)
{
char errstr[1024];
if (dict_stats_drop_table(name.m_name, errstr, sizeof(errstr)) != DB_SUCCESS)
{
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, ER_ALTER_INFO,
"Deleting persistent statistics"
" for table '%s' in InnoDB failed: %s",
table_name.str,
errstr);
}
}
/** Evict the table from cache and reopen it. Drop outdated statistics.
@param thd mariadb THD entity
@param table innodb table
@param maria_table_name user-friendly table name for errors
@return newly opened table */
static
dict_table_t*
innobase_reload_table(THD *thd, dict_table_t *table,
const LEX_CSTRING &table_name)
{
char *tb_name= strdup(table->name.m_name);
dict_table_close(table, true, false);
dict_sys.remove(table);
table= dict_table_open_on_name(tb_name, TRUE, TRUE,
DICT_ERR_IGNORE_FK_NOKEY);
/* Drop outdated table stats. */
dict_stats_try_drop_table(thd, table->name, table_name);
free(tb_name);
return table;
}
/** Commit the changes made during prepare_inplace_alter_table()
and inplace_alter_table() inside the data dictionary tables,
when not rebuilding the table.
@ -11358,44 +11396,25 @@ foreign_fail:
Currently dict_load_column_low() is the only place where
num_base for virtual columns is assigned to nonzero. */
if (ctx0->num_to_drop_vcol || ctx0->num_to_add_vcol
|| (ctx0->new_table->n_v_cols && !new_clustered
&& (ha_alter_info->alter_info->drop_list.elements
|| ha_alter_info->alter_info->create_list.elements))
|| (ctx0->is_instant()
&& m_prebuilt->table->n_v_cols
&& ha_alter_info->handler_flags & ALTER_STORED_COLUMN_ORDER)) {
/* FIXME: this workaround does not seem to work with
partitioned tables */
DBUG_ASSERT(ctx0->old_table->get_ref_count() == 1);
trx_commit_for_mysql(m_prebuilt->trx);
char tb_name[NAME_LEN * 2 + 1 + 1];
strcpy(tb_name, m_prebuilt->table->name.m_name);
dict_table_close(m_prebuilt->table, true, false);
if (ctx0->is_instant()) {
for (unsigned i = ctx0->old_n_v_cols; i--; ) {
ctx0->old_v_cols[i].~dict_v_col_t();
}
const_cast<unsigned&>(ctx0->old_n_v_cols) = 0;
}
dict_sys.remove(m_prebuilt->table);
m_prebuilt->table = dict_table_open_on_name(
tb_name, TRUE, TRUE, DICT_ERR_IGNORE_FK_NOKEY);
/* Drop outdated table stats. */
char errstr[1024];
if (dict_stats_drop_table(
m_prebuilt->table->name.m_name,
errstr, sizeof(errstr))
!= DB_SUCCESS) {
push_warning_printf(
m_user_thd,
Sql_condition::WARN_LEVEL_WARN,
ER_ALTER_INFO,
"Deleting persistent statistics"
" for table '%s' in"
" InnoDB failed: %s",
table->s->table_name.str,
errstr);
}
m_prebuilt->table = innobase_reload_table(m_user_thd,
m_prebuilt->table,
table->s->table_name);
row_mysql_unlock_data_dictionary(trx);
trx->free();
@ -11455,25 +11474,12 @@ foreign_fail:
old copy of the table (which was renamed to
ctx->tmp_name). */
char errstr[1024];
DBUG_ASSERT(0 == strcmp(ctx->old_table->name.m_name,
ctx->tmp_name));
if (dict_stats_drop_table(
ctx->new_table->name.m_name,
errstr, sizeof(errstr))
!= DB_SUCCESS) {
push_warning_printf(
m_user_thd,
Sql_condition::WARN_LEVEL_WARN,
ER_ALTER_INFO,
"Deleting persistent statistics"
" for rebuilt table '%s' in"
" InnoDB failed: %s",
table->s->table_name.str,
errstr);
}
dict_stats_try_drop_table(m_user_thd,
ctx->new_table->name,
table->s->table_name);
DBUG_EXECUTE_IF("ib_ddl_crash_before_commit",
DBUG_SUICIDE(););

View File

@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, 2020, MariaDB Corporation.
Copyright (c) 2017, 2021, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@ -303,7 +303,6 @@ que_fork_scheduler_round_robin(
/** Query thread states */
enum que_thr_state_t {
QUE_THR_RUNNING,
QUE_THR_PROCEDURE_WAIT,
/** in selects this means that the thread is at the end of its
result set (or start, in case of a scroll cursor); in other
statements, this means the thread has done its task */

View File

@ -6150,6 +6150,7 @@ lock_cancel_waiting_and_release(
ut_ad(lock_mutex_own());
ut_ad(trx_mutex_own(lock->trx));
ut_ad(lock->trx->state == TRX_STATE_ACTIVE);
lock->trx->lock.cancel = true;

View File

@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, 2018, 2020 MariaDB Corporation.
Copyright (c) 2017, 2021, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@ -349,7 +349,6 @@ que_fork_start_command(
case QUE_THR_RUNNING:
case QUE_THR_LOCK_WAIT:
case QUE_THR_PROCEDURE_WAIT:
ut_error;
}
}

View File

@ -4342,6 +4342,8 @@ row_rename_table_for_mysql(
"END;\n"
, FALSE, trx);
ut_ad(err != DB_DUPLICATE_KEY);
/* SYS_TABLESPACES and SYS_DATAFILES need to be updated if
the table is in a single-table tablespace. */
if (err != DB_SUCCESS || !dict_table_is_file_per_table(table)) {

View File

@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2015, 2020, MariaDB Corporation.
Copyright (c) 2015, 2021, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@ -414,9 +414,11 @@ void trx_t::free()
/* do not poison mutex */
MEM_NOACCESS(&id, sizeof id);
MEM_NOACCESS(&no, sizeof no);
/* state is accessed by innobase_kill_connection() */
MEM_NOACCESS(&state, sizeof state);
MEM_NOACCESS(&is_recovered, sizeof is_recovered);
/* wsrep is accessed by innobase_kill_connection() */
#ifdef WITH_WSREP
MEM_NOACCESS(&wsrep, sizeof wsrep);
#endif
MEM_NOACCESS(&read_view, sizeof read_view);
MEM_NOACCESS(&trx_list, sizeof trx_list);
MEM_NOACCESS(&lock, sizeof lock);
@ -437,7 +439,7 @@ void trx_t::free()
MEM_NOACCESS(&start_time_micro, sizeof start_time_micro);
MEM_NOACCESS(&commit_lsn, sizeof commit_lsn);
MEM_NOACCESS(&table_id, sizeof table_id);
/* mysql_thd is accessed by innobase_kill_connection() */
MEM_NOACCESS(&mysql_thd, sizeof mysql_thd);
MEM_NOACCESS(&mysql_log_file_name, sizeof mysql_log_file_name);
MEM_NOACCESS(&mysql_log_offset, sizeof mysql_log_offset);
MEM_NOACCESS(&n_mysql_tables_in_use, sizeof n_mysql_tables_in_use);