mirror of
https://github.com/MariaDB/server.git
synced 2026-10-23 18:49:29 +03:00
Merge 10.11 into 11.4
This commit is contained in:
@@ -5376,7 +5376,7 @@ void do_sync_with_master(struct st_command *command)
|
||||
long offset= 0;
|
||||
char *p= command->first_argument;
|
||||
const char *offset_start= p;
|
||||
char *start, *buff= 0;
|
||||
char *start, *buff= 0, *str;
|
||||
start= const_cast<char*>("");
|
||||
|
||||
if (*offset_start)
|
||||
@@ -5394,15 +5394,15 @@ void do_sync_with_master(struct st_command *command)
|
||||
p++;
|
||||
while (*p && my_isspace(charset_info, *p))
|
||||
p++;
|
||||
start= buff= (char*)my_malloc(PSI_NOT_INSTRUMENTED, strlen(p)+1,
|
||||
MYF(MY_WME|MY_FAE));
|
||||
get_string(&buff, &p, command);
|
||||
str= buff= (char*)my_malloc(PSI_NOT_INSTRUMENTED, strlen(p)+1,
|
||||
MYF(MY_WME|MY_FAE));
|
||||
start= get_string(&str, &p, command);
|
||||
}
|
||||
command->last_argument= p;
|
||||
}
|
||||
do_sync_with_master2(command, offset, start);
|
||||
if (buff)
|
||||
my_free(start);
|
||||
my_free(buff);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -8453,7 +8453,7 @@ void do_get_errcodes(struct st_command *command)
|
||||
|
||||
|
||||
/*
|
||||
Get a string; Return ptr to end of string
|
||||
Get a string; Return ptr to start of string
|
||||
Strings may be surrounded by " or '
|
||||
|
||||
If string is a '$variable', return the value of the variable.
|
||||
|
||||
115
mysql-test/suite/galera/r/MDEV-41012-collision.result
Normal file
115
mysql-test/suite/galera/r/MDEV-41012-collision.result
Normal file
@@ -0,0 +1,115 @@
|
||||
connection node_2;
|
||||
connection node_1;
|
||||
#
|
||||
# Each pair below is two distinct values whose bytes fold to the same
|
||||
# latin1_swedish_ci weight string (0xC0->0x41, 0x6A->0x4A, 0x6B->0x4B,
|
||||
# 0xD2->0x4F, 0x7A->0x5A). A UUID is stored as a byte permutation of the
|
||||
# value shown, which does not affect a byte-wise folding.
|
||||
#
|
||||
SELECT WEIGHT_STRING(_latin1 0xC0A8016B9E4D4F7AB3D26A1E8F9C0D1B) =
|
||||
WEIGHT_STRING(_latin1 0x41A8014B9E4D4F5AB34F4A1E8F9C0D1B) AS uuid_pair_collides,
|
||||
WEIGHT_STRING(_latin1 0x20010DB80000000000000000C0A8016B) =
|
||||
WEIGHT_STRING(_latin1 0x20010DB8000000000000000041A8014B) AS inet6_pair_collides,
|
||||
WEIGHT_STRING(_latin1 0xC0A8016B) =
|
||||
WEIGHT_STRING(_latin1 0x41A8014B) AS inet4_pair_collides;
|
||||
uuid_pair_collides inet6_pair_collides inet4_pair_collides
|
||||
1 1 1
|
||||
#
|
||||
# UUID
|
||||
#
|
||||
connection node_1;
|
||||
CREATE TABLE t (id UUID PRIMARY KEY, v INT) ENGINE=InnoDB;
|
||||
INSERT INTO t VALUES ('c0a8016b-9e4d-4f7a-b3d2-6a1e8f9c0d1b', 0), ('41a8014b-9e4d-4f5a-b34f-4a1e8f9c0d1b', 0);
|
||||
connection node_2;
|
||||
SET SESSION wsrep_sync_wait = 0;
|
||||
SET GLOBAL wsrep_slave_threads = 2;
|
||||
SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
|
||||
connection node_1;
|
||||
UPDATE t SET v = 1 WHERE id = 'c0a8016b-9e4d-4f7a-b3d2-6a1e8f9c0d1b';
|
||||
connection node_2;
|
||||
SET SESSION wsrep_on = 0;
|
||||
SET SESSION wsrep_on = 1;
|
||||
SET GLOBAL wsrep_provider_options = 'dbug=';
|
||||
connection node_1;
|
||||
UPDATE t SET v = 2 WHERE id = '41a8014b-9e4d-4f5a-b34f-4a1e8f9c0d1b';
|
||||
connection node_2;
|
||||
no_false_dependency
|
||||
1
|
||||
SELECT COUNT(*) = 1 AS second_row_applied_in_parallel FROM INFORMATION_SCHEMA.INNODB_TRX WHERE trx_rows_modified > 0;
|
||||
second_row_applied_in_parallel
|
||||
1
|
||||
SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
|
||||
SELECT id, v FROM t ORDER BY v;
|
||||
id v
|
||||
c0a8016b-9e4d-4f7a-b3d2-6a1e8f9c0d1b 1
|
||||
41a8014b-9e4d-4f5a-b34f-4a1e8f9c0d1b 2
|
||||
SET GLOBAL wsrep_slave_threads = DEFAULT;
|
||||
SET SESSION wsrep_sync_wait = DEFAULT;
|
||||
connection node_1;
|
||||
DROP TABLE t;
|
||||
#
|
||||
# INET6
|
||||
#
|
||||
connection node_1;
|
||||
CREATE TABLE t (id INET6 PRIMARY KEY, v INT) ENGINE=InnoDB;
|
||||
INSERT INTO t VALUES ('2001:db8::c0a8:16b', 0), ('2001:db8::41a8:14b', 0);
|
||||
connection node_2;
|
||||
SET SESSION wsrep_sync_wait = 0;
|
||||
SET GLOBAL wsrep_slave_threads = 2;
|
||||
SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
|
||||
connection node_1;
|
||||
UPDATE t SET v = 1 WHERE id = '2001:db8::c0a8:16b';
|
||||
connection node_2;
|
||||
SET SESSION wsrep_on = 0;
|
||||
SET SESSION wsrep_on = 1;
|
||||
SET GLOBAL wsrep_provider_options = 'dbug=';
|
||||
connection node_1;
|
||||
UPDATE t SET v = 2 WHERE id = '2001:db8::41a8:14b';
|
||||
connection node_2;
|
||||
no_false_dependency
|
||||
1
|
||||
SELECT COUNT(*) = 1 AS second_row_applied_in_parallel FROM INFORMATION_SCHEMA.INNODB_TRX WHERE trx_rows_modified > 0;
|
||||
second_row_applied_in_parallel
|
||||
1
|
||||
SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
|
||||
SELECT id, v FROM t ORDER BY v;
|
||||
id v
|
||||
2001:db8::c0a8:16b 1
|
||||
2001:db8::41a8:14b 2
|
||||
SET GLOBAL wsrep_slave_threads = DEFAULT;
|
||||
SET SESSION wsrep_sync_wait = DEFAULT;
|
||||
connection node_1;
|
||||
DROP TABLE t;
|
||||
#
|
||||
# INET4
|
||||
#
|
||||
connection node_1;
|
||||
CREATE TABLE t (id INET4 PRIMARY KEY, v INT) ENGINE=InnoDB;
|
||||
INSERT INTO t VALUES ('192.168.1.107', 0), ('65.168.1.75', 0);
|
||||
connection node_2;
|
||||
SET SESSION wsrep_sync_wait = 0;
|
||||
SET GLOBAL wsrep_slave_threads = 2;
|
||||
SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
|
||||
connection node_1;
|
||||
UPDATE t SET v = 1 WHERE id = '192.168.1.107';
|
||||
connection node_2;
|
||||
SET SESSION wsrep_on = 0;
|
||||
SET SESSION wsrep_on = 1;
|
||||
SET GLOBAL wsrep_provider_options = 'dbug=';
|
||||
connection node_1;
|
||||
UPDATE t SET v = 2 WHERE id = '65.168.1.75';
|
||||
connection node_2;
|
||||
no_false_dependency
|
||||
1
|
||||
SELECT COUNT(*) = 1 AS second_row_applied_in_parallel FROM INFORMATION_SCHEMA.INNODB_TRX WHERE trx_rows_modified > 0;
|
||||
second_row_applied_in_parallel
|
||||
1
|
||||
SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
|
||||
SELECT id, v FROM t ORDER BY v;
|
||||
id v
|
||||
192.168.1.107 1
|
||||
65.168.1.75 2
|
||||
SET GLOBAL wsrep_slave_threads = DEFAULT;
|
||||
SET SESSION wsrep_sync_wait = DEFAULT;
|
||||
connection node_1;
|
||||
DROP TABLE t;
|
||||
104
mysql-test/suite/galera/r/MDEV-41012.result
Normal file
104
mysql-test/suite/galera/r/MDEV-41012.result
Normal file
@@ -0,0 +1,104 @@
|
||||
connection node_2;
|
||||
connection node_1;
|
||||
#
|
||||
# UUID
|
||||
#
|
||||
connection node_1;
|
||||
CREATE TABLE p (id UUID PRIMARY KEY, v INT) ENGINE=InnoDB;
|
||||
CREATE TABLE c (id INT AUTO_INCREMENT PRIMARY KEY, p_id UUID NOT NULL, KEY k (p_id), FOREIGN KEY (p_id) REFERENCES p (id)) ENGINE=InnoDB;
|
||||
INSERT INTO p VALUES ('c0a8016b-9e4d-4f7a-b3d2-6a1e8f9c0d1b', 0);
|
||||
connection node_2;
|
||||
SET SESSION wsrep_sync_wait = 0;
|
||||
SET GLOBAL wsrep_slave_threads = 2;
|
||||
SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
|
||||
connection node_1;
|
||||
INSERT INTO c (p_id) VALUES ('c0a8016b-9e4d-4f7a-b3d2-6a1e8f9c0d1b');
|
||||
connection node_2;
|
||||
SET SESSION wsrep_on = 0;
|
||||
SET SESSION wsrep_on = 1;
|
||||
SET GLOBAL wsrep_provider_options = 'dbug=';
|
||||
connection node_1;
|
||||
UPDATE p SET v = v + 1 WHERE id = 'c0a8016b-9e4d-4f7a-b3d2-6a1e8f9c0d1b';
|
||||
connection node_2;
|
||||
SELECT COUNT(*) = 0 AS no_row_modified_in_parallel FROM INFORMATION_SCHEMA.INNODB_TRX WHERE trx_rows_modified > 0;
|
||||
no_row_modified_in_parallel
|
||||
1
|
||||
SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
|
||||
SELECT v FROM p;
|
||||
v
|
||||
1
|
||||
SELECT COUNT(*) FROM c;
|
||||
COUNT(*)
|
||||
1
|
||||
SET GLOBAL wsrep_slave_threads = DEFAULT;
|
||||
SET SESSION wsrep_sync_wait = DEFAULT;
|
||||
connection node_1;
|
||||
DROP TABLE c, p;
|
||||
#
|
||||
# INET6
|
||||
#
|
||||
connection node_1;
|
||||
CREATE TABLE p (id INET6 PRIMARY KEY, v INT) ENGINE=InnoDB;
|
||||
CREATE TABLE c (id INT AUTO_INCREMENT PRIMARY KEY, p_id INET6 NOT NULL, KEY k (p_id), FOREIGN KEY (p_id) REFERENCES p (id)) ENGINE=InnoDB;
|
||||
INSERT INTO p VALUES ('2001:db8::c0a8:16b', 0);
|
||||
connection node_2;
|
||||
SET SESSION wsrep_sync_wait = 0;
|
||||
SET GLOBAL wsrep_slave_threads = 2;
|
||||
SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
|
||||
connection node_1;
|
||||
INSERT INTO c (p_id) VALUES ('2001:db8::c0a8:16b');
|
||||
connection node_2;
|
||||
SET SESSION wsrep_on = 0;
|
||||
SET SESSION wsrep_on = 1;
|
||||
SET GLOBAL wsrep_provider_options = 'dbug=';
|
||||
connection node_1;
|
||||
UPDATE p SET v = v + 1 WHERE id = '2001:db8::c0a8:16b';
|
||||
connection node_2;
|
||||
SELECT COUNT(*) = 0 AS no_row_modified_in_parallel FROM INFORMATION_SCHEMA.INNODB_TRX WHERE trx_rows_modified > 0;
|
||||
no_row_modified_in_parallel
|
||||
1
|
||||
SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
|
||||
SELECT v FROM p;
|
||||
v
|
||||
1
|
||||
SELECT COUNT(*) FROM c;
|
||||
COUNT(*)
|
||||
1
|
||||
SET GLOBAL wsrep_slave_threads = DEFAULT;
|
||||
SET SESSION wsrep_sync_wait = DEFAULT;
|
||||
connection node_1;
|
||||
DROP TABLE c, p;
|
||||
#
|
||||
# INET4
|
||||
#
|
||||
connection node_1;
|
||||
CREATE TABLE p (id INET4 PRIMARY KEY, v INT) ENGINE=InnoDB;
|
||||
CREATE TABLE c (id INT AUTO_INCREMENT PRIMARY KEY, p_id INET4 NOT NULL, KEY k (p_id), FOREIGN KEY (p_id) REFERENCES p (id)) ENGINE=InnoDB;
|
||||
INSERT INTO p VALUES ('192.168.1.107', 0);
|
||||
connection node_2;
|
||||
SET SESSION wsrep_sync_wait = 0;
|
||||
SET GLOBAL wsrep_slave_threads = 2;
|
||||
SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
|
||||
connection node_1;
|
||||
INSERT INTO c (p_id) VALUES ('192.168.1.107');
|
||||
connection node_2;
|
||||
SET SESSION wsrep_on = 0;
|
||||
SET SESSION wsrep_on = 1;
|
||||
SET GLOBAL wsrep_provider_options = 'dbug=';
|
||||
connection node_1;
|
||||
UPDATE p SET v = v + 1 WHERE id = '192.168.1.107';
|
||||
connection node_2;
|
||||
SELECT COUNT(*) = 0 AS no_row_modified_in_parallel FROM INFORMATION_SCHEMA.INNODB_TRX WHERE trx_rows_modified > 0;
|
||||
no_row_modified_in_parallel
|
||||
1
|
||||
SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
|
||||
SELECT v FROM p;
|
||||
v
|
||||
1
|
||||
SELECT COUNT(*) FROM c;
|
||||
COUNT(*)
|
||||
1
|
||||
SET GLOBAL wsrep_slave_threads = DEFAULT;
|
||||
SET SESSION wsrep_sync_wait = DEFAULT;
|
||||
connection node_1;
|
||||
DROP TABLE c, p;
|
||||
67
mysql-test/suite/galera/t/MDEV-41012-collision.inc
Normal file
67
mysql-test/suite/galera/t/MDEV-41012-collision.inc
Normal file
@@ -0,0 +1,67 @@
|
||||
#
|
||||
# Body of galera.MDEV-41012-collision, parameterized by the data type.
|
||||
#
|
||||
# $fbt_type - data type of the primary key column
|
||||
# $fbt_value1 - a literal of that type
|
||||
# $fbt_value2 - a *different* literal whose binary representation folds to
|
||||
# the same latin1_swedish_ci weight string as $fbt_value1
|
||||
#
|
||||
|
||||
--connection node_1
|
||||
--eval CREATE TABLE t (id $fbt_type PRIMARY KEY, v INT) ENGINE=InnoDB
|
||||
--eval INSERT INTO t VALUES ($fbt_value1, 0), ($fbt_value2, 0)
|
||||
|
||||
--connection node_2
|
||||
SET SESSION wsrep_sync_wait = 0;
|
||||
--let $wait_condition = SELECT COUNT(*) = 2 FROM t
|
||||
--source include/wait_condition.inc
|
||||
|
||||
SET GLOBAL wsrep_slave_threads = 2;
|
||||
|
||||
# Park the applier of the first UPDATE on entry to the apply monitor.
|
||||
--let $galera_sync_point = apply_monitor_slave_enter_sync
|
||||
--source include/galera_set_sync_point.inc
|
||||
|
||||
--connection node_1
|
||||
--eval UPDATE t SET v = 1 WHERE id = $fbt_value1
|
||||
|
||||
--connection node_2
|
||||
--let $galera_sync_point = apply_monitor_slave_enter_sync
|
||||
--source include/galera_wait_sync_point.inc
|
||||
|
||||
# Disarm, so the second applier runs into the real dependency check.
|
||||
--source include/galera_clear_sync_point.inc
|
||||
|
||||
--let $apply_waits = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_apply_waits'`
|
||||
|
||||
--connection node_1
|
||||
--eval UPDATE t SET v = 2 WHERE id = $fbt_value2
|
||||
|
||||
--connection node_2
|
||||
# The two statements modify two *different* rows, so their
|
||||
# certification keys must differ, there must be no dependency between the two
|
||||
# writesets, and the second applier must be free to apply its row while the
|
||||
# first one is still parked.
|
||||
--let $wait_condition = SELECT (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_apply_waits') > $apply_waits OR EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.INNODB_TRX WHERE trx_rows_modified > 0)
|
||||
--source include/wait_condition.inc
|
||||
|
||||
# While the key was collated with latin1_swedish_ci the two keys were equal,
|
||||
# the second writeset was made to depend on the first, and both of these
|
||||
# reported 0.
|
||||
--disable_query_log
|
||||
--eval SELECT VARIABLE_VALUE = $apply_waits AS no_false_dependency FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_apply_waits'
|
||||
--enable_query_log
|
||||
SELECT COUNT(*) = 1 AS second_row_applied_in_parallel FROM INFORMATION_SCHEMA.INNODB_TRX WHERE trx_rows_modified > 0;
|
||||
|
||||
--let $galera_sync_point = apply_monitor_slave_enter_sync
|
||||
--source include/galera_signal_sync_point.inc
|
||||
|
||||
--let $wait_condition = SELECT SUM(v) = 3 FROM t
|
||||
--source include/wait_condition.inc
|
||||
SELECT id, v FROM t ORDER BY v;
|
||||
|
||||
SET GLOBAL wsrep_slave_threads = DEFAULT;
|
||||
SET SESSION wsrep_sync_wait = DEFAULT;
|
||||
|
||||
--connection node_1
|
||||
DROP TABLE t;
|
||||
64
mysql-test/suite/galera/t/MDEV-41012-collision.test
Normal file
64
mysql-test/suite/galera/t/MDEV-41012-collision.test
Normal file
@@ -0,0 +1,64 @@
|
||||
#
|
||||
# MDEV-41012: certification key collision between distinct values of a fixed
|
||||
# binary data type (UUID, INET6, INET4).
|
||||
#
|
||||
# Testing key collisions with data types on Field_fbt: UUID, INET6 and INET4,
|
||||
# where different keys could potentially generate same certification keys.
|
||||
# i.e. a scenario where two transactions modifying two *different*
|
||||
# rows certified as a conflict and the later one was aborted with a spurious
|
||||
# ER_LOCK_DEADLOCK.
|
||||
#
|
||||
# A shared key also gives the two writesets a false dependency on each other,
|
||||
# which serializes applying that should have run in parallel. The test detects
|
||||
# the collision that way, because it can be driven deterministically. Whether
|
||||
# the spurious ER_LOCK_DEADLOCK is observed instead depends on whether the
|
||||
# first writeset has already been applied by the time the second transaction
|
||||
# replicates, which is a race.
|
||||
#
|
||||
# This needs no foreign key: it is the row key path,
|
||||
# wsrep_store_key_val_for_row(), alone.
|
||||
#
|
||||
# This is the second half of MDEV-41012. The other half, a key *mismatch* for
|
||||
# one and the same row, is covered by galera.MDEV-41012.
|
||||
#
|
||||
|
||||
--source include/galera_cluster.inc
|
||||
--source include/have_innodb.inc
|
||||
--source include/galera_have_debug_sync.inc
|
||||
|
||||
--echo #
|
||||
--echo # Each pair below is two distinct values whose bytes fold to the same
|
||||
--echo # latin1_swedish_ci weight string (0xC0->0x41, 0x6A->0x4A, 0x6B->0x4B,
|
||||
--echo # 0xD2->0x4F, 0x7A->0x5A). A UUID is stored as a byte permutation of the
|
||||
--echo # value shown, which does not affect a byte-wise folding.
|
||||
--echo #
|
||||
SELECT WEIGHT_STRING(_latin1 0xC0A8016B9E4D4F7AB3D26A1E8F9C0D1B) =
|
||||
WEIGHT_STRING(_latin1 0x41A8014B9E4D4F5AB34F4A1E8F9C0D1B) AS uuid_pair_collides,
|
||||
WEIGHT_STRING(_latin1 0x20010DB80000000000000000C0A8016B) =
|
||||
WEIGHT_STRING(_latin1 0x20010DB8000000000000000041A8014B) AS inet6_pair_collides,
|
||||
WEIGHT_STRING(_latin1 0xC0A8016B) =
|
||||
WEIGHT_STRING(_latin1 0x41A8014B) AS inet4_pair_collides;
|
||||
|
||||
--echo #
|
||||
--echo # UUID
|
||||
--echo #
|
||||
--let $fbt_type = UUID
|
||||
--let $fbt_value1 = 'c0a8016b-9e4d-4f7a-b3d2-6a1e8f9c0d1b'
|
||||
--let $fbt_value2 = '41a8014b-9e4d-4f5a-b34f-4a1e8f9c0d1b'
|
||||
--source MDEV-41012-collision.inc
|
||||
|
||||
--echo #
|
||||
--echo # INET6
|
||||
--echo #
|
||||
--let $fbt_type = INET6
|
||||
--let $fbt_value1 = '2001:db8::c0a8:16b'
|
||||
--let $fbt_value2 = '2001:db8::41a8:14b'
|
||||
--source MDEV-41012-collision.inc
|
||||
|
||||
--echo #
|
||||
--echo # INET4
|
||||
--echo #
|
||||
--let $fbt_type = INET4
|
||||
--let $fbt_value1 = '192.168.1.107'
|
||||
--let $fbt_value2 = '65.168.1.75'
|
||||
--source MDEV-41012-collision.inc
|
||||
67
mysql-test/suite/galera/t/MDEV-41012.inc
Normal file
67
mysql-test/suite/galera/t/MDEV-41012.inc
Normal file
@@ -0,0 +1,67 @@
|
||||
#
|
||||
# Body of galera.MDEV-41012, parameterized by the data type of the foreign key.
|
||||
#
|
||||
# $fbt_type - data type of the parent PK / child FK column
|
||||
# $fbt_value - a literal of that type whose binary representation contains
|
||||
# bytes that latin1_swedish_ci folds (0xC0, 0x6A, 0x6B, 0xD2 ...)
|
||||
#
|
||||
|
||||
--connection node_1
|
||||
--eval CREATE TABLE p (id $fbt_type PRIMARY KEY, v INT) ENGINE=InnoDB
|
||||
--eval CREATE TABLE c (id INT AUTO_INCREMENT PRIMARY KEY, p_id $fbt_type NOT NULL, KEY k (p_id), FOREIGN KEY (p_id) REFERENCES p (id)) ENGINE=InnoDB
|
||||
--eval INSERT INTO p VALUES ($fbt_value, 0)
|
||||
|
||||
--connection node_2
|
||||
SET SESSION wsrep_sync_wait = 0;
|
||||
--let $wait_condition = SELECT COUNT(*) = 1 FROM p
|
||||
--source include/wait_condition.inc
|
||||
|
||||
# Two appliers, so that the two writesets below *can* be applied in parallel
|
||||
# if certification does not make them depend on each other.
|
||||
SET GLOBAL wsrep_slave_threads = 2;
|
||||
|
||||
# Park the first applier on entry to the apply monitor, i.e. before the child
|
||||
# INSERT is applied and before its FK check locks the parent row.
|
||||
--let $galera_sync_point = apply_monitor_slave_enter_sync
|
||||
--source include/galera_set_sync_point.inc
|
||||
|
||||
--connection node_1
|
||||
--eval INSERT INTO c (p_id) VALUES ($fbt_value)
|
||||
|
||||
--connection node_2
|
||||
--let $galera_sync_point = apply_monitor_slave_enter_sync
|
||||
--source include/galera_wait_sync_point.inc
|
||||
|
||||
# clear the sync point. The second applier must run into the real dependency
|
||||
--source include/galera_clear_sync_point.inc
|
||||
|
||||
--let $apply_waits = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_apply_waits'`
|
||||
|
||||
--connection node_1
|
||||
--eval UPDATE p SET v = v + 1 WHERE id = $fbt_value
|
||||
|
||||
--connection node_2
|
||||
# Wait until the second applier has blocked in the apply monitor because
|
||||
--let $wait_condition = SELECT (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_apply_waits') > $apply_waits
|
||||
--source include/wait_condition.inc
|
||||
|
||||
# the second applier waited instead of applying it in parallel.
|
||||
SELECT COUNT(*) = 0 AS no_row_modified_in_parallel FROM INFORMATION_SCHEMA.INNODB_TRX WHERE trx_rows_modified > 0;
|
||||
|
||||
# Release the child INSERT
|
||||
--let $galera_sync_point = apply_monitor_slave_enter_sync
|
||||
--source include/galera_signal_sync_point.inc
|
||||
|
||||
--let $wait_condition = SELECT COUNT(*) = 1 FROM c
|
||||
--source include/wait_condition.inc
|
||||
--let $wait_condition = SELECT v = 1 FROM p
|
||||
--source include/wait_condition.inc
|
||||
|
||||
SELECT v FROM p;
|
||||
SELECT COUNT(*) FROM c;
|
||||
|
||||
SET GLOBAL wsrep_slave_threads = DEFAULT;
|
||||
SET SESSION wsrep_sync_wait = DEFAULT;
|
||||
|
||||
--connection node_1
|
||||
DROP TABLE c, p;
|
||||
40
mysql-test/suite/galera/t/MDEV-41012.test
Normal file
40
mysql-test/suite/galera/t/MDEV-41012.test
Normal file
@@ -0,0 +1,40 @@
|
||||
#
|
||||
# MDEV-41012: BF-BF conflict when applying a child INSERT and a parent UPDATE
|
||||
# in parallel, for a foreign key on a fixed binary data type.
|
||||
#
|
||||
# The test sends two write sets having access with the same primary key of fixed
|
||||
# binary data type, the transactions are:
|
||||
# * INSERT into the child table havinga reference key for the parent row
|
||||
# * UPDATE of the parent row having the parent's primary key,
|
||||
#
|
||||
# The test orders appliers so that the child INSERT is parked before it
|
||||
# is applied, the parent UPDATE is replicated after it, and we verify that the
|
||||
# UPDATE has to wait for the INSERT instead of being applied in parallel.
|
||||
#
|
||||
# All three Field_fbt types (UUID, INET4 and INET6) are covered.
|
||||
#
|
||||
|
||||
--source include/galera_cluster.inc
|
||||
--source include/have_innodb.inc
|
||||
--source include/galera_have_debug_sync.inc
|
||||
|
||||
--echo #
|
||||
--echo # UUID
|
||||
--echo #
|
||||
--let $fbt_type = UUID
|
||||
--let $fbt_value = 'c0a8016b-9e4d-4f7a-b3d2-6a1e8f9c0d1b'
|
||||
--source MDEV-41012.inc
|
||||
|
||||
--echo #
|
||||
--echo # INET6
|
||||
--echo #
|
||||
--let $fbt_type = INET6
|
||||
--let $fbt_value = '2001:db8::c0a8:16b'
|
||||
--source MDEV-41012.inc
|
||||
|
||||
--echo #
|
||||
--echo # INET4
|
||||
--echo #
|
||||
--let $fbt_type = INET4
|
||||
--let $fbt_value = '192.168.1.107'
|
||||
--source MDEV-41012.inc
|
||||
@@ -453,6 +453,9 @@ Executed_log_entries 7
|
||||
Slave_received_heartbeats 0
|
||||
Slave_heartbeat_period 60.000
|
||||
Gtid_Slave_Pos
|
||||
#
|
||||
# MDEV-40996: the connection name may be given as a variable
|
||||
#
|
||||
stop all slaves;
|
||||
Warnings:
|
||||
Note 1938 SLAVE 'slave2' stopped
|
||||
|
||||
@@ -77,6 +77,12 @@ reset slave 'slave1' all;
|
||||
--replace_result $SERVER_MYPORT_1 MYPORT_1 $SERVER_MYPORT_2 MYPORT_2 $read_master_log_pos <read_master_log_pos> $relay_log_pos <relay_log_pos> $relay_log_space1 <relay_log_space1> $relay_log_space2 <relay_log_space2>
|
||||
query_vertical show all slaves status;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-40996: the connection name may be given as a variable
|
||||
--echo #
|
||||
--let $conn_name= slave2
|
||||
--sync_with_master 0,$conn_name
|
||||
|
||||
stop all slaves;
|
||||
--replace_result $SERVER_MYPORT_1 MYPORT_1 $SERVER_MYPORT_2 MYPORT_2 $read_master_log_pos <read_master_log_pos> $relay_log_pos <relay_log_pos> $relay_log_space1 <relay_log_space1> $relay_log_space2 <relay_log_space2>
|
||||
query_vertical show all slaves status;
|
||||
|
||||
@@ -352,3 +352,149 @@ SELECT * FROM t;
|
||||
SELECT * FROM tp;
|
||||
|
||||
DROP TABLE t, tp, tsp;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-38757 Exchange partition fails with compound expressions
|
||||
--echo #
|
||||
|
||||
--echo # Test EXCHANGE PARTITION with generated columns containing AND/OR conditions
|
||||
--echo # This verifies set comparison of generated column conditions during
|
||||
--echo # partition exchange.
|
||||
|
||||
--echo # Test 1: Generated column with OR condition
|
||||
CREATE TABLE t1 (
|
||||
id INT NOT NULL AUTO_INCREMENT,
|
||||
userId INT NOT NULL,
|
||||
col1 INT NOT NULL,
|
||||
vcol1 TINYINT(1) GENERATED ALWAYS AS (col1 > 80 OR col1 < 20) STORED,
|
||||
PRIMARY KEY (id, userId)
|
||||
) DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
||||
PARTITION BY LIST (userId)
|
||||
(PARTITION p1 VALUES IN (1),
|
||||
PARTITION p2 VALUES IN (2));
|
||||
|
||||
CREATE TABLE t1_working LIKE t1;
|
||||
ALTER TABLE t1_working REMOVE PARTITIONING;
|
||||
|
||||
INSERT INTO t1_working (userId, col1) VALUES (1, 10), (1, 50), (1, 90);
|
||||
|
||||
--echo # This should succeed: EXCHANGE PARTITION with OR condition
|
||||
ALTER TABLE t1 EXCHANGE PARTITION p1 WITH TABLE t1_working;
|
||||
|
||||
SELECT id, userId, col1, vcol1 FROM t1 ORDER BY id;
|
||||
DROP TABLE t1_working;
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo # Test 2: Generated column with AND condition
|
||||
CREATE TABLE t1 (
|
||||
id INT NOT NULL AUTO_INCREMENT,
|
||||
userId INT NOT NULL,
|
||||
col1 INT NOT NULL,
|
||||
col2 INT NOT NULL,
|
||||
vcol2 TINYINT(1) GENERATED ALWAYS AS (col1 > 10 AND col2 < 100) STORED,
|
||||
PRIMARY KEY (id, userId)
|
||||
) DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
||||
PARTITION BY LIST (userId)
|
||||
(PARTITION p1 VALUES IN (1));
|
||||
|
||||
CREATE TABLE t1_working LIKE t1;
|
||||
ALTER TABLE t1_working REMOVE PARTITIONING;
|
||||
|
||||
INSERT INTO t1_working (userId, col1, col2) VALUES (1, 20, 50), (1, 5, 200);
|
||||
|
||||
--echo # This should succeed: EXCHANGE PARTITION with AND condition
|
||||
ALTER TABLE t1 EXCHANGE PARTITION p1 WITH TABLE t1_working;
|
||||
|
||||
SELECT id, userId, col1, col2, vcol2 FROM t1 ORDER BY id;
|
||||
DROP TABLE t1_working;
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo # Test 3: Multiple generated columns with different AND/OR combinations
|
||||
CREATE TABLE t1 (
|
||||
id INT NOT NULL AUTO_INCREMENT,
|
||||
userId INT NOT NULL,
|
||||
col1 INT NOT NULL,
|
||||
col2 INT NOT NULL,
|
||||
vcol1 TINYINT(1) GENERATED ALWAYS AS (col1 > 80 OR col1 < 20) STORED,
|
||||
vcol2 TINYINT(1) GENERATED ALWAYS AS (col1 > 10 AND col2 < 100) STORED,
|
||||
vcol3 TINYINT(1) GENERATED ALWAYS AS (col2 > 50 OR col2 < 10) STORED,
|
||||
PRIMARY KEY (id, userId)
|
||||
) DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
||||
PARTITION BY LIST (userId)
|
||||
(PARTITION p1 VALUES IN (1),
|
||||
PARTITION p2 VALUES IN (2));
|
||||
|
||||
CREATE TABLE t1_working LIKE t1;
|
||||
ALTER TABLE t1_working REMOVE PARTITIONING;
|
||||
|
||||
INSERT INTO t1_working (userId, col1, col2) VALUES (1, 15, 75), (1, 90, 5), (1, 50, 200);
|
||||
|
||||
--echo # This should succeed: EXCHANGE PARTITION with multiple AND/OR conditions
|
||||
ALTER TABLE t1 EXCHANGE PARTITION p1 WITH TABLE t1_working;
|
||||
|
||||
SELECT id, userId, col1, col2, vcol1, vcol2, vcol3 FROM t1 ORDER BY id;
|
||||
DROP TABLE t1_working;
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo # Test 4: Nested AND/OR conditions
|
||||
CREATE TABLE t1 (
|
||||
id INT NOT NULL AUTO_INCREMENT,
|
||||
userId INT NOT NULL,
|
||||
col1 INT NOT NULL,
|
||||
col2 INT NOT NULL,
|
||||
col3 INT NOT NULL,
|
||||
vcol4 TINYINT(1) GENERATED ALWAYS AS ((col1 > 10 AND col2 < 100) OR col3 > 50) STORED,
|
||||
PRIMARY KEY (id, userId)
|
||||
) DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
||||
PARTITION BY LIST (userId)
|
||||
(PARTITION p1 VALUES IN (1));
|
||||
|
||||
CREATE TABLE t1_working LIKE t1;
|
||||
ALTER TABLE t1_working REMOVE PARTITIONING;
|
||||
|
||||
INSERT INTO t1_working (userId, col1, col2, col3) VALUES (1, 20, 50, 30), (1, 5, 200, 60);
|
||||
|
||||
--echo # This should succeed: EXCHANGE PARTITION with nested AND/OR conditions
|
||||
ALTER TABLE t1 EXCHANGE PARTITION p1 WITH TABLE t1_working;
|
||||
|
||||
SELECT id, userId, col1, col2, col3, vcol4 FROM t1 ORDER BY id;
|
||||
DROP TABLE t1_working;
|
||||
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo # Test 5: Reordered condition with a duplicate term
|
||||
CREATE TABLE t1 (
|
||||
id INT NOT NULL AUTO_INCREMENT,
|
||||
userId INT NOT NULL,
|
||||
col1 INT NOT NULL,
|
||||
col2 INT NOT NULL,
|
||||
col3 INT NOT NULL,
|
||||
vcol4 TINYINT(1) GENERATED ALWAYS AS
|
||||
(col1 > 10 AND col2 < 100 OR col3 > 50) STORED,
|
||||
PRIMARY KEY (id, userId)
|
||||
) DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
||||
PARTITION BY LIST (userId)
|
||||
(PARTITION p1 VALUES IN (1));
|
||||
|
||||
CREATE TABLE t1_working (
|
||||
id INT NOT NULL AUTO_INCREMENT,
|
||||
userId INT NOT NULL,
|
||||
col1 INT NOT NULL,
|
||||
col2 INT NOT NULL,
|
||||
col3 INT NOT NULL,
|
||||
vcol4 TINYINT(1) GENERATED ALWAYS AS
|
||||
(col3 > 50 OR col1 > 10 AND col2 < 100 OR col3 > 50) STORED,
|
||||
PRIMARY KEY (id, userId)
|
||||
) DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
INSERT INTO t1_working (userId, col1, col2, col3)
|
||||
VALUES (1, 20, 50, 30), (1, 5, 200, 60);
|
||||
|
||||
ALTER TABLE t1 EXCHANGE PARTITION p1 WITH TABLE t1_working;
|
||||
SELECT id, userId, col1, col2, col3, vcol4 FROM t1 ORDER BY id;
|
||||
|
||||
DROP TABLE t1_working;
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo # End of 10.11 tests
|
||||
|
||||
@@ -373,3 +373,136 @@ a b
|
||||
63 Sixty three, new
|
||||
99 End of values
|
||||
DROP TABLE t, tp, tsp;
|
||||
#
|
||||
# MDEV-38757 Exchange partition fails with compound expressions
|
||||
#
|
||||
# Test EXCHANGE PARTITION with generated columns containing AND/OR conditions
|
||||
# This verifies set comparison of generated column conditions during
|
||||
# partition exchange.
|
||||
# Test 1: Generated column with OR condition
|
||||
CREATE TABLE t1 (
|
||||
id INT NOT NULL AUTO_INCREMENT,
|
||||
userId INT NOT NULL,
|
||||
col1 INT NOT NULL,
|
||||
vcol1 TINYINT(1) GENERATED ALWAYS AS (col1 > 80 OR col1 < 20) STORED,
|
||||
PRIMARY KEY (id, userId)
|
||||
) DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
||||
PARTITION BY LIST (userId)
|
||||
(PARTITION p1 VALUES IN (1),
|
||||
PARTITION p2 VALUES IN (2));
|
||||
CREATE TABLE t1_working LIKE t1;
|
||||
ALTER TABLE t1_working REMOVE PARTITIONING;
|
||||
INSERT INTO t1_working (userId, col1) VALUES (1, 10), (1, 50), (1, 90);
|
||||
# This should succeed: EXCHANGE PARTITION with OR condition
|
||||
ALTER TABLE t1 EXCHANGE PARTITION p1 WITH TABLE t1_working;
|
||||
SELECT id, userId, col1, vcol1 FROM t1 ORDER BY id;
|
||||
id userId col1 vcol1
|
||||
1 1 10 1
|
||||
2 1 50 0
|
||||
3 1 90 1
|
||||
DROP TABLE t1_working;
|
||||
DROP TABLE t1;
|
||||
# Test 2: Generated column with AND condition
|
||||
CREATE TABLE t1 (
|
||||
id INT NOT NULL AUTO_INCREMENT,
|
||||
userId INT NOT NULL,
|
||||
col1 INT NOT NULL,
|
||||
col2 INT NOT NULL,
|
||||
vcol2 TINYINT(1) GENERATED ALWAYS AS (col1 > 10 AND col2 < 100) STORED,
|
||||
PRIMARY KEY (id, userId)
|
||||
) DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
||||
PARTITION BY LIST (userId)
|
||||
(PARTITION p1 VALUES IN (1));
|
||||
CREATE TABLE t1_working LIKE t1;
|
||||
ALTER TABLE t1_working REMOVE PARTITIONING;
|
||||
INSERT INTO t1_working (userId, col1, col2) VALUES (1, 20, 50), (1, 5, 200);
|
||||
# This should succeed: EXCHANGE PARTITION with AND condition
|
||||
ALTER TABLE t1 EXCHANGE PARTITION p1 WITH TABLE t1_working;
|
||||
SELECT id, userId, col1, col2, vcol2 FROM t1 ORDER BY id;
|
||||
id userId col1 col2 vcol2
|
||||
1 1 20 50 1
|
||||
2 1 5 200 0
|
||||
DROP TABLE t1_working;
|
||||
DROP TABLE t1;
|
||||
# Test 3: Multiple generated columns with different AND/OR combinations
|
||||
CREATE TABLE t1 (
|
||||
id INT NOT NULL AUTO_INCREMENT,
|
||||
userId INT NOT NULL,
|
||||
col1 INT NOT NULL,
|
||||
col2 INT NOT NULL,
|
||||
vcol1 TINYINT(1) GENERATED ALWAYS AS (col1 > 80 OR col1 < 20) STORED,
|
||||
vcol2 TINYINT(1) GENERATED ALWAYS AS (col1 > 10 AND col2 < 100) STORED,
|
||||
vcol3 TINYINT(1) GENERATED ALWAYS AS (col2 > 50 OR col2 < 10) STORED,
|
||||
PRIMARY KEY (id, userId)
|
||||
) DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
||||
PARTITION BY LIST (userId)
|
||||
(PARTITION p1 VALUES IN (1),
|
||||
PARTITION p2 VALUES IN (2));
|
||||
CREATE TABLE t1_working LIKE t1;
|
||||
ALTER TABLE t1_working REMOVE PARTITIONING;
|
||||
INSERT INTO t1_working (userId, col1, col2) VALUES (1, 15, 75), (1, 90, 5), (1, 50, 200);
|
||||
# This should succeed: EXCHANGE PARTITION with multiple AND/OR conditions
|
||||
ALTER TABLE t1 EXCHANGE PARTITION p1 WITH TABLE t1_working;
|
||||
SELECT id, userId, col1, col2, vcol1, vcol2, vcol3 FROM t1 ORDER BY id;
|
||||
id userId col1 col2 vcol1 vcol2 vcol3
|
||||
1 1 15 75 1 1 1
|
||||
2 1 90 5 1 1 1
|
||||
3 1 50 200 0 0 1
|
||||
DROP TABLE t1_working;
|
||||
DROP TABLE t1;
|
||||
# Test 4: Nested AND/OR conditions
|
||||
CREATE TABLE t1 (
|
||||
id INT NOT NULL AUTO_INCREMENT,
|
||||
userId INT NOT NULL,
|
||||
col1 INT NOT NULL,
|
||||
col2 INT NOT NULL,
|
||||
col3 INT NOT NULL,
|
||||
vcol4 TINYINT(1) GENERATED ALWAYS AS ((col1 > 10 AND col2 < 100) OR col3 > 50) STORED,
|
||||
PRIMARY KEY (id, userId)
|
||||
) DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
||||
PARTITION BY LIST (userId)
|
||||
(PARTITION p1 VALUES IN (1));
|
||||
CREATE TABLE t1_working LIKE t1;
|
||||
ALTER TABLE t1_working REMOVE PARTITIONING;
|
||||
INSERT INTO t1_working (userId, col1, col2, col3) VALUES (1, 20, 50, 30), (1, 5, 200, 60);
|
||||
# This should succeed: EXCHANGE PARTITION with nested AND/OR conditions
|
||||
ALTER TABLE t1 EXCHANGE PARTITION p1 WITH TABLE t1_working;
|
||||
SELECT id, userId, col1, col2, col3, vcol4 FROM t1 ORDER BY id;
|
||||
id userId col1 col2 col3 vcol4
|
||||
1 1 20 50 30 1
|
||||
2 1 5 200 60 1
|
||||
DROP TABLE t1_working;
|
||||
DROP TABLE t1;
|
||||
# Test 5: Reordered condition with a duplicate term
|
||||
CREATE TABLE t1 (
|
||||
id INT NOT NULL AUTO_INCREMENT,
|
||||
userId INT NOT NULL,
|
||||
col1 INT NOT NULL,
|
||||
col2 INT NOT NULL,
|
||||
col3 INT NOT NULL,
|
||||
vcol4 TINYINT(1) GENERATED ALWAYS AS
|
||||
(col1 > 10 AND col2 < 100 OR col3 > 50) STORED,
|
||||
PRIMARY KEY (id, userId)
|
||||
) DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
||||
PARTITION BY LIST (userId)
|
||||
(PARTITION p1 VALUES IN (1));
|
||||
CREATE TABLE t1_working (
|
||||
id INT NOT NULL AUTO_INCREMENT,
|
||||
userId INT NOT NULL,
|
||||
col1 INT NOT NULL,
|
||||
col2 INT NOT NULL,
|
||||
col3 INT NOT NULL,
|
||||
vcol4 TINYINT(1) GENERATED ALWAYS AS
|
||||
(col3 > 50 OR col1 > 10 AND col2 < 100 OR col3 > 50) STORED,
|
||||
PRIMARY KEY (id, userId)
|
||||
) DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
INSERT INTO t1_working (userId, col1, col2, col3)
|
||||
VALUES (1, 20, 50, 30), (1, 5, 200, 60);
|
||||
ALTER TABLE t1 EXCHANGE PARTITION p1 WITH TABLE t1_working;
|
||||
SELECT id, userId, col1, col2, col3, vcol4 FROM t1 ORDER BY id;
|
||||
id userId col1 col2 col3 vcol4
|
||||
1 1 20 50 30 1
|
||||
2 1 5 200 60 1
|
||||
DROP TABLE t1_working;
|
||||
DROP TABLE t1;
|
||||
# End of 10.11 tests
|
||||
|
||||
@@ -373,3 +373,136 @@ a b
|
||||
63 Sixty three, new
|
||||
99 End of values
|
||||
DROP TABLE t, tp, tsp;
|
||||
#
|
||||
# MDEV-38757 Exchange partition fails with compound expressions
|
||||
#
|
||||
# Test EXCHANGE PARTITION with generated columns containing AND/OR conditions
|
||||
# This verifies set comparison of generated column conditions during
|
||||
# partition exchange.
|
||||
# Test 1: Generated column with OR condition
|
||||
CREATE TABLE t1 (
|
||||
id INT NOT NULL AUTO_INCREMENT,
|
||||
userId INT NOT NULL,
|
||||
col1 INT NOT NULL,
|
||||
vcol1 TINYINT(1) GENERATED ALWAYS AS (col1 > 80 OR col1 < 20) STORED,
|
||||
PRIMARY KEY (id, userId)
|
||||
) DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
||||
PARTITION BY LIST (userId)
|
||||
(PARTITION p1 VALUES IN (1),
|
||||
PARTITION p2 VALUES IN (2));
|
||||
CREATE TABLE t1_working LIKE t1;
|
||||
ALTER TABLE t1_working REMOVE PARTITIONING;
|
||||
INSERT INTO t1_working (userId, col1) VALUES (1, 10), (1, 50), (1, 90);
|
||||
# This should succeed: EXCHANGE PARTITION with OR condition
|
||||
ALTER TABLE t1 EXCHANGE PARTITION p1 WITH TABLE t1_working;
|
||||
SELECT id, userId, col1, vcol1 FROM t1 ORDER BY id;
|
||||
id userId col1 vcol1
|
||||
1 1 10 1
|
||||
2 1 50 0
|
||||
3 1 90 1
|
||||
DROP TABLE t1_working;
|
||||
DROP TABLE t1;
|
||||
# Test 2: Generated column with AND condition
|
||||
CREATE TABLE t1 (
|
||||
id INT NOT NULL AUTO_INCREMENT,
|
||||
userId INT NOT NULL,
|
||||
col1 INT NOT NULL,
|
||||
col2 INT NOT NULL,
|
||||
vcol2 TINYINT(1) GENERATED ALWAYS AS (col1 > 10 AND col2 < 100) STORED,
|
||||
PRIMARY KEY (id, userId)
|
||||
) DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
||||
PARTITION BY LIST (userId)
|
||||
(PARTITION p1 VALUES IN (1));
|
||||
CREATE TABLE t1_working LIKE t1;
|
||||
ALTER TABLE t1_working REMOVE PARTITIONING;
|
||||
INSERT INTO t1_working (userId, col1, col2) VALUES (1, 20, 50), (1, 5, 200);
|
||||
# This should succeed: EXCHANGE PARTITION with AND condition
|
||||
ALTER TABLE t1 EXCHANGE PARTITION p1 WITH TABLE t1_working;
|
||||
SELECT id, userId, col1, col2, vcol2 FROM t1 ORDER BY id;
|
||||
id userId col1 col2 vcol2
|
||||
1 1 20 50 1
|
||||
2 1 5 200 0
|
||||
DROP TABLE t1_working;
|
||||
DROP TABLE t1;
|
||||
# Test 3: Multiple generated columns with different AND/OR combinations
|
||||
CREATE TABLE t1 (
|
||||
id INT NOT NULL AUTO_INCREMENT,
|
||||
userId INT NOT NULL,
|
||||
col1 INT NOT NULL,
|
||||
col2 INT NOT NULL,
|
||||
vcol1 TINYINT(1) GENERATED ALWAYS AS (col1 > 80 OR col1 < 20) STORED,
|
||||
vcol2 TINYINT(1) GENERATED ALWAYS AS (col1 > 10 AND col2 < 100) STORED,
|
||||
vcol3 TINYINT(1) GENERATED ALWAYS AS (col2 > 50 OR col2 < 10) STORED,
|
||||
PRIMARY KEY (id, userId)
|
||||
) DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
||||
PARTITION BY LIST (userId)
|
||||
(PARTITION p1 VALUES IN (1),
|
||||
PARTITION p2 VALUES IN (2));
|
||||
CREATE TABLE t1_working LIKE t1;
|
||||
ALTER TABLE t1_working REMOVE PARTITIONING;
|
||||
INSERT INTO t1_working (userId, col1, col2) VALUES (1, 15, 75), (1, 90, 5), (1, 50, 200);
|
||||
# This should succeed: EXCHANGE PARTITION with multiple AND/OR conditions
|
||||
ALTER TABLE t1 EXCHANGE PARTITION p1 WITH TABLE t1_working;
|
||||
SELECT id, userId, col1, col2, vcol1, vcol2, vcol3 FROM t1 ORDER BY id;
|
||||
id userId col1 col2 vcol1 vcol2 vcol3
|
||||
1 1 15 75 1 1 1
|
||||
2 1 90 5 1 1 1
|
||||
3 1 50 200 0 0 1
|
||||
DROP TABLE t1_working;
|
||||
DROP TABLE t1;
|
||||
# Test 4: Nested AND/OR conditions
|
||||
CREATE TABLE t1 (
|
||||
id INT NOT NULL AUTO_INCREMENT,
|
||||
userId INT NOT NULL,
|
||||
col1 INT NOT NULL,
|
||||
col2 INT NOT NULL,
|
||||
col3 INT NOT NULL,
|
||||
vcol4 TINYINT(1) GENERATED ALWAYS AS ((col1 > 10 AND col2 < 100) OR col3 > 50) STORED,
|
||||
PRIMARY KEY (id, userId)
|
||||
) DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
||||
PARTITION BY LIST (userId)
|
||||
(PARTITION p1 VALUES IN (1));
|
||||
CREATE TABLE t1_working LIKE t1;
|
||||
ALTER TABLE t1_working REMOVE PARTITIONING;
|
||||
INSERT INTO t1_working (userId, col1, col2, col3) VALUES (1, 20, 50, 30), (1, 5, 200, 60);
|
||||
# This should succeed: EXCHANGE PARTITION with nested AND/OR conditions
|
||||
ALTER TABLE t1 EXCHANGE PARTITION p1 WITH TABLE t1_working;
|
||||
SELECT id, userId, col1, col2, col3, vcol4 FROM t1 ORDER BY id;
|
||||
id userId col1 col2 col3 vcol4
|
||||
1 1 20 50 30 1
|
||||
2 1 5 200 60 1
|
||||
DROP TABLE t1_working;
|
||||
DROP TABLE t1;
|
||||
# Test 5: Reordered condition with a duplicate term
|
||||
CREATE TABLE t1 (
|
||||
id INT NOT NULL AUTO_INCREMENT,
|
||||
userId INT NOT NULL,
|
||||
col1 INT NOT NULL,
|
||||
col2 INT NOT NULL,
|
||||
col3 INT NOT NULL,
|
||||
vcol4 TINYINT(1) GENERATED ALWAYS AS
|
||||
(col1 > 10 AND col2 < 100 OR col3 > 50) STORED,
|
||||
PRIMARY KEY (id, userId)
|
||||
) DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
||||
PARTITION BY LIST (userId)
|
||||
(PARTITION p1 VALUES IN (1));
|
||||
CREATE TABLE t1_working (
|
||||
id INT NOT NULL AUTO_INCREMENT,
|
||||
userId INT NOT NULL,
|
||||
col1 INT NOT NULL,
|
||||
col2 INT NOT NULL,
|
||||
col3 INT NOT NULL,
|
||||
vcol4 TINYINT(1) GENERATED ALWAYS AS
|
||||
(col3 > 50 OR col1 > 10 AND col2 < 100 OR col3 > 50) STORED,
|
||||
PRIMARY KEY (id, userId)
|
||||
) DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
INSERT INTO t1_working (userId, col1, col2, col3)
|
||||
VALUES (1, 20, 50, 30), (1, 5, 200, 60);
|
||||
ALTER TABLE t1 EXCHANGE PARTITION p1 WITH TABLE t1_working;
|
||||
SELECT id, userId, col1, col2, col3, vcol4 FROM t1 ORDER BY id;
|
||||
id userId col1 col2 col3 vcol4
|
||||
1 1 20 50 30 1
|
||||
2 1 5 200 60 1
|
||||
DROP TABLE t1_working;
|
||||
DROP TABLE t1;
|
||||
# End of 10.11 tests
|
||||
|
||||
@@ -373,3 +373,136 @@ a b
|
||||
63 Sixty three, new
|
||||
99 End of values
|
||||
DROP TABLE t, tp, tsp;
|
||||
#
|
||||
# MDEV-38757 Exchange partition fails with compound expressions
|
||||
#
|
||||
# Test EXCHANGE PARTITION with generated columns containing AND/OR conditions
|
||||
# This verifies set comparison of generated column conditions during
|
||||
# partition exchange.
|
||||
# Test 1: Generated column with OR condition
|
||||
CREATE TABLE t1 (
|
||||
id INT NOT NULL AUTO_INCREMENT,
|
||||
userId INT NOT NULL,
|
||||
col1 INT NOT NULL,
|
||||
vcol1 TINYINT(1) GENERATED ALWAYS AS (col1 > 80 OR col1 < 20) STORED,
|
||||
PRIMARY KEY (id, userId)
|
||||
) DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
||||
PARTITION BY LIST (userId)
|
||||
(PARTITION p1 VALUES IN (1),
|
||||
PARTITION p2 VALUES IN (2));
|
||||
CREATE TABLE t1_working LIKE t1;
|
||||
ALTER TABLE t1_working REMOVE PARTITIONING;
|
||||
INSERT INTO t1_working (userId, col1) VALUES (1, 10), (1, 50), (1, 90);
|
||||
# This should succeed: EXCHANGE PARTITION with OR condition
|
||||
ALTER TABLE t1 EXCHANGE PARTITION p1 WITH TABLE t1_working;
|
||||
SELECT id, userId, col1, vcol1 FROM t1 ORDER BY id;
|
||||
id userId col1 vcol1
|
||||
1 1 10 1
|
||||
2 1 50 0
|
||||
3 1 90 1
|
||||
DROP TABLE t1_working;
|
||||
DROP TABLE t1;
|
||||
# Test 2: Generated column with AND condition
|
||||
CREATE TABLE t1 (
|
||||
id INT NOT NULL AUTO_INCREMENT,
|
||||
userId INT NOT NULL,
|
||||
col1 INT NOT NULL,
|
||||
col2 INT NOT NULL,
|
||||
vcol2 TINYINT(1) GENERATED ALWAYS AS (col1 > 10 AND col2 < 100) STORED,
|
||||
PRIMARY KEY (id, userId)
|
||||
) DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
||||
PARTITION BY LIST (userId)
|
||||
(PARTITION p1 VALUES IN (1));
|
||||
CREATE TABLE t1_working LIKE t1;
|
||||
ALTER TABLE t1_working REMOVE PARTITIONING;
|
||||
INSERT INTO t1_working (userId, col1, col2) VALUES (1, 20, 50), (1, 5, 200);
|
||||
# This should succeed: EXCHANGE PARTITION with AND condition
|
||||
ALTER TABLE t1 EXCHANGE PARTITION p1 WITH TABLE t1_working;
|
||||
SELECT id, userId, col1, col2, vcol2 FROM t1 ORDER BY id;
|
||||
id userId col1 col2 vcol2
|
||||
1 1 20 50 1
|
||||
2 1 5 200 0
|
||||
DROP TABLE t1_working;
|
||||
DROP TABLE t1;
|
||||
# Test 3: Multiple generated columns with different AND/OR combinations
|
||||
CREATE TABLE t1 (
|
||||
id INT NOT NULL AUTO_INCREMENT,
|
||||
userId INT NOT NULL,
|
||||
col1 INT NOT NULL,
|
||||
col2 INT NOT NULL,
|
||||
vcol1 TINYINT(1) GENERATED ALWAYS AS (col1 > 80 OR col1 < 20) STORED,
|
||||
vcol2 TINYINT(1) GENERATED ALWAYS AS (col1 > 10 AND col2 < 100) STORED,
|
||||
vcol3 TINYINT(1) GENERATED ALWAYS AS (col2 > 50 OR col2 < 10) STORED,
|
||||
PRIMARY KEY (id, userId)
|
||||
) DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
||||
PARTITION BY LIST (userId)
|
||||
(PARTITION p1 VALUES IN (1),
|
||||
PARTITION p2 VALUES IN (2));
|
||||
CREATE TABLE t1_working LIKE t1;
|
||||
ALTER TABLE t1_working REMOVE PARTITIONING;
|
||||
INSERT INTO t1_working (userId, col1, col2) VALUES (1, 15, 75), (1, 90, 5), (1, 50, 200);
|
||||
# This should succeed: EXCHANGE PARTITION with multiple AND/OR conditions
|
||||
ALTER TABLE t1 EXCHANGE PARTITION p1 WITH TABLE t1_working;
|
||||
SELECT id, userId, col1, col2, vcol1, vcol2, vcol3 FROM t1 ORDER BY id;
|
||||
id userId col1 col2 vcol1 vcol2 vcol3
|
||||
1 1 15 75 1 1 1
|
||||
2 1 90 5 1 1 1
|
||||
3 1 50 200 0 0 1
|
||||
DROP TABLE t1_working;
|
||||
DROP TABLE t1;
|
||||
# Test 4: Nested AND/OR conditions
|
||||
CREATE TABLE t1 (
|
||||
id INT NOT NULL AUTO_INCREMENT,
|
||||
userId INT NOT NULL,
|
||||
col1 INT NOT NULL,
|
||||
col2 INT NOT NULL,
|
||||
col3 INT NOT NULL,
|
||||
vcol4 TINYINT(1) GENERATED ALWAYS AS ((col1 > 10 AND col2 < 100) OR col3 > 50) STORED,
|
||||
PRIMARY KEY (id, userId)
|
||||
) DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
||||
PARTITION BY LIST (userId)
|
||||
(PARTITION p1 VALUES IN (1));
|
||||
CREATE TABLE t1_working LIKE t1;
|
||||
ALTER TABLE t1_working REMOVE PARTITIONING;
|
||||
INSERT INTO t1_working (userId, col1, col2, col3) VALUES (1, 20, 50, 30), (1, 5, 200, 60);
|
||||
# This should succeed: EXCHANGE PARTITION with nested AND/OR conditions
|
||||
ALTER TABLE t1 EXCHANGE PARTITION p1 WITH TABLE t1_working;
|
||||
SELECT id, userId, col1, col2, col3, vcol4 FROM t1 ORDER BY id;
|
||||
id userId col1 col2 col3 vcol4
|
||||
1 1 20 50 30 1
|
||||
2 1 5 200 60 1
|
||||
DROP TABLE t1_working;
|
||||
DROP TABLE t1;
|
||||
# Test 5: Reordered condition with a duplicate term
|
||||
CREATE TABLE t1 (
|
||||
id INT NOT NULL AUTO_INCREMENT,
|
||||
userId INT NOT NULL,
|
||||
col1 INT NOT NULL,
|
||||
col2 INT NOT NULL,
|
||||
col3 INT NOT NULL,
|
||||
vcol4 TINYINT(1) GENERATED ALWAYS AS
|
||||
(col1 > 10 AND col2 < 100 OR col3 > 50) STORED,
|
||||
PRIMARY KEY (id, userId)
|
||||
) DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
||||
PARTITION BY LIST (userId)
|
||||
(PARTITION p1 VALUES IN (1));
|
||||
CREATE TABLE t1_working (
|
||||
id INT NOT NULL AUTO_INCREMENT,
|
||||
userId INT NOT NULL,
|
||||
col1 INT NOT NULL,
|
||||
col2 INT NOT NULL,
|
||||
col3 INT NOT NULL,
|
||||
vcol4 TINYINT(1) GENERATED ALWAYS AS
|
||||
(col3 > 50 OR col1 > 10 AND col2 < 100 OR col3 > 50) STORED,
|
||||
PRIMARY KEY (id, userId)
|
||||
) DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
INSERT INTO t1_working (userId, col1, col2, col3)
|
||||
VALUES (1, 20, 50, 30), (1, 5, 200, 60);
|
||||
ALTER TABLE t1 EXCHANGE PARTITION p1 WITH TABLE t1_working;
|
||||
SELECT id, userId, col1, col2, col3, vcol4 FROM t1 ORDER BY id;
|
||||
id userId col1 col2 col3 vcol4
|
||||
1 1 20 50 30 1
|
||||
2 1 5 200 60 1
|
||||
DROP TABLE t1_working;
|
||||
DROP TABLE t1;
|
||||
# End of 10.11 tests
|
||||
|
||||
@@ -15,3 +15,4 @@ rpl_row_binlog_max_cache_size : MDEV-11092
|
||||
rpl_row_index_choice : MDEV-11666
|
||||
rpl_auto_increment_update_failure : disabled for now
|
||||
rpl_current_user : waits for MDEV-22374 fix
|
||||
rpl_parallel_multi_domain_xa : (2026-07-24) MDEV-34104: waits for MDEV-32020
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
include/master-slave.inc
|
||||
[connection master]
|
||||
connection slave;
|
||||
CHANGE MASTER TO MASTER_DELAY=1 FOR CHANNEL '################################################';
|
||||
ERROR HY000: Could not initialize master info structure for '################################################'; more error messages can be found in the MariaDB error log
|
||||
connection master;
|
||||
CREATE TABLE t1 (a INT);
|
||||
INSERT INTO t1 VALUES (1);
|
||||
connection slave;
|
||||
connection slave;
|
||||
include/diff_tables.inc [master:t1, slave:t1]
|
||||
CHANGE MASTER 'new_channel' TO MASTER_HOST='127.0.0.1', MASTER_PORT=1, MASTER_USER='root';
|
||||
RESET SLAVE 'new_channel' ALL;
|
||||
connection master;
|
||||
DROP TABLE t1;
|
||||
connection slave;
|
||||
include/rpl_end.inc
|
||||
@@ -0,0 +1,40 @@
|
||||
#
|
||||
# CHANGE MASTER ... FOR CHANNEL with a name that overflows the relay
|
||||
# log file name once escaped should return an error, not crash.
|
||||
#
|
||||
# STEPS:
|
||||
# 1. Issue CHANGE MASTER ... FOR CHANNEL with a channel name that is
|
||||
# within MAX_CONNECTION_NAME, but expands past the file name
|
||||
# limit once escaped into the relay log file name.
|
||||
# 2. Verify the statement fails with a clean error, not a crash.
|
||||
# 3. Verify the server is still usable: a normal CHANGE MASTER for a
|
||||
# new, short-named channel succeeds.
|
||||
#
|
||||
--source include/master-slave.inc
|
||||
|
||||
--connection slave
|
||||
--let $channel= `SELECT REPEAT('#', 48)`
|
||||
--error ER_MASTER_INFO
|
||||
eval CHANGE MASTER TO MASTER_DELAY=1 FOR CHANNEL '$channel';
|
||||
|
||||
--connection master
|
||||
CREATE TABLE t1 (a INT);
|
||||
INSERT INTO t1 VALUES (1);
|
||||
--sync_slave_with_master
|
||||
|
||||
--connection slave
|
||||
--let $diff_tables= master:t1, slave:t1
|
||||
--source include/diff_tables.inc
|
||||
|
||||
CHANGE MASTER 'new_channel' TO MASTER_HOST='127.0.0.1', MASTER_PORT=1, MASTER_USER='root';
|
||||
RESET SLAVE 'new_channel' ALL;
|
||||
|
||||
--disable_query_log
|
||||
call mtr.add_suppression("Failed when trying to open logs");
|
||||
--enable_query_log
|
||||
|
||||
--connection master
|
||||
DROP TABLE t1;
|
||||
--sync_slave_with_master
|
||||
|
||||
--source include/rpl_end.inc
|
||||
@@ -655,7 +655,8 @@ public:
|
||||
bool cleanup_session_expr();
|
||||
bool fix_and_check_expr(THD *thd, TABLE *table);
|
||||
bool check_access(THD *thd);
|
||||
inline bool is_equal(const Virtual_column_info* vcol, bool cmp_names) const;
|
||||
inline bool is_equal(const Virtual_column_info* vcol, bool cmp_names,
|
||||
bool unordered_conditions= false) const;
|
||||
inline void print(String*);
|
||||
};
|
||||
|
||||
|
||||
13
sql/item.h
13
sql/item.h
@@ -1274,8 +1274,11 @@ public:
|
||||
{
|
||||
bool binary_cmp; /**< Make binary comparison */
|
||||
bool omit_table_names; /**< Skip table and db names comparison */
|
||||
Eq_config(bool binary_cmp, bool omit_table_names= false)
|
||||
: binary_cmp(binary_cmp), omit_table_names(omit_table_names) {}
|
||||
bool unordered_conditions; /**< Ignore AND/OR operand order and duplicates */
|
||||
Eq_config(bool binary_cmp, bool omit_table_names= false,
|
||||
bool unordered_conditions= false)
|
||||
: binary_cmp(binary_cmp), omit_table_names(omit_table_names),
|
||||
unordered_conditions(unordered_conditions) {}
|
||||
};
|
||||
virtual bool eq(const Item *, const Eq_config &config) const;
|
||||
enum_field_types field_type() const
|
||||
@@ -8433,11 +8436,13 @@ bool fix_escape_item(THD *thd, Item *escape_item, String *tmp_str,
|
||||
int *escape);
|
||||
|
||||
inline bool Virtual_column_info::is_equal(const Virtual_column_info* vcol,
|
||||
bool omit_table_names) const
|
||||
bool omit_table_names,
|
||||
bool unordered_conditions) const
|
||||
{
|
||||
return type_handler() == vcol->type_handler()
|
||||
&& is_stored() == vcol->is_stored()
|
||||
&& expr->eq(vcol->expr, {true, omit_table_names});
|
||||
&& expr->eq(vcol->expr,
|
||||
{true, omit_table_names, unordered_conditions});
|
||||
}
|
||||
|
||||
inline void Virtual_column_info::print(String* str)
|
||||
|
||||
@@ -5638,6 +5638,80 @@ bool Item_cond::excl_dep_on_grouping_fields(st_select_lex *sel)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Compare two Item_cond expressions for equality.
|
||||
|
||||
Distinct AND/OR items are normally not considered equal, preserving their
|
||||
execution order. Some metadata comparisons can explicitly request a set
|
||||
comparison because table definitions may be serialized with their
|
||||
arguments reordered.
|
||||
|
||||
@param item The other Item to compare with
|
||||
@param config Comparison configuration
|
||||
|
||||
@return true if expressions are equivalent, false otherwise
|
||||
*/
|
||||
bool Item_cond::eq(const Item *item, const Eq_config &config) const
|
||||
{
|
||||
if (this == item)
|
||||
return true;
|
||||
|
||||
if (!config.unordered_conditions)
|
||||
return false;
|
||||
|
||||
if (item->type() != COND_ITEM || (used_tables() & RAND_TABLE_BIT))
|
||||
return false;
|
||||
|
||||
const Item_cond *item_cond= (const Item_cond *) item;
|
||||
if (functype() != item_cond->functype())
|
||||
return false;
|
||||
|
||||
/*
|
||||
Treat the argument lists as sets. Checking both directions deliberately
|
||||
ignores duplicate terms: A OR B and A OR B OR A are equivalent here.
|
||||
*/
|
||||
List_iterator_fast<Item> li1(const_cast<List<Item>&>(list));
|
||||
Item *arg1;
|
||||
while ((arg1= li1++))
|
||||
{
|
||||
bool found_match= false;
|
||||
List_iterator_fast<Item> li2(const_cast<List<Item>&>(item_cond->list));
|
||||
Item *arg2;
|
||||
while ((arg2= li2++))
|
||||
{
|
||||
if (arg1->eq(arg2, config))
|
||||
{
|
||||
found_match= true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found_match)
|
||||
return false;
|
||||
}
|
||||
|
||||
List_iterator_fast<Item> li2(const_cast<List<Item>&>(item_cond->list));
|
||||
Item *arg2;
|
||||
while ((arg2= li2++))
|
||||
{
|
||||
bool found_match= false;
|
||||
List_iterator_fast<Item> li1(const_cast<List<Item>&>(list));
|
||||
Item *arg1;
|
||||
while ((arg1= li1++))
|
||||
{
|
||||
if (arg2->eq(arg1, config))
|
||||
{
|
||||
found_match= true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found_match)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void Item_cond_and::mark_as_condition_AND_part(TABLE_LIST *embedding)
|
||||
{
|
||||
List_iterator<Item> li(list);
|
||||
|
||||
@@ -3355,6 +3355,7 @@ public:
|
||||
Item *deep_copy(THD *thd) const override;
|
||||
bool excl_dep_on_table(table_map tab_map) override;
|
||||
bool excl_dep_on_grouping_fields(st_select_lex *sel) override;
|
||||
bool eq(const Item *item, const Eq_config &config) const override;
|
||||
|
||||
private:
|
||||
void merge_sub_condition(List_iterator<Item>& li);
|
||||
|
||||
10
sql/log.cc
10
sql/log.cc
@@ -3717,15 +3717,15 @@ bool MYSQL_BIN_LOG::open_index_file(const char *index_file_name_arg,
|
||||
Create an index file that will hold all file names uses for logging.
|
||||
Add new entries to the end of it.
|
||||
*/
|
||||
myf opt= MY_UNPACK_FILENAME;
|
||||
myf opt= MY_UNPACK_FILENAME | MY_SAFE_PATH;
|
||||
if (!index_file_name_arg)
|
||||
{
|
||||
index_file_name_arg= log_name; // Use same basename for index file
|
||||
opt= MY_UNPACK_FILENAME | MY_REPLACE_EXT;
|
||||
opt= MY_UNPACK_FILENAME | MY_REPLACE_EXT | MY_SAFE_PATH;
|
||||
}
|
||||
fn_format(index_file_name, index_file_name_arg, mysql_data_home,
|
||||
".index", opt);
|
||||
if ((index_file_nr= mysql_file_open(m_key_file_log_index,
|
||||
if (!fn_format(index_file_name, index_file_name_arg, mysql_data_home,
|
||||
".index", opt) ||
|
||||
(index_file_nr= mysql_file_open(m_key_file_log_index,
|
||||
index_file_name,
|
||||
O_RDWR | O_CREAT | O_BINARY | O_CLOEXEC,
|
||||
MYF(MY_WME))) < 0 ||
|
||||
|
||||
@@ -1482,7 +1482,8 @@ bool Master_info_index::remove_master_info(Master_info *mi, bool clear_log_files
|
||||
/* This code is only executed when change_master() failes to create a new master info */
|
||||
|
||||
// Delete any temporary relay log files that could have been created by change_master()
|
||||
mi->rli.relay_log.reset_logs(current_thd, 0, (rpl_gtid*) 0, 0, 0);
|
||||
if (mi->rli.relay_log.is_open())
|
||||
mi->rli.relay_log.reset_logs(current_thd, 0, (rpl_gtid*) 0, 0, 0);
|
||||
/* Delete master-'connection'.info */
|
||||
create_logfile_name_with_suffix(tmp_name,
|
||||
sizeof(tmp_name),
|
||||
|
||||
@@ -248,7 +248,7 @@ bool compare_table_with_partition(THD *thd, TABLE *table, TABLE *part_table,
|
||||
the same, so any table using data/index_file_name will fail.
|
||||
*/
|
||||
if (mysql_compare_tables(table, &part_alter_info, &part_create_info,
|
||||
&metadata_equal))
|
||||
&metadata_equal, true))
|
||||
{
|
||||
my_error(ER_TABLES_DIFFERENT_METADATA, MYF(0));
|
||||
DBUG_RETURN(TRUE);
|
||||
|
||||
@@ -7529,13 +7529,17 @@ static void update_altered_table(const Alter_inplace_info &ha_alter_info,
|
||||
second table.
|
||||
@param[in] create_info Create options for the second table.
|
||||
@param[out] metadata_equal Result of comparison.
|
||||
@param[in] compare_vcol_expr_as_sets
|
||||
Ignore AND/OR order and duplicate terms in
|
||||
generated column expressions.
|
||||
|
||||
@retval true error
|
||||
@retval false success
|
||||
*/
|
||||
|
||||
bool mysql_compare_tables(TABLE *table, Alter_info *alter_info,
|
||||
HA_CREATE_INFO *create_info, bool *metadata_equal)
|
||||
HA_CREATE_INFO *create_info, bool *metadata_equal,
|
||||
bool compare_vcol_expr_as_sets)
|
||||
{
|
||||
DBUG_ENTER("mysql_compare_tables");
|
||||
|
||||
@@ -7604,7 +7608,8 @@ bool mysql_compare_tables(TABLE *table, Alter_info *alter_info,
|
||||
{
|
||||
if (!tmp_new_field->field->vcol_info)
|
||||
DBUG_RETURN(false);
|
||||
if (!field->vcol_info->is_equal(tmp_new_field->field->vcol_info, true))
|
||||
if (!field->vcol_info->is_equal(tmp_new_field->field->vcol_info,
|
||||
true, compare_vcol_expr_as_sets))
|
||||
DBUG_RETURN(false);
|
||||
}
|
||||
|
||||
|
||||
@@ -165,7 +165,8 @@ bool mysql_alter_table(THD *thd, const LEX_CSTRING *new_db,
|
||||
bool mysql_compare_tables(TABLE *table,
|
||||
Alter_info *alter_info,
|
||||
HA_CREATE_INFO *create_info,
|
||||
bool *metadata_equal);
|
||||
bool *metadata_equal,
|
||||
bool compare_vcol_expr_as_sets);
|
||||
bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list,
|
||||
class Recreate_info *recreate_info, bool table_copy);
|
||||
bool mysql_rename_table(handlerton *base, const LEX_CSTRING *old_db,
|
||||
|
||||
@@ -228,11 +228,18 @@ void Wsrep_server_service::log_view(
|
||||
static_cast<Wsrep_high_priority_service*>(high_priority_service);
|
||||
/* Update global system variables */
|
||||
mysql_mutex_lock(&LOCK_global_system_variables);
|
||||
/* The negotiated protocol version gates the writeset format, so it must be
|
||||
picked up regardless of wsrep_auto_increment_control. Leaving it at this
|
||||
node's own maximum would make a node in a cluster that settled on an older
|
||||
version keep emitting the newer format. */
|
||||
if (view.own_index() >= 0)
|
||||
{
|
||||
wsrep_protocol_version= view.protocol_version();
|
||||
}
|
||||
if (wsrep_auto_increment_control && view.own_index() >= 0)
|
||||
{
|
||||
global_system_variables.auto_increment_offset= view.own_index() + 1;
|
||||
global_system_variables.auto_increment_increment= view.members().size();
|
||||
wsrep_protocol_version= view.protocol_version();
|
||||
}
|
||||
mysql_mutex_unlock(&LOCK_global_system_variables);
|
||||
|
||||
|
||||
@@ -6931,10 +6931,31 @@ wsrep_store_key_val_for_row(
|
||||
/* Character set for the field is defined only
|
||||
to fields whose type is string and real field
|
||||
type is not enum or set. For these fields check
|
||||
if character set is multi byte. */
|
||||
if character set is multi byte.
|
||||
|
||||
Fields that InnoDB stores as DATA_BINARY,
|
||||
DATA_FIXBINARY or DATA_BLOB must not be collated
|
||||
here: their bytes are opaque. Note that data types
|
||||
implemented on top of Field_fbt (UUID, INET6, INET4)
|
||||
report type() == MYSQL_TYPE_STRING and charset() ==
|
||||
my_charset_numeric (i.e. latin1), while their values
|
||||
are plain binary and InnoDB maps them to
|
||||
DATA_FIXBINARY. The binary test below mirrors
|
||||
get_innobase_type_from_mysql_type().
|
||||
|
||||
Skipping the collation changes the key bytes on the
|
||||
wire, so it is gated on protocol version 5. Below
|
||||
that version the value is still collated, and
|
||||
wsrep_rec_get_foreign_key() collates the matching
|
||||
reference key the same way, so the two agree in a
|
||||
cluster that has not fully upgraded yet.
|
||||
See MDEV-41012. */
|
||||
if (real_type != MYSQL_TYPE_ENUM
|
||||
&& real_type != MYSQL_TYPE_SET
|
||||
&& (wsrep_protocol_version < 5
|
||||
|| (!field->binary()
|
||||
&& field->key_type()
|
||||
!= HA_KEYTYPE_BINARY))
|
||||
&& ( mysql_type == MYSQL_TYPE_VAR_STRING
|
||||
|| mysql_type == MYSQL_TYPE_STRING)) {
|
||||
|
||||
|
||||
@@ -2667,6 +2667,7 @@ rec_offs_make_nth_extern(
|
||||
}
|
||||
#ifdef WITH_WSREP
|
||||
# include "ha_prototypes.h"
|
||||
# include <mysql/service_wsrep.h> /* wsrep_protocol_version */
|
||||
|
||||
int
|
||||
wsrep_rec_get_foreign_key(
|
||||
@@ -2781,9 +2782,31 @@ wsrep_rec_get_foreign_key(
|
||||
data, len, buf,
|
||||
*buf_len - key_len, false);
|
||||
break;
|
||||
case DATA_FIXBINARY:
|
||||
if (wsrep_protocol_version < 5
|
||||
&& !(col_f->prtype
|
||||
& DATA_BINARY_TYPE)) {
|
||||
/* A UUID, INET6 or INET4 column is
|
||||
stored as fixed length binary, but
|
||||
below protocol version 5
|
||||
wsrep_store_key_val_for_row() still
|
||||
collates the row key of the parent
|
||||
with the character set of the field.
|
||||
Collate the reference key the same
|
||||
way, so that the two match in a
|
||||
cluster that has not fully upgraded
|
||||
yet. See MDEV-41012. */
|
||||
len = wsrep_normalize_string(
|
||||
(int)(col_f->prtype
|
||||
& DATA_MYSQL_TYPE_MASK),
|
||||
dtype_get_charset_coll(
|
||||
col_f->prtype),
|
||||
data, buf, len, *buf_len);
|
||||
break;
|
||||
}
|
||||
/* fall through */
|
||||
case DATA_BLOB:
|
||||
case DATA_BINARY:
|
||||
case DATA_FIXBINARY:
|
||||
case DATA_GEOMETRY:
|
||||
memcpy(buf, data, len);
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user