[Commits] ddc4b7ea106: Support Create_time and Update_time in MyRocks table status
by psergey 18 Sep '19
by psergey 18 Sep '19
18 Sep '19
revision-id: ddc4b7ea106f8a0efdd786f99873f5b06168dc5f (fb-prod201903-144-gddc4b7ea106)
parent(s): d97c0c628e5dc60abd725f6a7120a8d87b09321e
author: Sergei Petrunia
committer: Sergei Petrunia
timestamp: 2019-09-19 00:33:38 +0300
message:
Support Create_time and Update_time in MyRocks table status
- Create_time is stored in the MyRocks' internal data dictionary.
- Update_time is in-memory only (like in InnoDB).
(variant #2, with review input addressed).
---
mysql-test/suite/rocksdb/include/bulk_load.inc | 4 +-
.../suite/rocksdb/include/bulk_load_unsorted.inc | 4 +-
mysql-test/suite/rocksdb/r/bulk_load.result | 12 +--
mysql-test/suite/rocksdb/r/bulk_load_rev_cf.result | 12 +--
.../rocksdb/r/bulk_load_rev_cf_and_data.result | 12 +--
.../suite/rocksdb/r/bulk_load_rev_data.result | 12 +--
.../suite/rocksdb/r/bulk_load_unsorted.result | 12 +--
.../suite/rocksdb/r/bulk_load_unsorted_rev.result | 12 +--
mysql-test/suite/rocksdb/r/issue255.result | 16 ++--
mysql-test/suite/rocksdb/r/rocksdb.result | 6 +-
.../suite/rocksdb/r/show_table_status.result | 85 +++++++++++++++++++++-
.../suite/rocksdb/r/show_table_status_debug.result | 13 ++++
mysql-test/suite/rocksdb/r/truncate_table.result | 8 +-
mysql-test/suite/rocksdb/t/issue255.test | 17 +++--
mysql-test/suite/rocksdb/t/rocksdb.test | 4 +-
mysql-test/suite/rocksdb/t/show_table_status.test | 81 ++++++++++++++++++++-
.../suite/rocksdb/t/show_table_status_debug.test | 21 ++++++
mysql-test/suite/rocksdb/t/truncate_table.test | 8 +-
storage/rocksdb/ha_rocksdb.cc | 38 ++++++++++
storage/rocksdb/rdb_datadic.cc | 56 +++++++++++---
storage/rocksdb/rdb_datadic.h | 15 +++-
storage/rocksdb/rdb_global.h | 2 +
22 files changed, 365 insertions(+), 85 deletions(-)
diff --git a/mysql-test/suite/rocksdb/include/bulk_load.inc b/mysql-test/suite/rocksdb/include/bulk_load.inc
index 1b79825e507..7e163602202 100644
--- a/mysql-test/suite/rocksdb/include/bulk_load.inc
+++ b/mysql-test/suite/rocksdb/include/bulk_load.inc
@@ -121,12 +121,12 @@ set rocksdb_bulk_load=0;
--remove_file $file
# Make sure row count index stats are correct
---replace_column 6 # 7 # 8 # 9 #
+--replace_column 6 # 7 # 8 # 9 # 12 # 13 #
SHOW TABLE STATUS WHERE name LIKE 't%';
ANALYZE TABLE t1, t2, t3;
---replace_column 6 # 7 # 8 # 9 #
+--replace_column 6 # 7 # 8 # 9 # 12 # 13 #
SHOW TABLE STATUS WHERE name LIKE 't%';
# Make sure all the data is there.
diff --git a/mysql-test/suite/rocksdb/include/bulk_load_unsorted.inc b/mysql-test/suite/rocksdb/include/bulk_load_unsorted.inc
index 5cdc76a32d4..812af0401aa 100644
--- a/mysql-test/suite/rocksdb/include/bulk_load_unsorted.inc
+++ b/mysql-test/suite/rocksdb/include/bulk_load_unsorted.inc
@@ -119,12 +119,12 @@ set rocksdb_bulk_load=0;
--remove_file $file
# Make sure row count index stats are correct
---replace_column 6 # 7 # 8 # 9 #
+--replace_column 6 # 7 # 8 # 9 # 12 # 13 #
SHOW TABLE STATUS WHERE name LIKE 't%';
ANALYZE TABLE t1, t2, t3;
---replace_column 6 # 7 # 8 # 9 #
+--replace_column 6 # 7 # 8 # 9 # 12 # 13 #
SHOW TABLE STATUS WHERE name LIKE 't%';
# Make sure all the data is there.
diff --git a/mysql-test/suite/rocksdb/r/bulk_load.result b/mysql-test/suite/rocksdb/r/bulk_load.result
index a36f99a7619..76db28e66bd 100644
--- a/mysql-test/suite/rocksdb/r/bulk_load.result
+++ b/mysql-test/suite/rocksdb/r/bulk_load.result
@@ -38,9 +38,9 @@ pk a b
set rocksdb_bulk_load=0;
SHOW TABLE STATUS WHERE name LIKE 't%';
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-t1 ROCKSDB 10 Fixed 5000000 # # # # 0 NULL NULL NULL NULL latin1_bin NULL
-t2 ROCKSDB 10 Fixed 5000000 # # # # 0 NULL NULL NULL NULL latin1_bin NULL
-t3 ROCKSDB 10 Fixed 5000000 # # # # 0 NULL NULL NULL NULL latin1_bin NULL partitioned
+t1 ROCKSDB 10 Fixed 5000000 # # # # 0 NULL # # NULL latin1_bin NULL
+t2 ROCKSDB 10 Fixed 5000000 # # # # 0 NULL # # NULL latin1_bin NULL
+t3 ROCKSDB 10 Fixed 5000000 # # # # 0 NULL # # NULL latin1_bin NULL partitioned
ANALYZE TABLE t1, t2, t3;
Table Op Msg_type Msg_text
test.t1 analyze status OK
@@ -48,9 +48,9 @@ test.t2 analyze status OK
test.t3 analyze status OK
SHOW TABLE STATUS WHERE name LIKE 't%';
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-t1 ROCKSDB 10 Fixed 5000000 # # # # 0 NULL NULL NULL NULL latin1_bin NULL
-t2 ROCKSDB 10 Fixed 5000000 # # # # 0 NULL NULL NULL NULL latin1_bin NULL
-t3 ROCKSDB 10 Fixed 5000000 # # # # 0 NULL NULL NULL NULL latin1_bin NULL partitioned
+t1 ROCKSDB 10 Fixed 5000000 # # # # 0 NULL # # NULL latin1_bin NULL
+t2 ROCKSDB 10 Fixed 5000000 # # # # 0 NULL # # NULL latin1_bin NULL
+t3 ROCKSDB 10 Fixed 5000000 # # # # 0 NULL # # NULL latin1_bin NULL partitioned
select count(pk) from t1;
count(pk)
5000000
diff --git a/mysql-test/suite/rocksdb/r/bulk_load_rev_cf.result b/mysql-test/suite/rocksdb/r/bulk_load_rev_cf.result
index b5d3e252c5d..ae363f7ec0c 100644
--- a/mysql-test/suite/rocksdb/r/bulk_load_rev_cf.result
+++ b/mysql-test/suite/rocksdb/r/bulk_load_rev_cf.result
@@ -38,9 +38,9 @@ pk a b
set rocksdb_bulk_load=0;
SHOW TABLE STATUS WHERE name LIKE 't%';
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-t1 ROCKSDB 10 Fixed 5000000 # # # # 0 NULL NULL NULL NULL latin1_bin NULL
-t2 ROCKSDB 10 Fixed 5000000 # # # # 0 NULL NULL NULL NULL latin1_bin NULL
-t3 ROCKSDB 10 Fixed 5000000 # # # # 0 NULL NULL NULL NULL latin1_bin NULL partitioned
+t1 ROCKSDB 10 Fixed 5000000 # # # # 0 NULL # # NULL latin1_bin NULL
+t2 ROCKSDB 10 Fixed 5000000 # # # # 0 NULL # # NULL latin1_bin NULL
+t3 ROCKSDB 10 Fixed 5000000 # # # # 0 NULL # # NULL latin1_bin NULL partitioned
ANALYZE TABLE t1, t2, t3;
Table Op Msg_type Msg_text
test.t1 analyze status OK
@@ -48,9 +48,9 @@ test.t2 analyze status OK
test.t3 analyze status OK
SHOW TABLE STATUS WHERE name LIKE 't%';
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-t1 ROCKSDB 10 Fixed 5000000 # # # # 0 NULL NULL NULL NULL latin1_bin NULL
-t2 ROCKSDB 10 Fixed 5000000 # # # # 0 NULL NULL NULL NULL latin1_bin NULL
-t3 ROCKSDB 10 Fixed 5000000 # # # # 0 NULL NULL NULL NULL latin1_bin NULL partitioned
+t1 ROCKSDB 10 Fixed 5000000 # # # # 0 NULL # # NULL latin1_bin NULL
+t2 ROCKSDB 10 Fixed 5000000 # # # # 0 NULL # # NULL latin1_bin NULL
+t3 ROCKSDB 10 Fixed 5000000 # # # # 0 NULL # # NULL latin1_bin NULL partitioned
select count(pk) from t1;
count(pk)
5000000
diff --git a/mysql-test/suite/rocksdb/r/bulk_load_rev_cf_and_data.result b/mysql-test/suite/rocksdb/r/bulk_load_rev_cf_and_data.result
index f46acd41080..dd8dd7e60a8 100644
--- a/mysql-test/suite/rocksdb/r/bulk_load_rev_cf_and_data.result
+++ b/mysql-test/suite/rocksdb/r/bulk_load_rev_cf_and_data.result
@@ -38,9 +38,9 @@ pk a b
set rocksdb_bulk_load=0;
SHOW TABLE STATUS WHERE name LIKE 't%';
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-t1 ROCKSDB 10 Fixed 5000000 # # # # 0 NULL NULL NULL NULL latin1_bin NULL
-t2 ROCKSDB 10 Fixed 5000000 # # # # 0 NULL NULL NULL NULL latin1_bin NULL
-t3 ROCKSDB 10 Fixed 5000000 # # # # 0 NULL NULL NULL NULL latin1_bin NULL partitioned
+t1 ROCKSDB 10 Fixed 5000000 # # # # 0 NULL # # NULL latin1_bin NULL
+t2 ROCKSDB 10 Fixed 5000000 # # # # 0 NULL # # NULL latin1_bin NULL
+t3 ROCKSDB 10 Fixed 5000000 # # # # 0 NULL # # NULL latin1_bin NULL partitioned
ANALYZE TABLE t1, t2, t3;
Table Op Msg_type Msg_text
test.t1 analyze status OK
@@ -48,9 +48,9 @@ test.t2 analyze status OK
test.t3 analyze status OK
SHOW TABLE STATUS WHERE name LIKE 't%';
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-t1 ROCKSDB 10 Fixed 5000000 # # # # 0 NULL NULL NULL NULL latin1_bin NULL
-t2 ROCKSDB 10 Fixed 5000000 # # # # 0 NULL NULL NULL NULL latin1_bin NULL
-t3 ROCKSDB 10 Fixed 5000000 # # # # 0 NULL NULL NULL NULL latin1_bin NULL partitioned
+t1 ROCKSDB 10 Fixed 5000000 # # # # 0 NULL # # NULL latin1_bin NULL
+t2 ROCKSDB 10 Fixed 5000000 # # # # 0 NULL # # NULL latin1_bin NULL
+t3 ROCKSDB 10 Fixed 5000000 # # # # 0 NULL # # NULL latin1_bin NULL partitioned
select count(pk) from t1;
count(pk)
5000000
diff --git a/mysql-test/suite/rocksdb/r/bulk_load_rev_data.result b/mysql-test/suite/rocksdb/r/bulk_load_rev_data.result
index 3389968ef37..96738ae62e2 100644
--- a/mysql-test/suite/rocksdb/r/bulk_load_rev_data.result
+++ b/mysql-test/suite/rocksdb/r/bulk_load_rev_data.result
@@ -38,9 +38,9 @@ pk a b
set rocksdb_bulk_load=0;
SHOW TABLE STATUS WHERE name LIKE 't%';
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-t1 ROCKSDB 10 Fixed 5000000 # # # # 0 NULL NULL NULL NULL latin1_bin NULL
-t2 ROCKSDB 10 Fixed 5000000 # # # # 0 NULL NULL NULL NULL latin1_bin NULL
-t3 ROCKSDB 10 Fixed 5000000 # # # # 0 NULL NULL NULL NULL latin1_bin NULL partitioned
+t1 ROCKSDB 10 Fixed 5000000 # # # # 0 NULL # # NULL latin1_bin NULL
+t2 ROCKSDB 10 Fixed 5000000 # # # # 0 NULL # # NULL latin1_bin NULL
+t3 ROCKSDB 10 Fixed 5000000 # # # # 0 NULL # # NULL latin1_bin NULL partitioned
ANALYZE TABLE t1, t2, t3;
Table Op Msg_type Msg_text
test.t1 analyze status OK
@@ -48,9 +48,9 @@ test.t2 analyze status OK
test.t3 analyze status OK
SHOW TABLE STATUS WHERE name LIKE 't%';
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-t1 ROCKSDB 10 Fixed 5000000 # # # # 0 NULL NULL NULL NULL latin1_bin NULL
-t2 ROCKSDB 10 Fixed 5000000 # # # # 0 NULL NULL NULL NULL latin1_bin NULL
-t3 ROCKSDB 10 Fixed 5000000 # # # # 0 NULL NULL NULL NULL latin1_bin NULL partitioned
+t1 ROCKSDB 10 Fixed 5000000 # # # # 0 NULL # # NULL latin1_bin NULL
+t2 ROCKSDB 10 Fixed 5000000 # # # # 0 NULL # # NULL latin1_bin NULL
+t3 ROCKSDB 10 Fixed 5000000 # # # # 0 NULL # # NULL latin1_bin NULL partitioned
select count(pk) from t1;
count(pk)
5000000
diff --git a/mysql-test/suite/rocksdb/r/bulk_load_unsorted.result b/mysql-test/suite/rocksdb/r/bulk_load_unsorted.result
index 924032549ac..87fc63af2da 100644
--- a/mysql-test/suite/rocksdb/r/bulk_load_unsorted.result
+++ b/mysql-test/suite/rocksdb/r/bulk_load_unsorted.result
@@ -70,9 +70,9 @@ LOAD DATA INFILE <input_file> INTO TABLE t3;
set rocksdb_bulk_load=0;
SHOW TABLE STATUS WHERE name LIKE 't%';
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-t1 ROCKSDB 10 Fixed 5000000 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
-t2 ROCKSDB 10 Fixed 5000000 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
-t3 ROCKSDB 10 Fixed 5000000 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL partitioned
+t1 ROCKSDB 10 Fixed 5000000 # # # # 0 NULL # # NULL latin1_swedish_ci NULL
+t2 ROCKSDB 10 Fixed 5000000 # # # # 0 NULL # # NULL latin1_swedish_ci NULL
+t3 ROCKSDB 10 Fixed 5000000 # # # # 0 NULL # # NULL latin1_swedish_ci NULL partitioned
ANALYZE TABLE t1, t2, t3;
Table Op Msg_type Msg_text
test.t1 analyze status OK
@@ -80,9 +80,9 @@ test.t2 analyze status OK
test.t3 analyze status OK
SHOW TABLE STATUS WHERE name LIKE 't%';
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-t1 ROCKSDB 10 Fixed 5000000 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
-t2 ROCKSDB 10 Fixed 5000000 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
-t3 ROCKSDB 10 Fixed 5000000 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL partitioned
+t1 ROCKSDB 10 Fixed 5000000 # # # # 0 NULL # # NULL latin1_swedish_ci NULL
+t2 ROCKSDB 10 Fixed 5000000 # # # # 0 NULL # # NULL latin1_swedish_ci NULL
+t3 ROCKSDB 10 Fixed 5000000 # # # # 0 NULL # # NULL latin1_swedish_ci NULL partitioned
select count(a) from t1;
count(a)
5000000
diff --git a/mysql-test/suite/rocksdb/r/bulk_load_unsorted_rev.result b/mysql-test/suite/rocksdb/r/bulk_load_unsorted_rev.result
index 3cc9fb8e459..8e0914f0159 100644
--- a/mysql-test/suite/rocksdb/r/bulk_load_unsorted_rev.result
+++ b/mysql-test/suite/rocksdb/r/bulk_load_unsorted_rev.result
@@ -70,9 +70,9 @@ LOAD DATA INFILE <input_file> INTO TABLE t3;
set rocksdb_bulk_load=0;
SHOW TABLE STATUS WHERE name LIKE 't%';
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-t1 ROCKSDB 10 Fixed 5000000 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
-t2 ROCKSDB 10 Fixed 5000000 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
-t3 ROCKSDB 10 Fixed 5000000 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL partitioned
+t1 ROCKSDB 10 Fixed 5000000 # # # # 0 NULL # # NULL latin1_swedish_ci NULL
+t2 ROCKSDB 10 Fixed 5000000 # # # # 0 NULL # # NULL latin1_swedish_ci NULL
+t3 ROCKSDB 10 Fixed 5000000 # # # # 0 NULL # # NULL latin1_swedish_ci NULL partitioned
ANALYZE TABLE t1, t2, t3;
Table Op Msg_type Msg_text
test.t1 analyze status OK
@@ -80,9 +80,9 @@ test.t2 analyze status OK
test.t3 analyze status OK
SHOW TABLE STATUS WHERE name LIKE 't%';
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-t1 ROCKSDB 10 Fixed 5000000 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
-t2 ROCKSDB 10 Fixed 5000000 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
-t3 ROCKSDB 10 Fixed 5000000 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL partitioned
+t1 ROCKSDB 10 Fixed 5000000 # # # # 0 NULL # # NULL latin1_swedish_ci NULL
+t2 ROCKSDB 10 Fixed 5000000 # # # # 0 NULL # # NULL latin1_swedish_ci NULL
+t3 ROCKSDB 10 Fixed 5000000 # # # # 0 NULL # # NULL latin1_swedish_ci NULL partitioned
select count(a) from t1;
count(a)
5000000
diff --git a/mysql-test/suite/rocksdb/r/issue255.result b/mysql-test/suite/rocksdb/r/issue255.result
index c1ce3be2276..b45b3b5afc7 100644
--- a/mysql-test/suite/rocksdb/r/issue255.result
+++ b/mysql-test/suite/rocksdb/r/issue255.result
@@ -2,7 +2,7 @@ CREATE TABLE t1 (pk BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT);
INSERT INTO t1 VALUES (5);
SHOW TABLE STATUS LIKE 't1';
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-t1 ROCKSDB # Fixed # # # # # # 6 NULL NULL NULL latin1_swedish_ci NULL
+t1 ROCKSDB # Fixed # # # # # # 6 # # NULL latin1_swedish_ci NULL
INSERT INTO t1 VALUES ('538647864786478647864');
Warnings:
Warning 1264 Out of range value for column 'pk' at row 1
@@ -12,7 +12,7 @@ pk
9223372036854775807
SHOW TABLE STATUS LIKE 't1';
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-t1 ROCKSDB 10 Fixed 2 22 44 0 0 0 9223372036854775807 NULL NULL NULL latin1_swedish_ci NULL
+t1 ROCKSDB 10 Fixed 2 22 44 0 0 0 9223372036854775807 # # NULL latin1_swedish_ci NULL
INSERT INTO t1 VALUES ();
ERROR 23000: Duplicate entry '9223372036854775807' for key 'PRIMARY'
SELECT * FROM t1;
@@ -21,7 +21,7 @@ pk
9223372036854775807
SHOW TABLE STATUS LIKE 't1';
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-t1 ROCKSDB # Fixed # # # # # # 9223372036854775807 NULL NULL NULL latin1_swedish_ci NULL
+t1 ROCKSDB # Fixed # # # # # # 9223372036854775807 # # NULL latin1_swedish_ci NULL
INSERT INTO t1 VALUES ();
ERROR 23000: Duplicate entry '9223372036854775807' for key 'PRIMARY'
SELECT * FROM t1;
@@ -30,13 +30,13 @@ pk
9223372036854775807
SHOW TABLE STATUS LIKE 't1';
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-t1 ROCKSDB # Fixed # # # # # # 9223372036854775807 NULL NULL NULL latin1_swedish_ci NULL
+t1 ROCKSDB # Fixed # # # # # # 9223372036854775807 # # NULL latin1_swedish_ci NULL
DROP TABLE t1;
CREATE TABLE t1 (pk TINYINT NOT NULL PRIMARY KEY AUTO_INCREMENT);
INSERT INTO t1 VALUES (5);
SHOW TABLE STATUS LIKE 't1';
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-t1 ROCKSDB # Fixed # # # # # # 6 NULL NULL NULL latin1_swedish_ci NULL
+t1 ROCKSDB # Fixed # # # # # # 6 # # NULL latin1_swedish_ci NULL
INSERT INTO t1 VALUES (1000);
Warnings:
Warning 1264 Out of range value for column 'pk' at row 1
@@ -46,7 +46,7 @@ pk
127
SHOW TABLE STATUS LIKE 't1';
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-t1 ROCKSDB # Fixed # # # # # # 127 NULL NULL NULL latin1_swedish_ci NULL
+t1 ROCKSDB # Fixed # # # # # # 127 # # NULL latin1_swedish_ci NULL
INSERT INTO t1 VALUES ();
ERROR 23000: Duplicate entry '127' for key 'PRIMARY'
SELECT * FROM t1;
@@ -55,7 +55,7 @@ pk
127
SHOW TABLE STATUS LIKE 't1';
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-t1 ROCKSDB # Fixed # # # # # # 127 NULL NULL NULL latin1_swedish_ci NULL
+t1 ROCKSDB # Fixed # # # # # # 127 # # NULL latin1_swedish_ci NULL
INSERT INTO t1 VALUES ();
ERROR 23000: Duplicate entry '127' for key 'PRIMARY'
SELECT * FROM t1;
@@ -64,5 +64,5 @@ pk
127
SHOW TABLE STATUS LIKE 't1';
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-t1 ROCKSDB # Fixed # # # # # # 127 NULL NULL NULL latin1_swedish_ci NULL
+t1 ROCKSDB # Fixed # # # # # # 127 # # NULL latin1_swedish_ci NULL
DROP TABLE t1;
diff --git a/mysql-test/suite/rocksdb/r/rocksdb.result b/mysql-test/suite/rocksdb/r/rocksdb.result
index 088eb050f6f..a631d58ac69 100644
--- a/mysql-test/suite/rocksdb/r/rocksdb.result
+++ b/mysql-test/suite/rocksdb/r/rocksdb.result
@@ -1417,7 +1417,7 @@ create table t1 (i int primary key auto_increment) engine=RocksDB;
insert into t1 values (null),(null);
show table status like 't1';
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-t1 ROCKSDB 10 Fixed 1000 0 # 0 0 0 3 NULL NULL NULL latin1_swedish_ci NULL
+t1 ROCKSDB 10 Fixed 1000 0 # 0 0 0 3 # # NULL latin1_swedish_ci NULL
drop table t1;
#
# Fix Issue #4: Crash when using pseudo-unique keys
@@ -2612,7 +2612,7 @@ CREATE TABLE t1(a INT AUTO_INCREMENT KEY);
INSERT INTO t1 VALUES(0),(-1),(0);
SHOW TABLE STATUS LIKE 't1';
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-t1 ROCKSDB 10 Fixed 1000 0 0 0 0 0 3 NULL NULL NULL latin1_swedish_ci NULL
+t1 ROCKSDB 10 Fixed 1000 0 0 0 0 0 3 # # NULL latin1_swedish_ci NULL
SELECT * FROM t1;
a
-1
@@ -2623,7 +2623,7 @@ CREATE TABLE t1(a INT AUTO_INCREMENT KEY);
INSERT INTO t1 VALUES(0),(10),(0);
SHOW TABLE STATUS LIKE 't1';
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-t1 ROCKSDB 10 Fixed 1000 0 0 0 0 0 12 NULL NULL NULL latin1_swedish_ci NULL
+t1 ROCKSDB 10 Fixed 1000 0 0 0 0 0 12 # # NULL latin1_swedish_ci NULL
SELECT * FROM t1;
a
1
diff --git a/mysql-test/suite/rocksdb/r/show_table_status.result b/mysql-test/suite/rocksdb/r/show_table_status.result
index 29140f045e4..345882040ef 100644
--- a/mysql-test/suite/rocksdb/r/show_table_status.result
+++ b/mysql-test/suite/rocksdb/r/show_table_status.result
@@ -7,12 +7,12 @@ set global rocksdb_force_flush_memtable_now = true;
CREATE TABLE t3 (a INT, b CHAR(8), pk INT PRIMARY KEY) ENGINE=rocksdb CHARACTER SET utf8;
SHOW TABLE STATUS WHERE name IN ( 't1', 't2', 't3' );
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-t1 ROCKSDB 10 Fixed 1000 # # 0 0 0 NULL NULL NULL NULL latin1_swedish_ci NULL
-t2 ROCKSDB 10 Fixed 1000 # # 0 0 0 NULL NULL NULL NULL latin1_swedish_ci NULL
-t3 ROCKSDB 10 Fixed 1000 # # 0 0 0 NULL NULL NULL NULL utf8_general_ci NULL
+t1 ROCKSDB 10 Fixed 1000 # # 0 0 0 NULL # # NULL latin1_swedish_ci NULL
+t2 ROCKSDB 10 Fixed 1000 # # 0 0 0 NULL # # NULL latin1_swedish_ci NULL
+t3 ROCKSDB 10 Fixed 1000 # # 0 0 0 NULL # # NULL utf8_general_ci NULL
SHOW TABLE STATUS WHERE name LIKE 't2';
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-t2 ROCKSDB 10 Fixed 1000 # # 0 0 0 NULL NULL NULL NULL latin1_swedish_ci NULL
+t2 ROCKSDB 10 Fixed 1000 # # 0 0 0 NULL # # NULL latin1_swedish_ci NULL
DROP TABLE t1, t2, t3;
CREATE DATABASE `db_new..............................................end`;
USE `db_new..............................................end`;
@@ -22,3 +22,80 @@ SELECT TABLE_SCHEMA, TABLE_NAME FROM information_schema.table_statistics WHERE T
TABLE_SCHEMA db_new..............................................end
TABLE_NAME t1_new..............................................end
DROP DATABASE `db_new..............................................end`;
+#
+# MDEV-17171: Bug: RocksDB Tables do not have "Creation Date"
+#
+use test;
+create table t1 (a int) engine=rocksdb;
+select create_time is not null, update_time, check_time
+from information_schema.tables where table_schema=database() and table_name='t1';
+create_time is not null update_time check_time
+1 NULL NULL
+insert into t1 values (1);
+select create_time is not null, update_time is not null, check_time
+from information_schema.tables where table_schema=database() and table_name='t1';
+create_time is not null update_time is not null check_time
+1 1 NULL
+flush tables;
+select create_time is not null, update_time is not null, check_time
+from information_schema.tables where table_schema=database() and table_name='t1';
+create_time is not null update_time is not null check_time
+1 1 NULL
+select create_time, update_time into @create_tm, @update_tm
+from information_schema.tables
+where table_schema=database() and table_name='t1';
+select sleep(3);
+sleep(3)
+0
+insert into t1 values (2);
+select
+create_time=@create_tm /* should not change */ ,
+timestampdiff(second, @update_tm, update_time) > 2,
+check_time
+from information_schema.tables
+where table_schema=database() and table_name='t1';
+create_time=@create_tm 1
+timestampdiff(second, @update_tm, update_time) > 2 1
+check_time NULL
+#
+# Check how create_time survives ALTER TABLE.
+# First, an ALTER TABLE that re-creates the table:
+alter table t1 add b int;
+select
+create_time<>@create_tm /* should change */,
+create_time IS NOT NULL,
+update_time IS NULL
+from information_schema.tables
+where table_schema=database() and table_name='t1';
+create_time<>@create_tm 1
+create_time IS NOT NULL 1
+update_time IS NULL 1
+insert into t1 values (5,5);
+select create_time, update_time into @create_tm, @update_tm
+from information_schema.tables
+where table_schema=database() and table_name='t1';
+# Then, an in-place ALTER TABLE:
+alter table t1 add key (a);
+select
+create_time=@create_tm /* should not change */,
+update_time
+from information_schema.tables
+where table_schema=database() and table_name='t1';
+create_time=@create_tm 1
+update_time NULL
+#
+# Check what is left after server restart
+#
+# Save t1's creation time
+create table t2 as
+select create_time
+from information_schema.tables
+where table_schema=database() and table_name='t1';
+select
+create_time=(select create_time from t2) /* should change */,
+update_time
+from information_schema.tables
+where table_schema=database() and table_name='t1';
+create_time=(select create_time from t2) 1
+update_time NULL
+drop table t1, t2;
diff --git a/mysql-test/suite/rocksdb/r/show_table_status_debug.result b/mysql-test/suite/rocksdb/r/show_table_status_debug.result
new file mode 100644
index 00000000000..25b36954ef6
--- /dev/null
+++ b/mysql-test/suite/rocksdb/r/show_table_status_debug.result
@@ -0,0 +1,13 @@
+set session debug='+d,myrocks_produce_ddl_entry_v1';
+create table t1 (a int) engine=rocksdb;
+insert into t1 values (123);
+set session debug='-d,myrocks_produce_ddl_entry_v1';
+select * from t1;
+a
+123
+select create_time, update_time
+from information_schema.tables
+where table_schema=database() and table_name='t1';
+create_time update_time
+NULL NULL
+drop table t1;
diff --git a/mysql-test/suite/rocksdb/r/truncate_table.result b/mysql-test/suite/rocksdb/r/truncate_table.result
index 1544256f194..79b266a2453 100644
--- a/mysql-test/suite/rocksdb/r/truncate_table.result
+++ b/mysql-test/suite/rocksdb/r/truncate_table.result
@@ -9,19 +9,19 @@ DROP TABLE t1;
CREATE TABLE t1 (a INT KEY AUTO_INCREMENT, c CHAR(8)) ENGINE=rocksdb;
SHOW TABLE STATUS LIKE 't1';
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-t1 ROCKSDB 10 Fixed # # # 0 0 0 1 NULL NULL NULL latin1_swedish_ci NULL
+t1 ROCKSDB 10 Fixed # # # 0 0 0 1 # # NULL latin1_swedish_ci NULL
INSERT INTO t1 (c) VALUES ('a'),('b'),('c');
SHOW TABLE STATUS LIKE 't1';
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-t1 ROCKSDB 10 Fixed # # # 0 0 0 4 NULL NULL NULL latin1_swedish_ci NULL
+t1 ROCKSDB 10 Fixed # # # 0 0 0 4 # # NULL latin1_swedish_ci NULL
TRUNCATE TABLE t1;
SHOW TABLE STATUS LIKE 't1';
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-t1 ROCKSDB 10 Fixed # # # 0 0 0 1 NULL NULL NULL latin1_swedish_ci NULL
+t1 ROCKSDB 10 Fixed # # # 0 0 0 1 # # NULL latin1_swedish_ci NULL
INSERT INTO t1 (c) VALUES ('d');
SHOW TABLE STATUS LIKE 't1';
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-t1 ROCKSDB 10 Fixed # # # 0 0 0 2 NULL NULL NULL latin1_swedish_ci NULL
+t1 ROCKSDB 10 Fixed # # # 0 0 0 2 # # NULL latin1_swedish_ci NULL
SELECT a,c FROM t1;
a c
1 d
diff --git a/mysql-test/suite/rocksdb/t/issue255.test b/mysql-test/suite/rocksdb/t/issue255.test
index 370dece0c6c..686f45b4056 100644
--- a/mysql-test/suite/rocksdb/t/issue255.test
+++ b/mysql-test/suite/rocksdb/t/issue255.test
@@ -3,24 +3,25 @@
CREATE TABLE t1 (pk BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT);
INSERT INTO t1 VALUES (5);
---replace_column 3 # 5 # 6 # 7 # 8 # 9 # 10 #
+--replace_column 3 # 5 # 6 # 7 # 8 # 9 # 10 # 12 # 13 #
SHOW TABLE STATUS LIKE 't1';
INSERT INTO t1 VALUES ('538647864786478647864');
---replace_column 3 # 5 # 6 # 7 # 8 # 9 # 10 #
+--replace_column 3 # 5 # 6 # 7 # 8 # 9 # 10 # 12 # 13 #
SELECT * FROM t1;
+--replace_column 12 # 13 #
SHOW TABLE STATUS LIKE 't1';
--error ER_DUP_ENTRY
INSERT INTO t1 VALUES ();
SELECT * FROM t1;
---replace_column 3 # 5 # 6 # 7 # 8 # 9 # 10 #
+--replace_column 3 # 5 # 6 # 7 # 8 # 9 # 10 # 12 # 13 #
SHOW TABLE STATUS LIKE 't1';
--error ER_DUP_ENTRY
INSERT INTO t1 VALUES ();
SELECT * FROM t1;
---replace_column 3 # 5 # 6 # 7 # 8 # 9 # 10 #
+--replace_column 3 # 5 # 6 # 7 # 8 # 9 # 10 # 12 # 13 #
SHOW TABLE STATUS LIKE 't1';
DROP TABLE t1;
@@ -28,24 +29,24 @@ DROP TABLE t1;
CREATE TABLE t1 (pk TINYINT NOT NULL PRIMARY KEY AUTO_INCREMENT);
INSERT INTO t1 VALUES (5);
---replace_column 3 # 5 # 6 # 7 # 8 # 9 # 10 #
+--replace_column 3 # 5 # 6 # 7 # 8 # 9 # 10 # 12 # 13 #
SHOW TABLE STATUS LIKE 't1';
INSERT INTO t1 VALUES (1000);
SELECT * FROM t1;
---replace_column 3 # 5 # 6 # 7 # 8 # 9 # 10 #
+--replace_column 3 # 5 # 6 # 7 # 8 # 9 # 10 # 12 # 13 #
SHOW TABLE STATUS LIKE 't1';
--error ER_DUP_ENTRY
INSERT INTO t1 VALUES ();
SELECT * FROM t1;
---replace_column 3 # 5 # 6 # 7 # 8 # 9 # 10 #
+--replace_column 3 # 5 # 6 # 7 # 8 # 9 # 10 # 12 # 13 #
SHOW TABLE STATUS LIKE 't1';
--error ER_DUP_ENTRY
INSERT INTO t1 VALUES ();
SELECT * FROM t1;
---replace_column 3 # 5 # 6 # 7 # 8 # 9 # 10 #
+--replace_column 3 # 5 # 6 # 7 # 8 # 9 # 10 # 12 # 13 #
SHOW TABLE STATUS LIKE 't1';
DROP TABLE t1;
diff --git a/mysql-test/suite/rocksdb/t/rocksdb.test b/mysql-test/suite/rocksdb/t/rocksdb.test
index 5eff0fbf38f..7dcae569c92 100644
--- a/mysql-test/suite/rocksdb/t/rocksdb.test
+++ b/mysql-test/suite/rocksdb/t/rocksdb.test
@@ -1198,7 +1198,7 @@ drop table t1;
create table t1 (i int primary key auto_increment) engine=RocksDB;
insert into t1 values (null),(null);
---replace_column 7 #
+--replace_column 7 # 12 # 13 #
show table status like 't1';
drop table t1;
@@ -1903,11 +1903,13 @@ DROP TABLE t1;
# value is 4 while MyRocks will show it as 3.
CREATE TABLE t1(a INT AUTO_INCREMENT KEY);
INSERT INTO t1 VALUES(0),(-1),(0);
+--replace_column 12 # 13 #
SHOW TABLE STATUS LIKE 't1';
SELECT * FROM t1;
DROP TABLE t1;
CREATE TABLE t1(a INT AUTO_INCREMENT KEY);
INSERT INTO t1 VALUES(0),(10),(0);
+--replace_column 12 # 13 #
SHOW TABLE STATUS LIKE 't1';
SELECT * FROM t1;
DROP TABLE t1;
diff --git a/mysql-test/suite/rocksdb/t/show_table_status.test b/mysql-test/suite/rocksdb/t/show_table_status.test
index 29cc2ccfb5e..59effcc788c 100644
--- a/mysql-test/suite/rocksdb/t/show_table_status.test
+++ b/mysql-test/suite/rocksdb/t/show_table_status.test
@@ -24,7 +24,7 @@ set global rocksdb_force_flush_memtable_now = true;
CREATE TABLE t3 (a INT, b CHAR(8), pk INT PRIMARY KEY) ENGINE=rocksdb CHARACTER SET utf8;
---replace_column 6 # 7 #
+--replace_column 6 # 7 # 12 # 13 #
SHOW TABLE STATUS WHERE name IN ( 't1', 't2', 't3' );
# Some statistics don't get updated as quickly. The Data_length and
@@ -48,7 +48,7 @@ set global rocksdb_force_flush_memtable_now = true;
# We expect the number of rows to be 10000. Data_len and Avg_row_len
# may vary, depending on built-in compression library.
---replace_column 6 # 7 #
+--replace_column 6 # 7 # 12 # 13 #
SHOW TABLE STATUS WHERE name LIKE 't2';
DROP TABLE t1, t2, t3;
@@ -62,3 +62,80 @@ CREATE TABLE `t1_new..............................................end`(a int) en
INSERT INTO `t1_new..............................................end` VALUES (1);
--query_vertical SELECT TABLE_SCHEMA, TABLE_NAME FROM information_schema.table_statistics WHERE TABLE_NAME = 't1_new..............................................end'
DROP DATABASE `db_new..............................................end`;
+--echo #
+--echo # MDEV-17171: Bug: RocksDB Tables do not have "Creation Date"
+--echo #
+use test;
+create table t1 (a int) engine=rocksdb;
+
+select create_time is not null, update_time, check_time
+from information_schema.tables where table_schema=database() and table_name='t1';
+
+insert into t1 values (1);
+select create_time is not null, update_time is not null, check_time
+from information_schema.tables where table_schema=database() and table_name='t1';
+
+flush tables;
+select create_time is not null, update_time is not null, check_time
+from information_schema.tables where table_schema=database() and table_name='t1';
+
+select create_time, update_time into @create_tm, @update_tm
+from information_schema.tables
+where table_schema=database() and table_name='t1';
+
+select sleep(3);
+insert into t1 values (2);
+
+--vertical_results
+select
+ create_time=@create_tm /* should not change */ ,
+ timestampdiff(second, @update_tm, update_time) > 2,
+ check_time
+from information_schema.tables
+where table_schema=database() and table_name='t1';
+
+--echo #
+--echo # Check how create_time survives ALTER TABLE.
+--echo # First, an ALTER TABLE that re-creates the table:
+alter table t1 add b int;
+select
+ create_time<>@create_tm /* should change */,
+ create_time IS NOT NULL,
+ update_time IS NULL
+from information_schema.tables
+where table_schema=database() and table_name='t1';
+
+insert into t1 values (5,5);
+
+select create_time, update_time into @create_tm, @update_tm
+from information_schema.tables
+where table_schema=database() and table_name='t1';
+
+--echo # Then, an in-place ALTER TABLE:
+alter table t1 add key (a);
+
+select
+ create_time=@create_tm /* should not change */,
+ update_time
+from information_schema.tables
+where table_schema=database() and table_name='t1';
+
+--echo #
+--echo # Check what is left after server restart
+--echo #
+
+--echo # Save t1's creation time
+create table t2 as
+select create_time
+from information_schema.tables
+where table_schema=database() and table_name='t1';
+
+--source include/restart_mysqld.inc
+
+select
+ create_time=(select create_time from t2) /* should change */,
+ update_time
+from information_schema.tables
+where table_schema=database() and table_name='t1';
+
+drop table t1, t2;
diff --git a/mysql-test/suite/rocksdb/t/show_table_status_debug.test b/mysql-test/suite/rocksdb/t/show_table_status_debug.test
new file mode 100644
index 00000000000..7dcc023cd68
--- /dev/null
+++ b/mysql-test/suite/rocksdb/t/show_table_status_debug.test
@@ -0,0 +1,21 @@
+--source include/have_rocksdb.inc
+--source include/have_debug.inc
+
+#
+# Check the upgrade from Rdb_key_def::DDL_ENTRY_INDEX_VERSION_1 to _2
+#
+
+set session debug='+d,myrocks_produce_ddl_entry_v1';
+
+create table t1 (a int) engine=rocksdb;
+insert into t1 values (123);
+set session debug='-d,myrocks_produce_ddl_entry_v1';
+
+--source include/restart_mysqld.inc
+
+select * from t1;
+select create_time, update_time
+from information_schema.tables
+where table_schema=database() and table_name='t1';
+
+drop table t1;
diff --git a/mysql-test/suite/rocksdb/t/truncate_table.test b/mysql-test/suite/rocksdb/t/truncate_table.test
index a61488654a3..1001eeb6cde 100644
--- a/mysql-test/suite/rocksdb/t/truncate_table.test
+++ b/mysql-test/suite/rocksdb/t/truncate_table.test
@@ -29,22 +29,22 @@ DROP TABLE t1;
CREATE TABLE t1 (a INT KEY AUTO_INCREMENT, c CHAR(8)) ENGINE=rocksdb;
#--replace_column 2 # 3 # 4 # 5 # 6 # 7 # 8 # 9 # 10 # 12 # 13 # 14 # 15 # 16 # 17 # 18 #
---replace_column 5 # 6 # 7 #
+--replace_column 5 # 6 # 7 # 12 # 13 #
SHOW TABLE STATUS LIKE 't1';
INSERT INTO t1 (c) VALUES ('a'),('b'),('c');
#--replace_column 2 # 3 # 4 # 5 # 6 # 7 # 8 # 9 # 10 # 12 # 13 # 14 # 15 # 16 # 17 # 18 #
---replace_column 5 # 6 # 7 #
+--replace_column 5 # 6 # 7 # 12 # 13 #
SHOW TABLE STATUS LIKE 't1';
TRUNCATE TABLE t1;
#--replace_column 2 # 3 # 4 # 5 # 6 # 7 # 8 # 9 # 10 # 12 # 13 # 14 # 15 # 16 # 17 # 18 #
---replace_column 5 # 6 # 7 #
+--replace_column 5 # 6 # 7 # 12 # 13 #
SHOW TABLE STATUS LIKE 't1';
INSERT INTO t1 (c) VALUES ('d');
#--replace_column 2 # 3 # 4 # 5 # 6 # 7 # 8 # 9 # 10 # 12 # 13 # 14 # 15 # 16 # 17 # 18 #
---replace_column 5 # 6 # 7 #
+--replace_column 5 # 6 # 7 # 12 # 13 #
SHOW TABLE STATUS LIKE 't1';
--sorted_result
diff --git a/storage/rocksdb/ha_rocksdb.cc b/storage/rocksdb/ha_rocksdb.cc
index d6c89087bea..446e2d64c1c 100644
--- a/storage/rocksdb/ha_rocksdb.cc
+++ b/storage/rocksdb/ha_rocksdb.cc
@@ -2456,6 +2456,8 @@ class Rdb_transaction {
bool m_is_delayed_snapshot = false;
bool m_is_two_phase = false;
+ std::unordered_set<Rdb_tbl_def*> modified_tables;
+
private:
/*
Number of write operations this transaction had when we took the last
@@ -3139,6 +3141,25 @@ class Rdb_transaction {
virtual void start_tx() = 0;
virtual void start_stmt() = 0;
+ protected:
+ // Non-virtual functions with actions to be done on transaction start and
+ // commit.
+ void on_commit() {
+ time_t tm;
+ tm = time(nullptr);
+ for (auto &it : modified_tables) {
+ it->update_time = tm;
+ }
+ modified_tables.clear();
+ }
+ void on_rollback() {
+ modified_tables.clear();
+ }
+ public:
+ void log_table_write_op(Rdb_tbl_def *tbl) {
+ modified_tables.insert(tbl);
+ }
+
void set_initial_savepoint() {
/*
Set the initial savepoint. If the first statement in the transaction
@@ -3322,7 +3343,9 @@ class Rdb_transaction_impl : public Rdb_transaction {
goto error;
}
+ on_commit();
error:
+ on_rollback();
/* Save the transaction object to be reused */
release_tx();
@@ -3338,6 +3361,7 @@ class Rdb_transaction_impl : public Rdb_transaction {
public:
void rollback() override {
+ on_rollback();
m_write_count = 0;
m_insert_count = 0;
m_update_count = 0;
@@ -3659,7 +3683,9 @@ class Rdb_writebatch_impl : public Rdb_transaction {
res = true;
goto error;
}
+ on_commit();
error:
+ on_rollback();
reset();
m_write_count = 0;
@@ -3691,6 +3717,7 @@ class Rdb_writebatch_impl : public Rdb_transaction {
}
void rollback() override {
+ on_rollback();
m_write_count = 0;
m_insert_count = 0;
m_update_count = 0;
@@ -7549,6 +7576,7 @@ int ha_rocksdb::create_table(const std::string &table_name,
/* Create table/key descriptions and put them into the data dictionary */
m_tbl_def = new Rdb_tbl_def(table_name);
+ m_tbl_def->set_create_time(time(nullptr));
uint n_keys = table_arg->s->keys;
@@ -10177,6 +10205,8 @@ int ha_rocksdb::update_write_row(const uchar *const old_data,
row_info.tx->incr_insert_count();
}
+ row_info.tx->log_table_write_op(m_tbl_def);
+
if (do_bulk_commit(row_info.tx)) {
DBUG_RETURN(HA_ERR_ROCKSDB_BULK_LOAD);
}
@@ -10648,6 +10678,7 @@ int ha_rocksdb::delete_row(const uchar *const buf) {
}
tx->incr_delete_count();
+ tx->log_table_write_op(m_tbl_def);
if (do_bulk_commit(tx)) {
DBUG_RETURN(HA_ERR_ROCKSDB_BULK_LOAD);
@@ -10802,6 +10833,12 @@ int ha_rocksdb::info(uint flag) {
k->rec_per_key[j] = x;
}
}
+
+ stats.create_time = m_tbl_def->get_create_time();
+ }
+
+ if (flag & HA_STATUS_TIME) {
+ stats.update_time = m_tbl_def->update_time;
}
if (flag & HA_STATUS_ERRKEY) {
@@ -12603,6 +12640,7 @@ bool ha_rocksdb::prepare_inplace_alter_table(
m_tbl_def->m_auto_incr_val.load(std::memory_order_relaxed);
new_tdef->m_hidden_pk_val =
m_tbl_def->m_hidden_pk_val.load(std::memory_order_relaxed);
+ new_tdef->set_create_time(m_tbl_def->get_create_time());
if (create_key_defs(altered_table, new_tdef, table, m_tbl_def)) {
/* Delete the new key descriptors */
diff --git a/storage/rocksdb/rdb_datadic.cc b/storage/rocksdb/rdb_datadic.cc
index c0741a1ce9b..60555215996 100644
--- a/storage/rocksdb/rdb_datadic.cc
+++ b/storage/rocksdb/rdb_datadic.cc
@@ -3514,8 +3514,19 @@ bool Rdb_tbl_def::put_dict(Rdb_dict_manager *const dict,
const rocksdb::Slice &key) {
StringBuffer<8 * Rdb_key_def::PACKED_SIZE> indexes;
indexes.alloc(Rdb_key_def::VERSION_SIZE +
+ Rdb_key_def::TABLE_CREATE_TIMESTAMP_SIZE +
m_key_count * Rdb_key_def::PACKED_SIZE * 2);
- rdb_netstr_append_uint16(&indexes, Rdb_key_def::DDL_ENTRY_INDEX_VERSION);
+ bool simulate_old_version = false;
+
+ DBUG_EXECUTE_IF("myrocks_produce_ddl_entry_v1",
+ simulate_old_version = true; );
+
+ if (simulate_old_version)
+ rdb_netstr_append_uint16(&indexes, Rdb_key_def::DDL_ENTRY_INDEX_VERSION_1);
+ else {
+ rdb_netstr_append_uint16(&indexes, Rdb_key_def::DDL_ENTRY_INDEX_VERSION_2);
+ rdb_netstr_append_uint64(&indexes, create_time);
+ }
for (uint i = 0; i < m_key_count; i++) {
const Rdb_key_def &kd = *m_key_descr_arr[i];
@@ -4015,27 +4026,52 @@ bool Rdb_ddl_manager::init(Rdb_dict_manager *const dict_arg,
Rdb_tbl_def *const tdef =
new Rdb_tbl_def(key, Rdb_key_def::INDEX_NUMBER_SIZE);
- // Now, read the DDLs.
- const int real_val_size = val.size() - Rdb_key_def::VERSION_SIZE;
- if (real_val_size % Rdb_key_def::PACKED_SIZE * 2 > 0) {
+ if (val.size() < Rdb_key_def::VERSION_SIZE) {
// NO_LINT_DEBUG
sql_print_error("RocksDB: Table_store: invalid keylist for table %s",
tdef->full_tablename().c_str());
return true;
}
- tdef->m_key_count = real_val_size / (Rdb_key_def::PACKED_SIZE * 2);
- tdef->m_key_descr_arr = new std::shared_ptr<Rdb_key_def>[tdef->m_key_count];
ptr = reinterpret_cast<const uchar *>(val.data());
const int version = rdb_netbuf_read_uint16(&ptr);
- if (version != Rdb_key_def::DDL_ENTRY_INDEX_VERSION) {
+
+ if (version != Rdb_key_def::DDL_ENTRY_INDEX_VERSION_1 &&
+ version != Rdb_key_def::DDL_ENTRY_INDEX_VERSION_2) {
// NO_LINT_DEBUG
sql_print_error(
"RocksDB: DDL ENTRY Version was not expected."
- "Expected: %d, Actual: %d",
- Rdb_key_def::DDL_ENTRY_INDEX_VERSION, version);
+ "Expected: %d..%d, Actual: %d",
+ Rdb_key_def::DDL_ENTRY_INDEX_VERSION_1,
+ Rdb_key_def::DDL_ENTRY_INDEX_VERSION_2, version);
+ return true;
+ }
+ int real_val_size = val.size() - Rdb_key_def::VERSION_SIZE;
+
+ if (version == Rdb_key_def::DDL_ENTRY_INDEX_VERSION_2) {
+ if (real_val_size < Rdb_key_def::TABLE_CREATE_TIMESTAMP_SIZE) {
+ sql_print_error( "RocksDB: DDL ENTRY V2 doesn't have timestamp");
+ delete tdef;
+ return true;
+ }
+ tdef->set_create_time(rdb_netbuf_read_uint64(&ptr));
+ real_val_size -= Rdb_key_def::TABLE_CREATE_TIMESTAMP_SIZE;
+ }
+ else
+ tdef->set_create_time(0); // shown as SQL NULL.
+
+
+ // Now, read the DDLs.
+ if (real_val_size % Rdb_key_def::PACKED_SIZE * 2 > 0) {
+ // NO_LINT_DEBUG
+ sql_print_error("RocksDB: Table_store: invalid keylist for table %s",
+ tdef->full_tablename().c_str());
return true;
}
+ tdef->m_key_count = real_val_size / (Rdb_key_def::PACKED_SIZE * 2);
+ tdef->m_key_descr_arr = new std::shared_ptr<Rdb_key_def>[tdef->m_key_count];
+
+
ptr_end = ptr + real_val_size;
for (uint keyno = 0; ptr < ptr_end; keyno++) {
GL_INDEX_ID gl_index_id;
@@ -4471,6 +4507,7 @@ bool Rdb_ddl_manager::rename(const std::string &from, const std::string &to,
rec->m_hidden_pk_val.load(std::memory_order_relaxed);
new_rec->m_tbl_stats = rec->m_tbl_stats;
+ new_rec->set_create_time(rec->get_create_time());
// so that it's not free'd when deleting the old rec
rec->m_key_descr_arr = nullptr;
@@ -5538,6 +5575,7 @@ rocksdb::Status Rdb_dict_manager::put_auto_incr_val(
value_writer.to_slice());
}
+
bool Rdb_dict_manager::get_auto_incr_val(const GL_INDEX_ID &gl_index_id,
ulonglong *new_val) const {
Rdb_buf_writer<Rdb_key_def::INDEX_NUMBER_SIZE * 3> key_writer;
diff --git a/storage/rocksdb/rdb_datadic.h b/storage/rocksdb/rdb_datadic.h
index 416857cad38..268e0a513d2 100644
--- a/storage/rocksdb/rdb_datadic.h
+++ b/storage/rocksdb/rdb_datadic.h
@@ -465,6 +465,7 @@ class Rdb_key_def {
CF_NUMBER_SIZE = 4,
CF_FLAG_SIZE = 4,
PACKED_SIZE = 4, // one int
+ TABLE_CREATE_TIMESTAMP_SIZE = 8,
};
// bit flags for combining bools when writing to disk
@@ -506,7 +507,9 @@ class Rdb_key_def {
// Data dictionary schema version. Introduce newer versions
// if changing schema layout
enum {
- DDL_ENTRY_INDEX_VERSION = 1,
+ DDL_ENTRY_INDEX_VERSION_1 = 1,
+ // this includes a 64-bit table_creation_time at the end.
+ DDL_ENTRY_INDEX_VERSION_2 = 2,
CF_DEFINITION_VERSION = 1,
BINLOG_INFO_INDEX_NUMBER_VERSION = 1,
DDL_DROP_INDEX_ONGOING_VERSION = 1,
@@ -1116,6 +1119,12 @@ class Rdb_tbl_def {
~Rdb_tbl_def();
+ // time values are shown in SHOW TABLE STATUS
+ void set_create_time(time_t val) { create_time = val; }
+ time_t get_create_time() { return create_time; }
+
+ time_t update_time = 0; // in-memory only value, maintained right here
+
void check_and_set_read_free_rpl_table();
/* Number of indexes */
@@ -1161,6 +1170,9 @@ class Rdb_tbl_def {
const std::string &base_tablename() const { return m_tablename; }
const std::string &base_partition() const { return m_partition; }
GL_INDEX_ID get_autoincr_gl_index_id();
+
+ private:
+ time_t create_time = 0;
};
/*
@@ -1565,7 +1577,6 @@ class Rdb_dict_manager {
bool overwrite = false) const;
bool get_auto_incr_val(const GL_INDEX_ID &gl_index_id,
ulonglong *new_val) const;
-
private:
/* dropped cf flags */
void delete_cf_flags(rocksdb::WriteBatch *const batch,
diff --git a/storage/rocksdb/rdb_global.h b/storage/rocksdb/rdb_global.h
index d24160ab1c8..2de201db354 100644
--- a/storage/rocksdb/rdb_global.h
+++ b/storage/rocksdb/rdb_global.h
@@ -269,6 +269,8 @@ const char *const RDB_TTL_COL_QUALIFIER = "ttl_col";
#define ROCKSDB_SIZEOF_AUTOINC_VALUE sizeof(longlong)
+#define ROCKSDB_SIZEOF_TABLE_CREATION_TS sizeof(uint64_t)
+
/*
Maximum index prefix length in bytes.
*/
1
0
[Commits] cde9170709c: MDEV-18648: slave_parallel_mode= optimistic default in 10.5
by sujatha 18 Sep '19
by sujatha 18 Sep '19
18 Sep '19
revision-id: cde9170709cec4d64ecf8c4c162be851223206fd (mariadb-10.4.4-331-gcde9170709c)
parent(s): 2eeac537151058d0a695026766389ef1f867dc79
author: Sujatha
committer: Sujatha
timestamp: 2019-09-18 12:45:20 +0530
message:
MDEV-18648: slave_parallel_mode= optimistic default in 10.5
Description:
============
To change CONSERVATIVE @@global.slave_parallel_mode default to OPTIMISTIC in
10.5.
@sql/sys_vars.cc
Changed default parallel_mode to 'OPTIMISTIC'
@sql/sql_class.h
Moved 'wait_for_prior_commit(THD *thd)' method inside sql_class.cc
@sql/sql_class.cc
Added code to check for 'stop_on_error_sub_id' for event groups which get skipped
and don't have any preceding group to wait for.
@sql/rpl_filter.cc
Changed default parallel_mode to 'OPTIMISTIC'
@sql/mysqld.cc
Removed the initialization of 'SLAVE_PARALLEL_CONSERVATIVE' to 'opt_slave_parallel_mode' variable.
@mysql-test/suite/rpl/t/rpl_parallel_mdev6589.test
@mysql-test/suite/rpl/t/rpl_mdev6386.test
Added mtr suppression to ignore 'ER_PRIOR_COMMIT_FAILED'. In case of
OPTIMISTIC mode if a transaction gets killed during "wait_for_prior_commit" it
results in above error "1964". Hence suppression needs to be added for this
error.
@mysql-test/suite/rpl/t/rpl_parallel_conflicts.test
Test has a 'slave.opt' which explicitly sets
slave_parallel_mode='conservative'. When the test ends this mode conflicts
with new default mode. Hence check test case reports an error. The 'slave.opt'
is removed and options are set and reset within test.
@mysql-test/suite/multi_source/info_logs.result
@mysql-test/suite/multi_source/reset_slave.result
@mysql-test/suite/multi_source/simple.result
Result content mismatch in "show slave status" output. This is expected as new
slave_parallel_mode='OPTIMISTIC'.
@mysql-test/include/check-testcase.test
Updated default 'slave_parallel_mode' to 'optimistic'.
@mysql-test/suite/rpl/t/rpl_parallel_analyze_table_hang.test
@mysql-test/suite/rpl/t/rpl_parallel_deadlock_corrupt_binlog.test
@mysql-test/suite/rpl/t/rpl_parallel_domain.test
@mysql-test/suite/rpl/t/rpl_parallel_domain_slave_single_grp.test
@mysql-test/suite/rpl/t/rpl_parallel_free_deferred_event.test
@mysql-test/suite/rpl/t/rpl_parallel_gco_wait_kill.test
@mysql-test/suite/rpl/t/rpl_parallel_gtid_slave_pos_update_fail.test
@mysql-test/suite/rpl/t/rpl_parallel_ignored_errors.test
@mysql-test/suite/rpl/t/rpl_parallel_incorrect_relay_pos.test
@mysql-test/suite/rpl/t/rpl_parallel_innodb_lock_conflict.test
@mysql-test/suite/rpl/t/rpl_parallel_missed_error_handling.test
@mysql-test/suite/rpl/t/rpl_parallel_mode.test
@mysql-test/suite/rpl/t/rpl_parallel_partial_binlog_trans.test
@mysql-test/suite/rpl/t/rpl_parallel_record_gtid_wakeup.test
@mysql-test/suite/rpl/t/rpl_parallel_retry_deadlock.test
@mysql-test/suite/rpl/t/rpl_parallel_rollback_assert.test
@mysql-test/suite/rpl/t/rpl_parallel_single_grpcmt.test
@mysql-test/suite/rpl/t/rpl_parallel_slave_bgc_kill.test
@mysql-test/suite/rpl/t/rpl_parallel_stop_on_con_kill.test
@mysql-test/suite/rpl/t/rpl_parallel_stop_slave.test
@mysql-test/suite/rpl/t/rpl_parallel_wrong_binlog_order.test
@mysql-test/suite/rpl/t/rpl_parallel_wrong_exec_master_pos.test
Refactored rpl_parallel.test into above individual test cases.
rpl_parallel_ignored_errors.test had sporadic failures with following
symptoms.
Problem:
=======
CURRENT_TEST: rpl.rpl_parallel_ignored_errors
--- /test-10.5/mysql-test/suite/rpl/r/rpl_parallel_ignored_errors.result
+++ /test-10.5/mysql-test/suite/rpl/r/rpl_parallel_ignored_errors.reject
@@ -53,6 +53,7 @@
a
31
32
+34
SET sql_slave_skip_counter= 1;
ERROR HY000: When using parallel replication and GTID with multiple
replication domains, @@sql_slave_skip_counter can not be used. Instead,
setting @@gtid_slave_pos explicitly can be used to skip to after a given GTID
position
include/stop_slave_io.inc
@@ -62,7 +63,6 @@
a
31
32
-33
34
connection server_2;
include/stop_slave.inc
Analysis:
=========
In general if there are three groups.
1 - Inserts 32 which fails due to local entry '32' on slave.
2 - Inserts 33
3 - Inserts 34
Each group considers itself as a waiter and it waits for prior group 'waitee'.
This is done in 'register_wait_for_prior_event_group_commit'. If there is no
other parallel group being scheduled then no waitee will be there.
Let us assume 3 groups are being scheduled in parallel.
3-> waits for 2-> waits for->1
'1' upon completion it checks is there any registered subsequent waiter. If
so it wakes up the subsequent waiter with its execution status. This execution
status is stored in wakeup_error.
If '1' failed then it sends corresponding wakeup_error to 2. Then '2' aborts
and it propagates error to '3'. So all further commits are aborted. This
mechanism works only when all transactions reach a stage where they are
waiting for their prior commit to complete.
In case of optimistic following scenario occurs.
1,2,3 are scheduled in parallel.
3 - Reaches group_commit_code waits for 2 to complete.
1 - errors out sets stop_on_error_sub_id=1.
When a group execution results in error its corresponding sub_id is set to
'stop_on_error_sub_id'. Any new groups queued for execution will check if
their sub_id is > stop_on_error_sub_id. If it is true their execution will be
skipped as prior group execution failed. 'skip_event_group=1' will be set.
Since the execution of SQL thread is about to stop we just skip execution of
all the following event groups. We still do all the normal waiting and wakeup
processing between the event groups as a simple way to ensure that everything
is stopped and cleaned up correctly.
Upon error '1' transaction checks for registered waiters. Since no one is
there it simply goes away.
2 - Starts the execution. It checks do I have a waitee.
Since wait_commit_sub_id == entry->last_committed_sub_id no waitee is set.
Secondly: 'entry->stop_on_error_sub_id' is set by '1'st execution. Now
'handle_parallel_thread' code checks if the current group 'sub_id' is greater
than the 'sub_id' set within 'stop_on_error_sub_id'.
Since the above is true 'skip_event_group=true' is set. Simply call
'wait_for_prior_commit' to wakeup all waiters. Group '2' didn't had any
waitee and its execution is skipped. Hence its wakeup_error=0.It sends a
positive wakeup signal to '3'. Which commits. This results in a missed
transaction. i.e 33 is missed.
Fix is to check for 'ston_on_error_sub_id' during wakeup. Please check
sql_class.cc specific changes.
---
mysql-test/include/check-testcase.test | 2 +-
.../suite/binlog_encryption/rpl_parallel.result | 1691 ---------------
.../suite/binlog_encryption/rpl_parallel.test | 1 -
.../rpl_parallel_analyze_table_hang.result | 51 +
.../rpl_parallel_analyze_table_hang.test | 1 +
.../rpl_parallel_deadlock_corrupt_binlog.result | 93 +
.../rpl_parallel_deadlock_corrupt_binlog.test | 1 +
.../binlog_encryption/rpl_parallel_domain.result | 71 +
.../binlog_encryption/rpl_parallel_domain.test | 1 +
.../rpl_parallel_domain_slave_single_grp.result | 101 +
.../rpl_parallel_domain_slave_single_grp.test | 1 +
.../rpl_parallel_free_deferred_event.result | 44 +
.../rpl_parallel_free_deferred_event.test | 1 +
.../rpl_parallel_gco_wait_kill.result | 257 +++
.../rpl_parallel_gco_wait_kill.test | 1 +
.../rpl_parallel_gtid_slave_pos_update_fail.result | 65 +
.../rpl_parallel_gtid_slave_pos_update_fail.test | 1 +
.../rpl_parallel_ignored_errors.result | 74 +
.../rpl_parallel_ignored_errors.test | 1 +
.../rpl_parallel_incorrect_relay_pos.result | 75 +
.../rpl_parallel_incorrect_relay_pos.test | 1 +
.../rpl_parallel_innodb_lock_conflict.result | 79 +
.../rpl_parallel_innodb_lock_conflict.test | 1 +
.../rpl_parallel_missed_error_handling.result | 65 +
.../rpl_parallel_missed_error_handling.test | 1 +
.../binlog_encryption/rpl_parallel_mode.result | 75 +
.../suite/binlog_encryption/rpl_parallel_mode.test | 1 +
.../rpl_parallel_partial_binlog_trans.result | 51 +
.../rpl_parallel_partial_binlog_trans.test | 1 +
.../rpl_parallel_record_gtid_wakeup.result | 48 +
.../rpl_parallel_record_gtid_wakeup.test | 1 +
.../rpl_parallel_retry_deadlock.result | 192 ++
.../rpl_parallel_retry_deadlock.test | 1 +
.../rpl_parallel_rollback_assert.result | 45 +
.../rpl_parallel_rollback_assert.test | 1 +
.../rpl_parallel_single_grpcmt.result | 161 ++
.../rpl_parallel_single_grpcmt.test | 1 +
.../rpl_parallel_slave_bgc_kill.result | 323 +++
.../rpl_parallel_slave_bgc_kill.test | 1 +
.../rpl_parallel_stop_on_con_kill.result | 102 +
.../rpl_parallel_stop_on_con_kill.test | 1 +
.../rpl_parallel_stop_slave.result | 85 +
.../binlog_encryption/rpl_parallel_stop_slave.test | 1 +
.../rpl_parallel_wrong_binlog_order.result | 75 +
.../rpl_parallel_wrong_binlog_order.test | 1 +
.../rpl_parallel_wrong_exec_master_pos.result | 34 +
.../rpl_parallel_wrong_exec_master_pos.test | 1 +
mysql-test/suite/multi_source/info_logs.result | 8 +-
mysql-test/suite/multi_source/reset_slave.result | 4 +-
mysql-test/suite/multi_source/simple.result | 14 +-
mysql-test/suite/rpl/include/rpl_parallel.inc | 2219 --------------------
.../include/rpl_parallel_analyze_table_hang.inc | 73 +
.../rpl_parallel_deadlock_corrupt_binlog.inc | 79 +
.../suite/rpl/include/rpl_parallel_domain.inc | 87 +
.../rpl_parallel_domain_slave_single_grp.inc | 128 ++
.../include/rpl_parallel_free_deferred_event.inc | 67 +
.../rpl/include/rpl_parallel_gco_wait_kill.inc | 366 ++++
.../rpl_parallel_gtid_slave_pos_update_fail.inc | 98 +
.../rpl/include/rpl_parallel_ignored_errors.inc | 96 +
.../include/rpl_parallel_incorrect_relay_pos.inc | 128 ++
.../include/rpl_parallel_innodb_lock_conflict.inc | 107 +
.../include/rpl_parallel_missed_error_handling.inc | 87 +
mysql-test/suite/rpl/include/rpl_parallel_mode.inc | 87 +
.../include/rpl_parallel_partial_binlog_trans.inc | 71 +
.../include/rpl_parallel_record_gtid_wakeup.inc | 72 +
.../rpl/include/rpl_parallel_retry_deadlock.inc | 281 +++
.../rpl/include/rpl_parallel_rollback_assert.inc | 62 +
.../rpl/include/rpl_parallel_single_grpcmt.inc | 170 ++
.../rpl/include/rpl_parallel_slave_bgc_kill.inc | 454 ++++
.../rpl/include/rpl_parallel_stop_on_con_kill.inc | 129 ++
.../suite/rpl/include/rpl_parallel_stop_slave.inc | 114 +
.../include/rpl_parallel_wrong_binlog_order.inc | 91 +
.../include/rpl_parallel_wrong_exec_master_pos.inc | 56 +
mysql-test/suite/rpl/r/rpl_mdev6386.result | 1 +
mysql-test/suite/rpl/r/rpl_parallel.result | 1690 ---------------
.../rpl/r/rpl_parallel_analyze_table_hang.result | 51 +
.../suite/rpl/r/rpl_parallel_conflicts.result | 9 +
.../r/rpl_parallel_deadlock_corrupt_binlog.result | 93 +
mysql-test/suite/rpl/r/rpl_parallel_domain.result | 71 +
.../r/rpl_parallel_domain_slave_single_grp.result | 101 +
.../rpl/r/rpl_parallel_free_deferred_event.result | 44 +
.../suite/rpl/r/rpl_parallel_gco_wait_kill.result | 257 +++
.../rpl_parallel_gtid_slave_pos_update_fail.result | 65 +
.../suite/rpl/r/rpl_parallel_ignored_errors.result | 74 +
.../rpl/r/rpl_parallel_incorrect_relay_pos.result | 75 +
.../rpl/r/rpl_parallel_innodb_lock_conflict.result | 79 +
.../suite/rpl/r/rpl_parallel_mdev6589.result | 1 +
.../r/rpl_parallel_missed_error_handling.result | 65 +
mysql-test/suite/rpl/r/rpl_parallel_mode.result | 75 +
.../rpl/r/rpl_parallel_partial_binlog_trans.result | 51 +
.../rpl/r/rpl_parallel_record_gtid_wakeup.result | 48 +
.../suite/rpl/r/rpl_parallel_retry_deadlock.result | 192 ++
.../rpl/r/rpl_parallel_rollback_assert.result | 45 +
.../suite/rpl/r/rpl_parallel_single_grpcmt.result | 160 ++
.../suite/rpl/r/rpl_parallel_slave_bgc_kill.result | 323 +++
.../rpl/r/rpl_parallel_stop_on_con_kill.result | 102 +
.../suite/rpl/r/rpl_parallel_stop_slave.result | 85 +
.../rpl/r/rpl_parallel_wrong_binlog_order.result | 75 +
.../r/rpl_parallel_wrong_exec_master_pos.result | 34 +
mysql-test/suite/rpl/t/rpl_mdev6386.test | 1 +
mysql-test/suite/rpl/t/rpl_parallel.test | 1 -
.../rpl/t/rpl_parallel_analyze_table_hang.test | 1 +
.../suite/rpl/t/rpl_parallel_conflicts-slave.opt | 1 -
mysql-test/suite/rpl/t/rpl_parallel_conflicts.test | 10 +-
.../t/rpl_parallel_deadlock_corrupt_binlog.test | 1 +
mysql-test/suite/rpl/t/rpl_parallel_domain.test | 1 +
.../t/rpl_parallel_domain_slave_single_grp.test | 1 +
.../rpl/t/rpl_parallel_free_deferred_event.test | 1 +
.../suite/rpl/t/rpl_parallel_gco_wait_kill.test | 1 +
.../t/rpl_parallel_gtid_slave_pos_update_fail.test | 1 +
.../suite/rpl/t/rpl_parallel_ignored_errors.test | 1 +
.../rpl/t/rpl_parallel_incorrect_relay_pos.test | 1 +
.../rpl/t/rpl_parallel_innodb_lock_conflict.test | 1 +
mysql-test/suite/rpl/t/rpl_parallel_mdev6589.test | 1 +
.../rpl/t/rpl_parallel_missed_error_handling.test | 1 +
mysql-test/suite/rpl/t/rpl_parallel_mode.test | 1 +
.../rpl/t/rpl_parallel_partial_binlog_trans.test | 1 +
.../rpl/t/rpl_parallel_record_gtid_wakeup.test | 1 +
.../suite/rpl/t/rpl_parallel_retry_deadlock.test | 1 +
.../suite/rpl/t/rpl_parallel_rollback_assert.test | 1 +
.../suite/rpl/t/rpl_parallel_single_grpcmt.test | 1 +
.../suite/rpl/t/rpl_parallel_slave_bgc_kill.test | 1 +
.../suite/rpl/t/rpl_parallel_stop_on_con_kill.test | 1 +
.../suite/rpl/t/rpl_parallel_stop_slave.test | 1 +
.../rpl/t/rpl_parallel_wrong_binlog_order.test | 1 +
.../rpl/t/rpl_parallel_wrong_exec_master_pos.test | 1 +
sql/mysqld.cc | 2 +-
sql/rpl_filter.cc | 2 +-
sql/sql_class.cc | 38 +
sql/sql_class.h | 16 +-
sql/sys_vars.cc | 2 +-
131 files changed, 7356 insertions(+), 5636 deletions(-)
diff --git a/mysql-test/include/check-testcase.test b/mysql-test/include/check-testcase.test
index 191feae1628..c5b3f9db6a8 100644
--- a/mysql-test/include/check-testcase.test
+++ b/mysql-test/include/check-testcase.test
@@ -66,7 +66,7 @@ if ($tmp)
--echo Gtid_IO_Pos #
--echo Replicate_Do_Domain_Ids
--echo Replicate_Ignore_Domain_Ids
- --echo Parallel_Mode conservative
+ --echo Parallel_Mode optimistic
--echo SQL_Delay 0
--echo SQL_Remaining_Delay NULL
--echo Slave_SQL_Running_State
diff --git a/mysql-test/suite/binlog_encryption/rpl_parallel.result b/mysql-test/suite/binlog_encryption/rpl_parallel.result
deleted file mode 100644
index 5f78a378829..00000000000
--- a/mysql-test/suite/binlog_encryption/rpl_parallel.result
+++ /dev/null
@@ -1,1691 +0,0 @@
-include/master-slave.inc
-[connection master]
-connection server_2;
-SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
-SET GLOBAL slave_parallel_threads=10;
-ERROR HY000: This operation cannot be performed as you have a running slave ''; run STOP SLAVE '' first
-include/stop_slave.inc
-SET GLOBAL slave_parallel_threads=10;
-SELECT IF(COUNT(*) < 10, "OK", CONCAT("Found too many system user processes: ", COUNT(*))) FROM information_schema.processlist WHERE user = "system user";
-IF(COUNT(*) < 10, "OK", CONCAT("Found too many system user processes: ", COUNT(*)))
-OK
-CHANGE MASTER TO master_use_gtid=slave_pos;
-include/start_slave.inc
-SELECT IF(COUNT(*) >= 10, "OK", CONCAT("Found too few system user processes: ", COUNT(*))) FROM information_schema.processlist WHERE user = "system user";
-IF(COUNT(*) >= 10, "OK", CONCAT("Found too few system user processes: ", COUNT(*)))
-OK
-include/stop_slave.inc
-SELECT IF(COUNT(*) < 10, "OK", CONCAT("Found too many system user processes: ", COUNT(*))) FROM information_schema.processlist WHERE user = "system user";
-IF(COUNT(*) < 10, "OK", CONCAT("Found too many system user processes: ", COUNT(*)))
-OK
-include/start_slave.inc
-SELECT IF(COUNT(*) >= 10, "OK", CONCAT("Found too few system user processes: ", COUNT(*))) FROM information_schema.processlist WHERE user = "system user";
-IF(COUNT(*) >= 10, "OK", CONCAT("Found too few system user processes: ", COUNT(*)))
-OK
-*** Test long-running query in domain 1 can run in parallel with short queries in domain 0 ***
-connection server_1;
-ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
-CREATE TABLE t1 (a int PRIMARY KEY) ENGINE=MyISAM;
-CREATE TABLE t2 (a int PRIMARY KEY) ENGINE=InnoDB;
-INSERT INTO t1 VALUES (1);
-INSERT INTO t2 VALUES (1);
-connection server_2;
-connect con_temp1,127.0.0.1,root,,test,$SERVER_MYPORT_2,;
-LOCK TABLE t1 WRITE;
-connection server_1;
-SET gtid_domain_id=1;
-INSERT INTO t1 VALUES (2);
-SET gtid_domain_id=0;
-INSERT INTO t2 VALUES (2);
-INSERT INTO t2 VALUES (3);
-BEGIN;
-INSERT INTO t2 VALUES (4);
-INSERT INTO t2 VALUES (5);
-COMMIT;
-INSERT INTO t2 VALUES (6);
-connection server_2;
-SELECT * FROM t2 ORDER by a;
-a
-1
-2
-3
-4
-5
-6
-connection con_temp1;
-SELECT * FROM t1;
-a
-1
-UNLOCK TABLES;
-connection server_2;
-SELECT * FROM t1 ORDER BY a;
-a
-1
-2
-*** Test two transactions in different domains committed in opposite order on slave but in a single group commit. ***
-connection server_2;
-include/stop_slave.inc
-connection server_1;
-SET sql_log_bin=0;
-CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
-RETURNS INT DETERMINISTIC
-BEGIN
-RETURN x;
-END
-||
-SET sql_log_bin=1;
-SET @old_format= @@SESSION.binlog_format;
-SET binlog_format='statement';
-SET gtid_domain_id=1;
-INSERT INTO t2 VALUES (foo(10,
-'commit_before_enqueue SIGNAL ready1 WAIT_FOR cont1',
-'commit_after_release_LOCK_prepare_ordered SIGNAL ready2'));
-connection server_2;
-FLUSH LOGS;
-SET sql_log_bin=0;
-CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
-RETURNS INT DETERMINISTIC
-BEGIN
-IF d1 != '' THEN
-SET debug_sync = d1;
-END IF;
-IF d2 != '' THEN
-SET debug_sync = d2;
-END IF;
-RETURN x;
-END
-||
-SET sql_log_bin=1;
-SET @old_format=@@GLOBAL.binlog_format;
-SET GLOBAL binlog_format=statement;
-SET GLOBAL slave_parallel_threads=0;
-SET GLOBAL slave_parallel_threads=10;
-include/start_slave.inc
-SET debug_sync='now WAIT_FOR ready1';
-connection server_1;
-SET gtid_domain_id=2;
-INSERT INTO t2 VALUES (foo(11,
-'commit_before_enqueue SIGNAL ready3 WAIT_FOR cont3',
-'commit_after_release_LOCK_prepare_ordered SIGNAL ready4 WAIT_FOR cont4'));
-SET gtid_domain_id=0;
-SELECT * FROM t2 WHERE a >= 10 ORDER BY a;
-a
-10
-11
-connection server_2;
-SET debug_sync='now WAIT_FOR ready3';
-SET debug_sync='now SIGNAL cont3';
-SET debug_sync='now WAIT_FOR ready4';
-SET debug_sync='now SIGNAL cont1';
-SET debug_sync='now WAIT_FOR ready2';
-SET debug_sync='now SIGNAL cont4';
-SELECT * FROM t2 WHERE a >= 10 ORDER BY a;
-a
-10
-11
-include/show_binlog_events.inc
-Log_name Pos Event_type Server_id End_log_pos Info
-slave-bin.000002 # Binlog_checkpoint # # slave-bin.000002
-slave-bin.000002 # Gtid # # BEGIN GTID #-#-# cid=#
-slave-bin.000002 # Query # # use `test`; INSERT INTO t2 VALUES (foo(11,
-'commit_before_enqueue SIGNAL ready3 WAIT_FOR cont3',
-'commit_after_release_LOCK_prepare_ordered SIGNAL ready4 WAIT_FOR cont4'))
-slave-bin.000002 # Xid # # COMMIT /* XID */
-slave-bin.000002 # Gtid # # BEGIN GTID #-#-# cid=#
-slave-bin.000002 # Query # # use `test`; INSERT INTO t2 VALUES (foo(10,
-'commit_before_enqueue SIGNAL ready1 WAIT_FOR cont1',
-'commit_after_release_LOCK_prepare_ordered SIGNAL ready2'))
-slave-bin.000002 # Xid # # COMMIT /* XID */
-FLUSH LOGS;
-connection server_2;
-include/stop_slave.inc
-SET GLOBAL slave_parallel_threads=0;
-SET GLOBAL slave_parallel_threads=10;
-SET debug_sync='RESET';
-include/start_slave.inc
-*** Test that group-committed transactions on the master can replicate in parallel on the slave. ***
-connection server_1;
-SET debug_sync='RESET';
-FLUSH LOGS;
-CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
-INSERT INTO t3 VALUES (1,1), (3,3), (5,5), (7,7);
-connection server_2;
-connection con_temp1;
-BEGIN;
-INSERT INTO t3 VALUES (2,102);
-connect con_temp2,127.0.0.1,root,,test,$SERVER_MYPORT_2,;
-BEGIN;
-INSERT INTO t3 VALUES (4,104);
-connect con_temp3,127.0.0.1,root,,test,$SERVER_MYPORT_1,;
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
-SET binlog_format=statement;
-INSERT INTO t3 VALUES (2, foo(12,
-'commit_after_release_LOCK_prepare_ordered SIGNAL slave_queued1 WAIT_FOR slave_cont1',
-''));
-connection server_1;
-SET debug_sync='now WAIT_FOR master_queued1';
-connect con_temp4,127.0.0.1,root,,test,$SERVER_MYPORT_1,;
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
-SET binlog_format=statement;
-INSERT INTO t3 VALUES (4, foo(14,
-'commit_after_release_LOCK_prepare_ordered SIGNAL slave_queued2',
-''));
-connection server_1;
-SET debug_sync='now WAIT_FOR master_queued2';
-connect con_temp5,127.0.0.1,root,,test,$SERVER_MYPORT_1,;
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued3';
-SET binlog_format=statement;
-INSERT INTO t3 VALUES (6, foo(16,
-'group_commit_waiting_for_prior SIGNAL slave_queued3',
-''));
-connection server_1;
-SET debug_sync='now WAIT_FOR master_queued3';
-SET debug_sync='now SIGNAL master_cont1';
-connection con_temp3;
-connection con_temp4;
-connection con_temp5;
-SET debug_sync='RESET';
-connection server_1;
-SELECT * FROM t3 ORDER BY a;
-a b
-1 1
-2 12
-3 3
-4 14
-5 5
-6 16
-7 7
-include/show_binlog_events.inc
-Log_name Pos Event_type Server_id End_log_pos Info
-master-bin.000002 # Binlog_checkpoint # # master-bin.000001
-master-bin.000002 # Binlog_checkpoint # # master-bin.000002
-master-bin.000002 # Gtid # # GTID #-#-#
-master-bin.000002 # Query # # use `test`; CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB
-master-bin.000002 # Gtid # # BEGIN GTID #-#-#
-master-bin.000002 # Query # # use `test`; INSERT INTO t3 VALUES (1,1), (3,3), (5,5), (7,7)
-master-bin.000002 # Xid # # COMMIT /* XID */
-master-bin.000002 # Gtid # # BEGIN GTID #-#-# cid=#
-master-bin.000002 # Query # # use `test`; INSERT INTO t3 VALUES (2, foo(12,
-'commit_after_release_LOCK_prepare_ordered SIGNAL slave_queued1 WAIT_FOR slave_cont1',
-''))
-master-bin.000002 # Xid # # COMMIT /* XID */
-master-bin.000002 # Gtid # # BEGIN GTID #-#-# cid=#
-master-bin.000002 # Query # # use `test`; INSERT INTO t3 VALUES (4, foo(14,
-'commit_after_release_LOCK_prepare_ordered SIGNAL slave_queued2',
-''))
-master-bin.000002 # Xid # # COMMIT /* XID */
-master-bin.000002 # Gtid # # BEGIN GTID #-#-# cid=#
-master-bin.000002 # Query # # use `test`; INSERT INTO t3 VALUES (6, foo(16,
-'group_commit_waiting_for_prior SIGNAL slave_queued3',
-''))
-master-bin.000002 # Xid # # COMMIT /* XID */
-connection server_2;
-SET debug_sync='now WAIT_FOR slave_queued3';
-connection con_temp1;
-ROLLBACK;
-connection server_2;
-SET debug_sync='now WAIT_FOR slave_queued1';
-connection con_temp2;
-ROLLBACK;
-connection server_2;
-SET debug_sync='now WAIT_FOR slave_queued2';
-SET debug_sync='now SIGNAL slave_cont1';
-SELECT * FROM t3 ORDER BY a;
-a b
-1 1
-2 12
-3 3
-4 14
-5 5
-6 16
-7 7
-include/show_binlog_events.inc
-Log_name Pos Event_type Server_id End_log_pos Info
-slave-bin.000003 # Binlog_checkpoint # # slave-bin.000003
-slave-bin.000003 # Gtid # # GTID #-#-#
-slave-bin.000003 # Query # # use `test`; CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB
-slave-bin.000003 # Gtid # # BEGIN GTID #-#-#
-slave-bin.000003 # Query # # use `test`; INSERT INTO t3 VALUES (1,1), (3,3), (5,5), (7,7)
-slave-bin.000003 # Xid # # COMMIT /* XID */
-slave-bin.000003 # Gtid # # BEGIN GTID #-#-# cid=#
-slave-bin.000003 # Query # # use `test`; INSERT INTO t3 VALUES (2, foo(12,
-'commit_after_release_LOCK_prepare_ordered SIGNAL slave_queued1 WAIT_FOR slave_cont1',
-''))
-slave-bin.000003 # Xid # # COMMIT /* XID */
-slave-bin.000003 # Gtid # # BEGIN GTID #-#-# cid=#
-slave-bin.000003 # Query # # use `test`; INSERT INTO t3 VALUES (4, foo(14,
-'commit_after_release_LOCK_prepare_ordered SIGNAL slave_queued2',
-''))
-slave-bin.000003 # Xid # # COMMIT /* XID */
-slave-bin.000003 # Gtid # # BEGIN GTID #-#-# cid=#
-slave-bin.000003 # Query # # use `test`; INSERT INTO t3 VALUES (6, foo(16,
-'group_commit_waiting_for_prior SIGNAL slave_queued3',
-''))
-slave-bin.000003 # Xid # # COMMIT /* XID */
-*** Test STOP SLAVE in parallel mode ***
-connection server_2;
-include/stop_slave.inc
-SET debug_sync='RESET';
-SET GLOBAL slave_parallel_threads=0;
-SET GLOBAL slave_parallel_threads=10;
-connection server_1;
-SET binlog_direct_non_transactional_updates=0;
-SET sql_log_bin=0;
-CALL mtr.add_suppression("Statement is unsafe because it accesses a non-transactional table after accessing a transactional table within the same transaction");
-SET sql_log_bin=1;
-BEGIN;
-INSERT INTO t2 VALUES (20);
-INSERT INTO t1 VALUES (20);
-INSERT INTO t2 VALUES (21);
-INSERT INTO t3 VALUES (20, 20);
-COMMIT;
-INSERT INTO t3 VALUES(21, 21);
-INSERT INTO t3 VALUES(22, 22);
-SET binlog_format=@old_format;
-connection con_temp1;
-BEGIN;
-INSERT INTO t2 VALUES (21);
-connection server_2;
-START SLAVE;
-connection con_temp2;
-SET @old_dbug= @@GLOBAL.debug_dbug;
-SET GLOBAL debug_dbug="+d,rpl_parallel_wait_for_done_trigger";
-STOP SLAVE;
-connection con_temp1;
-SET debug_sync='now WAIT_FOR wait_for_done_waiting';
-ROLLBACK;
-connection con_temp2;
-SET GLOBAL debug_dbug=@old_dbug;
-SET debug_sync='RESET';
-connection server_2;
-include/wait_for_slave_to_stop.inc
-SELECT * FROM t1 WHERE a >= 20 ORDER BY a;
-a
-20
-SELECT * FROM t2 WHERE a >= 20 ORDER BY a;
-a
-20
-21
-SELECT * FROM t3 WHERE a >= 20 ORDER BY a;
-a b
-20 20
-include/start_slave.inc
-SELECT * FROM t1 WHERE a >= 20 ORDER BY a;
-a
-20
-SELECT * FROM t2 WHERE a >= 20 ORDER BY a;
-a
-20
-21
-SELECT * FROM t3 WHERE a >= 20 ORDER BY a;
-a b
-20 20
-21 21
-22 22
-connection server_2;
-include/stop_slave.inc
-SET GLOBAL binlog_format=@old_format;
-SET GLOBAL slave_parallel_threads=0;
-SET GLOBAL slave_parallel_threads=10;
-include/start_slave.inc
-*** Test killing slave threads at various wait points ***
-*** 1. Test killing transaction waiting in commit for previous transaction to commit ***
-connection con_temp3;
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
-SET binlog_format=statement;
-INSERT INTO t3 VALUES (31, foo(31,
-'commit_before_prepare_ordered WAIT_FOR t2_waiting',
-'commit_after_prepare_ordered SIGNAL t1_ready WAIT_FOR t1_cont'));
-connection server_1;
-SET debug_sync='now WAIT_FOR master_queued1';
-connection con_temp4;
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
-SET binlog_format=statement;
-BEGIN;
-INSERT INTO t3 VALUES (32, foo(32,
-'ha_write_row_end SIGNAL t2_query WAIT_FOR t2_cont',
-''));
-INSERT INTO t3 VALUES (33, foo(33,
-'group_commit_waiting_for_prior SIGNAL t2_waiting',
-'group_commit_waiting_for_prior_killed SIGNAL t2_killed'));
-COMMIT;
-connection server_1;
-SET debug_sync='now WAIT_FOR master_queued2';
-connection con_temp5;
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued3';
-SET binlog_format=statement;
-INSERT INTO t3 VALUES (34, foo(34,
-'',
-''));
-connection server_1;
-SET debug_sync='now WAIT_FOR master_queued3';
-SET debug_sync='now SIGNAL master_cont1';
-connection con_temp3;
-connection con_temp4;
-connection con_temp5;
-connection server_1;
-SELECT * FROM t3 WHERE a >= 30 ORDER BY a;
-a b
-31 31
-32 32
-33 33
-34 34
-SET debug_sync='RESET';
-connection server_2;
-SET sql_log_bin=0;
-CALL mtr.add_suppression("Query execution was interrupted");
-CALL mtr.add_suppression("Commit failed due to failure of an earlier commit on which this one depends");
-CALL mtr.add_suppression("Slave: Connection was killed");
-SET sql_log_bin=1;
-SET debug_sync='now WAIT_FOR t2_query';
-SET debug_sync='now SIGNAL t2_cont';
-SET debug_sync='now WAIT_FOR t1_ready';
-KILL THD_ID;
-SET debug_sync='now WAIT_FOR t2_killed';
-SET debug_sync='now SIGNAL t1_cont';
-include/wait_for_slave_sql_error.inc [errno=1317,1927,1964]
-STOP SLAVE IO_THREAD;
-SELECT * FROM t3 WHERE a >= 30 ORDER BY a;
-a b
-31 31
-SET debug_sync='RESET';
-SET GLOBAL slave_parallel_threads=0;
-SET GLOBAL slave_parallel_threads=10;
-SET sql_log_bin=0;
-DROP FUNCTION foo;
-CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
-RETURNS INT DETERMINISTIC
-BEGIN
-RETURN x;
-END
-||
-SET sql_log_bin=1;
-connection server_1;
-INSERT INTO t3 VALUES (39,0);
-connection server_2;
-include/start_slave.inc
-SELECT * FROM t3 WHERE a >= 30 ORDER BY a;
-a b
-31 31
-32 32
-33 33
-34 34
-39 0
-SET sql_log_bin=0;
-DROP FUNCTION foo;
-CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
-RETURNS INT DETERMINISTIC
-BEGIN
-IF d1 != '' THEN
-SET debug_sync = d1;
-END IF;
-IF d2 != '' THEN
-SET debug_sync = d2;
-END IF;
-RETURN x;
-END
-||
-SET sql_log_bin=1;
-connection server_2;
-include/stop_slave.inc
-SET GLOBAL binlog_format=@old_format;
-SET GLOBAL slave_parallel_threads=0;
-SET GLOBAL slave_parallel_threads=10;
-include/start_slave.inc
-*** 2. Same as (1), but without restarting IO thread after kill of SQL threads ***
-connection con_temp3;
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
-SET binlog_format=statement;
-INSERT INTO t3 VALUES (41, foo(41,
-'commit_before_prepare_ordered WAIT_FOR t2_waiting',
-'commit_after_prepare_ordered SIGNAL t1_ready WAIT_FOR t1_cont'));
-connection server_1;
-SET debug_sync='now WAIT_FOR master_queued1';
-connection con_temp4;
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
-SET binlog_format=statement;
-BEGIN;
-INSERT INTO t3 VALUES (42, foo(42,
-'ha_write_row_end SIGNAL t2_query WAIT_FOR t2_cont',
-''));
-INSERT INTO t3 VALUES (43, foo(43,
-'group_commit_waiting_for_prior SIGNAL t2_waiting',
-'group_commit_waiting_for_prior_killed SIGNAL t2_killed'));
-COMMIT;
-connection server_1;
-SET debug_sync='now WAIT_FOR master_queued2';
-connection con_temp5;
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued3';
-SET binlog_format=statement;
-INSERT INTO t3 VALUES (44, foo(44,
-'',
-''));
-connection server_1;
-SET debug_sync='now WAIT_FOR master_queued3';
-SET debug_sync='now SIGNAL master_cont1';
-connection con_temp3;
-connection con_temp4;
-connection con_temp5;
-connection server_1;
-SELECT * FROM t3 WHERE a >= 40 ORDER BY a;
-a b
-41 41
-42 42
-43 43
-44 44
-SET debug_sync='RESET';
-connection server_2;
-SET debug_sync='now WAIT_FOR t2_query';
-SET debug_sync='now SIGNAL t2_cont';
-SET debug_sync='now WAIT_FOR t1_ready';
-KILL THD_ID;
-SET debug_sync='now WAIT_FOR t2_killed';
-SET debug_sync='now SIGNAL t1_cont';
-include/wait_for_slave_sql_error.inc [errno=1317,1927,1964]
-SET debug_sync='RESET';
-SET GLOBAL slave_parallel_threads=0;
-SET GLOBAL slave_parallel_threads=10;
-SET sql_log_bin=0;
-DROP FUNCTION foo;
-CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
-RETURNS INT DETERMINISTIC
-BEGIN
-RETURN x;
-END
-||
-SET sql_log_bin=1;
-connection server_1;
-INSERT INTO t3 VALUES (49,0);
-connection server_2;
-START SLAVE SQL_THREAD;
-SELECT * FROM t3 WHERE a >= 40 ORDER BY a;
-a b
-41 41
-42 42
-43 43
-44 44
-49 0
-SET sql_log_bin=0;
-DROP FUNCTION foo;
-CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
-RETURNS INT DETERMINISTIC
-BEGIN
-IF d1 != '' THEN
-SET debug_sync = d1;
-END IF;
-IF d2 != '' THEN
-SET debug_sync = d2;
-END IF;
-RETURN x;
-END
-||
-SET sql_log_bin=1;
-connection server_2;
-include/stop_slave.inc
-SET GLOBAL binlog_format=@old_format;
-SET GLOBAL slave_parallel_threads=0;
-SET GLOBAL slave_parallel_threads=10;
-include/start_slave.inc
-*** 3. Same as (2), but not using gtid mode ***
-connection server_2;
-include/stop_slave.inc
-CHANGE MASTER TO master_use_gtid=no;
-include/start_slave.inc
-connection server_1;
-connection con_temp3;
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
-SET binlog_format=statement;
-INSERT INTO t3 VALUES (51, foo(51,
-'commit_before_prepare_ordered WAIT_FOR t2_waiting',
-'commit_after_prepare_ordered SIGNAL t1_ready WAIT_FOR t1_cont'));
-connection server_1;
-SET debug_sync='now WAIT_FOR master_queued1';
-connection con_temp4;
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
-SET binlog_format=statement;
-BEGIN;
-INSERT INTO t3 VALUES (52, foo(52,
-'ha_write_row_end SIGNAL t2_query WAIT_FOR t2_cont',
-''));
-INSERT INTO t3 VALUES (53, foo(53,
-'group_commit_waiting_for_prior SIGNAL t2_waiting',
-'group_commit_waiting_for_prior_killed SIGNAL t2_killed'));
-COMMIT;
-connection server_1;
-SET debug_sync='now WAIT_FOR master_queued2';
-connection con_temp5;
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued3';
-SET binlog_format=statement;
-INSERT INTO t3 VALUES (54, foo(54,
-'',
-''));
-connection server_1;
-SET debug_sync='now WAIT_FOR master_queued3';
-SET debug_sync='now SIGNAL master_cont1';
-connection con_temp3;
-connection con_temp4;
-connection con_temp5;
-connection server_1;
-SELECT * FROM t3 WHERE a >= 50 ORDER BY a;
-a b
-51 51
-52 52
-53 53
-54 54
-SET debug_sync='RESET';
-connection server_2;
-SET debug_sync='now WAIT_FOR t2_query';
-SET debug_sync='now SIGNAL t2_cont';
-SET debug_sync='now WAIT_FOR t1_ready';
-KILL THD_ID;
-SET debug_sync='now WAIT_FOR t2_killed';
-SET debug_sync='now SIGNAL t1_cont';
-include/wait_for_slave_sql_error.inc [errno=1317,1927,1964]
-SELECT * FROM t3 WHERE a >= 50 ORDER BY a;
-a b
-51 51
-SET debug_sync='RESET';
-SET GLOBAL slave_parallel_threads=0;
-SET GLOBAL slave_parallel_threads=10;
-SET sql_log_bin=0;
-DROP FUNCTION foo;
-CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
-RETURNS INT DETERMINISTIC
-BEGIN
-RETURN x;
-END
-||
-SET sql_log_bin=1;
-connection server_1;
-INSERT INTO t3 VALUES (59,0);
-connection server_2;
-START SLAVE SQL_THREAD;
-SELECT * FROM t3 WHERE a >= 50 ORDER BY a;
-a b
-51 51
-52 52
-53 53
-54 54
-59 0
-SET sql_log_bin=0;
-DROP FUNCTION foo;
-CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
-RETURNS INT DETERMINISTIC
-BEGIN
-IF d1 != '' THEN
-SET debug_sync = d1;
-END IF;
-IF d2 != '' THEN
-SET debug_sync = d2;
-END IF;
-RETURN x;
-END
-||
-SET sql_log_bin=1;
-include/stop_slave.inc
-CHANGE MASTER TO master_use_gtid=slave_pos;
-include/start_slave.inc
-connection server_2;
-include/stop_slave.inc
-SET GLOBAL binlog_format=@old_format;
-SET GLOBAL slave_parallel_threads=0;
-SET GLOBAL slave_parallel_threads=4;
-include/start_slave.inc
-*** 4. Test killing thread that is waiting to start transaction until previous transaction commits ***
-connection server_1;
-SET binlog_format=statement;
-SET gtid_domain_id=2;
-BEGIN;
-INSERT INTO t3 VALUES (70, foo(70,
-'rpl_parallel_start_waiting_for_prior SIGNAL t4_waiting', ''));
-INSERT INTO t3 VALUES (60, foo(60,
-'ha_write_row_end SIGNAL d2_query WAIT_FOR d2_cont2',
-'rpl_parallel_end_of_group SIGNAL d2_done WAIT_FOR d2_cont'));
-COMMIT;
-SET gtid_domain_id=0;
-connection server_2;
-SET debug_sync='now WAIT_FOR d2_query';
-connection server_1;
-SET gtid_domain_id=1;
-BEGIN;
-INSERT INTO t3 VALUES (61, foo(61,
-'rpl_parallel_start_waiting_for_prior SIGNAL t3_waiting',
-'rpl_parallel_start_waiting_for_prior_killed SIGNAL t3_killed'));
-INSERT INTO t3 VALUES (62, foo(62,
-'ha_write_row_end SIGNAL d1_query WAIT_FOR d1_cont2',
-'rpl_parallel_end_of_group SIGNAL d1_done WAIT_FOR d1_cont'));
-COMMIT;
-SET gtid_domain_id=0;
-connection server_2;
-SET debug_sync='now WAIT_FOR d1_query';
-connection server_1;
-SET gtid_domain_id=0;
-INSERT INTO t3 VALUES (63, foo(63,
-'ha_write_row_end SIGNAL d0_query WAIT_FOR d0_cont2',
-'rpl_parallel_end_of_group SIGNAL d0_done WAIT_FOR d0_cont'));
-connection server_2;
-SET debug_sync='now WAIT_FOR d0_query';
-connection server_1;
-SET gtid_domain_id=3;
-BEGIN;
-INSERT INTO t3 VALUES (68, foo(68,
-'rpl_parallel_start_waiting_for_prior SIGNAL t2_waiting', ''));
-INSERT INTO t3 VALUES (69, foo(69,
-'ha_write_row_end SIGNAL d3_query WAIT_FOR d3_cont2',
-'rpl_parallel_end_of_group SIGNAL d3_done WAIT_FOR d3_cont'));
-COMMIT;
-SET gtid_domain_id=0;
-connection server_2;
-SET debug_sync='now WAIT_FOR d3_query';
-SET debug_sync='now SIGNAL d2_cont2';
-SET debug_sync='now WAIT_FOR d2_done';
-SET debug_sync='now SIGNAL d1_cont2';
-SET debug_sync='now WAIT_FOR d1_done';
-SET debug_sync='now SIGNAL d0_cont2';
-SET debug_sync='now WAIT_FOR d0_done';
-SET debug_sync='now SIGNAL d3_cont2';
-SET debug_sync='now WAIT_FOR d3_done';
-connection con_temp3;
-SET binlog_format=statement;
-INSERT INTO t3 VALUES (64, foo(64,
-'rpl_parallel_before_mark_start_commit SIGNAL t1_waiting WAIT_FOR t1_cont', ''));
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2 WAIT_FOR master_cont2';
-INSERT INTO t3 VALUES (65, foo(65, '', ''));
-connection server_1;
-SET debug_sync='now WAIT_FOR master_queued2';
-connection con_temp4;
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued3';
-INSERT INTO t3 VALUES (66, foo(66, '', ''));
-connection server_1;
-SET debug_sync='now WAIT_FOR master_queued3';
-connection con_temp5;
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued4';
-INSERT INTO t3 VALUES (67, foo(67, '', ''));
-connection server_1;
-SET debug_sync='now WAIT_FOR master_queued4';
-SET debug_sync='now SIGNAL master_cont2';
-connection con_temp3;
-connection con_temp4;
-connection con_temp5;
-connection server_1;
-SELECT * FROM t3 WHERE a >= 60 ORDER BY a;
-a b
-60 60
-61 61
-62 62
-63 63
-64 64
-65 65
-66 66
-67 67
-68 68
-69 69
-70 70
-SET debug_sync='RESET';
-connection server_2;
-SET debug_sync='now SIGNAL d0_cont';
-SET debug_sync='now WAIT_FOR t1_waiting';
-SET debug_sync='now SIGNAL d3_cont';
-SET debug_sync='now WAIT_FOR t2_waiting';
-SET debug_sync='now SIGNAL d1_cont';
-SET debug_sync='now WAIT_FOR t3_waiting';
-SET debug_sync='now SIGNAL d2_cont';
-SET debug_sync='now WAIT_FOR t4_waiting';
-KILL THD_ID;
-SET debug_sync='now WAIT_FOR t3_killed';
-SET debug_sync='now SIGNAL t1_cont';
-include/wait_for_slave_sql_error.inc [errno=1317,1927,1964]
-STOP SLAVE IO_THREAD;
-SELECT * FROM t3 WHERE a >= 60 AND a != 65 ORDER BY a;
-a b
-60 60
-61 61
-62 62
-63 63
-64 64
-68 68
-69 69
-70 70
-SET debug_sync='RESET';
-SET GLOBAL slave_parallel_threads=0;
-SET GLOBAL slave_parallel_threads=10;
-SET sql_log_bin=0;
-DROP FUNCTION foo;
-CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
-RETURNS INT DETERMINISTIC
-BEGIN
-RETURN x;
-END
-||
-SET sql_log_bin=1;
-connection server_1;
-UPDATE t3 SET b=b+1 WHERE a=60;
-connection server_2;
-include/start_slave.inc
-SELECT * FROM t3 WHERE a >= 60 ORDER BY a;
-a b
-60 61
-61 61
-62 62
-63 63
-64 64
-65 65
-66 66
-67 67
-68 68
-69 69
-70 70
-SET sql_log_bin=0;
-DROP FUNCTION foo;
-CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
-RETURNS INT DETERMINISTIC
-BEGIN
-IF d1 != '' THEN
-SET debug_sync = d1;
-END IF;
-IF d2 != '' THEN
-SET debug_sync = d2;
-END IF;
-RETURN x;
-END
-||
-SET sql_log_bin=1;
-connection server_2;
-include/stop_slave.inc
-SET GLOBAL binlog_format=@old_format;
-SET GLOBAL slave_parallel_threads=0;
-SET GLOBAL slave_parallel_threads=10;
-include/start_slave.inc
-*** 5. Test killing thread that is waiting for queue of max length to shorten ***
-SET @old_max_queued= @@GLOBAL.slave_parallel_max_queued;
-SET GLOBAL slave_parallel_max_queued=9000;
-connection server_1;
-SET binlog_format=statement;
-INSERT INTO t3 VALUES (80, foo(0,
-'ha_write_row_end SIGNAL query_waiting WAIT_FOR query_cont', ''));
-connection server_2;
-SET debug_sync='now WAIT_FOR query_waiting';
-SET @old_dbug= @@GLOBAL.debug_dbug;
-SET GLOBAL debug_dbug="+d,rpl_parallel_wait_queue_max";
-connection server_1;
-SELECT * FROM t3 WHERE a >= 80 ORDER BY a;
-a b
-80 0
-81 10000
-connection server_2;
-SET debug_sync='now WAIT_FOR wait_queue_ready';
-KILL THD_ID;
-SET debug_sync='now WAIT_FOR wait_queue_killed';
-SET debug_sync='now SIGNAL query_cont';
-include/wait_for_slave_sql_error.inc [errno=1317,1927,1964]
-STOP SLAVE IO_THREAD;
-SET GLOBAL debug_dbug=@old_dbug;
-SET GLOBAL slave_parallel_max_queued= @old_max_queued;
-connection server_1;
-INSERT INTO t3 VALUES (82,0);
-SET binlog_format=@old_format;
-connection server_2;
-SET debug_sync='RESET';
-include/start_slave.inc
-SELECT * FROM t3 WHERE a >= 80 ORDER BY a;
-a b
-80 0
-81 10000
-82 0
-connection server_2;
-include/stop_slave.inc
-SET GLOBAL binlog_format=@old_format;
-SET GLOBAL slave_parallel_threads=0;
-SET GLOBAL slave_parallel_threads=10;
-include/start_slave.inc
-*** MDEV-5788 Incorrect free of rgi->deferred_events in parallel replication ***
-connection server_2;
-include/stop_slave.inc
-SET GLOBAL replicate_ignore_table="test.t3";
-SET GLOBAL slave_parallel_threads=2;
-include/start_slave.inc
-connection server_1;
-INSERT INTO t3 VALUES (100, rand());
-INSERT INTO t3 VALUES (101, rand());
-connection server_2;
-connection server_1;
-INSERT INTO t3 VALUES (102, rand());
-INSERT INTO t3 VALUES (103, rand());
-INSERT INTO t3 VALUES (104, rand());
-INSERT INTO t3 VALUES (105, rand());
-connection server_2;
-include/stop_slave.inc
-SET GLOBAL replicate_ignore_table="";
-include/start_slave.inc
-connection server_1;
-INSERT INTO t3 VALUES (106, rand());
-INSERT INTO t3 VALUES (107, rand());
-connection server_2;
-SELECT * FROM t3 WHERE a >= 100 ORDER BY a;
-a b
-106 #
-107 #
-*** MDEV-5921: In parallel replication, an error is not correctly signalled to the next transaction ***
-connection server_2;
-include/stop_slave.inc
-SET GLOBAL slave_parallel_threads=10;
-include/start_slave.inc
-connection server_1;
-INSERT INTO t3 VALUES (110, 1);
-connection server_2;
-SELECT * FROM t3 WHERE a >= 110 ORDER BY a;
-a b
-110 1
-SET sql_log_bin=0;
-INSERT INTO t3 VALUES (111, 666);
-SET sql_log_bin=1;
-connection server_1;
-connect con1,127.0.0.1,root,,test,$SERVER_MYPORT_1,;
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
-INSERT INTO t3 VALUES (111, 2);
-connection server_1;
-SET debug_sync='now WAIT_FOR master_queued1';
-connect con2,127.0.0.1,root,,test,$SERVER_MYPORT_1,;
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
-INSERT INTO t3 VALUES (112, 3);
-connection server_1;
-SET debug_sync='now WAIT_FOR master_queued2';
-SET debug_sync='now SIGNAL master_cont1';
-connection con1;
-connection con2;
-SET debug_sync='RESET';
-connection server_2;
-include/wait_for_slave_sql_error.inc [errno=1062]
-include/wait_for_slave_sql_to_stop.inc
-SELECT * FROM t3 WHERE a >= 110 ORDER BY a;
-a b
-110 1
-111 666
-SET sql_log_bin=0;
-DELETE FROM t3 WHERE a=111 AND b=666;
-SET sql_log_bin=1;
-START SLAVE SQL_THREAD;
-SELECT * FROM t3 WHERE a >= 110 ORDER BY a;
-a b
-110 1
-111 2
-112 3
-***MDEV-5914: Parallel replication deadlock due to InnoDB lock conflicts ***
-connection server_2;
-include/stop_slave.inc
-connection server_1;
-CREATE TABLE t4 (a INT PRIMARY KEY, b INT, KEY b_idx(b)) ENGINE=InnoDB;
-INSERT INTO t4 VALUES (1,NULL), (2,2), (3,NULL), (4,4), (5, NULL), (6, 6);
-connection con1;
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
-UPDATE t4 SET b=NULL WHERE a=6;
-connection server_1;
-SET debug_sync='now WAIT_FOR master_queued1';
-connection con2;
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
-DELETE FROM t4 WHERE b <= 3;
-connection server_1;
-SET debug_sync='now WAIT_FOR master_queued2';
-SET debug_sync='now SIGNAL master_cont1';
-connection con1;
-connection con2;
-SET debug_sync='RESET';
-connection server_2;
-include/start_slave.inc
-include/stop_slave.inc
-SELECT * FROM t4 ORDER BY a;
-a b
-1 NULL
-3 NULL
-4 4
-5 NULL
-6 NULL
-connection server_1;
-DELETE FROM t4;
-INSERT INTO t4 VALUES (1,NULL), (2,2), (3,NULL), (4,4), (5, NULL), (6, 6);
-connection con1;
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
-INSERT INTO t4 VALUES (7, NULL);
-connection server_1;
-SET debug_sync='now WAIT_FOR master_queued1';
-connection con2;
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
-DELETE FROM t4 WHERE b <= 3;
-connection server_1;
-SET debug_sync='now WAIT_FOR master_queued2';
-SET debug_sync='now SIGNAL master_cont1';
-connection con1;
-connection con2;
-SET debug_sync='RESET';
-connection server_2;
-include/start_slave.inc
-include/stop_slave.inc
-SELECT * FROM t4 ORDER BY a;
-a b
-1 NULL
-3 NULL
-4 4
-5 NULL
-6 6
-7 NULL
-connection server_1;
-DELETE FROM t4;
-INSERT INTO t4 VALUES (1,NULL), (2,2), (3,NULL), (4,4), (5, NULL), (6, 6);
-connection con1;
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
-UPDATE t4 SET b=NULL WHERE a=6;
-connection server_1;
-SET debug_sync='now WAIT_FOR master_queued1';
-connection con2;
-SET @old_format= @@SESSION.binlog_format;
-SET binlog_format='statement';
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
-DELETE FROM t4 WHERE b <= 1;
-connection server_1;
-SET debug_sync='now WAIT_FOR master_queued2';
-SET debug_sync='now SIGNAL master_cont1';
-connection con1;
-connection con2;
-SET @old_format=@@GLOBAL.binlog_format;
-SET debug_sync='RESET';
-connection server_2;
-SET @old_dbug= @@GLOBAL.debug_dbug;
-SET GLOBAL debug_dbug="+d,disable_thd_need_ordering_with";
-include/start_slave.inc
-SET GLOBAL debug_dbug=@old_dbug;
-SELECT * FROM t4 ORDER BY a;
-a b
-1 NULL
-2 2
-3 NULL
-4 4
-5 NULL
-6 NULL
-SET @last_gtid= 'GTID';
-SELECT IF(@@gtid_slave_pos LIKE CONCAT('%',@last_gtid,'%'), "GTID found ok",
-CONCAT("GTID ", @last_gtid, " not found in gtid_slave_pos=", @@gtid_slave_pos))
-AS result;
-result
-GTID found ok
-SELECT "ROW FOUND" AS `Is the row found?`
- FROM mysql.gtid_slave_pos
-WHERE CONCAT(domain_id, "-", server_id, "-", seq_no) = @last_gtid;
-Is the row found?
-ROW FOUND
-*** MDEV-5938: Exec_master_log_pos not updated at log rotate in parallel replication ***
-connection server_2;
-include/stop_slave.inc
-SET GLOBAL slave_parallel_threads=1;
-SET DEBUG_SYNC= 'RESET';
-include/start_slave.inc
-connection server_1;
-CREATE TABLE t5 (a INT PRIMARY KEY, b INT);
-INSERT INTO t5 VALUES (1,1);
-INSERT INTO t5 VALUES (2,2), (3,8);
-INSERT INTO t5 VALUES (4,16);
-connection server_2;
-test_check
-OK
-test_check
-OK
-connection server_1;
-FLUSH LOGS;
-connection server_2;
-test_check
-OK
-test_check
-OK
-*** MDEV_6435: Incorrect error handling when query binlogged partially on master with "killed" error ***
-connection server_1;
-CREATE TABLE t6 (a INT) ENGINE=MyISAM;
-CREATE TRIGGER tr AFTER INSERT ON t6 FOR EACH ROW SET @a = 1;
-connection con1;
-SET @old_format= @@binlog_format;
-SET binlog_format= statement;
-SET debug_sync='sp_head_execute_before_loop SIGNAL ready WAIT_FOR cont';
-INSERT INTO t6 VALUES (1), (2), (3);
-connection server_1;
-SET debug_sync='now WAIT_FOR ready';
-KILL QUERY CONID;
-SET debug_sync='now SIGNAL cont';
-connection con1;
-ERROR 70100: Query execution was interrupted
-SET binlog_format= @old_format;
-SET debug_sync='RESET';
-connection server_1;
-SET debug_sync='RESET';
-connection server_2;
-include/wait_for_slave_sql_error.inc [errno=1317]
-STOP SLAVE IO_THREAD;
-SET GLOBAL gtid_slave_pos= 'AFTER_ERROR_GTID_POS';
-include/start_slave.inc
-connection server_1;
-INSERT INTO t6 VALUES (4);
-SELECT * FROM t6 ORDER BY a;
-a
-1
-4
-connection server_2;
-SELECT * FROM t6 ORDER BY a;
-a
-4
-*** MDEV-6551: Some replication errors are ignored if slave_parallel_threads > 0 ***
-connection server_1;
-INSERT INTO t2 VALUES (31);
-include/save_master_gtid.inc
-connection server_2;
-include/sync_with_master_gtid.inc
-include/stop_slave.inc
-SET GLOBAL slave_parallel_threads= 0;
-include/start_slave.inc
-SET sql_log_bin= 0;
-INSERT INTO t2 VALUES (32);
-SET sql_log_bin= 1;
-connection server_1;
-INSERT INTO t2 VALUES (32);
-FLUSH LOGS;
-INSERT INTO t2 VALUES (33);
-INSERT INTO t2 VALUES (34);
-SELECT * FROM t2 WHERE a >= 30 ORDER BY a;
-a
-31
-32
-33
-34
-include/save_master_gtid.inc
-connection server_2;
-include/wait_for_slave_sql_error.inc [errno=1062]
-connection server_2;
-include/stop_slave_io.inc
-SET GLOBAL slave_parallel_threads=10;
-START SLAVE;
-include/wait_for_slave_sql_error.inc [errno=1062]
-START SLAVE SQL_THREAD;
-include/wait_for_slave_sql_error.inc [errno=1062]
-SELECT * FROM t2 WHERE a >= 30 ORDER BY a;
-a
-31
-32
-SET sql_slave_skip_counter= 1;
-ERROR HY000: When using parallel replication and GTID with multiple replication domains, @@sql_slave_skip_counter can not be used. Instead, setting @@gtid_slave_pos explicitly can be used to skip to after a given GTID position
-include/stop_slave_io.inc
-include/start_slave.inc
-include/sync_with_master_gtid.inc
-SELECT * FROM t2 WHERE a >= 30 ORDER BY a;
-a
-31
-32
-33
-34
-*** MDEV-6775: Wrong binlog order in parallel replication ***
-connection server_1;
-DELETE FROM t4;
-INSERT INTO t4 VALUES (1,NULL), (3,NULL), (4,4), (5, NULL), (6, 6);
-include/save_master_gtid.inc
-connection server_2;
-include/sync_with_master_gtid.inc
-include/stop_slave.inc
-SET @old_dbug= @@GLOBAL.debug_dbug;
-SET GLOBAL debug_dbug="+d,inject_binlog_commit_before_get_LOCK_log";
-SET @old_format=@@GLOBAL.binlog_format;
-SET GLOBAL binlog_format=ROW;
-SET GLOBAL slave_parallel_threads=0;
-SET GLOBAL slave_parallel_threads=10;
-connection con1;
-SET @old_format= @@binlog_format;
-SET binlog_format= statement;
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
-UPDATE t4 SET b=NULL WHERE a=6;
-connection server_1;
-SET debug_sync='now WAIT_FOR master_queued1';
-connection con2;
-SET @old_format= @@binlog_format;
-SET binlog_format= statement;
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
-DELETE FROM t4 WHERE b <= 3;
-connection server_1;
-SET debug_sync='now WAIT_FOR master_queued2';
-SET debug_sync='now SIGNAL master_cont1';
-connection con1;
-SET binlog_format= @old_format;
-connection con2;
-SET binlog_format= @old_format;
-SET debug_sync='RESET';
-SELECT * FROM t4 ORDER BY a;
-a b
-1 NULL
-3 NULL
-4 4
-5 NULL
-6 NULL
-connection server_2;
-include/start_slave.inc
-SET debug_sync= 'now WAIT_FOR waiting';
-SELECT * FROM t4 ORDER BY a;
-a b
-1 NULL
-3 NULL
-4 4
-5 NULL
-6 NULL
-SET debug_sync= 'now SIGNAL cont';
-include/stop_slave.inc
-SET GLOBAL debug_dbug=@old_dbug;
-SET GLOBAL binlog_format= @old_format;
-SET GLOBAL slave_parallel_threads=0;
-SET GLOBAL slave_parallel_threads=10;
-include/start_slave.inc
-*** MDEV-7237: Parallel replication: incorrect relaylog position after stop/start the slave ***
-connection server_1;
-INSERT INTO t2 VALUES (40);
-connection server_2;
-include/stop_slave.inc
-CHANGE MASTER TO master_use_gtid=no;
-SET @old_dbug= @@GLOBAL.debug_dbug;
-SET GLOBAL debug_dbug="+d,rpl_parallel_scheduled_gtid_0_x_100";
-SET GLOBAL debug_dbug="+d,rpl_parallel_wait_for_done_trigger";
-SET GLOBAL slave_parallel_threads=0;
-SET GLOBAL slave_parallel_threads=10;
-connection server_1;
-INSERT INTO t2 VALUES (41);
-INSERT INTO t2 VALUES (42);
-SET @old_format= @@binlog_format;
-SET binlog_format= statement;
-DELETE FROM t2 WHERE a=40;
-SET binlog_format= @old_format;
-INSERT INTO t2 VALUES (43);
-INSERT INTO t2 VALUES (44);
-FLUSH LOGS;
-INSERT INTO t2 VALUES (45);
-SET gtid_seq_no=100;
-INSERT INTO t2 VALUES (46);
-connection con_temp2;
-BEGIN;
-SELECT * FROM t2 WHERE a=40 FOR UPDATE;
-a
-40
-connection server_2;
-include/start_slave.inc
-SET debug_sync= 'now WAIT_FOR scheduled_gtid_0_x_100';
-STOP SLAVE;
-connection con_temp2;
-SET debug_sync= 'now WAIT_FOR wait_for_done_waiting';
-ROLLBACK;
-connection server_2;
-include/wait_for_slave_sql_to_stop.inc
-SELECT * FROM t2 WHERE a >= 40 ORDER BY a;
-a
-41
-42
-include/start_slave.inc
-SELECT * FROM t2 WHERE a >= 40 ORDER BY a;
-a
-41
-42
-43
-44
-45
-46
-include/stop_slave.inc
-SET GLOBAL debug_dbug=@old_dbug;
-SET DEBUG_SYNC= 'RESET';
-SET GLOBAL slave_parallel_threads=0;
-SET GLOBAL slave_parallel_threads=10;
-CHANGE MASTER TO master_use_gtid=slave_pos;
-include/start_slave.inc
-*** MDEV-7326 Server deadlock in connection with parallel replication ***
-connection server_2;
-include/stop_slave.inc
-SET GLOBAL slave_parallel_threads=0;
-SET GLOBAL slave_parallel_threads=3;
-SET GLOBAL debug_dbug="+d,rpl_parallel_simulate_temp_err_xid";
-include/start_slave.inc
-connection server_1;
-SET @old_format= @@SESSION.binlog_format;
-SET binlog_format= STATEMENT;
-INSERT INTO t1 VALUES (foo(50,
-"rpl_parallel_start_waiting_for_prior SIGNAL t3_ready",
-"rpl_parallel_end_of_group SIGNAL prep_ready WAIT_FOR prep_cont"));
-connection server_2;
-SET DEBUG_SYNC= "now WAIT_FOR prep_ready";
-connection server_1;
-INSERT INTO t2 VALUES (foo(50,
-"rpl_parallel_simulate_temp_err_xid SIGNAL t1_ready1 WAIT_FOR t1_cont1",
-"rpl_parallel_retry_after_unmark SIGNAL t1_ready2 WAIT_FOR t1_cont2"));
-connection server_2;
-SET DEBUG_SYNC= "now WAIT_FOR t1_ready1";
-connection server_1;
-INSERT INTO t1 VALUES (foo(51,
-"rpl_parallel_before_mark_start_commit SIGNAL t2_ready1 WAIT_FOR t2_cont1",
-"rpl_parallel_after_mark_start_commit SIGNAL t2_ready2"));
-connection server_2;
-SET DEBUG_SYNC= "now WAIT_FOR t2_ready1";
-SET DEBUG_SYNC= "now SIGNAL t1_cont1";
-SET DEBUG_SYNC= "now WAIT_FOR t1_ready2";
-connection server_1;
-INSERT INTO t1 VALUES (52);
-SET BINLOG_FORMAT= @old_format;
-SELECT * FROM t2 WHERE a>=50 ORDER BY a;
-a
-50
-SELECT * FROM t1 WHERE a>=50 ORDER BY a;
-a
-50
-51
-52
-connection server_2;
-SET DEBUG_SYNC= "now SIGNAL prep_cont";
-SET DEBUG_SYNC= "now WAIT_FOR t3_ready";
-SET DEBUG_SYNC= "now SIGNAL t2_cont1";
-SET DEBUG_SYNC= "now WAIT_FOR t2_ready2";
-SET DEBUG_SYNC= "now SIGNAL t1_cont2";
-connection server_1;
-connection server_2;
-SELECT * FROM t2 WHERE a>=50 ORDER BY a;
-a
-50
-SELECT * FROM t1 WHERE a>=50 ORDER BY a;
-a
-50
-51
-52
-SET DEBUG_SYNC="reset";
-include/stop_slave.inc
-SET GLOBAL debug_dbug=@old_dbug;
-SET GLOBAL slave_parallel_threads=0;
-SET GLOBAL slave_parallel_threads=10;
-include/start_slave.inc
-*** MDEV-7326 Server deadlock in connection with parallel replication ***
-connection server_2;
-include/stop_slave.inc
-SET GLOBAL slave_parallel_threads=0;
-SET GLOBAL slave_parallel_threads=3;
-SET GLOBAL debug_dbug="+d,rpl_parallel_simulate_temp_err_xid";
-include/start_slave.inc
-connection server_1;
-SET @old_format= @@SESSION.binlog_format;
-SET binlog_format= STATEMENT;
-INSERT INTO t1 VALUES (foo(60,
-"rpl_parallel_start_waiting_for_prior SIGNAL t3_ready",
-"rpl_parallel_end_of_group SIGNAL prep_ready WAIT_FOR prep_cont"));
-connection server_2;
-SET DEBUG_SYNC= "now WAIT_FOR prep_ready";
-connection server_1;
-INSERT INTO t2 VALUES (foo(60,
-"rpl_parallel_simulate_temp_err_xid SIGNAL t1_ready1 WAIT_FOR t1_cont1",
-"rpl_parallel_retry_after_unmark SIGNAL t1_ready2 WAIT_FOR t1_cont2"));
-connection server_2;
-SET DEBUG_SYNC= "now WAIT_FOR t1_ready1";
-connection con_temp3;
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
-SET binlog_format=statement;
-INSERT INTO t1 VALUES (foo(61,
-"rpl_parallel_before_mark_start_commit SIGNAL t2_ready1 WAIT_FOR t2_cont1",
-"rpl_parallel_after_mark_start_commit SIGNAL t2_ready2"));
-connection server_1;
-SET debug_sync='now WAIT_FOR master_queued1';
-connection con_temp4;
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
-INSERT INTO t6 VALUES (62);
-connection server_1;
-SET debug_sync='now WAIT_FOR master_queued2';
-SET debug_sync='now SIGNAL master_cont1';
-connection con_temp3;
-connection con_temp4;
-connection server_1;
-SET debug_sync='RESET';
-SET BINLOG_FORMAT= @old_format;
-SELECT * FROM t2 WHERE a>=60 ORDER BY a;
-a
-60
-SELECT * FROM t1 WHERE a>=60 ORDER BY a;
-a
-60
-61
-SELECT * FROM t6 WHERE a>=60 ORDER BY a;
-a
-62
-connection server_2;
-SET DEBUG_SYNC= "now WAIT_FOR t2_ready1";
-SET DEBUG_SYNC= "now SIGNAL t1_cont1";
-SET DEBUG_SYNC= "now WAIT_FOR t1_ready2";
-connection server_2;
-SET DEBUG_SYNC= "now SIGNAL prep_cont";
-SET DEBUG_SYNC= "now WAIT_FOR t3_ready";
-SET DEBUG_SYNC= "now SIGNAL t2_cont1";
-SET DEBUG_SYNC= "now WAIT_FOR t2_ready2";
-SET DEBUG_SYNC= "now SIGNAL t1_cont2";
-connection server_1;
-connection server_2;
-SELECT * FROM t2 WHERE a>=60 ORDER BY a;
-a
-60
-SELECT * FROM t1 WHERE a>=60 ORDER BY a;
-a
-60
-61
-SELECT * FROM t6 WHERE a>=60 ORDER BY a;
-a
-62
-SET DEBUG_SYNC="reset";
-include/stop_slave.inc
-SET GLOBAL debug_dbug=@old_dbug;
-SET GLOBAL slave_parallel_threads=0;
-SET GLOBAL slave_parallel_threads=10;
-include/start_slave.inc
-*** MDEV-7335: Potential parallel slave deadlock with specific binlog corruption ***
-connection server_2;
-include/stop_slave.inc
-SET GLOBAL slave_parallel_threads=1;
-SET @old_dbug= @@GLOBAL.debug_dbug;
-SET GLOBAL debug_dbug="+d,slave_discard_xid_for_gtid_0_x_1000";
-connection server_1;
-INSERT INTO t2 VALUES (101);
-INSERT INTO t2 VALUES (102);
-INSERT INTO t2 VALUES (103);
-INSERT INTO t2 VALUES (104);
-INSERT INTO t2 VALUES (105);
-SET gtid_seq_no=1000;
-INSERT INTO t2 VALUES (106);
-INSERT INTO t2 VALUES (107);
-INSERT INTO t2 VALUES (108);
-INSERT INTO t2 VALUES (109);
-INSERT INTO t2 VALUES (110);
-INSERT INTO t2 VALUES (111);
-INSERT INTO t2 VALUES (112);
-INSERT INTO t2 VALUES (113);
-INSERT INTO t2 VALUES (114);
-INSERT INTO t2 VALUES (115);
-INSERT INTO t2 VALUES (116);
-INSERT INTO t2 VALUES (117);
-INSERT INTO t2 VALUES (118);
-INSERT INTO t2 VALUES (119);
-INSERT INTO t2 VALUES (120);
-INSERT INTO t2 VALUES (121);
-INSERT INTO t2 VALUES (122);
-INSERT INTO t2 VALUES (123);
-INSERT INTO t2 VALUES (124);
-INSERT INTO t2 VALUES (125);
-INSERT INTO t2 VALUES (126);
-INSERT INTO t2 VALUES (127);
-INSERT INTO t2 VALUES (128);
-INSERT INTO t2 VALUES (129);
-INSERT INTO t2 VALUES (130);
-include/save_master_gtid.inc
-connection server_2;
-include/start_slave.inc
-include/sync_with_master_gtid.inc
-SELECT * FROM t2 WHERE a >= 100 ORDER BY a;
-a
-101
-102
-103
-104
-105
-107
-108
-109
-110
-111
-112
-113
-114
-115
-116
-117
-118
-119
-120
-121
-122
-123
-124
-125
-126
-127
-128
-129
-130
-include/stop_slave.inc
-SET GLOBAL debug_dbug=@old_dbug;
-SET GLOBAL slave_parallel_threads=10;
-include/start_slave.inc
-*** MDEV-6676 - test syntax of @@slave_parallel_mode ***
-connection server_2;
-Parallel_Mode = 'conservative'
-include/stop_slave.inc
-SET GLOBAL slave_parallel_mode='aggressive';
-Parallel_Mode = 'aggressive'
-SET GLOBAL slave_parallel_mode='conservative';
-Parallel_Mode = 'conservative'
-*** MDEV-6676 - test that empty parallel_mode does not replicate in parallel ***
-connection server_1;
-INSERT INTO t2 VALUES (1040);
-include/save_master_gtid.inc
-connection server_2;
-SET GLOBAL slave_parallel_mode='none';
-SET @old_dbug= @@GLOBAL.debug_dbug;
-SET GLOBAL debug_dbug="+d,slave_crash_if_parallel_apply";
-include/start_slave.inc
-include/sync_with_master_gtid.inc
-SELECT * FROM t2 WHERE a >= 1040 ORDER BY a;
-a
-1040
-include/stop_slave.inc
-SET GLOBAL debug_dbug=@old_dbug;
-*** MDEV-6676 - test disabling domain-based parallel replication ***
-connection server_1;
-SET gtid_domain_id = 1;
-INSERT INTO t2 VALUES (1041);
-INSERT INTO t2 VALUES (1042);
-INSERT INTO t2 VALUES (1043);
-INSERT INTO t2 VALUES (1044);
-INSERT INTO t2 VALUES (1045);
-INSERT INTO t2 VALUES (1046);
-DELETE FROM t2 WHERE a >= 1041;
-SET gtid_domain_id = 2;
-INSERT INTO t2 VALUES (1041);
-INSERT INTO t2 VALUES (1042);
-INSERT INTO t2 VALUES (1043);
-INSERT INTO t2 VALUES (1044);
-INSERT INTO t2 VALUES (1045);
-INSERT INTO t2 VALUES (1046);
-SET gtid_domain_id = 0;
-include/save_master_gtid.inc
-connection server_2;
-SET GLOBAL slave_parallel_mode=minimal;
-include/start_slave.inc
-include/sync_with_master_gtid.inc
-SELECT * FROM t2 WHERE a >= 1040 ORDER BY a;
-a
-1040
-1041
-1042
-1043
-1044
-1045
-1046
-*** MDEV-7888: ANALYZE TABLE does wakeup_subsequent_commits(), causing wrong binlog order and parallel replication hang ***
-connection server_2;
-include/stop_slave.inc
-SET GLOBAL slave_parallel_mode='conservative';
-SET GLOBAL slave_parallel_threads=10;
-SET @old_dbug= @@GLOBAL.debug_dbug;
-SET GLOBAL debug_dbug= '+d,inject_analyze_table_sleep';
-connection server_1;
-SET @old_dbug= @@SESSION.debug_dbug;
-SET SESSION debug_dbug="+d,binlog_force_commit_id";
-SET @commit_id= 10000;
-ANALYZE TABLE t2;
-Table Op Msg_type Msg_text
-test.t2 analyze status Engine-independent statistics collected
-test.t2 analyze status OK
-INSERT INTO t3 VALUES (120, 0);
-SET @commit_id= 10001;
-INSERT INTO t3 VALUES (121, 0);
-SET SESSION debug_dbug=@old_dbug;
-SELECT * FROM t3 WHERE a >= 120 ORDER BY a;
-a b
-120 0
-121 0
-include/save_master_gtid.inc
-connection server_2;
-include/start_slave.inc
-include/sync_with_master_gtid.inc
-SELECT * FROM t3 WHERE a >= 120 ORDER BY a;
-a b
-120 0
-121 0
-include/stop_slave.inc
-SET GLOBAL debug_dbug= @old_dbug;
-include/start_slave.inc
-*** MDEV-7929: record_gtid() for non-transactional event group calls wakeup_subsequent_commits() too early, causing slave hang. ***
-connection server_2;
-include/stop_slave.inc
-SET @old_dbug= @@GLOBAL.debug_dbug;
-SET GLOBAL debug_dbug= '+d,inject_record_gtid_serverid_100_sleep';
-connection server_1;
-SET @old_dbug= @@SESSION.debug_dbug;
-SET SESSION debug_dbug="+d,binlog_force_commit_id";
-SET @old_server_id= @@SESSION.server_id;
-SET SESSION server_id= 100;
-SET @commit_id= 10010;
-ALTER TABLE t1 COMMENT "Hulubulu!";
-SET SESSION server_id= @old_server_id;
-INSERT INTO t3 VALUES (130, 0);
-SET @commit_id= 10011;
-INSERT INTO t3 VALUES (131, 0);
-SET SESSION debug_dbug=@old_dbug;
-SELECT * FROM t3 WHERE a >= 130 ORDER BY a;
-a b
-130 0
-131 0
-include/save_master_gtid.inc
-connection server_2;
-include/start_slave.inc
-include/sync_with_master_gtid.inc
-SELECT * FROM t3 WHERE a >= 130 ORDER BY a;
-a b
-130 0
-131 0
-include/stop_slave.inc
-SET GLOBAL debug_dbug= @old_dbug;
-include/start_slave.inc
-*** MDEV-8031: Parallel replication stops on "connection killed" error (probably incorrectly handled deadlock kill) ***
-connection server_1;
-INSERT INTO t3 VALUES (201,0), (202,0);
-include/save_master_gtid.inc
-connection server_2;
-include/sync_with_master_gtid.inc
-include/stop_slave.inc
-SET @old_dbug= @@GLOBAL.debug_dbug;
-SET GLOBAL debug_dbug= '+d,inject_mdev8031';
-connection server_1;
-SET @old_dbug= @@SESSION.debug_dbug;
-SET SESSION debug_dbug="+d,binlog_force_commit_id";
-SET @commit_id= 10200;
-INSERT INTO t3 VALUES (203, 1);
-INSERT INTO t3 VALUES (204, 1);
-INSERT INTO t3 VALUES (205, 1);
-UPDATE t3 SET b=b+1 WHERE a=201;
-UPDATE t3 SET b=b+1 WHERE a=201;
-UPDATE t3 SET b=b+1 WHERE a=201;
-UPDATE t3 SET b=b+1 WHERE a=202;
-UPDATE t3 SET b=b+1 WHERE a=202;
-UPDATE t3 SET b=b+1 WHERE a=202;
-UPDATE t3 SET b=b+1 WHERE a=202;
-UPDATE t3 SET b=b+1 WHERE a=203;
-UPDATE t3 SET b=b+1 WHERE a=203;
-UPDATE t3 SET b=b+1 WHERE a=204;
-UPDATE t3 SET b=b+1 WHERE a=204;
-UPDATE t3 SET b=b+1 WHERE a=204;
-UPDATE t3 SET b=b+1 WHERE a=203;
-UPDATE t3 SET b=b+1 WHERE a=205;
-UPDATE t3 SET b=b+1 WHERE a=205;
-SET SESSION debug_dbug=@old_dbug;
-SELECT * FROM t3 WHERE a>=200 ORDER BY a;
-a b
-201 3
-202 4
-203 4
-204 4
-205 3
-include/save_master_gtid.inc
-connection server_2;
-include/start_slave.inc
-include/sync_with_master_gtid.inc
-SELECT * FROM t3 WHERE a>=200 ORDER BY a;
-a b
-201 3
-202 4
-203 4
-204 4
-205 3
-include/stop_slave.inc
-SET GLOBAL debug_dbug= @old_dbug;
-include/start_slave.inc
-*** Check getting deadlock killed inside open_binlog() during retry. ***
-connection server_2;
-include/stop_slave.inc
-SET @old_dbug= @@GLOBAL.debug_dbug;
-SET GLOBAL debug_dbug= '+d,inject_retry_event_group_open_binlog_kill';
-SET @old_max= @@GLOBAL.max_relay_log_size;
-SET GLOBAL max_relay_log_size= 4096;
-connection server_1;
-SET @old_dbug= @@SESSION.debug_dbug;
-SET SESSION debug_dbug="+d,binlog_force_commit_id";
-SET @commit_id= 10210;
-Omit long queries that cause relaylog rotations and transaction retries...
-SET SESSION debug_dbug=@old_dbug;
-SELECT * FROM t3 WHERE a>=200 ORDER BY a;
-a b
-201 6
-202 8
-203 7
-204 7
-205 5
-include/save_master_gtid.inc
-connection server_2;
-include/start_slave.inc
-include/sync_with_master_gtid.inc
-SELECT * FROM t3 WHERE a>=200 ORDER BY a;
-a b
-201 6
-202 8
-203 7
-204 7
-205 5
-include/stop_slave.inc
-SET GLOBAL debug_dbug= @old_debg;
-SET GLOBAL max_relay_log_size= @old_max;
-include/start_slave.inc
-*** MDEV-8725: Assertion on ROLLBACK statement in the binary log ***
-connection server_1;
-BEGIN;
-INSERT INTO t2 VALUES (2000);
-INSERT INTO t1 VALUES (2000);
-INSERT INTO t2 VALUES (2001);
-ROLLBACK;
-SELECT * FROM t1 WHERE a>=2000 ORDER BY a;
-a
-2000
-SELECT * FROM t2 WHERE a>=2000 ORDER BY a;
-a
-include/save_master_gtid.inc
-connection server_2;
-include/sync_with_master_gtid.inc
-SELECT * FROM t1 WHERE a>=2000 ORDER BY a;
-a
-2000
-SELECT * FROM t2 WHERE a>=2000 ORDER BY a;
-a
-connection server_2;
-include/stop_slave.inc
-SET GLOBAL slave_parallel_threads=@old_parallel_threads;
-include/start_slave.inc
-SET DEBUG_SYNC= 'RESET';
-connection server_1;
-DROP function foo;
-DROP TABLE t1,t2,t3,t4,t5,t6;
-SET DEBUG_SYNC= 'RESET';
-include/rpl_end.inc
diff --git a/mysql-test/suite/binlog_encryption/rpl_parallel.test b/mysql-test/suite/binlog_encryption/rpl_parallel.test
deleted file mode 100644
index dba54e4fd7a..00000000000
--- a/mysql-test/suite/binlog_encryption/rpl_parallel.test
+++ /dev/null
@@ -1 +0,0 @@
---source suite/rpl/include/rpl_parallel.inc
diff --git a/mysql-test/suite/binlog_encryption/rpl_parallel_analyze_table_hang.result b/mysql-test/suite/binlog_encryption/rpl_parallel_analyze_table_hang.result
new file mode 100644
index 00000000000..3c3cd2601e8
--- /dev/null
+++ b/mysql-test/suite/binlog_encryption/rpl_parallel_analyze_table_hang.result
@@ -0,0 +1,51 @@
+*** MDEV-7888: ANALYZE TABLE does wakeup_subsequent_commits(), causing wrong binlog order and parallel replication hang ***
+include/master-slave.inc
+[connection master]
+connection server_2;
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+SET @old_parallel_mode=@@GLOBAL.slave_parallel_mode;
+include/stop_slave.inc
+SET GLOBAL slave_parallel_mode='conservative';
+SET GLOBAL slave_parallel_threads=10;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+include/start_slave.inc
+connection server_1;
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t2 (a int PRIMARY KEY) ENGINE=InnoDB;
+CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
+connection server_2;
+include/stop_slave.inc
+SET @old_dbug= @@GLOBAL.debug_dbug;
+SET GLOBAL debug_dbug= '+d,inject_analyze_table_sleep';
+connection server_1;
+SET @old_dbug= @@SESSION.debug_dbug;
+SET SESSION debug_dbug="+d,binlog_force_commit_id";
+SET @commit_id= 10000;
+ANALYZE TABLE t2;
+Table Op Msg_type Msg_text
+test.t2 analyze status Engine-independent statistics collected
+test.t2 analyze status OK
+INSERT INTO t3 VALUES (120, 0);
+SET @commit_id= 10001;
+INSERT INTO t3 VALUES (121, 0);
+SET SESSION debug_dbug=@old_dbug;
+SELECT * FROM t3 WHERE a >= 120 ORDER BY a;
+a b
+120 0
+121 0
+include/save_master_gtid.inc
+connection server_2;
+include/start_slave.inc
+include/sync_with_master_gtid.inc
+SELECT * FROM t3 WHERE a >= 120 ORDER BY a;
+a b
+120 0
+121 0
+include/stop_slave.inc
+SET GLOBAL debug_dbug= @old_dbug;
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+SET GLOBAL slave_parallel_mode=@old_parallel_mode;
+include/start_slave.inc
+connection server_1;
+DROP TABLE t2,t3;
+include/rpl_end.inc
diff --git a/mysql-test/suite/binlog_encryption/rpl_parallel_analyze_table_hang.test b/mysql-test/suite/binlog_encryption/rpl_parallel_analyze_table_hang.test
new file mode 100644
index 00000000000..69e76692ce1
--- /dev/null
+++ b/mysql-test/suite/binlog_encryption/rpl_parallel_analyze_table_hang.test
@@ -0,0 +1 @@
+--source suite/rpl/include/rpl_parallel_analyze_table_hang.inc
diff --git a/mysql-test/suite/binlog_encryption/rpl_parallel_deadlock_corrupt_binlog.result b/mysql-test/suite/binlog_encryption/rpl_parallel_deadlock_corrupt_binlog.result
new file mode 100644
index 00000000000..74d1d53b67c
--- /dev/null
+++ b/mysql-test/suite/binlog_encryption/rpl_parallel_deadlock_corrupt_binlog.result
@@ -0,0 +1,93 @@
+*** MDEV-7335: Potential parallel slave deadlock with specific binlog corruption ***
+include/master-slave.inc
+[connection master]
+connection server_2;
+include/stop_slave.inc
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+SET GLOBAL slave_parallel_threads=10;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+include/start_slave.inc
+connection server_1;
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t2 (a int PRIMARY KEY) ENGINE=InnoDB;
+connection server_2;
+include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=1;
+SET @old_dbug= @@GLOBAL.debug_dbug;
+SET GLOBAL debug_dbug="+d,slave_discard_xid_for_gtid_0_x_1000";
+connection server_1;
+INSERT INTO t2 VALUES (101);
+INSERT INTO t2 VALUES (102);
+INSERT INTO t2 VALUES (103);
+INSERT INTO t2 VALUES (104);
+INSERT INTO t2 VALUES (105);
+SET gtid_seq_no=1000;
+INSERT INTO t2 VALUES (106);
+INSERT INTO t2 VALUES (107);
+INSERT INTO t2 VALUES (108);
+INSERT INTO t2 VALUES (109);
+INSERT INTO t2 VALUES (110);
+INSERT INTO t2 VALUES (111);
+INSERT INTO t2 VALUES (112);
+INSERT INTO t2 VALUES (113);
+INSERT INTO t2 VALUES (114);
+INSERT INTO t2 VALUES (115);
+INSERT INTO t2 VALUES (116);
+INSERT INTO t2 VALUES (117);
+INSERT INTO t2 VALUES (118);
+INSERT INTO t2 VALUES (119);
+INSERT INTO t2 VALUES (120);
+INSERT INTO t2 VALUES (121);
+INSERT INTO t2 VALUES (122);
+INSERT INTO t2 VALUES (123);
+INSERT INTO t2 VALUES (124);
+INSERT INTO t2 VALUES (125);
+INSERT INTO t2 VALUES (126);
+INSERT INTO t2 VALUES (127);
+INSERT INTO t2 VALUES (128);
+INSERT INTO t2 VALUES (129);
+INSERT INTO t2 VALUES (130);
+include/save_master_gtid.inc
+connection server_2;
+include/start_slave.inc
+include/sync_with_master_gtid.inc
+SELECT * FROM t2 WHERE a >= 100 ORDER BY a;
+a
+101
+102
+103
+104
+105
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+include/stop_slave.inc
+SET GLOBAL debug_dbug=@old_dbug;
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+include/start_slave.inc
+SET DEBUG_SYNC= 'RESET';
+connection server_1;
+DROP TABLE t2;
+SET DEBUG_SYNC= 'RESET';
+include/rpl_end.inc
diff --git a/mysql-test/suite/binlog_encryption/rpl_parallel_deadlock_corrupt_binlog.test b/mysql-test/suite/binlog_encryption/rpl_parallel_deadlock_corrupt_binlog.test
new file mode 100644
index 00000000000..71c589dcd88
--- /dev/null
+++ b/mysql-test/suite/binlog_encryption/rpl_parallel_deadlock_corrupt_binlog.test
@@ -0,0 +1 @@
+--source suite/rpl/include/rpl_parallel_deadlock_corrupt_binlog.inc
diff --git a/mysql-test/suite/binlog_encryption/rpl_parallel_domain.result b/mysql-test/suite/binlog_encryption/rpl_parallel_domain.result
new file mode 100644
index 00000000000..69b9678d149
--- /dev/null
+++ b/mysql-test/suite/binlog_encryption/rpl_parallel_domain.result
@@ -0,0 +1,71 @@
+include/master-slave.inc
+[connection master]
+connection server_2;
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+SET GLOBAL slave_parallel_threads=10;
+ERROR HY000: This operation cannot be performed as you have a running slave ''; run STOP SLAVE '' first
+include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=10;
+SELECT IF(COUNT(*) < 10, "OK", CONCAT("Found too many system user processes: ", COUNT(*))) FROM information_schema.processlist WHERE user = "system user";
+IF(COUNT(*) < 10, "OK", CONCAT("Found too many system user processes: ", COUNT(*)))
+OK
+CHANGE MASTER TO master_use_gtid=slave_pos;
+include/start_slave.inc
+SELECT IF(COUNT(*) >= 10, "OK", CONCAT("Found too few system user processes: ", COUNT(*))) FROM information_schema.processlist WHERE user = "system user";
+IF(COUNT(*) >= 10, "OK", CONCAT("Found too few system user processes: ", COUNT(*)))
+OK
+include/stop_slave.inc
+SELECT IF(COUNT(*) < 10, "OK", CONCAT("Found too many system user processes: ", COUNT(*))) FROM information_schema.processlist WHERE user = "system user";
+IF(COUNT(*) < 10, "OK", CONCAT("Found too many system user processes: ", COUNT(*)))
+OK
+include/start_slave.inc
+SELECT IF(COUNT(*) >= 10, "OK", CONCAT("Found too few system user processes: ", COUNT(*))) FROM information_schema.processlist WHERE user = "system user";
+IF(COUNT(*) >= 10, "OK", CONCAT("Found too few system user processes: ", COUNT(*)))
+OK
+*** Test long-running query in domain 1 can run in parallel with short queries in domain 0 ***
+connection server_1;
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t1 (a int PRIMARY KEY) ENGINE=MyISAM;
+CREATE TABLE t2 (a int PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t2 VALUES (1);
+connection server_2;
+connect con_temp1,127.0.0.1,root,,test,$SERVER_MYPORT_2,;
+LOCK TABLE t1 WRITE;
+connection server_1;
+SET gtid_domain_id=1;
+INSERT INTO t1 VALUES (2);
+SET gtid_domain_id=0;
+INSERT INTO t2 VALUES (2);
+INSERT INTO t2 VALUES (3);
+BEGIN;
+INSERT INTO t2 VALUES (4);
+INSERT INTO t2 VALUES (5);
+COMMIT;
+INSERT INTO t2 VALUES (6);
+connection server_2;
+SELECT * FROM t2 ORDER by a;
+a
+1
+2
+3
+4
+5
+6
+connection con_temp1;
+SELECT * FROM t1;
+a
+1
+UNLOCK TABLES;
+connection server_2;
+SELECT * FROM t1 ORDER BY a;
+a
+1
+2
+connection server_2;
+include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+include/start_slave.inc
+connection server_1;
+DROP TABLE t1,t2;
+include/rpl_end.inc
diff --git a/mysql-test/suite/binlog_encryption/rpl_parallel_domain.test b/mysql-test/suite/binlog_encryption/rpl_parallel_domain.test
new file mode 100644
index 00000000000..b498b8616c8
--- /dev/null
+++ b/mysql-test/suite/binlog_encryption/rpl_parallel_domain.test
@@ -0,0 +1 @@
+--source suite/rpl/include/rpl_parallel_domain.inc
diff --git a/mysql-test/suite/binlog_encryption/rpl_parallel_domain_slave_single_grp.result b/mysql-test/suite/binlog_encryption/rpl_parallel_domain_slave_single_grp.result
new file mode 100644
index 00000000000..613aac64487
--- /dev/null
+++ b/mysql-test/suite/binlog_encryption/rpl_parallel_domain_slave_single_grp.result
@@ -0,0 +1,101 @@
+*** Test two transactions in different domains committed in opposite order on slave but in a single group commit. ***
+include/master-slave.inc
+[connection master]
+connection server_2;
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=10;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+include/start_slave.inc
+connection server_1;
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t1 (a int PRIMARY KEY) ENGINE=MyISAM;
+CREATE TABLE t2 (a int PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t2 VALUES (1);
+connection server_2;
+include/stop_slave.inc
+connection server_1;
+SET sql_log_bin=0;
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+RETURNS INT DETERMINISTIC
+BEGIN
+RETURN x;
+END
+||
+SET sql_log_bin=1;
+SET @old_format= @@SESSION.binlog_format;
+SET binlog_format='statement';
+SET gtid_domain_id=1;
+INSERT INTO t2 VALUES (foo(10,
+'commit_before_enqueue SIGNAL ready1 WAIT_FOR cont1',
+'commit_after_release_LOCK_prepare_ordered SIGNAL ready2'));
+connection server_2;
+FLUSH LOGS;
+SET sql_log_bin=0;
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+RETURNS INT DETERMINISTIC
+BEGIN
+IF d1 != '' THEN
+SET debug_sync = d1;
+END IF;
+IF d2 != '' THEN
+SET debug_sync = d2;
+END IF;
+RETURN x;
+END
+||
+SET sql_log_bin=1;
+SET @old_format=@@GLOBAL.binlog_format;
+SET GLOBAL binlog_format=statement;
+SET GLOBAL slave_parallel_threads=0;
+SET GLOBAL slave_parallel_threads=10;
+include/start_slave.inc
+SET debug_sync='now WAIT_FOR ready1';
+connection server_1;
+SET gtid_domain_id=2;
+INSERT INTO t2 VALUES (foo(11,
+'commit_before_enqueue SIGNAL ready3 WAIT_FOR cont3',
+'commit_after_release_LOCK_prepare_ordered SIGNAL ready4 WAIT_FOR cont4'));
+SET gtid_domain_id=0;
+SELECT * FROM t2 WHERE a >= 10 ORDER BY a;
+a
+10
+11
+connection server_2;
+SET debug_sync='now WAIT_FOR ready3';
+SET debug_sync='now SIGNAL cont3';
+SET debug_sync='now WAIT_FOR ready4';
+SET debug_sync='now SIGNAL cont1';
+SET debug_sync='now WAIT_FOR ready2';
+SET debug_sync='now SIGNAL cont4';
+SELECT * FROM t2 WHERE a >= 10 ORDER BY a;
+a
+10
+11
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+slave-bin.000002 # Binlog_checkpoint # # slave-bin.000002
+slave-bin.000002 # Gtid # # BEGIN GTID #-#-# cid=#
+slave-bin.000002 # Query # # use `test`; INSERT INTO t2 VALUES (foo(11,
+'commit_before_enqueue SIGNAL ready3 WAIT_FOR cont3',
+'commit_after_release_LOCK_prepare_ordered SIGNAL ready4 WAIT_FOR cont4'))
+slave-bin.000002 # Xid # # COMMIT /* XID */
+slave-bin.000002 # Gtid # # BEGIN GTID #-#-# cid=#
+slave-bin.000002 # Query # # use `test`; INSERT INTO t2 VALUES (foo(10,
+'commit_before_enqueue SIGNAL ready1 WAIT_FOR cont1',
+'commit_after_release_LOCK_prepare_ordered SIGNAL ready2'))
+slave-bin.000002 # Xid # # COMMIT /* XID */
+FLUSH LOGS;
+connection server_2;
+include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+include/start_slave.inc
+SET DEBUG_SYNC= 'RESET';
+SET GLOBAL binlog_format=@old_format;
+connection server_1;
+DROP function foo;
+DROP TABLE t1,t2;
+SET DEBUG_SYNC= 'RESET';
+SET GLOBAL binlog_format=@old_format;
+include/rpl_end.inc
diff --git a/mysql-test/suite/binlog_encryption/rpl_parallel_domain_slave_single_grp.test b/mysql-test/suite/binlog_encryption/rpl_parallel_domain_slave_single_grp.test
new file mode 100644
index 00000000000..ce9239f189e
--- /dev/null
+++ b/mysql-test/suite/binlog_encryption/rpl_parallel_domain_slave_single_grp.test
@@ -0,0 +1 @@
+--source suite/rpl/include/rpl_parallel_domain_slave_single_grp.inc
diff --git a/mysql-test/suite/binlog_encryption/rpl_parallel_free_deferred_event.result b/mysql-test/suite/binlog_encryption/rpl_parallel_free_deferred_event.result
new file mode 100644
index 00000000000..6718561a321
--- /dev/null
+++ b/mysql-test/suite/binlog_encryption/rpl_parallel_free_deferred_event.result
@@ -0,0 +1,44 @@
+*** MDEV-5788 Incorrect free of rgi->deferred_events in parallel replication ***
+include/master-slave.inc
+[connection master]
+connection server_2;
+include/stop_slave.inc
+CHANGE MASTER TO master_use_gtid=slave_pos;
+include/start_slave.inc
+connection server_1;
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
+connection server_2;
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+include/stop_slave.inc
+SET GLOBAL replicate_ignore_table="test.t3";
+SET GLOBAL slave_parallel_threads=2;
+include/start_slave.inc
+connection server_1;
+INSERT INTO t3 VALUES (100, rand());
+INSERT INTO t3 VALUES (101, rand());
+connection server_2;
+connection server_1;
+INSERT INTO t3 VALUES (102, rand());
+INSERT INTO t3 VALUES (103, rand());
+INSERT INTO t3 VALUES (104, rand());
+INSERT INTO t3 VALUES (105, rand());
+connection server_2;
+include/stop_slave.inc
+SET GLOBAL replicate_ignore_table="";
+include/start_slave.inc
+connection server_1;
+INSERT INTO t3 VALUES (106, rand());
+INSERT INTO t3 VALUES (107, rand());
+connection server_2;
+SELECT * FROM t3 WHERE a >= 100 ORDER BY a;
+a b
+106 #
+107 #
+connection server_2;
+include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+include/start_slave.inc
+connection server_1;
+DROP TABLE t3;
+include/rpl_end.inc
diff --git a/mysql-test/suite/binlog_encryption/rpl_parallel_free_deferred_event.test b/mysql-test/suite/binlog_encryption/rpl_parallel_free_deferred_event.test
new file mode 100644
index 00000000000..d0b6c970210
--- /dev/null
+++ b/mysql-test/suite/binlog_encryption/rpl_parallel_free_deferred_event.test
@@ -0,0 +1 @@
+--source suite/rpl/include/rpl_parallel_free_deferred_event.inc
diff --git a/mysql-test/suite/binlog_encryption/rpl_parallel_gco_wait_kill.result b/mysql-test/suite/binlog_encryption/rpl_parallel_gco_wait_kill.result
new file mode 100644
index 00000000000..4472550c4f2
--- /dev/null
+++ b/mysql-test/suite/binlog_encryption/rpl_parallel_gco_wait_kill.result
@@ -0,0 +1,257 @@
+*** Test killing thread that is waiting to start transaction until previous transaction commits ***
+include/master-slave.inc
+[connection master]
+connection server_2;
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+SET @old_parallel_mode= @@GLOBAL.slave_parallel_mode;
+include/stop_slave.inc
+SET sql_log_bin=0;
+CALL mtr.add_suppression("Query execution was interrupted");
+CALL mtr.add_suppression("Slave: Connection was killed");
+CALL mtr.add_suppression("Commit failed due to failure of an earlier commit on which this one depends");
+SET sql_log_bin=1;
+SET GLOBAL slave_parallel_threads=10;
+SET GLOBAL slave_parallel_mode= 'conservative';
+CHANGE MASTER TO master_use_gtid=slave_pos;
+include/start_slave.inc
+connection server_1;
+connect con_temp3,127.0.0.1,root,,test,$SERVER_MYPORT_1,;
+connect con_temp4,127.0.0.1,root,,test,$SERVER_MYPORT_1,;
+connect con_temp5,127.0.0.1,root,,test,$SERVER_MYPORT_1,;
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
+connection server_2;
+connection server_1;
+SET sql_log_bin=0;
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+RETURNS INT DETERMINISTIC
+BEGIN
+RETURN x;
+END
+||
+SET sql_log_bin=1;
+connection server_2;
+SET sql_log_bin=0;
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+RETURNS INT DETERMINISTIC
+BEGIN
+IF d1 != '' THEN
+SET debug_sync = d1;
+END IF;
+IF d2 != '' THEN
+SET debug_sync = d2;
+END IF;
+RETURN x;
+END
+||
+SET sql_log_bin=1;
+include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=0;
+SET GLOBAL slave_parallel_threads=4;
+include/start_slave.inc
+connection server_1;
+SET gtid_domain_id=2;
+BEGIN;
+INSERT INTO t3 VALUES (70, foo(70,
+'rpl_parallel_start_waiting_for_prior SIGNAL t4_waiting', ''));
+INSERT INTO t3 VALUES (60, foo(60,
+'ha_write_row_end SIGNAL d2_query WAIT_FOR d2_cont2',
+'rpl_parallel_end_of_group SIGNAL d2_done WAIT_FOR d2_cont'));
+COMMIT;
+SET gtid_domain_id=0;
+connection server_2;
+SET debug_sync='now WAIT_FOR d2_query';
+connection server_1;
+SET gtid_domain_id=1;
+BEGIN;
+INSERT INTO t3 VALUES (61, foo(61,
+'rpl_parallel_start_waiting_for_prior SIGNAL t3_waiting',
+'rpl_parallel_start_waiting_for_prior_killed SIGNAL t3_killed'));
+INSERT INTO t3 VALUES (62, foo(62,
+'ha_write_row_end SIGNAL d1_query WAIT_FOR d1_cont2',
+'rpl_parallel_end_of_group SIGNAL d1_done WAIT_FOR d1_cont'));
+COMMIT;
+SET gtid_domain_id=0;
+connection server_2;
+SET debug_sync='now WAIT_FOR d1_query';
+connection server_1;
+SET gtid_domain_id=0;
+INSERT INTO t3 VALUES (63, foo(63,
+'ha_write_row_end SIGNAL d0_query WAIT_FOR d0_cont2',
+'rpl_parallel_end_of_group SIGNAL d0_done WAIT_FOR d0_cont'));
+connection server_2;
+SET debug_sync='now WAIT_FOR d0_query';
+connection server_1;
+SET gtid_domain_id=3;
+BEGIN;
+INSERT INTO t3 VALUES (68, foo(68,
+'rpl_parallel_start_waiting_for_prior SIGNAL t2_waiting', ''));
+INSERT INTO t3 VALUES (69, foo(69,
+'ha_write_row_end SIGNAL d3_query WAIT_FOR d3_cont2',
+'rpl_parallel_end_of_group SIGNAL d3_done WAIT_FOR d3_cont'));
+COMMIT;
+SET gtid_domain_id=0;
+connection server_2;
+SET debug_sync='now WAIT_FOR d3_query';
+SET debug_sync='now SIGNAL d2_cont2';
+SET debug_sync='now WAIT_FOR d2_done';
+SET debug_sync='now SIGNAL d1_cont2';
+SET debug_sync='now WAIT_FOR d1_done';
+SET debug_sync='now SIGNAL d0_cont2';
+SET debug_sync='now WAIT_FOR d0_done';
+SET debug_sync='now SIGNAL d3_cont2';
+SET debug_sync='now WAIT_FOR d3_done';
+connection con_temp3;
+INSERT INTO t3 VALUES (64, foo(64,
+'rpl_parallel_before_mark_start_commit SIGNAL t1_waiting WAIT_FOR t1_cont', ''));
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2 WAIT_FOR master_cont2';
+INSERT INTO t3 VALUES (65, foo(65, '', ''));
+connection server_1;
+SET debug_sync='now WAIT_FOR master_queued2';
+connection con_temp4;
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued3';
+INSERT INTO t3 VALUES (66, foo(66, '', ''));
+connection server_1;
+SET debug_sync='now WAIT_FOR master_queued3';
+connection con_temp5;
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued4';
+INSERT INTO t3 VALUES (67, foo(67, '', ''));
+connection server_1;
+SET debug_sync='now WAIT_FOR master_queued4';
+SET debug_sync='now SIGNAL master_cont2';
+connection con_temp3;
+connection con_temp4;
+connection con_temp5;
+connection server_1;
+SELECT * FROM t3 WHERE a >= 60 ORDER BY a;
+a b
+60 60
+61 61
+62 62
+63 63
+64 64
+65 65
+66 66
+67 67
+68 68
+69 69
+70 70
+SET debug_sync='RESET';
+connection server_2;
+SET debug_sync='now SIGNAL d0_cont';
+SET debug_sync='now WAIT_FOR t1_waiting';
+SET debug_sync='now SIGNAL d3_cont';
+SET debug_sync='now WAIT_FOR t2_waiting';
+SET debug_sync='now SIGNAL d1_cont';
+SET debug_sync='now WAIT_FOR t3_waiting';
+SET debug_sync='now SIGNAL d2_cont';
+SET debug_sync='now WAIT_FOR t4_waiting';
+KILL THD_ID;
+SET debug_sync='now WAIT_FOR t3_killed';
+SET debug_sync='now SIGNAL t1_cont';
+include/wait_for_slave_sql_error.inc [errno=1317,1927,1964]
+STOP SLAVE IO_THREAD;
+SELECT * FROM t3 WHERE a >= 60 AND a != 65 ORDER BY a;
+a b
+60 60
+61 61
+62 62
+63 63
+64 64
+68 68
+69 69
+70 70
+SET debug_sync='RESET';
+SET GLOBAL slave_parallel_threads=0;
+SET GLOBAL slave_parallel_threads=10;
+SET sql_log_bin=0;
+DROP FUNCTION foo;
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+RETURNS INT DETERMINISTIC
+BEGIN
+RETURN x;
+END
+||
+SET sql_log_bin=1;
+connection server_1;
+UPDATE t3 SET b=b+1 WHERE a=60;
+connection server_2;
+include/start_slave.inc
+SELECT * FROM t3 WHERE a >= 60 ORDER BY a;
+a b
+60 61
+61 61
+62 62
+63 63
+64 64
+65 65
+66 66
+67 67
+68 68
+69 69
+70 70
+SET sql_log_bin=0;
+DROP FUNCTION foo;
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+RETURNS INT DETERMINISTIC
+BEGIN
+IF d1 != '' THEN
+SET debug_sync = d1;
+END IF;
+IF d2 != '' THEN
+SET debug_sync = d2;
+END IF;
+RETURN x;
+END
+||
+SET sql_log_bin=1;
+connection server_2;
+include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=0;
+SET GLOBAL slave_parallel_threads=10;
+include/start_slave.inc
+*** 5. Test killing thread that is waiting for queue of max length to shorten ***
+SET @old_max_queued= @@GLOBAL.slave_parallel_max_queued;
+SET GLOBAL slave_parallel_max_queued=9000;
+connection server_1;
+INSERT INTO t3 VALUES (80, foo(0,
+'ha_write_row_end SIGNAL query_waiting WAIT_FOR query_cont', ''));
+connection server_2;
+SET debug_sync='now WAIT_FOR query_waiting';
+SET @old_dbug= @@GLOBAL.debug_dbug;
+SET GLOBAL debug_dbug="+d,rpl_parallel_wait_queue_max";
+connection server_1;
+SELECT * FROM t3 WHERE a >= 80 ORDER BY a;
+a b
+80 0
+81 10000
+connection server_2;
+SET debug_sync='now WAIT_FOR wait_queue_ready';
+KILL THD_ID;
+SET debug_sync='now WAIT_FOR wait_queue_killed';
+SET debug_sync='now SIGNAL query_cont';
+include/wait_for_slave_sql_error.inc [errno=1317,1927,1964]
+STOP SLAVE IO_THREAD;
+SET GLOBAL debug_dbug=@old_dbug;
+SET GLOBAL slave_parallel_max_queued= @old_max_queued;
+connection server_1;
+INSERT INTO t3 VALUES (82,0);
+connection server_2;
+SET debug_sync='RESET';
+include/start_slave.inc
+SELECT * FROM t3 WHERE a >= 80 ORDER BY a;
+a b
+80 0
+81 10000
+82 0
+connection server_2;
+include/stop_slave.inc
+SET GLOBAL slave_parallel_mode=@old_parallel_mode;
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+include/start_slave.inc
+SET DEBUG_SYNC= 'RESET';
+connection server_1;
+DROP function foo;
+DROP TABLE t3;
+SET DEBUG_SYNC= 'RESET';
+include/rpl_end.inc
diff --git a/mysql-test/suite/binlog_encryption/rpl_parallel_gco_wait_kill.test b/mysql-test/suite/binlog_encryption/rpl_parallel_gco_wait_kill.test
new file mode 100644
index 00000000000..853465f1760
--- /dev/null
+++ b/mysql-test/suite/binlog_encryption/rpl_parallel_gco_wait_kill.test
@@ -0,0 +1 @@
+--source suite/rpl/include/rpl_parallel_gco_wait_kill.inc
diff --git a/mysql-test/suite/binlog_encryption/rpl_parallel_gtid_slave_pos_update_fail.result b/mysql-test/suite/binlog_encryption/rpl_parallel_gtid_slave_pos_update_fail.result
new file mode 100644
index 00000000000..2e7e7f547af
--- /dev/null
+++ b/mysql-test/suite/binlog_encryption/rpl_parallel_gtid_slave_pos_update_fail.result
@@ -0,0 +1,65 @@
+include/master-slave.inc
+[connection master]
+connection server_2;
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=10;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+include/start_slave.inc
+connection server_1;
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t4 (a INT PRIMARY KEY, b INT, KEY b_idx(b)) ENGINE=InnoDB;
+INSERT INTO t4 VALUES (1,NULL), (2,2), (3,NULL), (4,4), (5, NULL), (6, 6);
+connect con1,127.0.0.1,root,,test,$SERVER_MYPORT_1,;
+connect con2,127.0.0.1,root,,test,$SERVER_MYPORT_1,;
+connection server_2;
+include/stop_slave.inc
+connection con1;
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
+UPDATE t4 SET b=NULL WHERE a=6;
+connection server_1;
+SET debug_sync='now WAIT_FOR master_queued1';
+connection con2;
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
+DELETE FROM t4 WHERE b <= 1;
+connection server_1;
+SET debug_sync='now WAIT_FOR master_queued2';
+SET debug_sync='now SIGNAL master_cont1';
+connection con1;
+connection con2;
+SET debug_sync='RESET';
+connection server_2;
+SET @old_dbug= @@GLOBAL.debug_dbug;
+SET GLOBAL debug_dbug="+d,disable_thd_need_ordering_with";
+include/start_slave.inc
+SET GLOBAL debug_dbug=@old_dbug;
+SELECT * FROM t4 ORDER BY a;
+a b
+1 NULL
+2 2
+3 NULL
+4 4
+5 NULL
+6 NULL
+SET @last_gtid= 'GTID';
+SELECT IF(@@gtid_slave_pos LIKE CONCAT('%',@last_gtid,'%'), "GTID found ok",
+CONCAT("GTID ", @last_gtid, " not found in gtid_slave_pos=", @@gtid_slave_pos))
+AS result;
+result
+GTID found ok
+SELECT "ROW FOUND" AS `Is the row found?`
+ FROM mysql.gtid_slave_pos
+WHERE CONCAT(domain_id, "-", server_id, "-", seq_no) = @last_gtid;
+Is the row found?
+ROW FOUND
+connection server_2;
+include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+include/start_slave.inc
+SET DEBUG_SYNC= 'RESET';
+connection server_1;
+DROP TABLE t4;
+SET DEBUG_SYNC= 'RESET';
+disconnect con1;
+disconnect con2;
+include/rpl_end.inc
diff --git a/mysql-test/suite/binlog_encryption/rpl_parallel_gtid_slave_pos_update_fail.test b/mysql-test/suite/binlog_encryption/rpl_parallel_gtid_slave_pos_update_fail.test
new file mode 100644
index 00000000000..67105ccafee
--- /dev/null
+++ b/mysql-test/suite/binlog_encryption/rpl_parallel_gtid_slave_pos_update_fail.test
@@ -0,0 +1 @@
+--source suite/rpl/include/rpl_parallel_gtid_slave_pos_update_fail.inc
diff --git a/mysql-test/suite/binlog_encryption/rpl_parallel_ignored_errors.result b/mysql-test/suite/binlog_encryption/rpl_parallel_ignored_errors.result
new file mode 100644
index 00000000000..d00740dba3d
--- /dev/null
+++ b/mysql-test/suite/binlog_encryption/rpl_parallel_ignored_errors.result
@@ -0,0 +1,74 @@
+*** MDEV-6551: Some replication errors are ignored if slave_parallel_threads > 0 ***
+include/master-slave.inc
+[connection master]
+connection server_2;
+include/stop_slave.inc
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+SET @old_parallel_mode=@@GLOBAL.slave_parallel_mode;
+SET GLOBAL slave_parallel_threads=1;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+CALL mtr.add_suppression("Commit failed due to failure of an earlier commit on which this one depends");
+include/start_slave.inc
+connection server_1;
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t2 (a int PRIMARY KEY) ENGINE=InnoDB;
+SET gtid_domain_id=1;
+INSERT INTO t2 VALUES (1);
+SET gtid_domain_id=0;
+SET gtid_domain_id=2;
+INSERT INTO t2 VALUES (2);
+SET gtid_domain_id=0;
+INSERT INTO t2 VALUES (31);
+include/save_master_gtid.inc
+connection server_2;
+include/sync_with_master_gtid.inc
+include/stop_slave.inc
+SET GLOBAL slave_parallel_threads= 0;
+include/start_slave.inc
+SET sql_log_bin= 0;
+INSERT INTO t2 VALUES (32);
+SET sql_log_bin= 1;
+connection server_1;
+INSERT INTO t2 VALUES (32);
+FLUSH LOGS;
+INSERT INTO t2 VALUES (33);
+INSERT INTO t2 VALUES (34);
+SELECT * FROM t2 WHERE a >= 30 ORDER BY a;
+a
+31
+32
+33
+34
+include/save_master_gtid.inc
+connection server_2;
+include/wait_for_slave_sql_error.inc [errno=1062]
+connection server_2;
+include/stop_slave_io.inc
+SET GLOBAL slave_parallel_threads=10;
+START SLAVE;
+include/wait_for_slave_sql_error.inc [errno=1062]
+START SLAVE SQL_THREAD;
+include/wait_for_slave_sql_error.inc [errno=1062]
+SELECT * FROM t2 WHERE a >= 30 ORDER BY a;
+a
+31
+32
+SET sql_slave_skip_counter= 1;
+ERROR HY000: When using parallel replication and GTID with multiple replication domains, @@sql_slave_skip_counter can not be used. Instead, setting @@gtid_slave_pos explicitly can be used to skip to after a given GTID position
+include/stop_slave_io.inc
+include/start_slave.inc
+include/sync_with_master_gtid.inc
+SELECT * FROM t2 WHERE a >= 30 ORDER BY a;
+a
+31
+32
+33
+34
+connection server_2;
+include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+SET GLOBAL slave_parallel_mode=@old_parallel_mode;
+include/start_slave.inc
+connection server_1;
+DROP TABLE t2;
+include/rpl_end.inc
diff --git a/mysql-test/suite/binlog_encryption/rpl_parallel_ignored_errors.test b/mysql-test/suite/binlog_encryption/rpl_parallel_ignored_errors.test
new file mode 100644
index 00000000000..8a26778c8f2
--- /dev/null
+++ b/mysql-test/suite/binlog_encryption/rpl_parallel_ignored_errors.test
@@ -0,0 +1 @@
+--source suite/rpl/include/rpl_parallel_ignored_errors.inc
diff --git a/mysql-test/suite/binlog_encryption/rpl_parallel_incorrect_relay_pos.result b/mysql-test/suite/binlog_encryption/rpl_parallel_incorrect_relay_pos.result
new file mode 100644
index 00000000000..6ca7f2b68e8
--- /dev/null
+++ b/mysql-test/suite/binlog_encryption/rpl_parallel_incorrect_relay_pos.result
@@ -0,0 +1,75 @@
+*** MDEV-7237: Parallel replication: incorrect relaylog position after stop/start the slave ***
+include/master-slave.inc
+[connection master]
+connection server_2;
+include/stop_slave.inc
+CALL mtr.add_suppression("Commit failed due to failure of an earlier commit on which this one depends");
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+SET @old_parallel_mode=@@GLOBAL.slave_parallel_mode;
+SET GLOBAL slave_parallel_threads=10;
+SET GLOBAL slave_parallel_mode='conservative';
+CHANGE MASTER TO master_use_gtid=slave_pos;
+include/start_slave.inc
+connection server_1;
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t2 (a int PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t2 VALUES (40);
+connection server_2;
+connect con_temp2,127.0.0.1,root,,test,$SERVER_MYPORT_2,;
+include/stop_slave.inc
+CHANGE MASTER TO master_use_gtid=no;
+SET @old_dbug= @@GLOBAL.debug_dbug;
+SET GLOBAL debug_dbug="+d,rpl_parallel_scheduled_gtid_0_x_100";
+SET GLOBAL debug_dbug="+d,rpl_parallel_wait_for_done_trigger";
+SET GLOBAL slave_parallel_threads=0;
+SET GLOBAL slave_parallel_threads=10;
+connection server_1;
+INSERT INTO t2 VALUES (41);
+INSERT INTO t2 VALUES (42);
+SET @old_format= @@binlog_format;
+SET binlog_format= statement;
+DELETE FROM t2 WHERE a=40;
+SET binlog_format= @old_format;
+INSERT INTO t2 VALUES (43);
+INSERT INTO t2 VALUES (44);
+FLUSH LOGS;
+INSERT INTO t2 VALUES (45);
+SET gtid_seq_no=100;
+INSERT INTO t2 VALUES (46);
+connection con_temp2;
+BEGIN;
+SELECT * FROM t2 WHERE a=40 FOR UPDATE;
+a
+40
+connection server_2;
+include/start_slave.inc
+SET debug_sync= 'now WAIT_FOR scheduled_gtid_0_x_100';
+STOP SLAVE;
+connection con_temp2;
+SET debug_sync= 'now WAIT_FOR wait_for_done_waiting';
+ROLLBACK;
+connection server_2;
+include/wait_for_slave_sql_to_stop.inc
+SELECT * FROM t2 WHERE a >= 40 ORDER BY a;
+a
+41
+42
+include/start_slave.inc
+SELECT * FROM t2 WHERE a >= 40 ORDER BY a;
+a
+41
+42
+43
+44
+45
+46
+include/stop_slave.inc
+SET GLOBAL debug_dbug=@old_dbug;
+SET DEBUG_SYNC= 'RESET';
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+SET GLOBAL slave_parallel_mode=@old_parallel_mode;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+include/start_slave.inc
+connection server_1;
+DROP TABLE t2;
+include/rpl_end.inc
diff --git a/mysql-test/suite/binlog_encryption/rpl_parallel_incorrect_relay_pos.test b/mysql-test/suite/binlog_encryption/rpl_parallel_incorrect_relay_pos.test
new file mode 100644
index 00000000000..ddec96e8792
--- /dev/null
+++ b/mysql-test/suite/binlog_encryption/rpl_parallel_incorrect_relay_pos.test
@@ -0,0 +1 @@
+--source suite/rpl/include/rpl_parallel_incorrect_relay_pos.inc
diff --git a/mysql-test/suite/binlog_encryption/rpl_parallel_innodb_lock_conflict.result b/mysql-test/suite/binlog_encryption/rpl_parallel_innodb_lock_conflict.result
new file mode 100644
index 00000000000..1411db16af6
--- /dev/null
+++ b/mysql-test/suite/binlog_encryption/rpl_parallel_innodb_lock_conflict.result
@@ -0,0 +1,79 @@
+***MDEV-5914: Parallel replication deadlock due to InnoDB lock conflicts ***
+include/master-slave.inc
+[connection master]
+connection server_2;
+SET sql_log_bin=0;
+CALL mtr.add_suppression("Commit failed due to failure of an earlier commit on which this one depends");
+SET sql_log_bin=1;
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=10;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+connection server_1;
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t4 (a INT PRIMARY KEY, b INT, KEY b_idx(b)) ENGINE=InnoDB;
+INSERT INTO t4 VALUES (1,NULL), (2,2), (3,NULL), (4,4), (5, NULL), (6, 6);
+connect con1,127.0.0.1,root,,test,$SERVER_MYPORT_1,;
+connect con2,127.0.0.1,root,,test,$SERVER_MYPORT_1,;
+connection con1;
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
+UPDATE t4 SET b=NULL WHERE a=6;
+connection server_1;
+SET debug_sync='now WAIT_FOR master_queued1';
+connection con2;
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
+DELETE FROM t4 WHERE b <= 3;
+connection server_1;
+SET debug_sync='now WAIT_FOR master_queued2';
+SET debug_sync='now SIGNAL master_cont1';
+connection con1;
+connection con2;
+SET debug_sync='RESET';
+connection server_2;
+include/start_slave.inc
+include/stop_slave.inc
+SELECT * FROM t4 ORDER BY a;
+a b
+1 NULL
+3 NULL
+4 4
+5 NULL
+6 NULL
+connection server_1;
+DELETE FROM t4;
+INSERT INTO t4 VALUES (1,NULL), (2,2), (3,NULL), (4,4), (5, NULL), (6, 6);
+connection con1;
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
+INSERT INTO t4 VALUES (7, NULL);
+connection server_1;
+SET debug_sync='now WAIT_FOR master_queued1';
+connection con2;
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
+DELETE FROM t4 WHERE b <= 3;
+connection server_1;
+SET debug_sync='now WAIT_FOR master_queued2';
+SET debug_sync='now SIGNAL master_cont1';
+connection con1;
+connection con2;
+SET debug_sync='RESET';
+connection server_2;
+include/start_slave.inc
+include/stop_slave.inc
+SELECT * FROM t4 ORDER BY a;
+a b
+1 NULL
+3 NULL
+4 4
+5 NULL
+6 6
+7 NULL
+connection server_2;
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+include/start_slave.inc
+SET DEBUG_SYNC= 'RESET';
+connection server_1;
+disconnect con1;
+disconnect con2;
+DROP TABLE t4;
+SET DEBUG_SYNC= 'RESET';
+include/rpl_end.inc
diff --git a/mysql-test/suite/binlog_encryption/rpl_parallel_innodb_lock_conflict.test b/mysql-test/suite/binlog_encryption/rpl_parallel_innodb_lock_conflict.test
new file mode 100644
index 00000000000..624667d5408
--- /dev/null
+++ b/mysql-test/suite/binlog_encryption/rpl_parallel_innodb_lock_conflict.test
@@ -0,0 +1 @@
+--source suite/rpl/include/rpl_parallel_innodb_lock_conflict.inc
diff --git a/mysql-test/suite/binlog_encryption/rpl_parallel_missed_error_handling.result b/mysql-test/suite/binlog_encryption/rpl_parallel_missed_error_handling.result
new file mode 100644
index 00000000000..e9d04c02d7a
--- /dev/null
+++ b/mysql-test/suite/binlog_encryption/rpl_parallel_missed_error_handling.result
@@ -0,0 +1,65 @@
+*** MDEV-5921: In parallel replication, an error is not correctly signalled to the next transaction ***
+include/master-slave.inc
+[connection master]
+connection server_2;
+include/stop_slave.inc
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+SET GLOBAL slave_parallel_threads=10;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+CALL mtr.add_suppression("Commit failed due to failure of an earlier commit on which this one depends");
+include/start_slave.inc
+connection server_1;
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
+connection server_2;
+connection server_1;
+INSERT INTO t3 VALUES (110, 1);
+connection server_2;
+SELECT * FROM t3 WHERE a >= 110 ORDER BY a;
+a b
+110 1
+SET sql_log_bin=0;
+INSERT INTO t3 VALUES (111, 666);
+SET sql_log_bin=1;
+connection server_1;
+connect con1,127.0.0.1,root,,test,$SERVER_MYPORT_1,;
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
+INSERT INTO t3 VALUES (111, 2);
+connection server_1;
+SET debug_sync='now WAIT_FOR master_queued1';
+connect con2,127.0.0.1,root,,test,$SERVER_MYPORT_1,;
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
+INSERT INTO t3 VALUES (112, 3);
+connection server_1;
+SET debug_sync='now WAIT_FOR master_queued2';
+SET debug_sync='now SIGNAL master_cont1';
+connection con1;
+connection con2;
+SET debug_sync='RESET';
+connection server_2;
+include/wait_for_slave_sql_error.inc [errno=1062]
+include/wait_for_slave_sql_to_stop.inc
+SELECT * FROM t3 WHERE a >= 110 ORDER BY a;
+a b
+110 1
+111 666
+SET sql_log_bin=0;
+DELETE FROM t3 WHERE a=111 AND b=666;
+SET sql_log_bin=1;
+START SLAVE SQL_THREAD;
+SELECT * FROM t3 WHERE a >= 110 ORDER BY a;
+a b
+110 1
+111 2
+112 3
+connection server_2;
+include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+include/start_slave.inc
+SET DEBUG_SYNC= 'RESET';
+connection server_1;
+disconnect con1;
+disconnect con2;
+DROP TABLE t3;
+SET DEBUG_SYNC= 'RESET';
+include/rpl_end.inc
diff --git a/mysql-test/suite/binlog_encryption/rpl_parallel_missed_error_handling.test b/mysql-test/suite/binlog_encryption/rpl_parallel_missed_error_handling.test
new file mode 100644
index 00000000000..c6d09f2196b
--- /dev/null
+++ b/mysql-test/suite/binlog_encryption/rpl_parallel_missed_error_handling.test
@@ -0,0 +1 @@
+--source suite/rpl/include/rpl_parallel_missed_error_handling.inc
diff --git a/mysql-test/suite/binlog_encryption/rpl_parallel_mode.result b/mysql-test/suite/binlog_encryption/rpl_parallel_mode.result
new file mode 100644
index 00000000000..313290b1fd2
--- /dev/null
+++ b/mysql-test/suite/binlog_encryption/rpl_parallel_mode.result
@@ -0,0 +1,75 @@
+*** MDEV-6676 - test syntax of @@slave_parallel_mode ***
+include/master-slave.inc
+[connection master]
+connection server_2;
+include/stop_slave.inc
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+SET @old_parallel_mode=@@GLOBAL.slave_parallel_mode;
+SET GLOBAL slave_parallel_threads=10;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+include/start_slave.inc
+connection server_1;
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t2 (a int PRIMARY KEY) ENGINE=InnoDB;
+connection server_2;
+Parallel_Mode = 'optimistic'
+include/stop_slave.inc
+SET GLOBAL slave_parallel_mode='aggressive';
+Parallel_Mode = 'aggressive'
+SET GLOBAL slave_parallel_mode='conservative';
+Parallel_Mode = 'conservative'
+*** MDEV-6676 - test that empty parallel_mode does not replicate in parallel ***
+connection server_1;
+INSERT INTO t2 VALUES (1040);
+include/save_master_gtid.inc
+connection server_2;
+SET GLOBAL slave_parallel_mode='none';
+SET @old_dbug= @@GLOBAL.debug_dbug;
+SET GLOBAL debug_dbug="+d,slave_crash_if_parallel_apply";
+include/start_slave.inc
+include/sync_with_master_gtid.inc
+SELECT * FROM t2 WHERE a >= 1040 ORDER BY a;
+a
+1040
+include/stop_slave.inc
+SET GLOBAL debug_dbug=@old_dbug;
+*** MDEV-6676 - test disabling domain-based parallel replication ***
+connection server_1;
+SET gtid_domain_id = 1;
+INSERT INTO t2 VALUES (1041);
+INSERT INTO t2 VALUES (1042);
+INSERT INTO t2 VALUES (1043);
+INSERT INTO t2 VALUES (1044);
+INSERT INTO t2 VALUES (1045);
+INSERT INTO t2 VALUES (1046);
+DELETE FROM t2 WHERE a >= 1041;
+SET gtid_domain_id = 2;
+INSERT INTO t2 VALUES (1041);
+INSERT INTO t2 VALUES (1042);
+INSERT INTO t2 VALUES (1043);
+INSERT INTO t2 VALUES (1044);
+INSERT INTO t2 VALUES (1045);
+INSERT INTO t2 VALUES (1046);
+SET gtid_domain_id = 0;
+include/save_master_gtid.inc
+connection server_2;
+SET GLOBAL slave_parallel_mode=minimal;
+include/start_slave.inc
+include/sync_with_master_gtid.inc
+SELECT * FROM t2 WHERE a >= 1040 ORDER BY a;
+a
+1040
+1041
+1042
+1043
+1044
+1045
+1046
+include/stop_slave.inc
+SET GLOBAL debug_dbug=@old_dbug;
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+SET GLOBAL slave_parallel_mode=@old_parallel_mode;
+include/start_slave.inc
+connection server_1;
+DROP TABLE t2;
+include/rpl_end.inc
diff --git a/mysql-test/suite/binlog_encryption/rpl_parallel_mode.test b/mysql-test/suite/binlog_encryption/rpl_parallel_mode.test
new file mode 100644
index 00000000000..93170f61c95
--- /dev/null
+++ b/mysql-test/suite/binlog_encryption/rpl_parallel_mode.test
@@ -0,0 +1 @@
+--source suite/rpl/include/rpl_parallel_mode.inc
diff --git a/mysql-test/suite/binlog_encryption/rpl_parallel_partial_binlog_trans.result b/mysql-test/suite/binlog_encryption/rpl_parallel_partial_binlog_trans.result
new file mode 100644
index 00000000000..ab1cac692a0
--- /dev/null
+++ b/mysql-test/suite/binlog_encryption/rpl_parallel_partial_binlog_trans.result
@@ -0,0 +1,51 @@
+*** MDEV_6435: Incorrect error handling when query binlogged partially on master with "killed" error ***
+include/master-slave.inc
+[connection master]
+connection server_2;
+include/stop_slave.inc
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+SET GLOBAL slave_parallel_threads=1;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+include/start_slave.inc
+connection server_1;
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t6 (a INT) ENGINE=MyISAM;
+CREATE TRIGGER tr AFTER INSERT ON t6 FOR EACH ROW SET @a = 1;
+connect con1,127.0.0.1,root,,test,$SERVER_MYPORT_1,;
+connection con1;
+SET debug_sync='sp_head_execute_before_loop SIGNAL ready WAIT_FOR cont';
+INSERT INTO t6 VALUES (1), (2), (3);
+connection server_1;
+SET debug_sync='now WAIT_FOR ready';
+KILL QUERY CONID;
+SET debug_sync='now SIGNAL cont';
+connection con1;
+ERROR 70100: Query execution was interrupted
+SET debug_sync='RESET';
+connection server_1;
+SET debug_sync='RESET';
+connection server_2;
+include/wait_for_slave_sql_error.inc [errno=1317]
+STOP SLAVE IO_THREAD;
+SET GLOBAL gtid_slave_pos= 'AFTER_ERROR_GTID_POS';
+include/start_slave.inc
+connection server_1;
+INSERT INTO t6 VALUES (4);
+SELECT * FROM t6 ORDER BY a;
+a
+1
+4
+connection server_2;
+SELECT * FROM t6 ORDER BY a;
+a
+4
+connection server_2;
+include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+include/start_slave.inc
+SET DEBUG_SYNC= 'RESET';
+connection server_1;
+DROP TABLE t6;
+SET DEBUG_SYNC= 'RESET';
+disconnect con1;
+include/rpl_end.inc
diff --git a/mysql-test/suite/binlog_encryption/rpl_parallel_partial_binlog_trans.test b/mysql-test/suite/binlog_encryption/rpl_parallel_partial_binlog_trans.test
new file mode 100644
index 00000000000..4f90cf4808e
--- /dev/null
+++ b/mysql-test/suite/binlog_encryption/rpl_parallel_partial_binlog_trans.test
@@ -0,0 +1 @@
+--source suite/rpl/include/rpl_parallel_partial_binlog_trans.inc
diff --git a/mysql-test/suite/binlog_encryption/rpl_parallel_record_gtid_wakeup.result b/mysql-test/suite/binlog_encryption/rpl_parallel_record_gtid_wakeup.result
new file mode 100644
index 00000000000..cbe53e4f623
--- /dev/null
+++ b/mysql-test/suite/binlog_encryption/rpl_parallel_record_gtid_wakeup.result
@@ -0,0 +1,48 @@
+*** MDEV-7929: record_gtid() for non-transactional event group calls wakeup_subsequent_commits() too early, causing slave hang. ***
+include/master-slave.inc
+[connection master]
+connection server_2;
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=10;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+include/start_slave.inc
+connection server_1;
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t1 (a int PRIMARY KEY) ENGINE=MyISAM;
+CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
+connection server_2;
+include/stop_slave.inc
+SET @old_dbug= @@GLOBAL.debug_dbug;
+SET GLOBAL debug_dbug= '+d,inject_record_gtid_serverid_100_sleep';
+connection server_1;
+SET @old_dbug= @@SESSION.debug_dbug;
+SET SESSION debug_dbug="+d,binlog_force_commit_id";
+SET @old_server_id= @@SESSION.server_id;
+SET SESSION server_id= 100;
+SET @commit_id= 10010;
+ALTER TABLE t1 COMMENT "Hulubulu!";
+SET SESSION server_id= @old_server_id;
+INSERT INTO t3 VALUES (130, 0);
+SET @commit_id= 10011;
+INSERT INTO t3 VALUES (131, 0);
+SET SESSION debug_dbug=@old_dbug;
+SELECT * FROM t3 WHERE a >= 130 ORDER BY a;
+a b
+130 0
+131 0
+include/save_master_gtid.inc
+connection server_2;
+include/start_slave.inc
+include/sync_with_master_gtid.inc
+SELECT * FROM t3 WHERE a >= 130 ORDER BY a;
+a b
+130 0
+131 0
+include/stop_slave.inc
+SET GLOBAL debug_dbug= @old_dbug;
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+include/start_slave.inc
+connection server_1;
+DROP TABLE t1,t3;
+include/rpl_end.inc
diff --git a/mysql-test/suite/binlog_encryption/rpl_parallel_record_gtid_wakeup.test b/mysql-test/suite/binlog_encryption/rpl_parallel_record_gtid_wakeup.test
new file mode 100644
index 00000000000..cb3b0dfa119
--- /dev/null
+++ b/mysql-test/suite/binlog_encryption/rpl_parallel_record_gtid_wakeup.test
@@ -0,0 +1 @@
+--source suite/rpl/include/rpl_parallel_record_gtid_wakeup.inc
diff --git a/mysql-test/suite/binlog_encryption/rpl_parallel_retry_deadlock.result b/mysql-test/suite/binlog_encryption/rpl_parallel_retry_deadlock.result
new file mode 100644
index 00000000000..1f5a23db848
--- /dev/null
+++ b/mysql-test/suite/binlog_encryption/rpl_parallel_retry_deadlock.result
@@ -0,0 +1,192 @@
+*** MDEV-7326 Server deadlock in connection with parallel replication ***
+include/master-slave.inc
+[connection master]
+connection server_2;
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+SET @old_parallel_mode=@@GLOBAL.slave_parallel_mode;
+include/stop_slave.inc
+SET GLOBAL slave_parallel_mode='conservative';
+SET GLOBAL slave_parallel_threads=10;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+include/start_slave.inc
+connection server_1;
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t1 (a int PRIMARY KEY) ENGINE=MyISAM;
+CREATE TABLE t2 (a int PRIMARY KEY) ENGINE=InnoDB;
+CREATE TABLE t6 (a INT) ENGINE=MyISAM;
+connection server_2;
+connection server_1;
+SET sql_log_bin=0;
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+RETURNS INT DETERMINISTIC
+BEGIN
+RETURN x;
+END
+||
+SET sql_log_bin=1;
+connection server_2;
+SET sql_log_bin=0;
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+RETURNS INT DETERMINISTIC
+BEGIN
+IF d1 != '' THEN
+SET debug_sync = d1;
+END IF;
+IF d2 != '' THEN
+SET debug_sync = d2;
+END IF;
+RETURN x;
+END
+||
+SET sql_log_bin=1;
+connection server_2;
+include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=0;
+SET GLOBAL slave_parallel_threads=3;
+SET GLOBAL debug_dbug="+d,rpl_parallel_simulate_temp_err_xid";
+include/start_slave.inc
+connection server_1;
+SET @old_format= @@SESSION.binlog_format;
+SET binlog_format= STATEMENT;
+INSERT INTO t1 VALUES (foo(50,
+"rpl_parallel_start_waiting_for_prior SIGNAL t3_ready",
+"rpl_parallel_end_of_group SIGNAL prep_ready WAIT_FOR prep_cont"));
+connection server_2;
+SET DEBUG_SYNC= "now WAIT_FOR prep_ready";
+connection server_1;
+INSERT INTO t2 VALUES (foo(50,
+"rpl_parallel_simulate_temp_err_xid SIGNAL t1_ready1 WAIT_FOR t1_cont1",
+"rpl_parallel_retry_after_unmark SIGNAL t1_ready2 WAIT_FOR t1_cont2"));
+connection server_2;
+SET DEBUG_SYNC= "now WAIT_FOR t1_ready1";
+connection server_1;
+INSERT INTO t1 VALUES (foo(51,
+"rpl_parallel_before_mark_start_commit SIGNAL t2_ready1 WAIT_FOR t2_cont1",
+"rpl_parallel_after_mark_start_commit SIGNAL t2_ready2"));
+connection server_2;
+SET DEBUG_SYNC= "now WAIT_FOR t2_ready1";
+SET DEBUG_SYNC= "now SIGNAL t1_cont1";
+SET DEBUG_SYNC= "now WAIT_FOR t1_ready2";
+connection server_1;
+INSERT INTO t1 VALUES (52);
+SET BINLOG_FORMAT= @old_format;
+SELECT * FROM t2 WHERE a>=50 ORDER BY a;
+a
+50
+SELECT * FROM t1 WHERE a>=50 ORDER BY a;
+a
+50
+51
+52
+connection server_2;
+SET DEBUG_SYNC= "now SIGNAL prep_cont";
+SET DEBUG_SYNC= "now WAIT_FOR t3_ready";
+SET DEBUG_SYNC= "now SIGNAL t2_cont1";
+SET DEBUG_SYNC= "now WAIT_FOR t2_ready2";
+SET DEBUG_SYNC= "now SIGNAL t1_cont2";
+connection server_1;
+connection server_2;
+SELECT * FROM t2 WHERE a>=50 ORDER BY a;
+a
+50
+SELECT * FROM t1 WHERE a>=50 ORDER BY a;
+a
+50
+51
+52
+SET DEBUG_SYNC="reset";
+include/stop_slave.inc
+SET GLOBAL debug_dbug=@old_dbug;
+SET GLOBAL slave_parallel_mode=@old_parallel_mode;
+SET GLOBAL slave_parallel_threads=0;
+SET GLOBAL slave_parallel_threads=10;
+include/start_slave.inc
+*** MDEV-7326 Server deadlock in connection with parallel replication ***
+connect con_temp3,127.0.0.1,root,,test,$SERVER_MYPORT_1,;
+connect con_temp4,127.0.0.1,root,,test,$SERVER_MYPORT_1,;
+connection server_2;
+include/stop_slave.inc
+SET @old_parallel_mode= @@GLOBAL.slave_parallel_mode;
+SET GLOBAL slave_parallel_mode='conservative';
+SET GLOBAL slave_parallel_threads=0;
+SET GLOBAL slave_parallel_threads=3;
+SET GLOBAL debug_dbug="+d,rpl_parallel_simulate_temp_err_xid";
+include/start_slave.inc
+connection server_1;
+SET @old_format= @@SESSION.binlog_format;
+SET binlog_format= STATEMENT;
+INSERT INTO t1 VALUES (foo(60,
+"rpl_parallel_start_waiting_for_prior SIGNAL t3_ready",
+"rpl_parallel_end_of_group SIGNAL prep_ready WAIT_FOR prep_cont"));
+connection server_2;
+SET DEBUG_SYNC= "now WAIT_FOR prep_ready";
+connection server_1;
+INSERT INTO t2 VALUES (foo(60,
+"rpl_parallel_simulate_temp_err_xid SIGNAL t1_ready1 WAIT_FOR t1_cont1",
+"rpl_parallel_retry_after_unmark SIGNAL t1_ready2 WAIT_FOR t1_cont2"));
+connection server_2;
+SET DEBUG_SYNC= "now WAIT_FOR t1_ready1";
+connection con_temp3;
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
+SET binlog_format=statement;
+INSERT INTO t1 VALUES (foo(61,
+"rpl_parallel_before_mark_start_commit SIGNAL t2_ready1 WAIT_FOR t2_cont1",
+"rpl_parallel_after_mark_start_commit SIGNAL t2_ready2"));
+connection server_1;
+SET debug_sync='now WAIT_FOR master_queued1';
+connection con_temp4;
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
+INSERT INTO t6 VALUES (62);
+connection server_1;
+SET debug_sync='now WAIT_FOR master_queued2';
+SET debug_sync='now SIGNAL master_cont1';
+connection con_temp3;
+connection con_temp4;
+connection server_1;
+SET debug_sync='RESET';
+SET BINLOG_FORMAT= @old_format;
+SELECT * FROM t2 WHERE a>=60 ORDER BY a;
+a
+60
+SELECT * FROM t1 WHERE a>=60 ORDER BY a;
+a
+60
+61
+SELECT * FROM t6 WHERE a>=60 ORDER BY a;
+a
+62
+connection server_2;
+SET DEBUG_SYNC= "now WAIT_FOR t2_ready1";
+SET DEBUG_SYNC= "now SIGNAL t1_cont1";
+SET DEBUG_SYNC= "now WAIT_FOR t1_ready2";
+connection server_2;
+SET DEBUG_SYNC= "now SIGNAL prep_cont";
+SET DEBUG_SYNC= "now WAIT_FOR t3_ready";
+SET DEBUG_SYNC= "now SIGNAL t2_cont1";
+SET DEBUG_SYNC= "now WAIT_FOR t2_ready2";
+SET DEBUG_SYNC= "now SIGNAL t1_cont2";
+connection server_1;
+connection server_2;
+SELECT * FROM t2 WHERE a>=60 ORDER BY a;
+a
+60
+SELECT * FROM t1 WHERE a>=60 ORDER BY a;
+a
+60
+61
+SELECT * FROM t6 WHERE a>=60 ORDER BY a;
+a
+62
+SET DEBUG_SYNC="reset";
+include/stop_slave.inc
+SET GLOBAL debug_dbug=@old_dbug;
+SET GLOBAL slave_parallel_mode=@old_parallel_mode;
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+include/start_slave.inc
+connection server_1;
+DROP function foo;
+DROP TABLE t1,t2,t6;
+disconnect con_temp3;
+disconnect con_temp4;
+SET DEBUG_SYNC= 'RESET';
+include/rpl_end.inc
diff --git a/mysql-test/suite/binlog_encryption/rpl_parallel_retry_deadlock.test b/mysql-test/suite/binlog_encryption/rpl_parallel_retry_deadlock.test
new file mode 100644
index 00000000000..61c2cb22a75
--- /dev/null
+++ b/mysql-test/suite/binlog_encryption/rpl_parallel_retry_deadlock.test
@@ -0,0 +1 @@
+--source suite/rpl/include/rpl_parallel_retry_deadlock.inc
diff --git a/mysql-test/suite/binlog_encryption/rpl_parallel_rollback_assert.result b/mysql-test/suite/binlog_encryption/rpl_parallel_rollback_assert.result
new file mode 100644
index 00000000000..af9c5f14687
--- /dev/null
+++ b/mysql-test/suite/binlog_encryption/rpl_parallel_rollback_assert.result
@@ -0,0 +1,45 @@
+*** MDEV-8725: Assertion on ROLLBACK statement in the binary log ***
+include/master-slave.inc
+[connection master]
+connection server_2;
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=10;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+include/start_slave.inc
+connection server_1;
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t1 (a int PRIMARY KEY) ENGINE=MyISAM;
+CREATE TABLE t2 (a int PRIMARY KEY) ENGINE=InnoDB;
+connection server_2;
+connection server_1;
+BEGIN;
+INSERT INTO t2 VALUES (2000);
+INSERT INTO t1 VALUES (2000);
+INSERT INTO t2 VALUES (2001);
+ROLLBACK;
+SELECT * FROM t1 WHERE a>=2000 ORDER BY a;
+a
+2000
+SELECT * FROM t2 WHERE a>=2000 ORDER BY a;
+a
+include/save_master_gtid.inc
+connection server_2;
+include/sync_with_master_gtid.inc
+connection server_1;
+INSERT INTO t2 VALUES (2020);
+include/save_master_gtid.inc
+connection server_2;
+include/sync_with_master_gtid.inc
+SELECT * FROM t2 WHERE a>=2000 ORDER BY a;
+a
+2020
+SELECT * FROM t1 WHERE a>=2000 ORDER BY a;
+a
+2000
+include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+include/start_slave.inc
+connection server_1;
+DROP TABLE t1,t2;
+include/rpl_end.inc
diff --git a/mysql-test/suite/binlog_encryption/rpl_parallel_rollback_assert.test b/mysql-test/suite/binlog_encryption/rpl_parallel_rollback_assert.test
new file mode 100644
index 00000000000..181305219be
--- /dev/null
+++ b/mysql-test/suite/binlog_encryption/rpl_parallel_rollback_assert.test
@@ -0,0 +1 @@
+--source suite/rpl/include/rpl_parallel_rollback_assert.inc
diff --git a/mysql-test/suite/binlog_encryption/rpl_parallel_single_grpcmt.result b/mysql-test/suite/binlog_encryption/rpl_parallel_single_grpcmt.result
new file mode 100644
index 00000000000..25fc9a189ac
--- /dev/null
+++ b/mysql-test/suite/binlog_encryption/rpl_parallel_single_grpcmt.result
@@ -0,0 +1,161 @@
+*** Test that group-committed transactions on the master can replicate in parallel on the slave. ***
+include/master-slave.inc
+[connection master]
+connection server_1;
+SET sql_log_bin=0;
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+RETURNS INT DETERMINISTIC
+BEGIN
+RETURN x;
+END
+||
+SET sql_log_bin=1;
+connection server_2;
+include/stop_slave.inc
+SET sql_log_bin=0;
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+RETURNS INT DETERMINISTIC
+BEGIN
+IF d1 != '' THEN
+SET debug_sync = d1;
+END IF;
+IF d2 != '' THEN
+SET debug_sync = d2;
+END IF;
+RETURN x;
+END
+||
+SET sql_log_bin=1;
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+SET GLOBAL slave_parallel_threads=10;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+include/start_slave.inc
+connection server_1;
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
+INSERT INTO t3 VALUES (1,1), (3,3), (5,5), (7,7);
+connection server_2;
+connect con_temp1,127.0.0.1,root,,test,$SERVER_MYPORT_2,;
+BEGIN;
+INSERT INTO t3 VALUES (2,102);
+connect con_temp2,127.0.0.1,root,,test,$SERVER_MYPORT_2,;
+BEGIN;
+INSERT INTO t3 VALUES (4,104);
+connect con_temp3,127.0.0.1,root,,test,$SERVER_MYPORT_1,;
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
+SET binlog_format=statement;
+INSERT INTO t3 VALUES (2, foo(12,
+'commit_after_release_LOCK_prepare_ordered SIGNAL slave_queued1 WAIT_FOR slave_cont1',
+''));
+connection server_1;
+SET debug_sync='now WAIT_FOR master_queued1';
+connect con_temp4,127.0.0.1,root,,test,$SERVER_MYPORT_1,;
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
+SET binlog_format=statement;
+INSERT INTO t3 VALUES (4, foo(14,
+'commit_after_release_LOCK_prepare_ordered SIGNAL slave_queued2',
+''));
+connection server_1;
+SET debug_sync='now WAIT_FOR master_queued2';
+connect con_temp5,127.0.0.1,root,,test,$SERVER_MYPORT_1,;
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued3';
+SET binlog_format=statement;
+INSERT INTO t3 VALUES (6, foo(16,
+'group_commit_waiting_for_prior SIGNAL slave_queued3',
+''));
+connection server_1;
+SET debug_sync='now WAIT_FOR master_queued3';
+SET debug_sync='now SIGNAL master_cont1';
+connection con_temp3;
+connection con_temp4;
+connection con_temp5;
+SET debug_sync='RESET';
+connection server_1;
+SELECT * FROM t3 ORDER BY a;
+a b
+1 1
+2 12
+3 3
+4 14
+5 5
+6 16
+7 7
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Binlog_checkpoint # # master-bin.000001
+master-bin.000001 # Gtid # # GTID #-#-#
+master-bin.000001 # Query # # use `test`; ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB
+master-bin.000001 # Gtid # # GTID #-#-#
+master-bin.000001 # Query # # use `test`; CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t3 VALUES (1,1), (3,3), (5,5), (7,7)
+master-bin.000001 # Xid # # COMMIT /* XID */
+master-bin.000001 # Gtid # # BEGIN GTID #-#-# cid=#
+master-bin.000001 # Query # # use `test`; INSERT INTO t3 VALUES (2, foo(12,
+'commit_after_release_LOCK_prepare_ordered SIGNAL slave_queued1 WAIT_FOR slave_cont1',
+''))
+master-bin.000001 # Xid # # COMMIT /* XID */
+master-bin.000001 # Gtid # # BEGIN GTID #-#-# cid=#
+master-bin.000001 # Query # # use `test`; INSERT INTO t3 VALUES (4, foo(14,
+'commit_after_release_LOCK_prepare_ordered SIGNAL slave_queued2',
+''))
+master-bin.000001 # Xid # # COMMIT /* XID */
+master-bin.000001 # Gtid # # BEGIN GTID #-#-# cid=#
+master-bin.000001 # Query # # use `test`; INSERT INTO t3 VALUES (6, foo(16,
+'group_commit_waiting_for_prior SIGNAL slave_queued3',
+''))
+master-bin.000001 # Xid # # COMMIT /* XID */
+connection server_2;
+SET debug_sync='now WAIT_FOR slave_queued3';
+connection con_temp1;
+ROLLBACK;
+connection server_2;
+SET debug_sync='now WAIT_FOR slave_queued1';
+connection con_temp2;
+ROLLBACK;
+connection server_2;
+SET debug_sync='now WAIT_FOR slave_queued2';
+SET debug_sync='now SIGNAL slave_cont1';
+SELECT * FROM t3 ORDER BY a;
+a b
+1 1
+2 12
+3 3
+4 14
+5 5
+6 16
+7 7
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+slave-bin.000001 # Gtid # # GTID #-#-#
+slave-bin.000001 # Query # # use `test`; ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB
+slave-bin.000001 # Gtid # # GTID #-#-#
+slave-bin.000001 # Query # # use `test`; CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB
+slave-bin.000001 # Gtid # # BEGIN GTID #-#-#
+slave-bin.000001 # Query # # use `test`; INSERT INTO t3 VALUES (1,1), (3,3), (5,5), (7,7)
+slave-bin.000001 # Xid # # COMMIT /* XID */
+slave-bin.000001 # Gtid # # BEGIN GTID #-#-# cid=#
+slave-bin.000001 # Query # # use `test`; INSERT INTO t3 VALUES (2, foo(12,
+'commit_after_release_LOCK_prepare_ordered SIGNAL slave_queued1 WAIT_FOR slave_cont1',
+''))
+slave-bin.000001 # Xid # # COMMIT /* XID */
+slave-bin.000001 # Gtid # # BEGIN GTID #-#-# cid=#
+slave-bin.000001 # Query # # use `test`; INSERT INTO t3 VALUES (4, foo(14,
+'commit_after_release_LOCK_prepare_ordered SIGNAL slave_queued2',
+''))
+slave-bin.000001 # Xid # # COMMIT /* XID */
+slave-bin.000001 # Gtid # # BEGIN GTID #-#-# cid=#
+slave-bin.000001 # Query # # use `test`; INSERT INTO t3 VALUES (6, foo(16,
+'group_commit_waiting_for_prior SIGNAL slave_queued3',
+''))
+slave-bin.000001 # Xid # # COMMIT /* XID */
+connection server_2;
+include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+include/start_slave.inc
+SET DEBUG_SYNC= 'RESET';
+connection server_1;
+DROP function foo;
+DROP TABLE t3;
+SET DEBUG_SYNC= 'RESET';
+include/rpl_end.inc
diff --git a/mysql-test/suite/binlog_encryption/rpl_parallel_single_grpcmt.test b/mysql-test/suite/binlog_encryption/rpl_parallel_single_grpcmt.test
new file mode 100644
index 00000000000..6a13735c29c
--- /dev/null
+++ b/mysql-test/suite/binlog_encryption/rpl_parallel_single_grpcmt.test
@@ -0,0 +1 @@
+--source suite/rpl/include/rpl_parallel_single_grpcmt.inc
diff --git a/mysql-test/suite/binlog_encryption/rpl_parallel_slave_bgc_kill.result b/mysql-test/suite/binlog_encryption/rpl_parallel_slave_bgc_kill.result
new file mode 100644
index 00000000000..320bf0e49f8
--- /dev/null
+++ b/mysql-test/suite/binlog_encryption/rpl_parallel_slave_bgc_kill.result
@@ -0,0 +1,323 @@
+*** Test killing slave threads at various wait points ***
+include/master-slave.inc
+[connection master]
+connection server_2;
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+SET @old_parallel_mode=@@GLOBAL.slave_parallel_mode;
+include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=10;
+SET GLOBAL slave_parallel_mode='conservative';
+CHANGE MASTER TO master_use_gtid=slave_pos;
+include/start_slave.inc
+connection server_1;
+connect con_temp3,127.0.0.1,root,,test,$SERVER_MYPORT_1,;
+connect con_temp4,127.0.0.1,root,,test,$SERVER_MYPORT_1,;
+connect con_temp5,127.0.0.1,root,,test,$SERVER_MYPORT_1,;
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t1 (a int PRIMARY KEY) ENGINE=MyISAM;
+CREATE TABLE t2 (a int PRIMARY KEY) ENGINE=InnoDB;
+CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
+connection server_2;
+connection server_1;
+SET sql_log_bin=0;
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+RETURNS INT DETERMINISTIC
+BEGIN
+RETURN x;
+END
+||
+SET sql_log_bin=1;
+connection server_2;
+SET sql_log_bin=0;
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+RETURNS INT DETERMINISTIC
+BEGIN
+IF d1 != '' THEN
+SET debug_sync = d1;
+END IF;
+IF d2 != '' THEN
+SET debug_sync = d2;
+END IF;
+RETURN x;
+END
+||
+SET sql_log_bin=1;
+*** 1. Test killing transaction waiting in commit for previous transaction to commit ***
+connection con_temp3;
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
+INSERT INTO t3 VALUES (31, foo(31,
+'commit_before_prepare_ordered WAIT_FOR t2_waiting',
+'commit_after_prepare_ordered SIGNAL t1_ready WAIT_FOR t1_cont'));
+connection server_1;
+SET debug_sync='now WAIT_FOR master_queued1';
+connection con_temp4;
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
+BEGIN;
+INSERT INTO t3 VALUES (32, foo(32,
+'ha_write_row_end SIGNAL t2_query WAIT_FOR t2_cont',
+''));
+INSERT INTO t3 VALUES (33, foo(33,
+'group_commit_waiting_for_prior SIGNAL t2_waiting',
+'group_commit_waiting_for_prior_killed SIGNAL t2_killed'));
+COMMIT;
+connection server_1;
+SET debug_sync='now WAIT_FOR master_queued2';
+connection con_temp5;
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued3';
+INSERT INTO t3 VALUES (34, foo(34,
+'',
+''));
+connection server_1;
+SET debug_sync='now WAIT_FOR master_queued3';
+SET debug_sync='now SIGNAL master_cont1';
+connection con_temp3;
+connection con_temp4;
+connection con_temp5;
+connection server_1;
+SELECT * FROM t3 WHERE a >= 30 ORDER BY a;
+a b
+31 31
+32 32
+33 33
+34 34
+SET debug_sync='RESET';
+connection server_2;
+SET sql_log_bin=0;
+CALL mtr.add_suppression("Query execution was interrupted");
+CALL mtr.add_suppression("Commit failed due to failure of an earlier commit on which this one depends");
+CALL mtr.add_suppression("Slave: Connection was killed");
+SET sql_log_bin=1;
+SET debug_sync='now WAIT_FOR t2_query';
+SET debug_sync='now SIGNAL t2_cont';
+SET debug_sync='now WAIT_FOR t1_ready';
+KILL THD_ID;
+SET debug_sync='now WAIT_FOR t2_killed';
+SET debug_sync='now SIGNAL t1_cont';
+include/wait_for_slave_sql_error.inc [errno=1317,1927,1964]
+STOP SLAVE IO_THREAD;
+SELECT * FROM t3 WHERE a >= 30 ORDER BY a;
+a b
+31 31
+SET debug_sync='RESET';
+SET GLOBAL slave_parallel_threads=0;
+SET GLOBAL slave_parallel_threads=10;
+SET sql_log_bin=0;
+DROP FUNCTION foo;
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+RETURNS INT DETERMINISTIC
+BEGIN
+RETURN x;
+END
+||
+SET sql_log_bin=1;
+connection server_1;
+INSERT INTO t3 VALUES (39,0);
+connection server_2;
+include/start_slave.inc
+SELECT * FROM t3 WHERE a >= 30 ORDER BY a;
+a b
+31 31
+32 32
+33 33
+34 34
+39 0
+SET sql_log_bin=0;
+DROP FUNCTION foo;
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+RETURNS INT DETERMINISTIC
+BEGIN
+IF d1 != '' THEN
+SET debug_sync = d1;
+END IF;
+IF d2 != '' THEN
+SET debug_sync = d2;
+END IF;
+RETURN x;
+END
+||
+SET sql_log_bin=1;
+connection server_2;
+include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=0;
+SET GLOBAL slave_parallel_threads=10;
+include/start_slave.inc
+*** 2. Same as (1), but without restarting IO thread after kill of SQL threads ***
+connection con_temp3;
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
+INSERT INTO t3 VALUES (41, foo(41,
+'commit_before_prepare_ordered WAIT_FOR t2_waiting',
+'commit_after_prepare_ordered SIGNAL t1_ready WAIT_FOR t1_cont'));
+connection server_1;
+SET debug_sync='now WAIT_FOR master_queued1';
+connection con_temp4;
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
+BEGIN;
+INSERT INTO t3 VALUES (42, foo(42,
+'ha_write_row_end SIGNAL t2_query WAIT_FOR t2_cont',
+''));
+INSERT INTO t3 VALUES (43, foo(43,
+'group_commit_waiting_for_prior SIGNAL t2_waiting',
+'group_commit_waiting_for_prior_killed SIGNAL t2_killed'));
+COMMIT;
+connection server_1;
+SET debug_sync='now WAIT_FOR master_queued2';
+connection con_temp5;
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued3';
+INSERT INTO t3 VALUES (44, foo(44,
+'',
+''));
+connection server_1;
+SET debug_sync='now WAIT_FOR master_queued3';
+SET debug_sync='now SIGNAL master_cont1';
+connection con_temp3;
+connection con_temp4;
+connection con_temp5;
+connection server_1;
+SELECT * FROM t3 WHERE a >= 40 ORDER BY a;
+a b
+41 41
+42 42
+43 43
+44 44
+SET debug_sync='RESET';
+connection server_2;
+SET debug_sync='now WAIT_FOR t2_query';
+SET debug_sync='now SIGNAL t2_cont';
+SET debug_sync='now WAIT_FOR t1_ready';
+KILL THD_ID;
+SET debug_sync='now WAIT_FOR t2_killed';
+SET debug_sync='now SIGNAL t1_cont';
+include/wait_for_slave_sql_error.inc [errno=1317,1927,1964]
+SET debug_sync='RESET';
+SET GLOBAL slave_parallel_threads=0;
+SET GLOBAL slave_parallel_threads=10;
+SET sql_log_bin=0;
+DROP FUNCTION foo;
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+RETURNS INT DETERMINISTIC
+BEGIN
+RETURN x;
+END
+||
+SET sql_log_bin=1;
+connection server_1;
+INSERT INTO t3 VALUES (49,0);
+connection server_2;
+START SLAVE SQL_THREAD;
+SELECT * FROM t3 WHERE a >= 40 ORDER BY a;
+a b
+41 41
+42 42
+43 43
+44 44
+49 0
+SET sql_log_bin=0;
+DROP FUNCTION foo;
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+RETURNS INT DETERMINISTIC
+BEGIN
+IF d1 != '' THEN
+SET debug_sync = d1;
+END IF;
+IF d2 != '' THEN
+SET debug_sync = d2;
+END IF;
+RETURN x;
+END
+||
+SET sql_log_bin=1;
+connection server_2;
+include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=0;
+SET GLOBAL slave_parallel_threads=10;
+include/start_slave.inc
+*** 3. Same as (2), but not using gtid mode ***
+connection server_2;
+include/stop_slave.inc
+CHANGE MASTER TO master_use_gtid=no;
+include/start_slave.inc
+connection server_1;
+connection con_temp3;
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
+INSERT INTO t3 VALUES (51, foo(51,
+'commit_before_prepare_ordered WAIT_FOR t2_waiting',
+'commit_after_prepare_ordered SIGNAL t1_ready WAIT_FOR t1_cont'));
+connection server_1;
+SET debug_sync='now WAIT_FOR master_queued1';
+connection con_temp4;
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
+BEGIN;
+INSERT INTO t3 VALUES (52, foo(52,
+'ha_write_row_end SIGNAL t2_query WAIT_FOR t2_cont',
+''));
+INSERT INTO t3 VALUES (53, foo(53,
+'group_commit_waiting_for_prior SIGNAL t2_waiting',
+'group_commit_waiting_for_prior_killed SIGNAL t2_killed'));
+COMMIT;
+connection server_1;
+SET debug_sync='now WAIT_FOR master_queued2';
+connection con_temp5;
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued3';
+INSERT INTO t3 VALUES (54, foo(54,
+'',
+''));
+connection server_1;
+SET debug_sync='now WAIT_FOR master_queued3';
+SET debug_sync='now SIGNAL master_cont1';
+connection con_temp3;
+connection con_temp4;
+connection con_temp5;
+connection server_1;
+SELECT * FROM t3 WHERE a >= 50 ORDER BY a;
+a b
+51 51
+52 52
+53 53
+54 54
+SET debug_sync='RESET';
+connection server_2;
+SET debug_sync='now WAIT_FOR t2_query';
+SET debug_sync='now SIGNAL t2_cont';
+SET debug_sync='now WAIT_FOR t1_ready';
+KILL THD_ID;
+SET debug_sync='now WAIT_FOR t2_killed';
+SET debug_sync='now SIGNAL t1_cont';
+include/wait_for_slave_sql_error.inc [errno=1317,1927,1964]
+SELECT * FROM t3 WHERE a >= 50 ORDER BY a;
+a b
+51 51
+SET debug_sync='RESET';
+SET GLOBAL slave_parallel_threads=0;
+SET GLOBAL slave_parallel_threads=10;
+SET sql_log_bin=0;
+DROP FUNCTION foo;
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+RETURNS INT DETERMINISTIC
+BEGIN
+RETURN x;
+END
+||
+SET sql_log_bin=1;
+connection server_1;
+INSERT INTO t3 VALUES (59,0);
+connection server_2;
+START SLAVE SQL_THREAD;
+SELECT * FROM t3 WHERE a >= 50 ORDER BY a;
+a b
+51 51
+52 52
+53 53
+54 54
+59 0
+connection server_2;
+include/stop_slave.inc
+CHANGE MASTER TO master_use_gtid=slave_pos;
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+SET GLOBAL slave_parallel_mode=@old_parallel_mode;
+include/start_slave.inc
+SET DEBUG_SYNC= 'RESET';
+connection server_1;
+DROP function foo;
+DROP TABLE t1,t2,t3;
+SET DEBUG_SYNC= 'RESET';
+include/rpl_end.inc
diff --git a/mysql-test/suite/binlog_encryption/rpl_parallel_slave_bgc_kill.test b/mysql-test/suite/binlog_encryption/rpl_parallel_slave_bgc_kill.test
new file mode 100644
index 00000000000..72597f32685
--- /dev/null
+++ b/mysql-test/suite/binlog_encryption/rpl_parallel_slave_bgc_kill.test
@@ -0,0 +1 @@
+--source suite/rpl/include/rpl_parallel_slave_bgc_kill.inc
diff --git a/mysql-test/suite/binlog_encryption/rpl_parallel_stop_on_con_kill.result b/mysql-test/suite/binlog_encryption/rpl_parallel_stop_on_con_kill.result
new file mode 100644
index 00000000000..bf0ed9e4374
--- /dev/null
+++ b/mysql-test/suite/binlog_encryption/rpl_parallel_stop_on_con_kill.result
@@ -0,0 +1,102 @@
+*** MDEV-8031: Parallel replication stops on "connection killed" error (probably incorrectly handled deadlock kill) ***
+include/master-slave.inc
+[connection master]
+connection server_2;
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=10;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+include/start_slave.inc
+connection server_1;
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
+INSERT INTO t3 VALUES (201,0), (202,0);
+include/save_master_gtid.inc
+connection server_2;
+include/sync_with_master_gtid.inc
+include/stop_slave.inc
+SET @old_dbug= @@GLOBAL.debug_dbug;
+SET GLOBAL debug_dbug= '+d,inject_mdev8031';
+connection server_1;
+SET @old_dbug= @@SESSION.debug_dbug;
+SET SESSION debug_dbug="+d,binlog_force_commit_id";
+SET @commit_id= 10200;
+INSERT INTO t3 VALUES (203, 1);
+INSERT INTO t3 VALUES (204, 1);
+INSERT INTO t3 VALUES (205, 1);
+UPDATE t3 SET b=b+1 WHERE a=201;
+UPDATE t3 SET b=b+1 WHERE a=201;
+UPDATE t3 SET b=b+1 WHERE a=201;
+UPDATE t3 SET b=b+1 WHERE a=202;
+UPDATE t3 SET b=b+1 WHERE a=202;
+UPDATE t3 SET b=b+1 WHERE a=202;
+UPDATE t3 SET b=b+1 WHERE a=202;
+UPDATE t3 SET b=b+1 WHERE a=203;
+UPDATE t3 SET b=b+1 WHERE a=203;
+UPDATE t3 SET b=b+1 WHERE a=204;
+UPDATE t3 SET b=b+1 WHERE a=204;
+UPDATE t3 SET b=b+1 WHERE a=204;
+UPDATE t3 SET b=b+1 WHERE a=203;
+UPDATE t3 SET b=b+1 WHERE a=205;
+UPDATE t3 SET b=b+1 WHERE a=205;
+SET SESSION debug_dbug=@old_dbug;
+SELECT * FROM t3 WHERE a>=200 ORDER BY a;
+a b
+201 3
+202 4
+203 4
+204 4
+205 3
+include/save_master_gtid.inc
+connection server_2;
+include/start_slave.inc
+include/sync_with_master_gtid.inc
+SELECT * FROM t3 WHERE a>=200 ORDER BY a;
+a b
+201 3
+202 4
+203 4
+204 4
+205 3
+include/stop_slave.inc
+SET GLOBAL debug_dbug= @old_dbug;
+include/start_slave.inc
+*** Check getting deadlock killed inside open_binlog() during retry. ***
+connection server_2;
+include/stop_slave.inc
+SET @old_dbug= @@GLOBAL.debug_dbug;
+SET GLOBAL debug_dbug= '+d,inject_retry_event_group_open_binlog_kill';
+SET @old_max= @@GLOBAL.max_relay_log_size;
+SET GLOBAL max_relay_log_size= 4096;
+connection server_1;
+SET @old_dbug= @@SESSION.debug_dbug;
+SET SESSION debug_dbug="+d,binlog_force_commit_id";
+SET @commit_id= 10210;
+Omit long queries that cause relaylog rotations and transaction retries...
+SET SESSION debug_dbug=@old_dbug;
+SELECT * FROM t3 WHERE a>=200 ORDER BY a;
+a b
+201 6
+202 8
+203 7
+204 7
+205 5
+include/save_master_gtid.inc
+connection server_2;
+include/start_slave.inc
+include/sync_with_master_gtid.inc
+SELECT * FROM t3 WHERE a>=200 ORDER BY a;
+a b
+201 6
+202 8
+203 7
+204 7
+205 5
+include/stop_slave.inc
+SET GLOBAL debug_dbug= @old_debg;
+SET GLOBAL max_relay_log_size= @old_max;
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+include/start_slave.inc
+connection server_1;
+DROP TABLE t3;
+include/rpl_end.inc
diff --git a/mysql-test/suite/binlog_encryption/rpl_parallel_stop_on_con_kill.test b/mysql-test/suite/binlog_encryption/rpl_parallel_stop_on_con_kill.test
new file mode 100644
index 00000000000..adec2dc631c
--- /dev/null
+++ b/mysql-test/suite/binlog_encryption/rpl_parallel_stop_on_con_kill.test
@@ -0,0 +1 @@
+--source suite/rpl/include/rpl_parallel_stop_on_con_kill.inc
diff --git a/mysql-test/suite/binlog_encryption/rpl_parallel_stop_slave.result b/mysql-test/suite/binlog_encryption/rpl_parallel_stop_slave.result
new file mode 100644
index 00000000000..6c9fd168e73
--- /dev/null
+++ b/mysql-test/suite/binlog_encryption/rpl_parallel_stop_slave.result
@@ -0,0 +1,85 @@
+*** Test STOP SLAVE in parallel mode ***
+include/master-slave.inc
+[connection master]
+connection server_2;
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+SET @old_parallel_mode=@@GLOBAL.slave_parallel_mode;
+include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=10;
+SET GLOBAL slave_parallel_mode='conservative';
+CHANGE MASTER TO master_use_gtid=slave_pos;
+include/start_slave.inc
+connect con_temp1,127.0.0.1,root,,test,$SERVER_MYPORT_2,;
+connect con_temp2,127.0.0.1,root,,test,$SERVER_MYPORT_2,;
+connection server_1;
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t1 (a int PRIMARY KEY) ENGINE=MyISAM;
+CREATE TABLE t2 (a int PRIMARY KEY) ENGINE=InnoDB;
+CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
+connection server_2;
+include/stop_slave.inc
+connection server_1;
+SET binlog_direct_non_transactional_updates=0;
+SET sql_log_bin=0;
+CALL mtr.add_suppression("Statement is unsafe because it accesses a non-transactional table after accessing a transactional table within the same transaction");
+SET sql_log_bin=1;
+BEGIN;
+INSERT INTO t2 VALUES (20);
+INSERT INTO t1 VALUES (20);
+INSERT INTO t2 VALUES (21);
+INSERT INTO t3 VALUES (20, 20);
+COMMIT;
+INSERT INTO t3 VALUES(21, 21);
+INSERT INTO t3 VALUES(22, 22);
+connection con_temp1;
+BEGIN;
+INSERT INTO t2 VALUES (21);
+connection server_2;
+START SLAVE;
+connection con_temp2;
+SET @old_dbug= @@GLOBAL.debug_dbug;
+SET GLOBAL debug_dbug="+d,rpl_parallel_wait_for_done_trigger";
+STOP SLAVE;
+connection con_temp1;
+SET debug_sync='now WAIT_FOR wait_for_done_waiting';
+ROLLBACK;
+connection con_temp2;
+SET GLOBAL debug_dbug=@old_dbug;
+SET debug_sync='RESET';
+connection server_2;
+include/wait_for_slave_to_stop.inc
+SELECT * FROM t1 WHERE a >= 20 ORDER BY a;
+a
+20
+SELECT * FROM t2 WHERE a >= 20 ORDER BY a;
+a
+20
+21
+SELECT * FROM t3 WHERE a >= 20 ORDER BY a;
+a b
+20 20
+include/start_slave.inc
+SELECT * FROM t1 WHERE a >= 20 ORDER BY a;
+a
+20
+SELECT * FROM t2 WHERE a >= 20 ORDER BY a;
+a
+20
+21
+SELECT * FROM t3 WHERE a >= 20 ORDER BY a;
+a b
+20 20
+21 21
+22 22
+connection server_2;
+include/stop_slave.inc
+SET GLOBAL slave_parallel_mode=@old_parallel_mode;
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+include/start_slave.inc
+SET DEBUG_SYNC= 'RESET';
+disconnect con_temp1;
+disconnect con_temp2;
+connection server_1;
+DROP TABLE t1,t2,t3;
+SET DEBUG_SYNC= 'RESET';
+include/rpl_end.inc
diff --git a/mysql-test/suite/binlog_encryption/rpl_parallel_stop_slave.test b/mysql-test/suite/binlog_encryption/rpl_parallel_stop_slave.test
new file mode 100644
index 00000000000..c59b2805569
--- /dev/null
+++ b/mysql-test/suite/binlog_encryption/rpl_parallel_stop_slave.test
@@ -0,0 +1 @@
+--source suite/rpl/include/rpl_parallel_stop_slave.inc
diff --git a/mysql-test/suite/binlog_encryption/rpl_parallel_wrong_binlog_order.result b/mysql-test/suite/binlog_encryption/rpl_parallel_wrong_binlog_order.result
new file mode 100644
index 00000000000..f6781f64d30
--- /dev/null
+++ b/mysql-test/suite/binlog_encryption/rpl_parallel_wrong_binlog_order.result
@@ -0,0 +1,75 @@
+*** MDEV-6775: Wrong binlog order in parallel replication ***
+include/master-slave.inc
+[connection master]
+connection server_2;
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=10;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+include/start_slave.inc
+connection server_1;
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t4 (a INT PRIMARY KEY, b INT, KEY b_idx(b)) ENGINE=InnoDB;
+INSERT INTO t4 VALUES (1,NULL), (3,NULL), (4,4), (5, NULL), (6, 6);
+connect con1,127.0.0.1,root,,test,$SERVER_MYPORT_1,;
+connect con2,127.0.0.1,root,,test,$SERVER_MYPORT_1,;
+include/save_master_gtid.inc
+connection server_2;
+include/sync_with_master_gtid.inc
+include/stop_slave.inc
+SET @old_dbug= @@GLOBAL.debug_dbug;
+SET GLOBAL debug_dbug="+d,inject_binlog_commit_before_get_LOCK_log";
+SET @old_format=@@GLOBAL.binlog_format;
+SET GLOBAL binlog_format=ROW;
+SET GLOBAL slave_parallel_threads=0;
+SET GLOBAL slave_parallel_threads=10;
+connection con1;
+SET @old_format= @@binlog_format;
+SET binlog_format= statement;
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
+UPDATE t4 SET b=NULL WHERE a=6;
+connection server_1;
+SET debug_sync='now WAIT_FOR master_queued1';
+connection con2;
+SET @old_format= @@binlog_format;
+SET binlog_format= statement;
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
+DELETE FROM t4 WHERE b <= 3;
+connection server_1;
+SET debug_sync='now WAIT_FOR master_queued2';
+SET debug_sync='now SIGNAL master_cont1';
+connection con1;
+SET binlog_format= @old_format;
+connection con2;
+SET binlog_format= @old_format;
+SET debug_sync='RESET';
+SELECT * FROM t4 ORDER BY a;
+a b
+1 NULL
+3 NULL
+4 4
+5 NULL
+6 NULL
+connection server_2;
+include/start_slave.inc
+SET debug_sync= 'now WAIT_FOR waiting';
+SELECT * FROM t4 ORDER BY a;
+a b
+1 NULL
+3 NULL
+4 4
+5 NULL
+6 NULL
+SET debug_sync= 'now SIGNAL cont';
+include/stop_slave.inc
+SET GLOBAL debug_dbug=@old_dbug;
+SET GLOBAL binlog_format= @old_format;
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+include/start_slave.inc
+SET DEBUG_SYNC= 'RESET';
+connection server_1;
+DROP TABLE t4;
+SET DEBUG_SYNC= 'RESET';
+disconnect con1;
+disconnect con2;
+include/rpl_end.inc
diff --git a/mysql-test/suite/binlog_encryption/rpl_parallel_wrong_binlog_order.test b/mysql-test/suite/binlog_encryption/rpl_parallel_wrong_binlog_order.test
new file mode 100644
index 00000000000..4141dfce6d6
--- /dev/null
+++ b/mysql-test/suite/binlog_encryption/rpl_parallel_wrong_binlog_order.test
@@ -0,0 +1 @@
+--source suite/rpl/include/rpl_parallel_wrong_binlog_order.inc
diff --git a/mysql-test/suite/binlog_encryption/rpl_parallel_wrong_exec_master_pos.result b/mysql-test/suite/binlog_encryption/rpl_parallel_wrong_exec_master_pos.result
new file mode 100644
index 00000000000..47cfa5e08e2
--- /dev/null
+++ b/mysql-test/suite/binlog_encryption/rpl_parallel_wrong_exec_master_pos.result
@@ -0,0 +1,34 @@
+*** MDEV-5938: Exec_master_log_pos not updated at log rotate in parallel replication ***
+include/master-slave.inc
+[connection master]
+connection server_2;
+include/stop_slave.inc
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+SET GLOBAL slave_parallel_threads=1;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+include/start_slave.inc
+connection server_1;
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t5 (a INT PRIMARY KEY, b INT);
+INSERT INTO t5 VALUES (1,1);
+INSERT INTO t5 VALUES (2,2), (3,8);
+INSERT INTO t5 VALUES (4,16);
+connection server_2;
+test_check
+OK
+test_check
+OK
+connection server_1;
+FLUSH LOGS;
+connection server_2;
+test_check
+OK
+test_check
+OK
+connection server_2;
+include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+include/start_slave.inc
+connection server_1;
+DROP TABLE t5;
+include/rpl_end.inc
diff --git a/mysql-test/suite/binlog_encryption/rpl_parallel_wrong_exec_master_pos.test b/mysql-test/suite/binlog_encryption/rpl_parallel_wrong_exec_master_pos.test
new file mode 100644
index 00000000000..34268eb6622
--- /dev/null
+++ b/mysql-test/suite/binlog_encryption/rpl_parallel_wrong_exec_master_pos.test
@@ -0,0 +1 @@
+--source suite/rpl/include/rpl_parallel_wrong_exec_master_pos.inc
diff --git a/mysql-test/suite/multi_source/info_logs.result b/mysql-test/suite/multi_source/info_logs.result
index 531a6178cdb..f8519a99964 100644
--- a/mysql-test/suite/multi_source/info_logs.result
+++ b/mysql-test/suite/multi_source/info_logs.result
@@ -90,16 +90,16 @@ MASTER 2.2
#
show all slaves status;
Connection_name Slave_SQL_State Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Master_SSL_Crl Master_SSL_Crlpath Using_Gtid Gtid_IO_Pos Replicate_Do_Domain_Ids Replicate_Ignore_Domain_Ids Parallel_Mode SQL_Delay SQL_Remaining_Delay Slave_SQL_Running_State Slave_DDL_Groups Slave_Non_Transactional_Groups Slave_Transactional_Groups Retried_tra
nsaction
s Max_relay_log_size Executed_log_entries Slave_received_heartbeats Slave_heartbeat_period Gtid_Slave_Pos
- Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_1 60 master-bin.000001 <read_master_log_pos> relay.000002 <relay_log_pos> master-bin.000001 Yes Yes 0 0 <read_master_log_pos> <relay_log_space1> None 0 No 0 No 0 0 1 No conservative 0 NULL Slave has read all relay log; waiting for the slave I/O thread to update it 0 0 0 0 1073741824 7 0 60.000
-MASTER 2.2 Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_2 60 master-bin.000001 <read_master_log_pos> relay-master@00202@002e2.000002 <relay_log_pos> master-bin.000001 Yes Yes 0 0 <read_master_log_pos> <relay_log_space2> None 0 No 0 No 0 0 2 No conservative 0 NULL Slave has read all relay log; waiting for the slave I/O thread to update it 0 0 0 0 1073741824 7 0 60.000
+ Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_1 60 master-bin.000001 <read_master_log_pos> relay.000002 <relay_log_pos> master-bin.000001 Yes Yes 0 0 <read_master_log_pos> <relay_log_space1> None 0 No 0 No 0 0 1 No optimistic 0 NULL Slave has read all relay log; waiting for the slave I/O thread to update it 0 0 0 0 1073741824 7 0 60.000
+MASTER 2.2 Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_2 60 master-bin.000001 <read_master_log_pos> relay-master@00202@002e2.000002 <relay_log_pos> master-bin.000001 Yes Yes 0 0 <read_master_log_pos> <relay_log_space2> None 0 No 0 No 0 0 2 No optimistic 0 NULL Slave has read all relay log; waiting for the slave I/O thread to update it 0 0 0 0 1073741824 7 0 60.000
include/wait_for_slave_to_start.inc
set default_master_connection = 'MASTER 2.2';
include/wait_for_slave_to_start.inc
set default_master_connection = '';
show all slaves status;
Connection_name Slave_SQL_State Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Master_SSL_Crl Master_SSL_Crlpath Using_Gtid Gtid_IO_Pos Replicate_Do_Domain_Ids Replicate_Ignore_Domain_Ids Parallel_Mode SQL_Delay SQL_Remaining_Delay Slave_SQL_Running_State Slave_DDL_Groups Slave_Non_Transactional_Groups Slave_Transactional_Groups Retried_tra
nsaction
s Max_relay_log_size Executed_log_entries Slave_received_heartbeats Slave_heartbeat_period Gtid_Slave_Pos
- Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_1 60 master-bin.000001 <read_master_log_pos> relay.000004 <relay_log_pos> master-bin.000001 Yes Yes 0 0 <read_master_log_pos> <relay_log_space1> None 0 No 0 No 0 0 1 No conservative 0 NULL Slave has read all relay log; waiting for the slave I/O thread to update it 0 0 0 0 1073741824 6 0 60.000
-MASTER 2.2 Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_2 60 master-bin.000001 <read_master_log_pos> relay-master@00202@002e2.000004 <relay_log_pos> master-bin.000001 Yes Yes 0 0 <read_master_log_pos> <relay_log_space2> None 0 No 0 No 0 0 2 No conservative 0 NULL Slave has read all relay log; waiting for the slave I/O thread to update it 0 0 0 0 1073741824 6 0 60.000
+ Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_1 60 master-bin.000001 <read_master_log_pos> relay.000004 <relay_log_pos> master-bin.000001 Yes Yes 0 0 <read_master_log_pos> <relay_log_space1> None 0 No 0 No 0 0 1 No optimistic 0 NULL Slave has read all relay log; waiting for the slave I/O thread to update it 0 0 0 0 1073741824 6 0 60.000
+MASTER 2.2 Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_2 60 master-bin.000001 <read_master_log_pos> relay-master@00202@002e2.000004 <relay_log_pos> master-bin.000001 Yes Yes 0 0 <read_master_log_pos> <relay_log_space2> None 0 No 0 No 0 0 2 No optimistic 0 NULL Slave has read all relay log; waiting for the slave I/O thread to update it 0 0 0 0 1073741824 6 0 60.000
#
# List of files matching '*info*' pattern
# after slave server restart
diff --git a/mysql-test/suite/multi_source/reset_slave.result b/mysql-test/suite/multi_source/reset_slave.result
index c1d74ab9f3f..c048784e28d 100644
--- a/mysql-test/suite/multi_source/reset_slave.result
+++ b/mysql-test/suite/multi_source/reset_slave.result
@@ -14,14 +14,14 @@ connection slave;
stop slave 'master1';
show slave 'master1' status;
Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Master_SSL_Crl Master_SSL_Crlpath Using_Gtid Gtid_IO_Pos Replicate_Do_Domain_Ids Replicate_Ignore_Domain_Ids Parallel_Mode SQL_Delay SQL_Remaining_Delay Slave_SQL_Running_State Slave_DDL_Groups Slave_Non_Transactional_Groups Slave_Transactional_Groups
- 127.0.0.1 root MYPORT_1 60 master-bin.000001 <read_master_log_pos> mysqld-relay-bin-master1.000002 <relay_log_pos> master-bin.000001 No No 0 0 <read_master_log_pos> <relay_log_space> None 0 No NULL No 0 0 1 No conservative 0 NULL 2 1 0
+ 127.0.0.1 root MYPORT_1 60 master-bin.000001 <read_master_log_pos> mysqld-relay-bin-master1.000002 <relay_log_pos> master-bin.000001 No No 0 0 <read_master_log_pos> <relay_log_space> None 0 No NULL No 0 0 1 No optimistic 0 NULL 2 1 0
mysqld-relay-bin-master1.000001
mysqld-relay-bin-master1.000002
mysqld-relay-bin-master1.index
reset slave 'master1';
show slave 'master1' status;
Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Master_SSL_Crl Master_SSL_Crlpath Using_Gtid Gtid_IO_Pos Replicate_Do_Domain_Ids Replicate_Ignore_Domain_Ids Parallel_Mode SQL_Delay SQL_Remaining_Delay Slave_SQL_Running_State Slave_DDL_Groups Slave_Non_Transactional_Groups Slave_Transactional_Groups
- 127.0.0.1 root MYPORT_1 60 4 <relay_log_pos> No No 0 0 0 <relay_log_space> None 0 No NULL No 0 0 1 No conservative 0 NULL 2 1 0
+ 127.0.0.1 root MYPORT_1 60 4 <relay_log_pos> No No 0 0 0 <relay_log_space> None 0 No NULL No 0 0 1 No optimistic 0 NULL 2 1 0
reset slave 'master1' all;
show slave 'master1' status;
ERROR HY000: There is no master connection 'master1'
diff --git a/mysql-test/suite/multi_source/simple.result b/mysql-test/suite/multi_source/simple.result
index 93ea1c023bc..922c7555875 100644
--- a/mysql-test/suite/multi_source/simple.result
+++ b/mysql-test/suite/multi_source/simple.result
@@ -19,8 +19,8 @@ connection master2;
connection slave;
show all slaves status;
Connection_name Slave_SQL_State Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Master_SSL_Crl Master_SSL_Crlpath Using_Gtid Gtid_IO_Pos Replicate_Do_Domain_Ids Replicate_Ignore_Domain_Ids Parallel_Mode SQL_Delay SQL_Remaining_Delay Slave_SQL_Running_State Slave_DDL_Groups Slave_Non_Transactional_Groups Slave_Transactional_Groups Retried_tra
nsaction
s Max_relay_log_size Executed_log_entries Slave_received_heartbeats Slave_heartbeat_period Gtid_Slave_Pos
-slave1 Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_1 60 master-bin.000001 <read_master_log_pos> mysqld-relay-bin-slave1.000002 <relay_log_pos> master-bin.000001 Yes Yes 0 0 <read_master_log_pos> <relay_log_space1> None 0 No 0 No 0 0 1 No conservative 0 NULL Slave has read all relay log; waiting for the slave I/O thread to update it 0 0 0 0 1073741824 7 0 60.000
-slave2 Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_2 60 master-bin.000001 <read_master_log_pos> mysqld-relay-bin-slave2.000002 <relay_log_pos> master-bin.000001 Yes Yes 0 0 <read_master_log_pos> <relay_log_space1> None 0 No 0 No 0 0 2 No conservative 0 NULL Slave has read all relay log; waiting for the slave I/O thread to update it 0 0 0 0 1073741824 7 0 60.000
+slave1 Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_1 60 master-bin.000001 <read_master_log_pos> mysqld-relay-bin-slave1.000002 <relay_log_pos> master-bin.000001 Yes Yes 0 0 <read_master_log_pos> <relay_log_space1> None 0 No 0 No 0 0 1 No optimistic 0 NULL Slave has read all relay log; waiting for the slave I/O thread to update it 0 0 0 0 1073741824 7 0 60.000
+slave2 Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_2 60 master-bin.000001 <read_master_log_pos> mysqld-relay-bin-slave2.000002 <relay_log_pos> master-bin.000001 Yes Yes 0 0 <read_master_log_pos> <relay_log_space1> None 0 No 0 No 0 0 2 No optimistic 0 NULL Slave has read all relay log; waiting for the slave I/O thread to update it 0 0 0 0 1073741824 7 0 60.000
start all slaves;
stop slave 'slave1';
show slave 'slave1' status;
@@ -70,7 +70,7 @@ Using_Gtid No
Gtid_IO_Pos
Replicate_Do_Domain_Ids
Replicate_Ignore_Domain_Ids
-Parallel_Mode conservative
+Parallel_Mode optimistic
SQL_Delay 0
SQL_Remaining_Delay NULL
Slave_SQL_Running_State
@@ -80,18 +80,18 @@ Slave_Transactional_Groups 0
reset slave 'slave1';
show all slaves status;
Connection_name Slave_SQL_State Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Master_SSL_Crl Master_SSL_Crlpath Using_Gtid Gtid_IO_Pos Replicate_Do_Domain_Ids Replicate_Ignore_Domain_Ids Parallel_Mode SQL_Delay SQL_Remaining_Delay Slave_SQL_Running_State Slave_DDL_Groups Slave_Non_Transactional_Groups Slave_Transactional_Groups Retried_tra
nsaction
s Max_relay_log_size Executed_log_entries Slave_received_heartbeats Slave_heartbeat_period Gtid_Slave_Pos
-slave1 127.0.0.1 root MYPORT_1 60 4 <relay_log_pos> No No 0 0 0 <relay_log_space1> None 0 No NULL No 0 0 1 No conservative 0 NULL 0 0 0 0 1073741824 7 0 60.000
-slave2 Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_2 60 master-bin.000001 <read_master_log_pos> mysqld-relay-bin-slave2.000002 <relay_log_pos> master-bin.000001 Yes Yes 0 0 <read_master_log_pos> <relay_log_space1> None 0 No 0 No 0 0 2 No conservative 0 NULL Slave has read all relay log; waiting for the slave I/O thread to update it 0 0 0 0 1073741824 7 0 60.000
+slave1 127.0.0.1 root MYPORT_1 60 4 <relay_log_pos> No No 0 0 0 <relay_log_space1> None 0 No NULL No 0 0 1 No optimistic 0 NULL 0 0 0 0 1073741824 7 0 60.000
+slave2 Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_2 60 master-bin.000001 <read_master_log_pos> mysqld-relay-bin-slave2.000002 <relay_log_pos> master-bin.000001 Yes Yes 0 0 <read_master_log_pos> <relay_log_space1> None 0 No 0 No 0 0 2 No optimistic 0 NULL Slave has read all relay log; waiting for the slave I/O thread to update it 0 0 0 0 1073741824 7 0 60.000
reset slave 'slave1' all;
show all slaves status;
Connection_name Slave_SQL_State Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Master_SSL_Crl Master_SSL_Crlpath Using_Gtid Gtid_IO_Pos Replicate_Do_Domain_Ids Replicate_Ignore_Domain_Ids Parallel_Mode SQL_Delay SQL_Remaining_Delay Slave_SQL_Running_State Slave_DDL_Groups Slave_Non_Transactional_Groups Slave_Transactional_Groups Retried_tra
nsaction
s Max_relay_log_size Executed_log_entries Slave_received_heartbeats Slave_heartbeat_period Gtid_Slave_Pos
-slave2 Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_2 60 master-bin.000001 <read_master_log_pos> mysqld-relay-bin-slave2.000002 <relay_log_pos> master-bin.000001 Yes Yes 0 0 <read_master_log_pos> <relay_log_space1> None 0 No 0 No 0 0 2 No conservative 0 NULL Slave has read all relay log; waiting for the slave I/O thread to update it 0 0 0 0 1073741824 7 0 60.000
+slave2 Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_2 60 master-bin.000001 <read_master_log_pos> mysqld-relay-bin-slave2.000002 <relay_log_pos> master-bin.000001 Yes Yes 0 0 <read_master_log_pos> <relay_log_space1> None 0 No 0 No 0 0 2 No optimistic 0 NULL Slave has read all relay log; waiting for the slave I/O thread to update it 0 0 0 0 1073741824 7 0 60.000
stop all slaves;
Warnings:
Note 1938 SLAVE 'slave2' stopped
show all slaves status;
Connection_name Slave_SQL_State Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Master_SSL_Crl Master_SSL_Crlpath Using_Gtid Gtid_IO_Pos Replicate_Do_Domain_Ids Replicate_Ignore_Domain_Ids Parallel_Mode SQL_Delay SQL_Remaining_Delay Slave_SQL_Running_State Slave_DDL_Groups Slave_Non_Transactional_Groups Slave_Transactional_Groups Retried_tra
nsaction
s Max_relay_log_size Executed_log_entries Slave_received_heartbeats Slave_heartbeat_period Gtid_Slave_Pos
-slave2 127.0.0.1 root MYPORT_2 60 master-bin.000001 <read_master_log_pos> mysqld-relay-bin-slave2.000002 <relay_log_pos> master-bin.000001 No No 0 0 <read_master_log_pos> <relay_log_space1> None 0 No NULL No 0 0 2 No conservative 0 NULL 0 0 0 0 1073741824 7 0 60.000
+slave2 127.0.0.1 root MYPORT_2 60 master-bin.000001 <read_master_log_pos> mysqld-relay-bin-slave2.000002 <relay_log_pos> master-bin.000001 No No 0 0 <read_master_log_pos> <relay_log_space1> None 0 No NULL No 0 0 2 No optimistic 0 NULL 0 0 0 0 1073741824 7 0 60.000
stop all slaves;
include/reset_master_slave.inc
disconnect slave;
diff --git a/mysql-test/suite/rpl/include/rpl_parallel.inc b/mysql-test/suite/rpl/include/rpl_parallel.inc
deleted file mode 100644
index 42354343084..00000000000
--- a/mysql-test/suite/rpl/include/rpl_parallel.inc
+++ /dev/null
@@ -1,2219 +0,0 @@
-#
-# This include file is used by more than one test suite
-# (currently rpl and binlog_encryption).
-# Please check all dependent tests after modifying it
-#
-
---source include/have_innodb.inc
---source include/have_debug.inc
---source include/have_debug_sync.inc
---source include/master-slave.inc
-
-# Test various aspects of parallel replication.
-
---connection server_2
-SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
---error ER_SLAVE_MUST_STOP
-SET GLOBAL slave_parallel_threads=10;
---source include/stop_slave.inc
-SET GLOBAL slave_parallel_threads=10;
-
-# Check that we do not spawn any worker threads when no slave is running.
-SELECT IF(COUNT(*) < 10, "OK", CONCAT("Found too many system user processes: ", COUNT(*))) FROM information_schema.processlist WHERE user = "system user";
-
-CHANGE MASTER TO master_use_gtid=slave_pos;
---source include/start_slave.inc
-
-# Check that worker threads get spawned when slave starts.
-SELECT IF(COUNT(*) >= 10, "OK", CONCAT("Found too few system user processes: ", COUNT(*))) FROM information_schema.processlist WHERE user = "system user";
-# ... and that worker threads get removed when slave stops.
---source include/stop_slave.inc
-SELECT IF(COUNT(*) < 10, "OK", CONCAT("Found too many system user processes: ", COUNT(*))) FROM information_schema.processlist WHERE user = "system user";
---source include/start_slave.inc
-SELECT IF(COUNT(*) >= 10, "OK", CONCAT("Found too few system user processes: ", COUNT(*))) FROM information_schema.processlist WHERE user = "system user";
-
---echo *** Test long-running query in domain 1 can run in parallel with short queries in domain 0 ***
-
---connection server_1
-ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
-CREATE TABLE t1 (a int PRIMARY KEY) ENGINE=MyISAM;
-CREATE TABLE t2 (a int PRIMARY KEY) ENGINE=InnoDB;
-INSERT INTO t1 VALUES (1);
-INSERT INTO t2 VALUES (1);
---save_master_pos
-
---connection server_2
---sync_with_master
-
-# Block the table t1 to simulate a replicated query taking a long time.
---connect (con_temp1,127.0.0.1,root,,test,$SERVER_MYPORT_2,)
-LOCK TABLE t1 WRITE;
-
---connection server_1
-SET gtid_domain_id=1;
-# This query will be blocked on the slave until UNLOCK TABLES.
-INSERT INTO t1 VALUES (2);
-SET gtid_domain_id=0;
-# These t2 queries can be replicated in parallel with the prior t1 query, as
-# they are in a separate replication domain.
-INSERT INTO t2 VALUES (2);
-INSERT INTO t2 VALUES (3);
-BEGIN;
-INSERT INTO t2 VALUES (4);
-INSERT INTO t2 VALUES (5);
-COMMIT;
-INSERT INTO t2 VALUES (6);
-
---connection server_2
---let $wait_condition= SELECT COUNT(*) = 6 FROM t2
---source include/wait_condition.inc
-
-SELECT * FROM t2 ORDER by a;
-
---connection con_temp1
-SELECT * FROM t1;
-UNLOCK TABLES;
-
---connection server_2
---let $wait_condition= SELECT COUNT(*) = 2 FROM t1
---source include/wait_condition.inc
-
-SELECT * FROM t1 ORDER BY a;
-
-
---echo *** Test two transactions in different domains committed in opposite order on slave but in a single group commit. ***
---connection server_2
---source include/stop_slave.inc
-
---connection server_1
-# Use a stored function to inject a debug_sync into the appropriate THD.
-# The function does nothing on the master, and on the slave it injects the
-# desired debug_sync action(s).
-SET sql_log_bin=0;
---delimiter ||
-CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
- RETURNS INT DETERMINISTIC
- BEGIN
- RETURN x;
- END
-||
---delimiter ;
-SET sql_log_bin=1;
-
-SET @old_format= @@SESSION.binlog_format;
-SET binlog_format='statement';
-SET gtid_domain_id=1;
-INSERT INTO t2 VALUES (foo(10,
- 'commit_before_enqueue SIGNAL ready1 WAIT_FOR cont1',
- 'commit_after_release_LOCK_prepare_ordered SIGNAL ready2'));
-
---connection server_2
-FLUSH LOGS;
---source include/wait_for_binlog_checkpoint.inc
-SET sql_log_bin=0;
---delimiter ||
-CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
- RETURNS INT DETERMINISTIC
- BEGIN
- IF d1 != '' THEN
- SET debug_sync = d1;
- END IF;
- IF d2 != '' THEN
- SET debug_sync = d2;
- END IF;
- RETURN x;
- END
-||
---delimiter ;
-SET sql_log_bin=1;
-SET @old_format=@@GLOBAL.binlog_format;
-SET GLOBAL binlog_format=statement;
-# We need to restart all parallel threads for the new global setting to
-# be copied to the session-level values.
-SET GLOBAL slave_parallel_threads=0;
-SET GLOBAL slave_parallel_threads=10;
---source include/start_slave.inc
-
-# First make sure the first insert is ready to commit, but not queued yet.
-SET debug_sync='now WAIT_FOR ready1';
-
---connection server_1
-SET gtid_domain_id=2;
-INSERT INTO t2 VALUES (foo(11,
- 'commit_before_enqueue SIGNAL ready3 WAIT_FOR cont3',
- 'commit_after_release_LOCK_prepare_ordered SIGNAL ready4 WAIT_FOR cont4'));
-SET gtid_domain_id=0;
-SELECT * FROM t2 WHERE a >= 10 ORDER BY a;
-
---connection server_2
-# Now wait for the second insert to queue itself as the leader, and then
-# wait for more commits to queue up.
-SET debug_sync='now WAIT_FOR ready3';
-SET debug_sync='now SIGNAL cont3';
-SET debug_sync='now WAIT_FOR ready4';
-# Now allow the first insert to queue up to participate in group commit.
-SET debug_sync='now SIGNAL cont1';
-SET debug_sync='now WAIT_FOR ready2';
-# Finally allow the second insert to proceed and do the group commit.
-SET debug_sync='now SIGNAL cont4';
-
---let $wait_condition= SELECT COUNT(*) = 2 FROM t2 WHERE a >= 10
---source include/wait_condition.inc
-SELECT * FROM t2 WHERE a >= 10 ORDER BY a;
-# The two INSERT transactions should have been committed in opposite order,
-# but in the same group commit (seen by precense of cid=# in the SHOW
-# BINLOG output).
---let $binlog_file= slave-bin.000002
---source include/show_binlog_events.inc
-FLUSH LOGS;
---source include/wait_for_binlog_checkpoint.inc
-
-# Restart all the slave parallel worker threads, to clear all debug_sync actions.
---connection server_2
---source include/stop_slave.inc
-SET GLOBAL slave_parallel_threads=0;
-SET GLOBAL slave_parallel_threads=10;
-SET debug_sync='RESET';
---source include/start_slave.inc
-
-
---echo *** Test that group-committed transactions on the master can replicate in parallel on the slave. ***
---connection server_1
-SET debug_sync='RESET';
-FLUSH LOGS;
---source include/wait_for_binlog_checkpoint.inc
-CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
-# Create some sentinel rows so that the rows inserted in parallel fall into
-# separate gaps and do not cause gap lock conflicts.
-INSERT INTO t3 VALUES (1,1), (3,3), (5,5), (7,7);
---save_master_pos
---connection server_2
---sync_with_master
-
-# We want to test that the transactions can execute out-of-order on
-# the slave, but still end up committing in-order, and in a single
-# group commit.
-#
-# The idea is to group-commit three transactions together on the master:
-# A, B, and C. On the slave, C will execute the insert first, then A,
-# and then B. But B manages to complete before A has time to commit, so
-# all three end up committing together.
-#
-# So we start by setting up some row locks that will block transactions
-# A and B from executing, allowing C to run first.
-
---connection con_temp1
-BEGIN;
-INSERT INTO t3 VALUES (2,102);
---connect (con_temp2,127.0.0.1,root,,test,$SERVER_MYPORT_2,)
-BEGIN;
-INSERT INTO t3 VALUES (4,104);
-
-# On the master, queue three INSERT transactions as a single group commit.
---connect (con_temp3,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
-SET binlog_format=statement;
-send INSERT INTO t3 VALUES (2, foo(12,
- 'commit_after_release_LOCK_prepare_ordered SIGNAL slave_queued1 WAIT_FOR slave_cont1',
- ''));
-
---connection server_1
-SET debug_sync='now WAIT_FOR master_queued1';
-
---connect (con_temp4,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
-SET binlog_format=statement;
-send INSERT INTO t3 VALUES (4, foo(14,
- 'commit_after_release_LOCK_prepare_ordered SIGNAL slave_queued2',
- ''));
-
---connection server_1
-SET debug_sync='now WAIT_FOR master_queued2';
-
---connect (con_temp5,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued3';
-SET binlog_format=statement;
-send INSERT INTO t3 VALUES (6, foo(16,
- 'group_commit_waiting_for_prior SIGNAL slave_queued3',
- ''));
-
---connection server_1
-SET debug_sync='now WAIT_FOR master_queued3';
-SET debug_sync='now SIGNAL master_cont1';
-
---connection con_temp3
-REAP;
---connection con_temp4
-REAP;
---connection con_temp5
-REAP;
-SET debug_sync='RESET';
-
---connection server_1
-SELECT * FROM t3 ORDER BY a;
---let $binlog_file= master-bin.000002
---source include/show_binlog_events.inc
-
-# First, wait until insert 3 is ready to queue up for group commit, but is
-# waiting for insert 2 to commit before it can do so itself.
---connection server_2
-SET debug_sync='now WAIT_FOR slave_queued3';
-
-# Next, let insert 1 proceed, and allow it to queue up as the group commit
-# leader, but let it wait for insert 2 to also queue up before proceeding.
---connection con_temp1
-ROLLBACK;
---connection server_2
-SET debug_sync='now WAIT_FOR slave_queued1';
-
-# Now let insert 2 proceed and queue up.
---connection con_temp2
-ROLLBACK;
---connection server_2
-SET debug_sync='now WAIT_FOR slave_queued2';
-# And finally, we can let insert 1 proceed and do the group commit with all
-# three insert transactions together.
-SET debug_sync='now SIGNAL slave_cont1';
-
-# Wait for the commit to complete and check that all three transactions
-# group-committed together (will be seen in the binlog as all three having
-# cid=# on their GTID event).
---let $wait_condition= SELECT COUNT(*) = 3 FROM t3 WHERE a IN (2,4,6)
---source include/wait_condition.inc
-SELECT * FROM t3 ORDER BY a;
---let $binlog_file= slave-bin.000003
---source include/show_binlog_events.inc
-
-
---echo *** Test STOP SLAVE in parallel mode ***
---connection server_2
---source include/stop_slave.inc
-# Respawn all worker threads to clear any left-over debug_sync or other stuff.
-SET debug_sync='RESET';
-SET GLOBAL slave_parallel_threads=0;
-SET GLOBAL slave_parallel_threads=10;
-
---connection server_1
-# Set up a couple of transactions. The first will be blocked halfway
-# through on a lock, and while it is blocked we initiate STOP SLAVE.
-# We then test that the halfway-initiated transaction is allowed to
-# complete, but no subsequent ones.
-# We have to use statement-based mode and set
-# binlog_direct_non_transactional_updates=0; otherwise the binlog will
-# be split into two event groups, one for the MyISAM part and one for the
-# InnoDB part.
-SET binlog_direct_non_transactional_updates=0;
-SET sql_log_bin=0;
-CALL mtr.add_suppression("Statement is unsafe because it accesses a non-transactional table after accessing a transactional table within the same transaction");
-SET sql_log_bin=1;
-BEGIN;
-INSERT INTO t2 VALUES (20);
---disable_warnings
-INSERT INTO t1 VALUES (20);
---enable_warnings
-INSERT INTO t2 VALUES (21);
-INSERT INTO t3 VALUES (20, 20);
-COMMIT;
-INSERT INTO t3 VALUES(21, 21);
-INSERT INTO t3 VALUES(22, 22);
-SET binlog_format=@old_format;
---save_master_pos
-
-# Start a connection that will block the replicated transaction halfway.
---connection con_temp1
-BEGIN;
-INSERT INTO t2 VALUES (21);
-
---connection server_2
-START SLAVE;
-# Wait for the MyISAM change to be visible, after which replication will wait
-# for con_temp1 to roll back.
---let $wait_condition= SELECT COUNT(*) = 1 FROM t1 WHERE a=20
---source include/wait_condition.inc
-
---connection con_temp2
-# Initiate slave stop. It will have to wait for the current event group
-# to complete.
-# The dbug injection causes debug_sync to signal 'wait_for_done_waiting'
-# when the SQL driver thread is ready.
-SET @old_dbug= @@GLOBAL.debug_dbug;
-SET GLOBAL debug_dbug="+d,rpl_parallel_wait_for_done_trigger";
-send STOP SLAVE;
-
---connection con_temp1
-SET debug_sync='now WAIT_FOR wait_for_done_waiting';
-ROLLBACK;
-
---connection con_temp2
-reap;
-SET GLOBAL debug_dbug=@old_dbug;
-SET debug_sync='RESET';
-
---connection server_2
---source include/wait_for_slave_to_stop.inc
-# We should see the first transaction applied, but not the two others.
-SELECT * FROM t1 WHERE a >= 20 ORDER BY a;
-SELECT * FROM t2 WHERE a >= 20 ORDER BY a;
-SELECT * FROM t3 WHERE a >= 20 ORDER BY a;
-
---source include/start_slave.inc
---sync_with_master
-SELECT * FROM t1 WHERE a >= 20 ORDER BY a;
-SELECT * FROM t2 WHERE a >= 20 ORDER BY a;
-SELECT * FROM t3 WHERE a >= 20 ORDER BY a;
-
-
---connection server_2
-# Respawn all worker threads to clear any left-over debug_sync or other stuff.
---source include/stop_slave.inc
-SET GLOBAL binlog_format=@old_format;
-SET GLOBAL slave_parallel_threads=0;
-SET GLOBAL slave_parallel_threads=10;
---source include/start_slave.inc
-
-
---echo *** Test killing slave threads at various wait points ***
---echo *** 1. Test killing transaction waiting in commit for previous transaction to commit ***
-
-# Set up three transactions on the master that will be group-committed
-# together so they can be replicated in parallel on the slave.
---connection con_temp3
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
-SET binlog_format=statement;
-send INSERT INTO t3 VALUES (31, foo(31,
- 'commit_before_prepare_ordered WAIT_FOR t2_waiting',
- 'commit_after_prepare_ordered SIGNAL t1_ready WAIT_FOR t1_cont'));
-
---connection server_1
-SET debug_sync='now WAIT_FOR master_queued1';
-
---connection con_temp4
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
-SET binlog_format=statement;
-BEGIN;
-# This insert is just so we can get T2 to wait while a query is running that we
-# can see in SHOW PROCESSLIST so we can get its thread_id to kill later.
-INSERT INTO t3 VALUES (32, foo(32,
- 'ha_write_row_end SIGNAL t2_query WAIT_FOR t2_cont',
- ''));
-# This insert sets up debug_sync points so that T2 will tell when it is at its
-# wait point where we want to kill it - and when it has been killed.
-INSERT INTO t3 VALUES (33, foo(33,
- 'group_commit_waiting_for_prior SIGNAL t2_waiting',
- 'group_commit_waiting_for_prior_killed SIGNAL t2_killed'));
-send COMMIT;
-
---connection server_1
-SET debug_sync='now WAIT_FOR master_queued2';
-
---connection con_temp5
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued3';
-SET binlog_format=statement;
-send INSERT INTO t3 VALUES (34, foo(34,
- '',
- ''));
-
---connection server_1
-SET debug_sync='now WAIT_FOR master_queued3';
-SET debug_sync='now SIGNAL master_cont1';
-
---connection con_temp3
-REAP;
---connection con_temp4
-REAP;
---connection con_temp5
-REAP;
-
---connection server_1
-SELECT * FROM t3 WHERE a >= 30 ORDER BY a;
-SET debug_sync='RESET';
-
---connection server_2
-SET sql_log_bin=0;
-CALL mtr.add_suppression("Query execution was interrupted");
-CALL mtr.add_suppression("Commit failed due to failure of an earlier commit on which this one depends");
-CALL mtr.add_suppression("Slave: Connection was killed");
-SET sql_log_bin=1;
-# Wait until T2 is inside executing its insert of 32, then find it in SHOW
-# PROCESSLIST to know its thread id for KILL later.
-SET debug_sync='now WAIT_FOR t2_query';
---let $thd_id= `SELECT ID FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO LIKE '%foo(32%' AND INFO NOT LIKE '%LIKE%'`
-SET debug_sync='now SIGNAL t2_cont';
-
-# Wait until T2 has entered its wait for T1 to commit, and T1 has
-# progressed into its commit phase.
-SET debug_sync='now WAIT_FOR t1_ready';
-
-# Now kill the transaction T2.
---replace_result $thd_id THD_ID
-eval KILL $thd_id;
-
-# Wait until T2 has reacted on the kill.
-SET debug_sync='now WAIT_FOR t2_killed';
-
-# Now we can allow T1 to proceed.
-SET debug_sync='now SIGNAL t1_cont';
-
---let $slave_sql_errno= 1317,1927,1964
---source include/wait_for_slave_sql_error.inc
-STOP SLAVE IO_THREAD;
-SELECT * FROM t3 WHERE a >= 30 ORDER BY a;
-
-# Now we have to disable the debug_sync statements, so they do not trigger
-# when the events are retried.
-SET debug_sync='RESET';
-SET GLOBAL slave_parallel_threads=0;
-SET GLOBAL slave_parallel_threads=10;
-SET sql_log_bin=0;
-DROP FUNCTION foo;
---delimiter ||
-CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
- RETURNS INT DETERMINISTIC
- BEGIN
- RETURN x;
- END
-||
---delimiter ;
-SET sql_log_bin=1;
-
---connection server_1
-INSERT INTO t3 VALUES (39,0);
---save_master_pos
-
---connection server_2
---source include/start_slave.inc
---sync_with_master
-SELECT * FROM t3 WHERE a >= 30 ORDER BY a;
-# Restore the foo() function.
-SET sql_log_bin=0;
-DROP FUNCTION foo;
---delimiter ||
-CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
- RETURNS INT DETERMINISTIC
- BEGIN
- IF d1 != '' THEN
- SET debug_sync = d1;
- END IF;
- IF d2 != '' THEN
- SET debug_sync = d2;
- END IF;
- RETURN x;
- END
-||
---delimiter ;
-SET sql_log_bin=1;
-
-
---connection server_2
-# Respawn all worker threads to clear any left-over debug_sync or other stuff.
---source include/stop_slave.inc
-SET GLOBAL binlog_format=@old_format;
-SET GLOBAL slave_parallel_threads=0;
-SET GLOBAL slave_parallel_threads=10;
---source include/start_slave.inc
-
-
---echo *** 2. Same as (1), but without restarting IO thread after kill of SQL threads ***
-
-# Set up three transactions on the master that will be group-committed
-# together so they can be replicated in parallel on the slave.
---connection con_temp3
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
-SET binlog_format=statement;
-send INSERT INTO t3 VALUES (41, foo(41,
- 'commit_before_prepare_ordered WAIT_FOR t2_waiting',
- 'commit_after_prepare_ordered SIGNAL t1_ready WAIT_FOR t1_cont'));
-
---connection server_1
-SET debug_sync='now WAIT_FOR master_queued1';
-
---connection con_temp4
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
-SET binlog_format=statement;
-BEGIN;
-# This insert is just so we can get T2 to wait while a query is running that we
-# can see in SHOW PROCESSLIST so we can get its thread_id to kill later.
-INSERT INTO t3 VALUES (42, foo(42,
- 'ha_write_row_end SIGNAL t2_query WAIT_FOR t2_cont',
- ''));
-# This insert sets up debug_sync points so that T2 will tell when it is at its
-# wait point where we want to kill it - and when it has been killed.
-INSERT INTO t3 VALUES (43, foo(43,
- 'group_commit_waiting_for_prior SIGNAL t2_waiting',
- 'group_commit_waiting_for_prior_killed SIGNAL t2_killed'));
-send COMMIT;
-
---connection server_1
-SET debug_sync='now WAIT_FOR master_queued2';
-
---connection con_temp5
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued3';
-SET binlog_format=statement;
-send INSERT INTO t3 VALUES (44, foo(44,
- '',
- ''));
-
---connection server_1
-SET debug_sync='now WAIT_FOR master_queued3';
-SET debug_sync='now SIGNAL master_cont1';
-
---connection con_temp3
-REAP;
---connection con_temp4
-REAP;
---connection con_temp5
-REAP;
-
---connection server_1
-SELECT * FROM t3 WHERE a >= 40 ORDER BY a;
-SET debug_sync='RESET';
-
---connection server_2
-# Wait until T2 is inside executing its insert of 42, then find it in SHOW
-# PROCESSLIST to know its thread id for KILL later.
-SET debug_sync='now WAIT_FOR t2_query';
---let $thd_id= `SELECT ID FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO LIKE '%foo(42%' AND INFO NOT LIKE '%LIKE%'`
-SET debug_sync='now SIGNAL t2_cont';
-
-# Wait until T2 has entered its wait for T1 to commit, and T1 has
-# progressed into its commit phase.
-SET debug_sync='now WAIT_FOR t1_ready';
-
-# Now kill the transaction T2.
---replace_result $thd_id THD_ID
-eval KILL $thd_id;
-
-# Wait until T2 has reacted on the kill.
-SET debug_sync='now WAIT_FOR t2_killed';
-
-# Now we can allow T1 to proceed.
-SET debug_sync='now SIGNAL t1_cont';
-
---let $slave_sql_errno= 1317,1927,1964
---source include/wait_for_slave_sql_error.inc
-
-# Now we have to disable the debug_sync statements, so they do not trigger
-# when the events are retried.
-SET debug_sync='RESET';
-SET GLOBAL slave_parallel_threads=0;
-SET GLOBAL slave_parallel_threads=10;
-SET sql_log_bin=0;
-DROP FUNCTION foo;
---delimiter ||
-CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
- RETURNS INT DETERMINISTIC
- BEGIN
- RETURN x;
- END
-||
---delimiter ;
-SET sql_log_bin=1;
-
---connection server_1
-INSERT INTO t3 VALUES (49,0);
---save_master_pos
-
---connection server_2
-START SLAVE SQL_THREAD;
---sync_with_master
-SELECT * FROM t3 WHERE a >= 40 ORDER BY a;
-# Restore the foo() function.
-SET sql_log_bin=0;
-DROP FUNCTION foo;
---delimiter ||
-CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
- RETURNS INT DETERMINISTIC
- BEGIN
- IF d1 != '' THEN
- SET debug_sync = d1;
- END IF;
- IF d2 != '' THEN
- SET debug_sync = d2;
- END IF;
- RETURN x;
- END
-||
---delimiter ;
-SET sql_log_bin=1;
-
-
---connection server_2
-# Respawn all worker threads to clear any left-over debug_sync or other stuff.
---source include/stop_slave.inc
-SET GLOBAL binlog_format=@old_format;
-SET GLOBAL slave_parallel_threads=0;
-SET GLOBAL slave_parallel_threads=10;
---source include/start_slave.inc
-
-
---echo *** 3. Same as (2), but not using gtid mode ***
-
---connection server_2
---source include/stop_slave.inc
-CHANGE MASTER TO master_use_gtid=no;
---source include/start_slave.inc
-
---connection server_1
-# Set up three transactions on the master that will be group-committed
-# together so they can be replicated in parallel on the slave.
---connection con_temp3
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
-SET binlog_format=statement;
-send INSERT INTO t3 VALUES (51, foo(51,
- 'commit_before_prepare_ordered WAIT_FOR t2_waiting',
- 'commit_after_prepare_ordered SIGNAL t1_ready WAIT_FOR t1_cont'));
-
---connection server_1
-SET debug_sync='now WAIT_FOR master_queued1';
-
---connection con_temp4
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
-SET binlog_format=statement;
-BEGIN;
-# This insert is just so we can get T2 to wait while a query is running that we
-# can see in SHOW PROCESSLIST so we can get its thread_id to kill later.
-INSERT INTO t3 VALUES (52, foo(52,
- 'ha_write_row_end SIGNAL t2_query WAIT_FOR t2_cont',
- ''));
-# This insert sets up debug_sync points so that T2 will tell when it is at its
-# wait point where we want to kill it - and when it has been killed.
-INSERT INTO t3 VALUES (53, foo(53,
- 'group_commit_waiting_for_prior SIGNAL t2_waiting',
- 'group_commit_waiting_for_prior_killed SIGNAL t2_killed'));
-send COMMIT;
-
---connection server_1
-SET debug_sync='now WAIT_FOR master_queued2';
-
---connection con_temp5
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued3';
-SET binlog_format=statement;
-send INSERT INTO t3 VALUES (54, foo(54,
- '',
- ''));
-
---connection server_1
-SET debug_sync='now WAIT_FOR master_queued3';
-SET debug_sync='now SIGNAL master_cont1';
-
---connection con_temp3
-REAP;
---connection con_temp4
-REAP;
---connection con_temp5
-REAP;
-
---connection server_1
-SELECT * FROM t3 WHERE a >= 50 ORDER BY a;
-SET debug_sync='RESET';
-
---connection server_2
-# Wait until T2 is inside executing its insert of 52, then find it in SHOW
-# PROCESSLIST to know its thread id for KILL later.
-SET debug_sync='now WAIT_FOR t2_query';
---let $thd_id= `SELECT ID FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO LIKE '%foo(52%' AND INFO NOT LIKE '%LIKE%'`
-SET debug_sync='now SIGNAL t2_cont';
-
-# Wait until T2 has entered its wait for T1 to commit, and T1 has
-# progressed into its commit phase.
-SET debug_sync='now WAIT_FOR t1_ready';
-
-# Now kill the transaction T2.
---replace_result $thd_id THD_ID
-eval KILL $thd_id;
-
-# Wait until T2 has reacted on the kill.
-SET debug_sync='now WAIT_FOR t2_killed';
-
-# Now we can allow T1 to proceed.
-SET debug_sync='now SIGNAL t1_cont';
-
---let $slave_sql_errno= 1317,1927,1964
---source include/wait_for_slave_sql_error.inc
-SELECT * FROM t3 WHERE a >= 50 ORDER BY a;
-
-# Now we have to disable the debug_sync statements, so they do not trigger
-# when the events are retried.
-SET debug_sync='RESET';
-SET GLOBAL slave_parallel_threads=0;
-SET GLOBAL slave_parallel_threads=10;
-SET sql_log_bin=0;
-DROP FUNCTION foo;
---delimiter ||
-CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
- RETURNS INT DETERMINISTIC
- BEGIN
- RETURN x;
- END
-||
---delimiter ;
-SET sql_log_bin=1;
-
---connection server_1
-INSERT INTO t3 VALUES (59,0);
---save_master_pos
-
---connection server_2
-START SLAVE SQL_THREAD;
---sync_with_master
-SELECT * FROM t3 WHERE a >= 50 ORDER BY a;
-# Restore the foo() function.
-SET sql_log_bin=0;
-DROP FUNCTION foo;
---delimiter ||
-CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
- RETURNS INT DETERMINISTIC
- BEGIN
- IF d1 != '' THEN
- SET debug_sync = d1;
- END IF;
- IF d2 != '' THEN
- SET debug_sync = d2;
- END IF;
- RETURN x;
- END
-||
---delimiter ;
-SET sql_log_bin=1;
-
-
---source include/stop_slave.inc
-CHANGE MASTER TO master_use_gtid=slave_pos;
---source include/start_slave.inc
-
---connection server_2
-# Respawn all worker threads to clear any left-over debug_sync or other stuff.
---source include/stop_slave.inc
-SET GLOBAL binlog_format=@old_format;
-SET GLOBAL slave_parallel_threads=0;
-SET GLOBAL slave_parallel_threads=4;
---source include/start_slave.inc
-
-
---echo *** 4. Test killing thread that is waiting to start transaction until previous transaction commits ***
-
-# We set up four transactions T1, T2, T3, and T4 on the master. T2, T3, and T4
-# can run in parallel with each other (same group commit and commit id),
-# but not in parallel with T1.
-#
-# We use four worker threads, each Ti will be queued on each their own
-# worker thread. We will delay T1 commit, T3 will wait for T1 to begin
-# commit before it can start. We will kill T3 during this wait, and
-# check that everything works correctly.
-#
-# It is rather tricky to get the correct thread id of the worker to kill.
-# We start by injecting four dummy transactions in a debug_sync-controlled
-# manner to be able to get known thread ids for the workers in a pool with
-# just 4 worker threads. Then we let in each of the real test transactions
-# T1-T4 one at a time in a way which allows us to know which transaction
-# ends up with which thread id.
-
---connection server_1
-SET binlog_format=statement;
-SET gtid_domain_id=2;
-BEGIN;
-# This debug_sync will linger on and be used to control T4 later.
-INSERT INTO t3 VALUES (70, foo(70,
- 'rpl_parallel_start_waiting_for_prior SIGNAL t4_waiting', ''));
-INSERT INTO t3 VALUES (60, foo(60,
- 'ha_write_row_end SIGNAL d2_query WAIT_FOR d2_cont2',
- 'rpl_parallel_end_of_group SIGNAL d2_done WAIT_FOR d2_cont'));
-COMMIT;
-SET gtid_domain_id=0;
-
---connection server_2
-SET debug_sync='now WAIT_FOR d2_query';
---let $d2_thd_id= `SELECT ID FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO LIKE '%foo(60%' AND INFO NOT LIKE '%LIKE%'`
-
---connection server_1
-SET gtid_domain_id=1;
-BEGIN;
-# These debug_sync's will linger on and be used to control T3 later.
-INSERT INTO t3 VALUES (61, foo(61,
- 'rpl_parallel_start_waiting_for_prior SIGNAL t3_waiting',
- 'rpl_parallel_start_waiting_for_prior_killed SIGNAL t3_killed'));
-INSERT INTO t3 VALUES (62, foo(62,
- 'ha_write_row_end SIGNAL d1_query WAIT_FOR d1_cont2',
- 'rpl_parallel_end_of_group SIGNAL d1_done WAIT_FOR d1_cont'));
-COMMIT;
-SET gtid_domain_id=0;
-
---connection server_2
-SET debug_sync='now WAIT_FOR d1_query';
---let $d1_thd_id= `SELECT ID FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO LIKE '%foo(62%' AND INFO NOT LIKE '%LIKE%'`
-
---connection server_1
-SET gtid_domain_id=0;
-INSERT INTO t3 VALUES (63, foo(63,
- 'ha_write_row_end SIGNAL d0_query WAIT_FOR d0_cont2',
- 'rpl_parallel_end_of_group SIGNAL d0_done WAIT_FOR d0_cont'));
-
---connection server_2
-SET debug_sync='now WAIT_FOR d0_query';
---let $d0_thd_id= `SELECT ID FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO LIKE '%foo(63%' AND INFO NOT LIKE '%LIKE%'`
-
---connection server_1
-SET gtid_domain_id=3;
-BEGIN;
-# These debug_sync's will linger on and be used to control T2 later.
-INSERT INTO t3 VALUES (68, foo(68,
- 'rpl_parallel_start_waiting_for_prior SIGNAL t2_waiting', ''));
-INSERT INTO t3 VALUES (69, foo(69,
- 'ha_write_row_end SIGNAL d3_query WAIT_FOR d3_cont2',
- 'rpl_parallel_end_of_group SIGNAL d3_done WAIT_FOR d3_cont'));
-COMMIT;
-SET gtid_domain_id=0;
-
---connection server_2
-SET debug_sync='now WAIT_FOR d3_query';
---let $d3_thd_id= `SELECT ID FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO LIKE '%foo(69%' AND INFO NOT LIKE '%LIKE%'`
-
-SET debug_sync='now SIGNAL d2_cont2';
-SET debug_sync='now WAIT_FOR d2_done';
-SET debug_sync='now SIGNAL d1_cont2';
-SET debug_sync='now WAIT_FOR d1_done';
-SET debug_sync='now SIGNAL d0_cont2';
-SET debug_sync='now WAIT_FOR d0_done';
-SET debug_sync='now SIGNAL d3_cont2';
-SET debug_sync='now WAIT_FOR d3_done';
-
-# Now prepare the real transactions T1, T2, T3, T4 on the master.
-
---connection con_temp3
-# Create transaction T1.
-SET binlog_format=statement;
-INSERT INTO t3 VALUES (64, foo(64,
- 'rpl_parallel_before_mark_start_commit SIGNAL t1_waiting WAIT_FOR t1_cont', ''));
-
-# Create transaction T2, as a group commit leader on the master.
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2 WAIT_FOR master_cont2';
-send INSERT INTO t3 VALUES (65, foo(65, '', ''));
-
---connection server_1
-SET debug_sync='now WAIT_FOR master_queued2';
-
---connection con_temp4
-# Create transaction T3, participating in T2's group commit.
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued3';
-send INSERT INTO t3 VALUES (66, foo(66, '', ''));
-
---connection server_1
-SET debug_sync='now WAIT_FOR master_queued3';
-
---connection con_temp5
-# Create transaction T4, participating in group commit with T2 and T3.
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued4';
-send INSERT INTO t3 VALUES (67, foo(67, '', ''));
-
---connection server_1
-SET debug_sync='now WAIT_FOR master_queued4';
-SET debug_sync='now SIGNAL master_cont2';
-
---connection con_temp3
-REAP;
---connection con_temp4
-REAP;
---connection con_temp5
-REAP;
-
---connection server_1
-SELECT * FROM t3 WHERE a >= 60 ORDER BY a;
-SET debug_sync='RESET';
-
---connection server_2
-# Now we have the four transactions pending for replication on the slave.
-# Let them be queued for our three worker threads in a controlled fashion.
-# We put them at a stage where T1 is delayed and T3 is waiting for T1 to
-# commit before T3 can start. Then we kill T3.
-
-# Make the worker D0 free, and wait for T1 to be queued in it.
-SET debug_sync='now SIGNAL d0_cont';
-SET debug_sync='now WAIT_FOR t1_waiting';
-
-# Make the worker D3 free, and wait for T2 to be queued in it.
-SET debug_sync='now SIGNAL d3_cont';
-SET debug_sync='now WAIT_FOR t2_waiting';
-
-# Now release worker D1, and wait for T3 to be queued in it.
-# T3 will wait for T1 to commit before it can start.
-SET debug_sync='now SIGNAL d1_cont';
-SET debug_sync='now WAIT_FOR t3_waiting';
-
-# Release worker D2. Wait for T4 to be queued, so we are sure it has
-# received the debug_sync signal (else we might overwrite it with the
-# next debug_sync).
-SET debug_sync='now SIGNAL d2_cont';
-SET debug_sync='now WAIT_FOR t4_waiting';
-
-# Now we kill the waiting transaction T3 in worker D1.
---replace_result $d1_thd_id THD_ID
-eval KILL $d1_thd_id;
-
-# Wait until T3 has reacted on the kill.
-SET debug_sync='now WAIT_FOR t3_killed';
-
-# Now we can allow T1 to proceed.
-SET debug_sync='now SIGNAL t1_cont';
-
---let $slave_sql_errno= 1317,1927,1964
---source include/wait_for_slave_sql_error.inc
-STOP SLAVE IO_THREAD;
-# Since T2, T3, and T4 run in parallel, we can not be sure if T2 will have time
-# to commit or not before the stop. However, T1 should commit, and T3/T4 may
-# not have committed. (After slave restart we check that all become committed
-# eventually).
-SELECT * FROM t3 WHERE a >= 60 AND a != 65 ORDER BY a;
-
-# Now we have to disable the debug_sync statements, so they do not trigger
-# when the events are retried.
-SET debug_sync='RESET';
-SET GLOBAL slave_parallel_threads=0;
-SET GLOBAL slave_parallel_threads=10;
-SET sql_log_bin=0;
-DROP FUNCTION foo;
---delimiter ||
-CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
- RETURNS INT DETERMINISTIC
- BEGIN
- RETURN x;
- END
-||
---delimiter ;
-SET sql_log_bin=1;
-
---connection server_1
-UPDATE t3 SET b=b+1 WHERE a=60;
---save_master_pos
-
---connection server_2
---source include/start_slave.inc
---sync_with_master
-SELECT * FROM t3 WHERE a >= 60 ORDER BY a;
-# Restore the foo() function.
-SET sql_log_bin=0;
-DROP FUNCTION foo;
---delimiter ||
-CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
- RETURNS INT DETERMINISTIC
- BEGIN
- IF d1 != '' THEN
- SET debug_sync = d1;
- END IF;
- IF d2 != '' THEN
- SET debug_sync = d2;
- END IF;
- RETURN x;
- END
-||
---delimiter ;
-SET sql_log_bin=1;
-
---connection server_2
-# Respawn all worker threads to clear any left-over debug_sync or other stuff.
---source include/stop_slave.inc
-SET GLOBAL binlog_format=@old_format;
-SET GLOBAL slave_parallel_threads=0;
-SET GLOBAL slave_parallel_threads=10;
---source include/start_slave.inc
-
-
---echo *** 5. Test killing thread that is waiting for queue of max length to shorten ***
-
-# Find the thread id of the driver SQL thread that we want to kill.
---let $wait_condition= SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE '%Slave has read all relay log%'
---source include/wait_condition.inc
---let $thd_id= `SELECT ID FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE '%Slave has read all relay log%'`
-SET @old_max_queued= @@GLOBAL.slave_parallel_max_queued;
-SET GLOBAL slave_parallel_max_queued=9000;
-
---connection server_1
---let bigstring= `SELECT REPEAT('x', 10000)`
-SET binlog_format=statement;
-# Create an event that will wait to be signalled.
-INSERT INTO t3 VALUES (80, foo(0,
- 'ha_write_row_end SIGNAL query_waiting WAIT_FOR query_cont', ''));
-
---connection server_2
-SET debug_sync='now WAIT_FOR query_waiting';
-# Inject that the SQL driver thread will signal `wait_queue_ready' to debug_sync
-# as it goes to wait for the event queue to become smaller than the value of
-# @@slave_parallel_max_queued.
-SET @old_dbug= @@GLOBAL.debug_dbug;
-SET GLOBAL debug_dbug="+d,rpl_parallel_wait_queue_max";
-
---connection server_1
---disable_query_log
-# Create an event that will fill up the queue.
-# The Xid event at the end of the event group will have to wait for the Query
-# event with the INSERT to drain so the queue becomes shorter. However that in
-# turn waits for the prior event group to continue.
-eval INSERT INTO t3 VALUES (81, LENGTH('$bigstring'));
---enable_query_log
-SELECT * FROM t3 WHERE a >= 80 ORDER BY a;
-
---connection server_2
-SET debug_sync='now WAIT_FOR wait_queue_ready';
-
---replace_result $thd_id THD_ID
-eval KILL $thd_id;
-
-SET debug_sync='now WAIT_FOR wait_queue_killed';
-SET debug_sync='now SIGNAL query_cont';
-
---let $slave_sql_errno= 1317,1927,1964
---source include/wait_for_slave_sql_error.inc
-STOP SLAVE IO_THREAD;
-
-SET GLOBAL debug_dbug=@old_dbug;
-SET GLOBAL slave_parallel_max_queued= @old_max_queued;
-
---connection server_1
-INSERT INTO t3 VALUES (82,0);
-SET binlog_format=@old_format;
---save_master_pos
-
---connection server_2
-SET debug_sync='RESET';
---source include/start_slave.inc
---sync_with_master
-SELECT * FROM t3 WHERE a >= 80 ORDER BY a;
-
-
---connection server_2
---source include/stop_slave.inc
-SET GLOBAL binlog_format=@old_format;
-SET GLOBAL slave_parallel_threads=0;
-SET GLOBAL slave_parallel_threads=10;
---source include/start_slave.inc
-
---echo *** MDEV-5788 Incorrect free of rgi->deferred_events in parallel replication ***
-
---connection server_2
-# Use just two worker threads, so we are sure to get the rpl_group_info added
-# to the free list, which is what triggered the bug.
---source include/stop_slave.inc
-SET GLOBAL replicate_ignore_table="test.t3";
-SET GLOBAL slave_parallel_threads=2;
---source include/start_slave.inc
-
---connection server_1
-INSERT INTO t3 VALUES (100, rand());
-INSERT INTO t3 VALUES (101, rand());
-
---save_master_pos
-
---connection server_2
---sync_with_master
-
---connection server_1
-INSERT INTO t3 VALUES (102, rand());
-INSERT INTO t3 VALUES (103, rand());
-INSERT INTO t3 VALUES (104, rand());
-INSERT INTO t3 VALUES (105, rand());
-
---save_master_pos
-
---connection server_2
---sync_with_master
---source include/stop_slave.inc
-SET GLOBAL replicate_ignore_table="";
---source include/start_slave.inc
-
---connection server_1
-INSERT INTO t3 VALUES (106, rand());
-INSERT INTO t3 VALUES (107, rand());
---save_master_pos
-
---connection server_2
---sync_with_master
---replace_column 2 #
-SELECT * FROM t3 WHERE a >= 100 ORDER BY a;
-
-
---echo *** MDEV-5921: In parallel replication, an error is not correctly signalled to the next transaction ***
-
---connection server_2
---source include/stop_slave.inc
-SET GLOBAL slave_parallel_threads=10;
---source include/start_slave.inc
-
---connection server_1
-INSERT INTO t3 VALUES (110, 1);
---save_master_pos
-
---connection server_2
---sync_with_master
-SELECT * FROM t3 WHERE a >= 110 ORDER BY a;
-# Inject a duplicate key error.
-SET sql_log_bin=0;
-INSERT INTO t3 VALUES (111, 666);
-SET sql_log_bin=1;
-
---connection server_1
-
-# Create a group commit with two inserts, the first one conflicts with a row on the slave
---connect (con1,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
-send INSERT INTO t3 VALUES (111, 2);
---connection server_1
-SET debug_sync='now WAIT_FOR master_queued1';
-
---connect (con2,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
-send INSERT INTO t3 VALUES (112, 3);
-
---connection server_1
-SET debug_sync='now WAIT_FOR master_queued2';
-SET debug_sync='now SIGNAL master_cont1';
-
---connection con1
-REAP;
---connection con2
-REAP;
-SET debug_sync='RESET';
---save_master_pos
-
---connection server_2
---let $slave_sql_errno= 1062
---source include/wait_for_slave_sql_error.inc
---source include/wait_for_slave_sql_to_stop.inc
-# We should not see the row (112,3) here, it should be rolled back due to
-# error signal from the prior transaction.
-SELECT * FROM t3 WHERE a >= 110 ORDER BY a;
-SET sql_log_bin=0;
-DELETE FROM t3 WHERE a=111 AND b=666;
-SET sql_log_bin=1;
-START SLAVE SQL_THREAD;
---sync_with_master
-SELECT * FROM t3 WHERE a >= 110 ORDER BY a;
-
-
---echo ***MDEV-5914: Parallel replication deadlock due to InnoDB lock conflicts ***
---connection server_2
---source include/stop_slave.inc
-
---connection server_1
-CREATE TABLE t4 (a INT PRIMARY KEY, b INT, KEY b_idx(b)) ENGINE=InnoDB;
-INSERT INTO t4 VALUES (1,NULL), (2,2), (3,NULL), (4,4), (5, NULL), (6, 6);
-
-# Create a group commit with UPDATE and DELETE, in that order.
-# The bug was that while the UPDATE's row lock does not block the DELETE, the
-# DELETE's gap lock _does_ block the UPDATE. This could cause a deadlock
-# on the slave.
---connection con1
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
-send UPDATE t4 SET b=NULL WHERE a=6;
---connection server_1
-SET debug_sync='now WAIT_FOR master_queued1';
-
---connection con2
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
-send DELETE FROM t4 WHERE b <= 3;
-
---connection server_1
-SET debug_sync='now WAIT_FOR master_queued2';
-SET debug_sync='now SIGNAL master_cont1';
-
---connection con1
-REAP;
---connection con2
-REAP;
-SET debug_sync='RESET';
---save_master_pos
-
---connection server_2
---source include/start_slave.inc
---sync_with_master
---source include/stop_slave.inc
-
-SELECT * FROM t4 ORDER BY a;
-
-
-# Another example, this one with INSERT vs. DELETE
---connection server_1
-DELETE FROM t4;
-INSERT INTO t4 VALUES (1,NULL), (2,2), (3,NULL), (4,4), (5, NULL), (6, 6);
-
-# Create a group commit with INSERT and DELETE, in that order.
-# The bug was that while the INSERT's insert intention lock does not block
-# the DELETE, the DELETE's gap lock _does_ block the INSERT. This could cause
-# a deadlock on the slave.
---connection con1
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
-send INSERT INTO t4 VALUES (7, NULL);
---connection server_1
-SET debug_sync='now WAIT_FOR master_queued1';
-
---connection con2
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
-send DELETE FROM t4 WHERE b <= 3;
-
---connection server_1
-SET debug_sync='now WAIT_FOR master_queued2';
-SET debug_sync='now SIGNAL master_cont1';
-
---connection con1
-REAP;
---connection con2
-REAP;
-SET debug_sync='RESET';
---save_master_pos
-
---connection server_2
---source include/start_slave.inc
---sync_with_master
---source include/stop_slave.inc
-
-SELECT * FROM t4 ORDER BY a;
-
-
-# MDEV-6549, failing to update gtid_slave_pos for a transaction that was retried.
-# The problem was that when a transaction updates the mysql.gtid_slave_pos
-# table, it clears the flag that marks that there is a GTID position that
-# needs to be updated. Then, if the transaction got killed after that due
-# to a deadlock, the subsequent retry would fail to notice that the GTID needs
-# to be recorded in gtid_slave_pos.
-#
-# (In the original bug report, the symptom was an assertion; this was however
-# just a side effect of the missing update of gtid_slave_pos, which also
-# happened to cause a missing clear of OPTION_GTID_BEGIN).
---connection server_1
-DELETE FROM t4;
-INSERT INTO t4 VALUES (1,NULL), (2,2), (3,NULL), (4,4), (5, NULL), (6, 6);
-
-# Create two transactions that can run in parallel on the slave but cause
-# a deadlock if the second runs before the first.
---connection con1
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
-send UPDATE t4 SET b=NULL WHERE a=6;
---connection server_1
-SET debug_sync='now WAIT_FOR master_queued1';
-
---connection con2
-# Must use statement-based binlogging. Otherwise the transaction will not be
-# binlogged at all, as it modifies no rows.
-SET @old_format= @@SESSION.binlog_format;
-SET binlog_format='statement';
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
-send DELETE FROM t4 WHERE b <= 1;
-
---connection server_1
-SET debug_sync='now WAIT_FOR master_queued2';
-SET debug_sync='now SIGNAL master_cont1';
-
---connection con1
-REAP;
---connection con2
-REAP;
-SET @old_format=@@GLOBAL.binlog_format;
-SET debug_sync='RESET';
---save_master_pos
---let $last_gtid= `SELECT @@last_gtid`
-
---connection server_2
-# Disable the usual skip of gap locks for transactions that are run in
-# parallel, using DBUG. This allows the deadlock to occur, and this in turn
-# triggers a retry of the second transaction, and the code that was buggy and
-# caused the gtid_slave_pos update to be skipped in the retry.
-SET @old_dbug= @@GLOBAL.debug_dbug;
-SET GLOBAL debug_dbug="+d,disable_thd_need_ordering_with";
---source include/start_slave.inc
---sync_with_master
-SET GLOBAL debug_dbug=@old_dbug;
-
-SELECT * FROM t4 ORDER BY a;
-# Check that the GTID of the second transaction was correctly recorded in
-# gtid_slave_pos, in the variable as well as in the table.
---replace_result $last_gtid GTID
-eval SET @last_gtid= '$last_gtid';
-SELECT IF(@@gtid_slave_pos LIKE CONCAT('%',@last_gtid,'%'), "GTID found ok",
- CONCAT("GTID ", @last_gtid, " not found in gtid_slave_pos=", @@gtid_slave_pos))
- AS result;
-SELECT "ROW FOUND" AS `Is the row found?`
- FROM mysql.gtid_slave_pos
- WHERE CONCAT(domain_id, "-", server_id, "-", seq_no) = @last_gtid;
-
-
---echo *** MDEV-5938: Exec_master_log_pos not updated at log rotate in parallel replication ***
---connection server_2
---source include/stop_slave.inc
-SET GLOBAL slave_parallel_threads=1;
-SET DEBUG_SYNC= 'RESET';
---source include/start_slave.inc
-
---connection server_1
-CREATE TABLE t5 (a INT PRIMARY KEY, b INT);
-INSERT INTO t5 VALUES (1,1);
-INSERT INTO t5 VALUES (2,2), (3,8);
-INSERT INTO t5 VALUES (4,16);
---save_master_pos
-
---connection server_2
---sync_with_master
-let $io_file= query_get_value(SHOW SLAVE STATUS, Master_Log_File, 1);
-let $io_pos= query_get_value(SHOW SLAVE STATUS, Read_Master_Log_Pos, 1);
-let $sql_file= query_get_value(SHOW SLAVE STATUS, Relay_Master_Log_File, 1);
-let $sql_pos= query_get_value(SHOW SLAVE STATUS, Exec_Master_Log_Pos, 1);
---disable_query_log
-eval SELECT IF('$io_file' = '$sql_file', "OK", "Not ok, $io_file <> $sql_file") AS test_check;
-eval SELECT IF('$io_pos' = '$sql_pos', "OK", "Not ok, $io_pos <> $sql_pos") AS test_check;
---enable_query_log
-
---connection server_1
-FLUSH LOGS;
---source include/wait_for_binlog_checkpoint.inc
---save_master_pos
-
---connection server_2
---sync_with_master
-let $io_file= query_get_value(SHOW SLAVE STATUS, Master_Log_File, 1);
-let $io_pos= query_get_value(SHOW SLAVE STATUS, Read_Master_Log_Pos, 1);
-let $sql_file= query_get_value(SHOW SLAVE STATUS, Relay_Master_Log_File, 1);
-let $sql_pos= query_get_value(SHOW SLAVE STATUS, Exec_Master_Log_Pos, 1);
---disable_query_log
-eval SELECT IF('$io_file' = '$sql_file', "OK", "Not ok, $io_file <> $sql_file") AS test_check;
-eval SELECT IF('$io_pos' = '$sql_pos', "OK", "Not ok, $io_pos <> $sql_pos") AS test_check;
---enable_query_log
-
-
---echo *** MDEV_6435: Incorrect error handling when query binlogged partially on master with "killed" error ***
-
---connection server_1
-CREATE TABLE t6 (a INT) ENGINE=MyISAM;
-CREATE TRIGGER tr AFTER INSERT ON t6 FOR EACH ROW SET @a = 1;
-
---connection con1
-SET @old_format= @@binlog_format;
-SET binlog_format= statement;
---let $conid = `SELECT CONNECTION_ID()`
-SET debug_sync='sp_head_execute_before_loop SIGNAL ready WAIT_FOR cont';
-send INSERT INTO t6 VALUES (1), (2), (3);
-
---connection server_1
-SET debug_sync='now WAIT_FOR ready';
---replace_result $conid CONID
-eval KILL QUERY $conid;
-SET debug_sync='now SIGNAL cont';
-
---connection con1
---error ER_QUERY_INTERRUPTED
---reap
-SET binlog_format= @old_format;
-SET debug_sync='RESET';
---let $after_error_gtid_pos= `SELECT @@gtid_binlog_pos`
-
---connection server_1
-SET debug_sync='RESET';
-
-
---connection server_2
---let $slave_sql_errno= 1317
---source include/wait_for_slave_sql_error.inc
-STOP SLAVE IO_THREAD;
---replace_result $after_error_gtid_pos AFTER_ERROR_GTID_POS
-eval SET GLOBAL gtid_slave_pos= '$after_error_gtid_pos';
---source include/start_slave.inc
-
---connection server_1
-INSERT INTO t6 VALUES (4);
-SELECT * FROM t6 ORDER BY a;
---save_master_pos
-
---connection server_2
---sync_with_master
-SELECT * FROM t6 ORDER BY a;
-
-
---echo *** MDEV-6551: Some replication errors are ignored if slave_parallel_threads > 0 ***
-
---connection server_1
-INSERT INTO t2 VALUES (31);
---let $gtid1= `SELECT @@LAST_GTID`
---source include/save_master_gtid.inc
-
---connection server_2
---source include/sync_with_master_gtid.inc
---source include/stop_slave.inc
-SET GLOBAL slave_parallel_threads= 0;
---source include/start_slave.inc
-
-# Force a duplicate key error on the slave.
-SET sql_log_bin= 0;
-INSERT INTO t2 VALUES (32);
-SET sql_log_bin= 1;
-
---connection server_1
-INSERT INTO t2 VALUES (32);
---let $gtid2= `SELECT @@LAST_GTID`
-# Rotate the binlog; the bug is triggered when the master binlog file changes
-# after the event group that causes the duplicate key error.
-FLUSH LOGS;
-INSERT INTO t2 VALUES (33);
-INSERT INTO t2 VALUES (34);
-SELECT * FROM t2 WHERE a >= 30 ORDER BY a;
---source include/save_master_gtid.inc
-
---connection server_2
---let $slave_sql_errno= 1062
---source include/wait_for_slave_sql_error.inc
-
---connection server_2
---source include/stop_slave_io.inc
-SET GLOBAL slave_parallel_threads=10;
-START SLAVE;
-
---let $slave_sql_errno= 1062
---source include/wait_for_slave_sql_error.inc
-
-# Note: IO thread is still running at this point.
-# The bug seems to have been that restarting the SQL thread after an error with
-# the IO thread still running, somehow picks up a later relay log position and
-# thus ends up skipping the failing event, rather than re-executing.
-
-START SLAVE SQL_THREAD;
---let $slave_sql_errno= 1062
---source include/wait_for_slave_sql_error.inc
-
-SELECT * FROM t2 WHERE a >= 30 ORDER BY a;
-
-# Skip the duplicate error, so we can proceed.
---error ER_SLAVE_SKIP_NOT_IN_GTID
-SET sql_slave_skip_counter= 1;
---source include/stop_slave_io.inc
---disable_query_log
-eval SET GLOBAL gtid_slave_pos = REPLACE(@@gtid_slave_pos, "$gtid1", "$gtid2");
---enable_query_log
---source include/start_slave.inc
---source include/sync_with_master_gtid.inc
-
-SELECT * FROM t2 WHERE a >= 30 ORDER BY a;
-
-
---echo *** MDEV-6775: Wrong binlog order in parallel replication ***
---connection server_1
-# A bit tricky bug to reproduce. On the master, we binlog in statement-mode
-# two transactions, an UPDATE followed by a DELETE. On the slave, we replicate
-# with binlog-mode set to ROW, which means the DELETE, which modifies no rows,
-# is not binlogged. Then we inject a wait in the group commit code on the
-# slave, shortly before the actual commit of the UPDATE. The bug was that the
-# DELETE could wake up from wait_for_prior_commit() before the commit of the
-# UPDATE. So the test could see the slave position updated to after DELETE,
-# while the UPDATE was still not visible.
-DELETE FROM t4;
-INSERT INTO t4 VALUES (1,NULL), (3,NULL), (4,4), (5, NULL), (6, 6);
---source include/save_master_gtid.inc
-
---connection server_2
---source include/sync_with_master_gtid.inc
---source include/stop_slave.inc
-SET @old_dbug= @@GLOBAL.debug_dbug;
-SET GLOBAL debug_dbug="+d,inject_binlog_commit_before_get_LOCK_log";
-SET @old_format=@@GLOBAL.binlog_format;
-SET GLOBAL binlog_format=ROW;
-# Re-spawn the worker threads to be sure they pick up the new binlog format
-SET GLOBAL slave_parallel_threads=0;
-SET GLOBAL slave_parallel_threads=10;
-
---connection con1
-SET @old_format= @@binlog_format;
-SET binlog_format= statement;
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
-send UPDATE t4 SET b=NULL WHERE a=6;
---connection server_1
-SET debug_sync='now WAIT_FOR master_queued1';
-
---connection con2
-SET @old_format= @@binlog_format;
-SET binlog_format= statement;
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
-send DELETE FROM t4 WHERE b <= 3;
-
---connection server_1
-SET debug_sync='now WAIT_FOR master_queued2';
-SET debug_sync='now SIGNAL master_cont1';
-
---connection con1
-REAP;
-SET binlog_format= @old_format;
---connection con2
-REAP;
-SET binlog_format= @old_format;
-SET debug_sync='RESET';
---save_master_pos
-SELECT * FROM t4 ORDER BY a;
-
---connection server_2
---source include/start_slave.inc
-SET debug_sync= 'now WAIT_FOR waiting';
---sync_with_master
-SELECT * FROM t4 ORDER BY a;
-SET debug_sync= 'now SIGNAL cont';
-
-# Re-spawn the worker threads to remove any DBUG injections or DEBUG_SYNC.
---source include/stop_slave.inc
-SET GLOBAL debug_dbug=@old_dbug;
-SET GLOBAL binlog_format= @old_format;
-SET GLOBAL slave_parallel_threads=0;
-SET GLOBAL slave_parallel_threads=10;
---source include/start_slave.inc
-
-
---echo *** MDEV-7237: Parallel replication: incorrect relaylog position after stop/start the slave ***
---connection server_1
-INSERT INTO t2 VALUES (40);
---save_master_pos
-
---connection server_2
---sync_with_master
---source include/stop_slave.inc
-CHANGE MASTER TO master_use_gtid=no;
-SET @old_dbug= @@GLOBAL.debug_dbug;
-# This DBUG injection causes a DEBUG_SYNC signal "scheduled_gtid_0_x_100" when
-# GTID 0-1-100 has been scheduled for and fetched by a worker thread.
-SET GLOBAL debug_dbug="+d,rpl_parallel_scheduled_gtid_0_x_100";
-# This DBUG injection causes a DEBUG_SYNC signal "wait_for_done_waiting" when
-# STOP SLAVE has signalled all worker threads to stop.
-SET GLOBAL debug_dbug="+d,rpl_parallel_wait_for_done_trigger";
-# Reset worker threads to make DBUG setting catch on.
-SET GLOBAL slave_parallel_threads=0;
-SET GLOBAL slave_parallel_threads=10;
-
-
---connection server_1
-# Setup some transaction for the slave to replicate.
-INSERT INTO t2 VALUES (41);
-INSERT INTO t2 VALUES (42);
-# Need to log the DELETE in statement format, so we can see it in processlist.
-SET @old_format= @@binlog_format;
-SET binlog_format= statement;
-DELETE FROM t2 WHERE a=40;
-SET binlog_format= @old_format;
-INSERT INTO t2 VALUES (43);
-INSERT INTO t2 VALUES (44);
-# Force the slave to switch to a new relay log file.
-FLUSH LOGS;
-INSERT INTO t2 VALUES (45);
-# Inject a GTID 0-1-100, which will trigger a DEBUG_SYNC signal when this
-# transaction has been fetched by a worker thread.
-SET gtid_seq_no=100;
-INSERT INTO t2 VALUES (46);
---save_master_pos
-
---connection con_temp2
-# Temporarily block the DELETE on a=40 from completing.
-BEGIN;
-SELECT * FROM t2 WHERE a=40 FOR UPDATE;
-
-
---connection server_2
---source include/start_slave.inc
-
-# Wait for a worker thread to start on the DELETE that will be blocked
-# temporarily by the SELECT FOR UPDATE.
---let $wait_condition= SELECT count(*) > 0 FROM information_schema.processlist WHERE state='updating' and info LIKE '%DELETE FROM t2 WHERE a=40%'
---source include/wait_condition.inc
-
-# The DBUG injection set above will make the worker thread signal the following
-# debug_sync when the GTID 0-1-100 has been reached by a worker thread.
-# Thus, at this point, the SQL driver thread has reached the next
-# relay log file name, while a worker thread is still processing a
-# transaction in the previous relay log file, blocked on the SELECT FOR
-# UPDATE.
-SET debug_sync= 'now WAIT_FOR scheduled_gtid_0_x_100';
-# At this point, the SQL driver thread is in the new relay log file, while
-# the DELETE from the old relay log file is not yet complete. We will stop
-# the slave at this point. The bug was that the DELETE statement would
-# update the slave position to the _new_ relay log file name instead of
-# its own old file name. Thus, by stoping and restarting the slave at this
-# point, we would get an error at restart due to incorrect position. (If
-# we would let the slave catch up before stopping, the incorrect position
-# would be corrected by a later transaction).
-
-send STOP SLAVE;
-
---connection con_temp2
-# Wait for STOP SLAVE to have proceeded sufficiently that it has signalled
-# all worker threads to stop; this ensures that we will stop after the DELETE
-# transaction (and not after a later transaction that might have been able
-# to set a fixed position).
-SET debug_sync= 'now WAIT_FOR wait_for_done_waiting';
-# Now release the row lock that was blocking the replication of DELETE.
-ROLLBACK;
-
---connection server_2
-reap;
---source include/wait_for_slave_sql_to_stop.inc
-SELECT * FROM t2 WHERE a >= 40 ORDER BY a;
-# Now restart the slave. With the bug present, this would start at an
-# incorrect relay log position, causing relay log read error (or if unlucky,
-# silently skip a number of events).
---source include/start_slave.inc
---sync_with_master
-SELECT * FROM t2 WHERE a >= 40 ORDER BY a;
---source include/stop_slave.inc
-SET GLOBAL debug_dbug=@old_dbug;
-SET DEBUG_SYNC= 'RESET';
-SET GLOBAL slave_parallel_threads=0;
-SET GLOBAL slave_parallel_threads=10;
-CHANGE MASTER TO master_use_gtid=slave_pos;
---source include/start_slave.inc
-
-
---echo *** MDEV-7326 Server deadlock in connection with parallel replication ***
-# We use three transactions, each in a separate group commit.
-# T1 does mark_start_commit(), then gets a deadlock error.
-# T2 wakes up and starts running
-# T1 does unmark_start_commit()
-# T3 goes to wait for T2 to start its commit
-# T2 does mark_start_commit()
-# The bug was that at this point, T3 got deadlocked. Because T1 has unmarked(),
-# T3 did not yet see the count_committing_event_groups reach its target value
-# yet. But when T1 later re-did mark_start_commit(), it failed to send a wakeup
-# to T3.
-
---connection server_2
---source include/stop_slave.inc
-SET GLOBAL slave_parallel_threads=0;
-SET GLOBAL slave_parallel_threads=3;
-SET GLOBAL debug_dbug="+d,rpl_parallel_simulate_temp_err_xid";
---source include/start_slave.inc
-
---connection server_1
-SET @old_format= @@SESSION.binlog_format;
-SET binlog_format= STATEMENT;
-# This debug_sync will linger on and be used to control T3 later.
-INSERT INTO t1 VALUES (foo(50,
- "rpl_parallel_start_waiting_for_prior SIGNAL t3_ready",
- "rpl_parallel_end_of_group SIGNAL prep_ready WAIT_FOR prep_cont"));
---save_master_pos
---connection server_2
-# Wait for the debug_sync point for T3 to be set. But let the preparation
-# transaction remain hanging, so that T1 and T2 will be scheduled for the
-# remaining two worker threads.
-SET DEBUG_SYNC= "now WAIT_FOR prep_ready";
-
---connection server_1
-INSERT INTO t2 VALUES (foo(50,
- "rpl_parallel_simulate_temp_err_xid SIGNAL t1_ready1 WAIT_FOR t1_cont1",
- "rpl_parallel_retry_after_unmark SIGNAL t1_ready2 WAIT_FOR t1_cont2"));
---save_master_pos
-
---connection server_2
-SET DEBUG_SYNC= "now WAIT_FOR t1_ready1";
-# T1 has now done mark_start_commit(). It will later do a rollback and retry.
-
---connection server_1
-# Use a MyISAM table for T2 and T3, so they do not trigger the
-# rpl_parallel_simulate_temp_err_xid DBUG insertion on XID event.
-INSERT INTO t1 VALUES (foo(51,
- "rpl_parallel_before_mark_start_commit SIGNAL t2_ready1 WAIT_FOR t2_cont1",
- "rpl_parallel_after_mark_start_commit SIGNAL t2_ready2"));
-
---connection server_2
-SET DEBUG_SYNC= "now WAIT_FOR t2_ready1";
-# T2 has now started running, but has not yet done mark_start_commit()
-SET DEBUG_SYNC= "now SIGNAL t1_cont1";
-SET DEBUG_SYNC= "now WAIT_FOR t1_ready2";
-# T1 has now done unmark_start_commit() in preparation for its retry.
-
---connection server_1
-INSERT INTO t1 VALUES (52);
-SET BINLOG_FORMAT= @old_format;
-SELECT * FROM t2 WHERE a>=50 ORDER BY a;
-SELECT * FROM t1 WHERE a>=50 ORDER BY a;
-
---connection server_2
-# Let the preparation transaction complete, so that the same worker thread
-# can continue with the transaction T3.
-SET DEBUG_SYNC= "now SIGNAL prep_cont";
-SET DEBUG_SYNC= "now WAIT_FOR t3_ready";
-# T3 has now gone to wait for T2 to start committing
-SET DEBUG_SYNC= "now SIGNAL t2_cont1";
-SET DEBUG_SYNC= "now WAIT_FOR t2_ready2";
-# T2 has now done mark_start_commit().
-# Let things run, and check that T3 does not get deadlocked.
-SET DEBUG_SYNC= "now SIGNAL t1_cont2";
---sync_with_master
-
---connection server_1
---save_master_pos
---connection server_2
---sync_with_master
-SELECT * FROM t2 WHERE a>=50 ORDER BY a;
-SELECT * FROM t1 WHERE a>=50 ORDER BY a;
-SET DEBUG_SYNC="reset";
-
-# Re-spawn the worker threads to remove any DBUG injections or DEBUG_SYNC.
---source include/stop_slave.inc
-SET GLOBAL debug_dbug=@old_dbug;
-SET GLOBAL slave_parallel_threads=0;
-SET GLOBAL slave_parallel_threads=10;
---source include/start_slave.inc
-
-
---echo *** MDEV-7326 Server deadlock in connection with parallel replication ***
-# Similar to the previous test, but with T2 and T3 in the same GCO.
-# We use three transactions, T1 in one group commit and T2/T3 in another.
-# T1 does mark_start_commit(), then gets a deadlock error.
-# T2 wakes up and starts running
-# T1 does unmark_start_commit()
-# T3 goes to wait for T1 to start its commit
-# T2 does mark_start_commit()
-# The bug was that at this point, T3 got deadlocked. T2 increments the
-# count_committing_event_groups but does not signal T3, as they are in
-# the same GCO. Then later when T1 increments, it would also not signal
-# T3, because now the count_committing_event_groups is not equal to the
-# wait_count of T3 (it is one larger).
-
---connection server_2
---source include/stop_slave.inc
-SET GLOBAL slave_parallel_threads=0;
-SET GLOBAL slave_parallel_threads=3;
-SET GLOBAL debug_dbug="+d,rpl_parallel_simulate_temp_err_xid";
---source include/start_slave.inc
-
---connection server_1
-SET @old_format= @@SESSION.binlog_format;
-SET binlog_format= STATEMENT;
-# This debug_sync will linger on and be used to control T3 later.
-INSERT INTO t1 VALUES (foo(60,
- "rpl_parallel_start_waiting_for_prior SIGNAL t3_ready",
- "rpl_parallel_end_of_group SIGNAL prep_ready WAIT_FOR prep_cont"));
---save_master_pos
---connection server_2
-# Wait for the debug_sync point for T3 to be set. But let the preparation
-# transaction remain hanging, so that T1 and T2 will be scheduled for the
-# remaining two worker threads.
-SET DEBUG_SYNC= "now WAIT_FOR prep_ready";
-
---connection server_1
-INSERT INTO t2 VALUES (foo(60,
- "rpl_parallel_simulate_temp_err_xid SIGNAL t1_ready1 WAIT_FOR t1_cont1",
- "rpl_parallel_retry_after_unmark SIGNAL t1_ready2 WAIT_FOR t1_cont2"));
---save_master_pos
-
---connection server_2
-SET DEBUG_SYNC= "now WAIT_FOR t1_ready1";
-# T1 has now done mark_start_commit(). It will later do a rollback and retry.
-
-# Do T2 and T3 in a single group commit.
-# Use a MyISAM table for T2 and T3, so they do not trigger the
-# rpl_parallel_simulate_temp_err_xid DBUG insertion on XID event.
---connection con_temp3
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
-SET binlog_format=statement;
-send INSERT INTO t1 VALUES (foo(61,
- "rpl_parallel_before_mark_start_commit SIGNAL t2_ready1 WAIT_FOR t2_cont1",
- "rpl_parallel_after_mark_start_commit SIGNAL t2_ready2"));
-
---connection server_1
-SET debug_sync='now WAIT_FOR master_queued1';
-
---connection con_temp4
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
-send INSERT INTO t6 VALUES (62);
-
---connection server_1
-SET debug_sync='now WAIT_FOR master_queued2';
-SET debug_sync='now SIGNAL master_cont1';
-
---connection con_temp3
-REAP;
---connection con_temp4
-REAP;
-
---connection server_1
-SET debug_sync='RESET';
-SET BINLOG_FORMAT= @old_format;
-SELECT * FROM t2 WHERE a>=60 ORDER BY a;
-SELECT * FROM t1 WHERE a>=60 ORDER BY a;
-SELECT * FROM t6 WHERE a>=60 ORDER BY a;
-
---connection server_2
-SET DEBUG_SYNC= "now WAIT_FOR t2_ready1";
-# T2 has now started running, but has not yet done mark_start_commit()
-SET DEBUG_SYNC= "now SIGNAL t1_cont1";
-SET DEBUG_SYNC= "now WAIT_FOR t1_ready2";
-# T1 has now done unmark_start_commit() in preparation for its retry.
-
---connection server_2
-# Let the preparation transaction complete, so that the same worker thread
-# can continue with the transaction T3.
-SET DEBUG_SYNC= "now SIGNAL prep_cont";
-SET DEBUG_SYNC= "now WAIT_FOR t3_ready";
-# T3 has now gone to wait for T2 to start committing
-SET DEBUG_SYNC= "now SIGNAL t2_cont1";
-SET DEBUG_SYNC= "now WAIT_FOR t2_ready2";
-# T2 has now done mark_start_commit().
-# Let things run, and check that T3 does not get deadlocked.
-SET DEBUG_SYNC= "now SIGNAL t1_cont2";
---sync_with_master
-
---connection server_1
---save_master_pos
---connection server_2
---sync_with_master
-SELECT * FROM t2 WHERE a>=60 ORDER BY a;
-SELECT * FROM t1 WHERE a>=60 ORDER BY a;
-SELECT * FROM t6 WHERE a>=60 ORDER BY a;
-SET DEBUG_SYNC="reset";
-
-# Re-spawn the worker threads to remove any DBUG injections or DEBUG_SYNC.
---source include/stop_slave.inc
-SET GLOBAL debug_dbug=@old_dbug;
-SET GLOBAL slave_parallel_threads=0;
-SET GLOBAL slave_parallel_threads=10;
---source include/start_slave.inc
-
---echo *** MDEV-7335: Potential parallel slave deadlock with specific binlog corruption ***
-
---connection server_2
---source include/stop_slave.inc
-SET GLOBAL slave_parallel_threads=1;
-SET @old_dbug= @@GLOBAL.debug_dbug;
-SET GLOBAL debug_dbug="+d,slave_discard_xid_for_gtid_0_x_1000";
-
---connection server_1
-INSERT INTO t2 VALUES (101);
-INSERT INTO t2 VALUES (102);
-INSERT INTO t2 VALUES (103);
-INSERT INTO t2 VALUES (104);
-INSERT INTO t2 VALUES (105);
-# Inject a partial event group (missing XID at the end). The bug was that such
-# partial group was not handled appropriately, leading to server deadlock.
-SET gtid_seq_no=1000;
-INSERT INTO t2 VALUES (106);
-INSERT INTO t2 VALUES (107);
-INSERT INTO t2 VALUES (108);
-INSERT INTO t2 VALUES (109);
-INSERT INTO t2 VALUES (110);
-INSERT INTO t2 VALUES (111);
-INSERT INTO t2 VALUES (112);
-INSERT INTO t2 VALUES (113);
-INSERT INTO t2 VALUES (114);
-INSERT INTO t2 VALUES (115);
-INSERT INTO t2 VALUES (116);
-INSERT INTO t2 VALUES (117);
-INSERT INTO t2 VALUES (118);
-INSERT INTO t2 VALUES (119);
-INSERT INTO t2 VALUES (120);
-INSERT INTO t2 VALUES (121);
-INSERT INTO t2 VALUES (122);
-INSERT INTO t2 VALUES (123);
-INSERT INTO t2 VALUES (124);
-INSERT INTO t2 VALUES (125);
-INSERT INTO t2 VALUES (126);
-INSERT INTO t2 VALUES (127);
-INSERT INTO t2 VALUES (128);
-INSERT INTO t2 VALUES (129);
-INSERT INTO t2 VALUES (130);
---source include/save_master_gtid.inc
-
---connection server_2
---source include/start_slave.inc
---source include/sync_with_master_gtid.inc
-# The partial event group (a=106) should be rolled back and thus missing.
-SELECT * FROM t2 WHERE a >= 100 ORDER BY a;
-
---source include/stop_slave.inc
-SET GLOBAL debug_dbug=@old_dbug;
-SET GLOBAL slave_parallel_threads=10;
---source include/start_slave.inc
-
---echo *** MDEV-6676 - test syntax of @@slave_parallel_mode ***
---connection server_2
-
---let $status_items= Parallel_Mode
---source include/show_slave_status.inc
---source include/stop_slave.inc
-SET GLOBAL slave_parallel_mode='aggressive';
---let $status_items= Parallel_Mode
---source include/show_slave_status.inc
-SET GLOBAL slave_parallel_mode='conservative';
---let $status_items= Parallel_Mode
---source include/show_slave_status.inc
-
-
---echo *** MDEV-6676 - test that empty parallel_mode does not replicate in parallel ***
---connection server_1
-INSERT INTO t2 VALUES (1040);
---source include/save_master_gtid.inc
-
---connection server_2
-SET GLOBAL slave_parallel_mode='none';
-# Test that we do not use parallel apply, by injecting an unconditional
-# crash in the parallel apply code.
-SET @old_dbug= @@GLOBAL.debug_dbug;
-SET GLOBAL debug_dbug="+d,slave_crash_if_parallel_apply";
---source include/start_slave.inc
---source include/sync_with_master_gtid.inc
-SELECT * FROM t2 WHERE a >= 1040 ORDER BY a;
---source include/stop_slave.inc
-SET GLOBAL debug_dbug=@old_dbug;
-
-
---echo *** MDEV-6676 - test disabling domain-based parallel replication ***
---connection server_1
-# Let's do a bunch of transactions that will conflict if run out-of-order in
-# domain-based parallel replication mode.
-SET gtid_domain_id = 1;
-INSERT INTO t2 VALUES (1041);
-INSERT INTO t2 VALUES (1042);
-INSERT INTO t2 VALUES (1043);
-INSERT INTO t2 VALUES (1044);
-INSERT INTO t2 VALUES (1045);
-INSERT INTO t2 VALUES (1046);
-DELETE FROM t2 WHERE a >= 1041;
-SET gtid_domain_id = 2;
-INSERT INTO t2 VALUES (1041);
-INSERT INTO t2 VALUES (1042);
-INSERT INTO t2 VALUES (1043);
-INSERT INTO t2 VALUES (1044);
-INSERT INTO t2 VALUES (1045);
-INSERT INTO t2 VALUES (1046);
-SET gtid_domain_id = 0;
---source include/save_master_gtid.inc
---connection server_2
-SET GLOBAL slave_parallel_mode=minimal;
---source include/start_slave.inc
---source include/sync_with_master_gtid.inc
-SELECT * FROM t2 WHERE a >= 1040 ORDER BY a;
-
---echo *** MDEV-7888: ANALYZE TABLE does wakeup_subsequent_commits(), causing wrong binlog order and parallel replication hang ***
-
---connection server_2
---source include/stop_slave.inc
-SET GLOBAL slave_parallel_mode='conservative';
-SET GLOBAL slave_parallel_threads=10;
-
-SET @old_dbug= @@GLOBAL.debug_dbug;
-SET GLOBAL debug_dbug= '+d,inject_analyze_table_sleep';
-
---connection server_1
-# Inject two group commits. The bug was that ANALYZE TABLE would call
-# wakeup_subsequent_commits() too early, allowing the following transaction
-# in the same group to run ahead and binlog and free the GCO. Then we get
-# wrong binlog order and later access freed GCO, which causes lost wakeup
-# of following GCO and thus replication hang.
-# We injected a small sleep in ANALYZE to make the race easier to hit (this
-# can only cause false negatives in versions with the bug, not false positives,
-# so sleep is ok here. And it's in general not possible to trigger reliably
-# the race with debug_sync, since the bugfix makes the race impossible).
-
-SET @old_dbug= @@SESSION.debug_dbug;
-SET SESSION debug_dbug="+d,binlog_force_commit_id";
-
-# Group commit with cid=10000, two event groups.
-SET @commit_id= 10000;
-ANALYZE TABLE t2;
-INSERT INTO t3 VALUES (120, 0);
-
-# Group commit with cid=10001, one event group.
-SET @commit_id= 10001;
-INSERT INTO t3 VALUES (121, 0);
-
-SET SESSION debug_dbug=@old_dbug;
-
-SELECT * FROM t3 WHERE a >= 120 ORDER BY a;
---source include/save_master_gtid.inc
-
---connection server_2
---source include/start_slave.inc
---source include/sync_with_master_gtid.inc
-
-SELECT * FROM t3 WHERE a >= 120 ORDER BY a;
-
---source include/stop_slave.inc
-SET GLOBAL debug_dbug= @old_dbug;
---source include/start_slave.inc
-
-
---echo *** MDEV-7929: record_gtid() for non-transactional event group calls wakeup_subsequent_commits() too early, causing slave hang. ***
-
---connection server_2
---source include/stop_slave.inc
-SET @old_dbug= @@GLOBAL.debug_dbug;
-SET GLOBAL debug_dbug= '+d,inject_record_gtid_serverid_100_sleep';
-
---connection server_1
-# Inject two group commits. The bug was that record_gtid for a
-# non-transactional event group would commit its own transaction, which would
-# cause ha_commit_trans() to call wakeup_subsequent_commits() too early. This
-# in turn lead to access to freed group_commit_orderer object, losing a wakeup
-# and causing slave threads to hang.
-# We inject a small sleep in the corresponding record_gtid() to make the race
-# easier to hit.
-
-SET @old_dbug= @@SESSION.debug_dbug;
-SET SESSION debug_dbug="+d,binlog_force_commit_id";
-
-# Group commit with cid=10010, two event groups.
-SET @old_server_id= @@SESSION.server_id;
-SET SESSION server_id= 100;
-SET @commit_id= 10010;
-ALTER TABLE t1 COMMENT "Hulubulu!";
-SET SESSION server_id= @old_server_id;
-INSERT INTO t3 VALUES (130, 0);
-
-# Group commit with cid=10011, one event group.
-SET @commit_id= 10011;
-INSERT INTO t3 VALUES (131, 0);
-
-SET SESSION debug_dbug=@old_dbug;
-
-SELECT * FROM t3 WHERE a >= 130 ORDER BY a;
---source include/save_master_gtid.inc
-
---connection server_2
---source include/start_slave.inc
---source include/sync_with_master_gtid.inc
-
-SELECT * FROM t3 WHERE a >= 130 ORDER BY a;
-
---source include/stop_slave.inc
-SET GLOBAL debug_dbug= @old_dbug;
---source include/start_slave.inc
-
-
---echo *** MDEV-8031: Parallel replication stops on "connection killed" error (probably incorrectly handled deadlock kill) ***
-
---connection server_1
-INSERT INTO t3 VALUES (201,0), (202,0);
---source include/save_master_gtid.inc
-
---connection server_2
---source include/sync_with_master_gtid.inc
---source include/stop_slave.inc
-SET @old_dbug= @@GLOBAL.debug_dbug;
-SET GLOBAL debug_dbug= '+d,inject_mdev8031';
-
---connection server_1
-# We artificially create a situation that hopefully resembles the original
-# bug which was only seen "in the wild", and only once.
-# Setup a fake group commit with lots of conflicts that will lead to deadloc
-# kill. The slave DBUG injection causes the slave to be deadlock killed at
-# a particular point during the retry, and then later do a small sleep at
-# another critical point where the prior transaction then has a chance to
-# complete. Finally an extra KILL check catches an unhandled, lingering
-# deadlock kill. So rather artificial, but at least it exercises the
-# relevant code paths.
-SET @old_dbug= @@SESSION.debug_dbug;
-SET SESSION debug_dbug="+d,binlog_force_commit_id";
-
-SET @commit_id= 10200;
-INSERT INTO t3 VALUES (203, 1);
-INSERT INTO t3 VALUES (204, 1);
-INSERT INTO t3 VALUES (205, 1);
-UPDATE t3 SET b=b+1 WHERE a=201;
-UPDATE t3 SET b=b+1 WHERE a=201;
-UPDATE t3 SET b=b+1 WHERE a=201;
-UPDATE t3 SET b=b+1 WHERE a=202;
-UPDATE t3 SET b=b+1 WHERE a=202;
-UPDATE t3 SET b=b+1 WHERE a=202;
-UPDATE t3 SET b=b+1 WHERE a=202;
-UPDATE t3 SET b=b+1 WHERE a=203;
-UPDATE t3 SET b=b+1 WHERE a=203;
-UPDATE t3 SET b=b+1 WHERE a=204;
-UPDATE t3 SET b=b+1 WHERE a=204;
-UPDATE t3 SET b=b+1 WHERE a=204;
-UPDATE t3 SET b=b+1 WHERE a=203;
-UPDATE t3 SET b=b+1 WHERE a=205;
-UPDATE t3 SET b=b+1 WHERE a=205;
-SET SESSION debug_dbug=@old_dbug;
-
-SELECT * FROM t3 WHERE a>=200 ORDER BY a;
---source include/save_master_gtid.inc
-
---connection server_2
---source include/start_slave.inc
---source include/sync_with_master_gtid.inc
-
-SELECT * FROM t3 WHERE a>=200 ORDER BY a;
---source include/stop_slave.inc
-SET GLOBAL debug_dbug= @old_dbug;
---source include/start_slave.inc
-
-
---echo *** Check getting deadlock killed inside open_binlog() during retry. ***
-
---connection server_2
---source include/stop_slave.inc
-SET @old_dbug= @@GLOBAL.debug_dbug;
-SET GLOBAL debug_dbug= '+d,inject_retry_event_group_open_binlog_kill';
-SET @old_max= @@GLOBAL.max_relay_log_size;
-SET GLOBAL max_relay_log_size= 4096;
-
---connection server_1
-SET @old_dbug= @@SESSION.debug_dbug;
-SET SESSION debug_dbug="+d,binlog_force_commit_id";
-
---let $large= `SELECT REPEAT("*", 8192)`
-SET @commit_id= 10210;
---echo Omit long queries that cause relaylog rotations and transaction retries...
---disable_query_log
-eval UPDATE t3 SET b=b+1 WHERE a=201 /* $large */;
-eval UPDATE t3 SET b=b+1 WHERE a=201 /* $large */;
-eval UPDATE t3 SET b=b+1 WHERE a=201 /* $large */;
-eval UPDATE t3 SET b=b+1 WHERE a=202 /* $large */;
-eval UPDATE t3 SET b=b+1 WHERE a=202 /* $large */;
-eval UPDATE t3 SET b=b+1 WHERE a=202 /* $large */;
-eval UPDATE t3 SET b=b+1 WHERE a=202 /* $large */;
-eval UPDATE t3 SET b=b+1 WHERE a=203 /* $large */;
-eval UPDATE t3 SET b=b+1 WHERE a=203 /* $large */;
-eval UPDATE t3 SET b=b+1 WHERE a=204 /* $large */;
-eval UPDATE t3 SET b=b+1 WHERE a=204 /* $large */;
-eval UPDATE t3 SET b=b+1 WHERE a=204 /* $large */;
-eval UPDATE t3 SET b=b+1 WHERE a=203 /* $large */;
-eval UPDATE t3 SET b=b+1 WHERE a=205 /* $large */;
-eval UPDATE t3 SET b=b+1 WHERE a=205 /* $large */;
---enable_query_log
-SET SESSION debug_dbug=@old_dbug;
-
-SELECT * FROM t3 WHERE a>=200 ORDER BY a;
---source include/save_master_gtid.inc
-
---connection server_2
---source include/start_slave.inc
---source include/sync_with_master_gtid.inc
-
-SELECT * FROM t3 WHERE a>=200 ORDER BY a;
---source include/stop_slave.inc
-SET GLOBAL debug_dbug= @old_debg;
-SET GLOBAL max_relay_log_size= @old_max;
---source include/start_slave.inc
-
---echo *** MDEV-8725: Assertion on ROLLBACK statement in the binary log ***
---connection server_1
-# Inject an event group terminated by ROLLBACK, by mixing MyISAM and InnoDB
-# in a transaction. The bug was an assertion on the ROLLBACK due to
-# mark_start_commit() being already called.
---disable_warnings
-BEGIN;
-INSERT INTO t2 VALUES (2000);
-INSERT INTO t1 VALUES (2000);
-INSERT INTO t2 VALUES (2001);
-ROLLBACK;
---enable_warnings
-SELECT * FROM t1 WHERE a>=2000 ORDER BY a;
-SELECT * FROM t2 WHERE a>=2000 ORDER BY a;
---source include/save_master_gtid.inc
-
---connection server_2
---source include/sync_with_master_gtid.inc
-SELECT * FROM t1 WHERE a>=2000 ORDER BY a;
-SELECT * FROM t2 WHERE a>=2000 ORDER BY a;
-
-
-# Clean up.
---connection server_2
---source include/stop_slave.inc
-SET GLOBAL slave_parallel_threads=@old_parallel_threads;
---source include/start_slave.inc
-SET DEBUG_SYNC= 'RESET';
-
---connection server_1
-DROP function foo;
-DROP TABLE t1,t2,t3,t4,t5,t6;
-SET DEBUG_SYNC= 'RESET';
-
---source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/include/rpl_parallel_analyze_table_hang.inc b/mysql-test/suite/rpl/include/rpl_parallel_analyze_table_hang.inc
new file mode 100644
index 00000000000..62a7501c36b
--- /dev/null
+++ b/mysql-test/suite/rpl/include/rpl_parallel_analyze_table_hang.inc
@@ -0,0 +1,73 @@
+--echo *** MDEV-7888: ANALYZE TABLE does wakeup_subsequent_commits(), causing wrong binlog order and parallel replication hang ***
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/have_debug_sync.inc
+--source include/master-slave.inc
+
+--connection server_2
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+SET @old_parallel_mode=@@GLOBAL.slave_parallel_mode;
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_mode='conservative';
+SET GLOBAL slave_parallel_threads=10;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+--source include/start_slave.inc
+
+--connection server_1
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t2 (a int PRIMARY KEY) ENGINE=InnoDB;
+CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+--source include/stop_slave.inc
+SET @old_dbug= @@GLOBAL.debug_dbug;
+SET GLOBAL debug_dbug= '+d,inject_analyze_table_sleep';
+
+--connection server_1
+# Inject two group commits. The bug was that ANALYZE TABLE would call
+# wakeup_subsequent_commits() too early, allowing the following transaction
+# in the same group to run ahead and binlog and free the GCO. Then we get
+# wrong binlog order and later access freed GCO, which causes lost wakeup
+# of following GCO and thus replication hang.
+# We injected a small sleep in ANALYZE to make the race easier to hit (this
+# can only cause false negatives in versions with the bug, not false positives,
+# so sleep is ok here. And it's in general not possible to trigger reliably
+# the race with debug_sync, since the bugfix makes the race impossible).
+
+SET @old_dbug= @@SESSION.debug_dbug;
+SET SESSION debug_dbug="+d,binlog_force_commit_id";
+
+# Group commit with cid=10000, two event groups.
+SET @commit_id= 10000;
+ANALYZE TABLE t2;
+INSERT INTO t3 VALUES (120, 0);
+
+# Group commit with cid=10001, one event group.
+SET @commit_id= 10001;
+INSERT INTO t3 VALUES (121, 0);
+
+SET SESSION debug_dbug=@old_dbug;
+
+SELECT * FROM t3 WHERE a >= 120 ORDER BY a;
+--source include/save_master_gtid.inc
+
+--connection server_2
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+
+SELECT * FROM t3 WHERE a >= 120 ORDER BY a;
+
+# Clean up.
+--source include/stop_slave.inc
+SET GLOBAL debug_dbug= @old_dbug;
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+SET GLOBAL slave_parallel_mode=@old_parallel_mode;
+--source include/start_slave.inc
+
+--connection server_1
+DROP TABLE t2,t3;
+
+--source include/rpl_end.inc
+
diff --git a/mysql-test/suite/rpl/include/rpl_parallel_deadlock_corrupt_binlog.inc b/mysql-test/suite/rpl/include/rpl_parallel_deadlock_corrupt_binlog.inc
new file mode 100644
index 00000000000..3a135ef5cc4
--- /dev/null
+++ b/mysql-test/suite/rpl/include/rpl_parallel_deadlock_corrupt_binlog.inc
@@ -0,0 +1,79 @@
+--echo *** MDEV-7335: Potential parallel slave deadlock with specific binlog corruption ***
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/have_debug_sync.inc
+--source include/master-slave.inc
+
+--connection server_2
+--source include/stop_slave.inc
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+SET GLOBAL slave_parallel_threads=10;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+--source include/start_slave.inc
+
+--connection server_1
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t2 (a int PRIMARY KEY) ENGINE=InnoDB;
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=1;
+SET @old_dbug= @@GLOBAL.debug_dbug;
+SET GLOBAL debug_dbug="+d,slave_discard_xid_for_gtid_0_x_1000";
+
+--connection server_1
+INSERT INTO t2 VALUES (101);
+INSERT INTO t2 VALUES (102);
+INSERT INTO t2 VALUES (103);
+INSERT INTO t2 VALUES (104);
+INSERT INTO t2 VALUES (105);
+# Inject a partial event group (missing XID at the end). The bug was that such
+# partial group was not handled appropriately, leading to server deadlock.
+SET gtid_seq_no=1000;
+INSERT INTO t2 VALUES (106);
+INSERT INTO t2 VALUES (107);
+INSERT INTO t2 VALUES (108);
+INSERT INTO t2 VALUES (109);
+INSERT INTO t2 VALUES (110);
+INSERT INTO t2 VALUES (111);
+INSERT INTO t2 VALUES (112);
+INSERT INTO t2 VALUES (113);
+INSERT INTO t2 VALUES (114);
+INSERT INTO t2 VALUES (115);
+INSERT INTO t2 VALUES (116);
+INSERT INTO t2 VALUES (117);
+INSERT INTO t2 VALUES (118);
+INSERT INTO t2 VALUES (119);
+INSERT INTO t2 VALUES (120);
+INSERT INTO t2 VALUES (121);
+INSERT INTO t2 VALUES (122);
+INSERT INTO t2 VALUES (123);
+INSERT INTO t2 VALUES (124);
+INSERT INTO t2 VALUES (125);
+INSERT INTO t2 VALUES (126);
+INSERT INTO t2 VALUES (127);
+INSERT INTO t2 VALUES (128);
+INSERT INTO t2 VALUES (129);
+INSERT INTO t2 VALUES (130);
+--source include/save_master_gtid.inc
+
+--connection server_2
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+# The partial event group (a=106) should be rolled back and thus missing.
+SELECT * FROM t2 WHERE a >= 100 ORDER BY a;
+
+# Cleanup
+--source include/stop_slave.inc
+SET GLOBAL debug_dbug=@old_dbug;
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+--source include/start_slave.inc
+SET DEBUG_SYNC= 'RESET';
+
+--connection server_1
+DROP TABLE t2;
+SET DEBUG_SYNC= 'RESET';
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/include/rpl_parallel_domain.inc b/mysql-test/suite/rpl/include/rpl_parallel_domain.inc
new file mode 100644
index 00000000000..eda08cc2916
--- /dev/null
+++ b/mysql-test/suite/rpl/include/rpl_parallel_domain.inc
@@ -0,0 +1,87 @@
+# Test should work with both conservative and optimistic modes
+
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/have_debug_sync.inc
+--source include/master-slave.inc
+
+# Test various aspects of parallel replication.
+
+--connection server_2
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+--error ER_SLAVE_MUST_STOP
+SET GLOBAL slave_parallel_threads=10;
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=10;
+
+# Check that we do not spawn any worker threads when no slave is running.
+SELECT IF(COUNT(*) < 10, "OK", CONCAT("Found too many system user processes: ", COUNT(*))) FROM information_schema.processlist WHERE user = "system user";
+
+CHANGE MASTER TO master_use_gtid=slave_pos;
+--source include/start_slave.inc
+
+# Check that worker threads get spawned when slave starts.
+SELECT IF(COUNT(*) >= 10, "OK", CONCAT("Found too few system user processes: ", COUNT(*))) FROM information_schema.processlist WHERE user = "system user";
+# ... and that worker threads get removed when slave stops.
+--source include/stop_slave.inc
+SELECT IF(COUNT(*) < 10, "OK", CONCAT("Found too many system user processes: ", COUNT(*))) FROM information_schema.processlist WHERE user = "system user";
+--source include/start_slave.inc
+SELECT IF(COUNT(*) >= 10, "OK", CONCAT("Found too few system user processes: ", COUNT(*))) FROM information_schema.processlist WHERE user = "system user";
+
+--echo *** Test long-running query in domain 1 can run in parallel with short queries in domain 0 ***
+
+--connection server_1
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t1 (a int PRIMARY KEY) ENGINE=MyISAM;
+CREATE TABLE t2 (a int PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t2 VALUES (1);
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+
+# Block the table t1 to simulate a replicated query taking a long time.
+--connect (con_temp1,127.0.0.1,root,,test,$SERVER_MYPORT_2,)
+LOCK TABLE t1 WRITE;
+
+--connection server_1
+SET gtid_domain_id=1;
+# This query will be blocked on the slave until UNLOCK TABLES.
+INSERT INTO t1 VALUES (2);
+SET gtid_domain_id=0;
+# These t2 queries can be replicated in parallel with the prior t1 query, as
+# they are in a separate replication domain.
+INSERT INTO t2 VALUES (2);
+INSERT INTO t2 VALUES (3);
+BEGIN;
+INSERT INTO t2 VALUES (4);
+INSERT INTO t2 VALUES (5);
+COMMIT;
+INSERT INTO t2 VALUES (6);
+
+--connection server_2
+--let $wait_condition= SELECT COUNT(*) = 6 FROM t2
+--source include/wait_condition.inc
+
+SELECT * FROM t2 ORDER by a;
+
+--connection con_temp1
+SELECT * FROM t1;
+UNLOCK TABLES;
+
+--connection server_2
+--let $wait_condition= SELECT COUNT(*) = 2 FROM t1
+--source include/wait_condition.inc
+
+SELECT * FROM t1 ORDER BY a;
+
+# Clean up.
+--connection server_2
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+--source include/start_slave.inc
+
+--connection server_1
+DROP TABLE t1,t2;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/include/rpl_parallel_domain_slave_single_grp.inc b/mysql-test/suite/rpl/include/rpl_parallel_domain_slave_single_grp.inc
new file mode 100644
index 00000000000..856efd065df
--- /dev/null
+++ b/mysql-test/suite/rpl/include/rpl_parallel_domain_slave_single_grp.inc
@@ -0,0 +1,128 @@
+# Test is independent of slave_parallel_mode
+--echo *** Test two transactions in different domains committed in opposite order on slave but in a single group commit. ***
+
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/have_debug_sync.inc
+--source include/master-slave.inc
+
+# Test various aspects of parallel replication.
+
+--connection server_2
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=10;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+--source include/start_slave.inc
+
+--connection server_1
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t1 (a int PRIMARY KEY) ENGINE=MyISAM;
+CREATE TABLE t2 (a int PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t2 VALUES (1);
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+--source include/stop_slave.inc
+
+--connection server_1
+# Use a stored function to inject a debug_sync into the appropriate THD.
+# The function does nothing on the master, and on the slave it injects the
+# desired debug_sync action(s).
+SET sql_log_bin=0;
+--delimiter ||
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+ RETURNS INT DETERMINISTIC
+ BEGIN
+ RETURN x;
+ END
+||
+--delimiter ;
+SET sql_log_bin=1;
+
+SET @old_format= @@SESSION.binlog_format;
+SET binlog_format='statement';
+SET gtid_domain_id=1;
+INSERT INTO t2 VALUES (foo(10,
+ 'commit_before_enqueue SIGNAL ready1 WAIT_FOR cont1',
+ 'commit_after_release_LOCK_prepare_ordered SIGNAL ready2'));
+
+--connection server_2
+FLUSH LOGS;
+--source include/wait_for_binlog_checkpoint.inc
+SET sql_log_bin=0;
+--delimiter ||
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+ RETURNS INT DETERMINISTIC
+ BEGIN
+ IF d1 != '' THEN
+ SET debug_sync = d1;
+ END IF;
+ IF d2 != '' THEN
+ SET debug_sync = d2;
+ END IF;
+ RETURN x;
+ END
+||
+--delimiter ;
+SET sql_log_bin=1;
+SET @old_format=@@GLOBAL.binlog_format;
+SET GLOBAL binlog_format=statement;
+# We need to restart all parallel threads for the new global setting to
+# be copied to the session-level values.
+SET GLOBAL slave_parallel_threads=0;
+SET GLOBAL slave_parallel_threads=10;
+--source include/start_slave.inc
+
+# First make sure the first insert is ready to commit, but not queued yet.
+SET debug_sync='now WAIT_FOR ready1';
+
+--connection server_1
+SET gtid_domain_id=2;
+INSERT INTO t2 VALUES (foo(11,
+ 'commit_before_enqueue SIGNAL ready3 WAIT_FOR cont3',
+ 'commit_after_release_LOCK_prepare_ordered SIGNAL ready4 WAIT_FOR cont4'));
+SET gtid_domain_id=0;
+SELECT * FROM t2 WHERE a >= 10 ORDER BY a;
+
+--connection server_2
+# Now wait for the second insert to queue itself as the leader, and then
+# wait for more commits to queue up.
+SET debug_sync='now WAIT_FOR ready3';
+SET debug_sync='now SIGNAL cont3';
+SET debug_sync='now WAIT_FOR ready4';
+# Now allow the first insert to queue up to participate in group commit.
+SET debug_sync='now SIGNAL cont1';
+SET debug_sync='now WAIT_FOR ready2';
+# Finally allow the second insert to proceed and do the group commit.
+SET debug_sync='now SIGNAL cont4';
+
+--let $wait_condition= SELECT COUNT(*) = 2 FROM t2 WHERE a >= 10
+--source include/wait_condition.inc
+SELECT * FROM t2 WHERE a >= 10 ORDER BY a;
+# The two INSERT transactions should have been committed in opposite order,
+# but in the same group commit (seen by precense of cid=# in the SHOW
+# BINLOG output).
+--let $binlog_file= slave-bin.000002
+--source include/show_binlog_events.inc
+FLUSH LOGS;
+--source include/wait_for_binlog_checkpoint.inc
+
+
+# Clean up.
+--connection server_2
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+--source include/start_slave.inc
+SET DEBUG_SYNC= 'RESET';
+SET GLOBAL binlog_format=@old_format;
+
+--connection server_1
+DROP function foo;
+DROP TABLE t1,t2;
+SET DEBUG_SYNC= 'RESET';
+SET GLOBAL binlog_format=@old_format;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/include/rpl_parallel_free_deferred_event.inc b/mysql-test/suite/rpl/include/rpl_parallel_free_deferred_event.inc
new file mode 100644
index 00000000000..41f372eddf8
--- /dev/null
+++ b/mysql-test/suite/rpl/include/rpl_parallel_free_deferred_event.inc
@@ -0,0 +1,67 @@
+--echo *** MDEV-5788 Incorrect free of rgi->deferred_events in parallel replication ***
+
+--source include/have_innodb.inc
+--source include/master-slave.inc
+
+--connection server_2
+--source include/stop_slave.inc
+CHANGE MASTER TO master_use_gtid=slave_pos;
+--source include/start_slave.inc
+
+--connection server_1
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+# Use just two worker threads, so we are sure to get the rpl_group_info added
+# to the free list, which is what triggered the bug.
+--source include/stop_slave.inc
+SET GLOBAL replicate_ignore_table="test.t3";
+SET GLOBAL slave_parallel_threads=2;
+--source include/start_slave.inc
+
+--connection server_1
+INSERT INTO t3 VALUES (100, rand());
+INSERT INTO t3 VALUES (101, rand());
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+
+--connection server_1
+INSERT INTO t3 VALUES (102, rand());
+INSERT INTO t3 VALUES (103, rand());
+INSERT INTO t3 VALUES (104, rand());
+INSERT INTO t3 VALUES (105, rand());
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+--source include/stop_slave.inc
+SET GLOBAL replicate_ignore_table="";
+--source include/start_slave.inc
+
+--connection server_1
+INSERT INTO t3 VALUES (106, rand());
+INSERT INTO t3 VALUES (107, rand());
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+--replace_column 2 #
+SELECT * FROM t3 WHERE a >= 100 ORDER BY a;
+
+
+# Clean up.
+--connection server_2
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+--source include/start_slave.inc
+
+--connection server_1
+DROP TABLE t3;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/include/rpl_parallel_gco_wait_kill.inc b/mysql-test/suite/rpl/include/rpl_parallel_gco_wait_kill.inc
new file mode 100644
index 00000000000..d918b2ea692
--- /dev/null
+++ b/mysql-test/suite/rpl/include/rpl_parallel_gco_wait_kill.inc
@@ -0,0 +1,366 @@
+--echo *** Test killing thread that is waiting to start transaction until previous transaction commits ***
+
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/have_debug_sync.inc
+--source include/have_binlog_format_statement.inc
+--source include/master-slave.inc
+
+--connection server_2
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+SET @old_parallel_mode= @@GLOBAL.slave_parallel_mode;
+--source include/stop_slave.inc
+SET sql_log_bin=0;
+CALL mtr.add_suppression("Query execution was interrupted");
+CALL mtr.add_suppression("Slave: Connection was killed");
+CALL mtr.add_suppression("Commit failed due to failure of an earlier commit on which this one depends");
+SET sql_log_bin=1;
+SET GLOBAL slave_parallel_threads=10;
+SET GLOBAL slave_parallel_mode= 'conservative';
+CHANGE MASTER TO master_use_gtid=slave_pos;
+--source include/start_slave.inc
+
+--connection server_1
+--connect (con_temp3,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
+--connect (con_temp4,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
+--connect (con_temp5,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+
+--connection server_1
+# Use a stored function to inject a debug_sync into the appropriate THD.
+# The function does nothing on the master, and on the slave it injects the
+# desired debug_sync action(s).
+SET sql_log_bin=0;
+--delimiter ||
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+ RETURNS INT DETERMINISTIC
+ BEGIN
+ RETURN x;
+ END
+||
+--delimiter ;
+SET sql_log_bin=1;
+
+--connection server_2
+SET sql_log_bin=0;
+--delimiter ||
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+ RETURNS INT DETERMINISTIC
+ BEGIN
+ IF d1 != '' THEN
+ SET debug_sync = d1;
+ END IF;
+ IF d2 != '' THEN
+ SET debug_sync = d2;
+ END IF;
+ RETURN x;
+ END
+||
+--delimiter ;
+SET sql_log_bin=1;
+# We need to restart all parallel threads for the new global setting to
+# be copied to the session-level values.
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=0;
+SET GLOBAL slave_parallel_threads=4;
+--source include/start_slave.inc
+
+
+# We set up four transactions T1, T2, T3, and T4 on the master. T2, T3, and T4
+# can run in parallel with each other (same group commit and commit id),
+# but not in parallel with T1.
+#
+# We use four worker threads, each Ti will be queued on each their own
+# worker thread. We will delay T1 commit, T3 will wait for T1 to begin
+# commit before it can start. We will kill T3 during this wait, and
+# check that everything works correctly.
+#
+# It is rather tricky to get the correct thread id of the worker to kill.
+# We start by injecting four dummy transactions in a debug_sync-controlled
+# manner to be able to get known thread ids for the workers in a pool with
+# just 4 worker threads. Then we let in each of the real test transactions
+# T1-T4 one at a time in a way which allows us to know which transaction
+# ends up with which thread id.
+
+--connection server_1
+SET gtid_domain_id=2;
+BEGIN;
+# This debug_sync will linger on and be used to control T4 later.
+INSERT INTO t3 VALUES (70, foo(70,
+ 'rpl_parallel_start_waiting_for_prior SIGNAL t4_waiting', ''));
+INSERT INTO t3 VALUES (60, foo(60,
+ 'ha_write_row_end SIGNAL d2_query WAIT_FOR d2_cont2',
+ 'rpl_parallel_end_of_group SIGNAL d2_done WAIT_FOR d2_cont'));
+COMMIT;
+SET gtid_domain_id=0;
+
+--connection server_2
+SET debug_sync='now WAIT_FOR d2_query';
+--let $d2_thd_id= `SELECT ID FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO LIKE '%foo(60%' AND INFO NOT LIKE '%LIKE%'`
+
+--connection server_1
+SET gtid_domain_id=1;
+BEGIN;
+# These debug_sync's will linger on and be used to control T3 later.
+INSERT INTO t3 VALUES (61, foo(61,
+ 'rpl_parallel_start_waiting_for_prior SIGNAL t3_waiting',
+ 'rpl_parallel_start_waiting_for_prior_killed SIGNAL t3_killed'));
+INSERT INTO t3 VALUES (62, foo(62,
+ 'ha_write_row_end SIGNAL d1_query WAIT_FOR d1_cont2',
+ 'rpl_parallel_end_of_group SIGNAL d1_done WAIT_FOR d1_cont'));
+COMMIT;
+SET gtid_domain_id=0;
+
+--connection server_2
+SET debug_sync='now WAIT_FOR d1_query';
+--let $d1_thd_id= `SELECT ID FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO LIKE '%foo(62%' AND INFO NOT LIKE '%LIKE%'`
+
+--connection server_1
+SET gtid_domain_id=0;
+INSERT INTO t3 VALUES (63, foo(63,
+ 'ha_write_row_end SIGNAL d0_query WAIT_FOR d0_cont2',
+ 'rpl_parallel_end_of_group SIGNAL d0_done WAIT_FOR d0_cont'));
+
+--connection server_2
+SET debug_sync='now WAIT_FOR d0_query';
+--let $d0_thd_id= `SELECT ID FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO LIKE '%foo(63%' AND INFO NOT LIKE '%LIKE%'`
+
+--connection server_1
+SET gtid_domain_id=3;
+BEGIN;
+# These debug_sync's will linger on and be used to control T2 later.
+INSERT INTO t3 VALUES (68, foo(68,
+ 'rpl_parallel_start_waiting_for_prior SIGNAL t2_waiting', ''));
+INSERT INTO t3 VALUES (69, foo(69,
+ 'ha_write_row_end SIGNAL d3_query WAIT_FOR d3_cont2',
+ 'rpl_parallel_end_of_group SIGNAL d3_done WAIT_FOR d3_cont'));
+COMMIT;
+SET gtid_domain_id=0;
+
+--connection server_2
+SET debug_sync='now WAIT_FOR d3_query';
+--let $d3_thd_id= `SELECT ID FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO LIKE '%foo(69%' AND INFO NOT LIKE '%LIKE%'`
+
+SET debug_sync='now SIGNAL d2_cont2';
+SET debug_sync='now WAIT_FOR d2_done';
+SET debug_sync='now SIGNAL d1_cont2';
+SET debug_sync='now WAIT_FOR d1_done';
+SET debug_sync='now SIGNAL d0_cont2';
+SET debug_sync='now WAIT_FOR d0_done';
+SET debug_sync='now SIGNAL d3_cont2';
+SET debug_sync='now WAIT_FOR d3_done';
+
+# Now prepare the real transactions T1, T2, T3, T4 on the master.
+
+--connection con_temp3
+# Create transaction T1.
+INSERT INTO t3 VALUES (64, foo(64,
+ 'rpl_parallel_before_mark_start_commit SIGNAL t1_waiting WAIT_FOR t1_cont', ''));
+
+# Create transaction T2, as a group commit leader on the master.
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2 WAIT_FOR master_cont2';
+send INSERT INTO t3 VALUES (65, foo(65, '', ''));
+
+--connection server_1
+SET debug_sync='now WAIT_FOR master_queued2';
+
+--connection con_temp4
+# Create transaction T3, participating in T2's group commit.
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued3';
+send INSERT INTO t3 VALUES (66, foo(66, '', ''));
+
+--connection server_1
+SET debug_sync='now WAIT_FOR master_queued3';
+
+--connection con_temp5
+# Create transaction T4, participating in group commit with T2 and T3.
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued4';
+send INSERT INTO t3 VALUES (67, foo(67, '', ''));
+
+--connection server_1
+SET debug_sync='now WAIT_FOR master_queued4';
+SET debug_sync='now SIGNAL master_cont2';
+
+--connection con_temp3
+REAP;
+--connection con_temp4
+REAP;
+--connection con_temp5
+REAP;
+
+--connection server_1
+SELECT * FROM t3 WHERE a >= 60 ORDER BY a;
+SET debug_sync='RESET';
+
+--connection server_2
+# Now we have the four transactions pending for replication on the slave.
+# Let them be queued for our three worker threads in a controlled fashion.
+# We put them at a stage where T1 is delayed and T3 is waiting for T1 to
+# commit before T3 can start. Then we kill T3.
+
+# Make the worker D0 free, and wait for T1 to be queued in it.
+SET debug_sync='now SIGNAL d0_cont';
+SET debug_sync='now WAIT_FOR t1_waiting';
+
+# Make the worker D3 free, and wait for T2 to be queued in it.
+SET debug_sync='now SIGNAL d3_cont';
+SET debug_sync='now WAIT_FOR t2_waiting';
+
+# Now release worker D1, and wait for T3 to be queued in it.
+# T3 will wait for T1 to commit before it can start.
+SET debug_sync='now SIGNAL d1_cont';
+SET debug_sync='now WAIT_FOR t3_waiting';
+
+# Release worker D2. Wait for T4 to be queued, so we are sure it has
+# received the debug_sync signal (else we might overwrite it with the
+# next debug_sync).
+SET debug_sync='now SIGNAL d2_cont';
+SET debug_sync='now WAIT_FOR t4_waiting';
+
+# Now we kill the waiting transaction T3 in worker D1.
+--replace_result $d1_thd_id THD_ID
+eval KILL $d1_thd_id;
+
+# Wait until T3 has reacted on the kill.
+SET debug_sync='now WAIT_FOR t3_killed';
+
+# Now we can allow T1 to proceed.
+SET debug_sync='now SIGNAL t1_cont';
+
+--let $slave_sql_errno= 1317,1927,1964
+--source include/wait_for_slave_sql_error.inc
+STOP SLAVE IO_THREAD;
+# Since T2, T3, and T4 run in parallel, we can not be sure if T2 will have time
+# to commit or not before the stop. However, T1 should commit, and T3/T4 may
+# not have committed. (After slave restart we check that all become committed
+# eventually).
+SELECT * FROM t3 WHERE a >= 60 AND a != 65 ORDER BY a;
+
+# Now we have to disable the debug_sync statements, so they do not trigger
+# when the events are retried.
+SET debug_sync='RESET';
+SET GLOBAL slave_parallel_threads=0;
+SET GLOBAL slave_parallel_threads=10;
+SET sql_log_bin=0;
+DROP FUNCTION foo;
+--delimiter ||
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+ RETURNS INT DETERMINISTIC
+ BEGIN
+ RETURN x;
+ END
+||
+--delimiter ;
+SET sql_log_bin=1;
+
+--connection server_1
+UPDATE t3 SET b=b+1 WHERE a=60;
+--save_master_pos
+
+--connection server_2
+--source include/start_slave.inc
+--sync_with_master
+SELECT * FROM t3 WHERE a >= 60 ORDER BY a;
+# Restore the foo() function.
+SET sql_log_bin=0;
+DROP FUNCTION foo;
+--delimiter ||
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+ RETURNS INT DETERMINISTIC
+ BEGIN
+ IF d1 != '' THEN
+ SET debug_sync = d1;
+ END IF;
+ IF d2 != '' THEN
+ SET debug_sync = d2;
+ END IF;
+ RETURN x;
+ END
+||
+--delimiter ;
+SET sql_log_bin=1;
+
+--connection server_2
+# Respawn all worker threads to clear any left-over debug_sync or other stuff.
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=0;
+SET GLOBAL slave_parallel_threads=10;
+--source include/start_slave.inc
+
+--echo *** 5. Test killing thread that is waiting for queue of max length to shorten ***
+
+# Find the thread id of the driver SQL thread that we want to kill.
+--let $wait_condition= SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE '%Slave has read all relay log%'
+--source include/wait_condition.inc
+--let $thd_id= `SELECT ID FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE '%Slave has read all relay log%'`
+SET @old_max_queued= @@GLOBAL.slave_parallel_max_queued;
+SET GLOBAL slave_parallel_max_queued=9000;
+
+--connection server_1
+--let bigstring= `SELECT REPEAT('x', 10000)`
+# Create an event that will wait to be signalled.
+INSERT INTO t3 VALUES (80, foo(0,
+ 'ha_write_row_end SIGNAL query_waiting WAIT_FOR query_cont', ''));
+
+--connection server_2
+SET debug_sync='now WAIT_FOR query_waiting';
+# Inject that the SQL driver thread will signal `wait_queue_ready' to debug_sync
+# as it goes to wait for the event queue to become smaller than the value of
+# @@slave_parallel_max_queued.
+SET @old_dbug= @@GLOBAL.debug_dbug;
+SET GLOBAL debug_dbug="+d,rpl_parallel_wait_queue_max";
+
+--connection server_1
+--disable_query_log
+# Create an event that will fill up the queue.
+# The Xid event at the end of the event group will have to wait for the Query
+# event with the INSERT to drain so the queue becomes shorter. However that in
+# turn waits for the prior event group to continue.
+eval INSERT INTO t3 VALUES (81, LENGTH('$bigstring'));
+--enable_query_log
+SELECT * FROM t3 WHERE a >= 80 ORDER BY a;
+
+--connection server_2
+SET debug_sync='now WAIT_FOR wait_queue_ready';
+
+--replace_result $thd_id THD_ID
+eval KILL $thd_id;
+
+SET debug_sync='now WAIT_FOR wait_queue_killed';
+SET debug_sync='now SIGNAL query_cont';
+
+--let $slave_sql_errno= 1317,1927,1964
+--source include/wait_for_slave_sql_error.inc
+STOP SLAVE IO_THREAD;
+
+SET GLOBAL debug_dbug=@old_dbug;
+SET GLOBAL slave_parallel_max_queued= @old_max_queued;
+
+--connection server_1
+INSERT INTO t3 VALUES (82,0);
+--save_master_pos
+
+--connection server_2
+SET debug_sync='RESET';
+--source include/start_slave.inc
+--sync_with_master
+SELECT * FROM t3 WHERE a >= 80 ORDER BY a;
+
+--connection server_2
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_mode=@old_parallel_mode;
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+--source include/start_slave.inc
+SET DEBUG_SYNC= 'RESET';
+
+--connection server_1
+DROP function foo;
+DROP TABLE t3;
+SET DEBUG_SYNC= 'RESET';
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/include/rpl_parallel_gtid_slave_pos_update_fail.inc b/mysql-test/suite/rpl/include/rpl_parallel_gtid_slave_pos_update_fail.inc
new file mode 100644
index 00000000000..da1a07d3b87
--- /dev/null
+++ b/mysql-test/suite/rpl/include/rpl_parallel_gtid_slave_pos_update_fail.inc
@@ -0,0 +1,98 @@
+# MDEV-6549, failing to update gtid_slave_pos for a transaction that was retried.
+
+# The problem was that when a transaction updates the mysql.gtid_slave_pos
+# table, it clears the flag that marks that there is a GTID position that
+# needs to be updated. Then, if the transaction got killed after that due
+# to a deadlock, the subsequent retry would fail to notice that the GTID needs
+# to be recorded in gtid_slave_pos.
+#
+# (In the original bug report, the symptom was an assertion; this was however
+# just a side effect of the missing update of gtid_slave_pos, which also
+# happened to cause a missing clear of OPTION_GTID_BEGIN).
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/have_debug_sync.inc
+# Must use statement-based binlogging. Otherwise the transaction will not be
+# binlogged at all, as it modifies no rows.
+--source include/have_binlog_format_statement.inc
+--source include/master-slave.inc
+
+--connection server_2
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=10;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+--source include/start_slave.inc
+
+--connection server_1
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t4 (a INT PRIMARY KEY, b INT, KEY b_idx(b)) ENGINE=InnoDB;
+INSERT INTO t4 VALUES (1,NULL), (2,2), (3,NULL), (4,4), (5, NULL), (6, 6);
+--connect (con1,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
+--connect (con2,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+--source include/stop_slave.inc
+
+# Create two transactions that can run in parallel on the slave but cause
+# a deadlock if the second runs before the first.
+--connection con1
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
+send UPDATE t4 SET b=NULL WHERE a=6;
+--connection server_1
+SET debug_sync='now WAIT_FOR master_queued1';
+
+--connection con2
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
+send DELETE FROM t4 WHERE b <= 1;
+
+--connection server_1
+SET debug_sync='now WAIT_FOR master_queued2';
+SET debug_sync='now SIGNAL master_cont1';
+
+--connection con1
+REAP;
+--connection con2
+REAP;
+SET debug_sync='RESET';
+--save_master_pos
+--let $last_gtid= `SELECT @@last_gtid`
+
+--connection server_2
+# Disable the usual skip of gap locks for transactions that are run in
+# parallel, using DBUG. This allows the deadlock to occur, and this in turn
+# triggers a retry of the second transaction, and the code that was buggy and
+# caused the gtid_slave_pos update to be skipped in the retry.
+SET @old_dbug= @@GLOBAL.debug_dbug;
+SET GLOBAL debug_dbug="+d,disable_thd_need_ordering_with";
+--source include/start_slave.inc
+--sync_with_master
+SET GLOBAL debug_dbug=@old_dbug;
+
+SELECT * FROM t4 ORDER BY a;
+# Check that the GTID of the second transaction was correctly recorded in
+# gtid_slave_pos, in the variable as well as in the table.
+--replace_result $last_gtid GTID
+eval SET @last_gtid= '$last_gtid';
+SELECT IF(@@gtid_slave_pos LIKE CONCAT('%',@last_gtid,'%'), "GTID found ok",
+ CONCAT("GTID ", @last_gtid, " not found in gtid_slave_pos=", @@gtid_slave_pos))
+ AS result;
+SELECT "ROW FOUND" AS `Is the row found?`
+ FROM mysql.gtid_slave_pos
+ WHERE CONCAT(domain_id, "-", server_id, "-", seq_no) = @last_gtid;
+
+# Clean up.
+--connection server_2
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+--source include/start_slave.inc
+SET DEBUG_SYNC= 'RESET';
+
+--connection server_1
+DROP TABLE t4;
+SET DEBUG_SYNC= 'RESET';
+--disconnect con1
+--disconnect con2
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/include/rpl_parallel_ignored_errors.inc b/mysql-test/suite/rpl/include/rpl_parallel_ignored_errors.inc
new file mode 100644
index 00000000000..2fab9f8032b
--- /dev/null
+++ b/mysql-test/suite/rpl/include/rpl_parallel_ignored_errors.inc
@@ -0,0 +1,96 @@
+--echo *** MDEV-6551: Some replication errors are ignored if slave_parallel_threads > 0 ***
+
+--source include/have_innodb.inc
+--source include/have_binlog_format_statement.inc
+--source include/master-slave.inc
+
+--connection server_2
+--source include/stop_slave.inc
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+SET @old_parallel_mode=@@GLOBAL.slave_parallel_mode;
+SET GLOBAL slave_parallel_threads=1;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+CALL mtr.add_suppression("Commit failed due to failure of an earlier commit on which this one depends");
+--source include/start_slave.inc
+
+--connection server_1
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t2 (a int PRIMARY KEY) ENGINE=InnoDB;
+SET gtid_domain_id=1;
+INSERT INTO t2 VALUES (1);
+SET gtid_domain_id=0;
+SET gtid_domain_id=2;
+INSERT INTO t2 VALUES (2);
+SET gtid_domain_id=0;
+INSERT INTO t2 VALUES (31);
+--let $gtid1= `SELECT @@LAST_GTID`
+--source include/save_master_gtid.inc
+
+--connection server_2
+--source include/sync_with_master_gtid.inc
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads= 0;
+--source include/start_slave.inc
+
+# Force a duplicate key error on the slave.
+SET sql_log_bin= 0;
+INSERT INTO t2 VALUES (32);
+SET sql_log_bin= 1;
+
+--connection server_1
+INSERT INTO t2 VALUES (32);
+--let $gtid2= `SELECT @@LAST_GTID`
+# Rotate the binlog; the bug is triggered when the master binlog file changes
+# after the event group that causes the duplicate key error.
+FLUSH LOGS;
+INSERT INTO t2 VALUES (33);
+INSERT INTO t2 VALUES (34);
+SELECT * FROM t2 WHERE a >= 30 ORDER BY a;
+--source include/save_master_gtid.inc
+
+--connection server_2
+--let $slave_sql_errno= 1062
+--source include/wait_for_slave_sql_error.inc
+
+--connection server_2
+--source include/stop_slave_io.inc
+SET GLOBAL slave_parallel_threads=10;
+START SLAVE;
+
+--let $slave_sql_errno= 1062
+--source include/wait_for_slave_sql_error.inc
+
+# Note: IO thread is still running at this point.
+# The bug seems to have been that restarting the SQL thread after an error with
+# the IO thread still running, somehow picks up a later relay log position and
+# thus ends up skipping the failing event, rather than re-executing.
+
+START SLAVE SQL_THREAD;
+--let $slave_sql_errno= 1062
+--source include/wait_for_slave_sql_error.inc
+
+SELECT * FROM t2 WHERE a >= 30 ORDER BY a;
+
+# Skip the duplicate error, so we can proceed.
+--error ER_SLAVE_SKIP_NOT_IN_GTID
+SET sql_slave_skip_counter= 1;
+--source include/stop_slave_io.inc
+--disable_query_log
+eval SET GLOBAL gtid_slave_pos = REPLACE(@@gtid_slave_pos, "$gtid1", "$gtid2");
+--enable_query_log
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+
+SELECT * FROM t2 WHERE a >= 30 ORDER BY a;
+
+# Clean up.
+--connection server_2
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+SET GLOBAL slave_parallel_mode=@old_parallel_mode;
+--source include/start_slave.inc
+
+--connection server_1
+DROP TABLE t2;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/include/rpl_parallel_incorrect_relay_pos.inc b/mysql-test/suite/rpl/include/rpl_parallel_incorrect_relay_pos.inc
new file mode 100644
index 00000000000..3cf0afd63ca
--- /dev/null
+++ b/mysql-test/suite/rpl/include/rpl_parallel_incorrect_relay_pos.inc
@@ -0,0 +1,128 @@
+--echo *** MDEV-7237: Parallel replication: incorrect relaylog position after stop/start the slave ***
+
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/have_debug_sync.inc
+--source include/master-slave.inc
+
+--connection server_2
+--source include/stop_slave.inc
+CALL mtr.add_suppression("Commit failed due to failure of an earlier commit on which this one depends");
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+SET @old_parallel_mode=@@GLOBAL.slave_parallel_mode;
+SET GLOBAL slave_parallel_threads=10;
+# Test assumes that 'conservative' mode is in effect. i.e
+# Do not start parallel execution of this event group until all prior groups
+# have reached the commit phase. Upon execution of STOP SLAVE there can be one
+# group which is executing and the rest are doing group commit order wait.
+SET GLOBAL slave_parallel_mode='conservative';
+CHANGE MASTER TO master_use_gtid=slave_pos;
+--source include/start_slave.inc
+
+--connection server_1
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t2 (a int PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t2 VALUES (40);
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+--connect (con_temp2,127.0.0.1,root,,test,$SERVER_MYPORT_2,)
+--source include/stop_slave.inc
+CHANGE MASTER TO master_use_gtid=no;
+SET @old_dbug= @@GLOBAL.debug_dbug;
+# This DBUG injection causes a DEBUG_SYNC signal "scheduled_gtid_0_x_100" when
+# GTID 0-1-100 has been scheduled for and fetched by a worker thread.
+SET GLOBAL debug_dbug="+d,rpl_parallel_scheduled_gtid_0_x_100";
+# This DBUG injection causes a DEBUG_SYNC signal "wait_for_done_waiting" when
+# STOP SLAVE has signalled all worker threads to stop.
+SET GLOBAL debug_dbug="+d,rpl_parallel_wait_for_done_trigger";
+# Reset worker threads to make DBUG setting catch on.
+SET GLOBAL slave_parallel_threads=0;
+SET GLOBAL slave_parallel_threads=10;
+
+
+--connection server_1
+# Setup some transaction for the slave to replicate.
+INSERT INTO t2 VALUES (41);
+INSERT INTO t2 VALUES (42);
+# Need to log the DELETE in statement format, so we can see it in processlist.
+SET @old_format= @@binlog_format;
+SET binlog_format= statement;
+DELETE FROM t2 WHERE a=40;
+SET binlog_format= @old_format;
+INSERT INTO t2 VALUES (43);
+INSERT INTO t2 VALUES (44);
+# Force the slave to switch to a new relay log file.
+FLUSH LOGS;
+INSERT INTO t2 VALUES (45);
+# Inject a GTID 0-1-100, which will trigger a DEBUG_SYNC signal when this
+# transaction has been fetched by a worker thread.
+SET gtid_seq_no=100;
+INSERT INTO t2 VALUES (46);
+--save_master_pos
+
+--connection con_temp2
+# Temporarily block the DELETE on a=40 from completing.
+BEGIN;
+SELECT * FROM t2 WHERE a=40 FOR UPDATE;
+
+--connection server_2
+--source include/start_slave.inc
+
+# Wait for a worker thread to start on the DELETE that will be blocked
+# temporarily by the SELECT FOR UPDATE.
+--let $wait_condition= SELECT count(*) > 0 FROM information_schema.processlist WHERE state='updating' and info LIKE '%DELETE FROM t2 WHERE a=40%'
+--source include/wait_condition.inc
+
+# The DBUG injection set above will make the worker thread signal the following
+# debug_sync when the GTID 0-1-100 has been reached by a worker thread.
+# Thus, at this point, the SQL driver thread has reached the next
+# relay log file name, while a worker thread is still processing a
+# transaction in the previous relay log file, blocked on the SELECT FOR
+# UPDATE.
+SET debug_sync= 'now WAIT_FOR scheduled_gtid_0_x_100';
+# At this point, the SQL driver thread is in the new relay log file, while
+# the DELETE from the old relay log file is not yet complete. We will stop
+# the slave at this point. The bug was that the DELETE statement would
+# update the slave position to the _new_ relay log file name instead of
+# its own old file name. Thus, by stoping and restarting the slave at this
+# point, we would get an error at restart due to incorrect position. (If
+# we would let the slave catch up before stopping, the incorrect position
+# would be corrected by a later transaction).
+
+send STOP SLAVE;
+
+--connection con_temp2
+# Wait for STOP SLAVE to have proceeded sufficiently that it has signalled
+# all worker threads to stop; this ensures that we will stop after the DELETE
+# transaction (and not after a later transaction that might have been able
+# to set a fixed position).
+SET debug_sync= 'now WAIT_FOR wait_for_done_waiting';
+# Now release the row lock that was blocking the replication of DELETE.
+ROLLBACK;
+
+--connection server_2
+reap;
+--source include/wait_for_slave_sql_to_stop.inc
+SELECT * FROM t2 WHERE a >= 40 ORDER BY a;
+# Now restart the slave. With the bug present, this would start at an
+# incorrect relay log position, causing relay log read error (or if unlucky,
+# silently skip a number of events).
+--source include/start_slave.inc
+--sync_with_master
+SELECT * FROM t2 WHERE a >= 40 ORDER BY a;
+
+# Clean up.
+--source include/stop_slave.inc
+SET GLOBAL debug_dbug=@old_dbug;
+SET DEBUG_SYNC= 'RESET';
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+SET GLOBAL slave_parallel_mode=@old_parallel_mode;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+--source include/start_slave.inc
+
+--connection server_1
+DROP TABLE t2;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/include/rpl_parallel_innodb_lock_conflict.inc b/mysql-test/suite/rpl/include/rpl_parallel_innodb_lock_conflict.inc
new file mode 100644
index 00000000000..90304937445
--- /dev/null
+++ b/mysql-test/suite/rpl/include/rpl_parallel_innodb_lock_conflict.inc
@@ -0,0 +1,107 @@
+--echo ***MDEV-5914: Parallel replication deadlock due to InnoDB lock conflicts ***
+
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/have_debug_sync.inc
+--source include/master-slave.inc
+
+--connection server_2
+SET sql_log_bin=0;
+CALL mtr.add_suppression("Commit failed due to failure of an earlier commit on which this one depends");
+SET sql_log_bin=1;
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=10;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+
+--connection server_1
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t4 (a INT PRIMARY KEY, b INT, KEY b_idx(b)) ENGINE=InnoDB;
+INSERT INTO t4 VALUES (1,NULL), (2,2), (3,NULL), (4,4), (5, NULL), (6, 6);
+--connect (con1,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
+--connect (con2,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
+
+# Create a group commit with UPDATE and DELETE, in that order.
+# The bug was that while the UPDATE's row lock does not block the DELETE, the
+# DELETE's gap lock _does_ block the UPDATE. This could cause a deadlock
+# on the slave.
+--connection con1
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
+send UPDATE t4 SET b=NULL WHERE a=6;
+--connection server_1
+SET debug_sync='now WAIT_FOR master_queued1';
+
+--connection con2
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
+send DELETE FROM t4 WHERE b <= 3;
+
+--connection server_1
+SET debug_sync='now WAIT_FOR master_queued2';
+SET debug_sync='now SIGNAL master_cont1';
+
+--connection con1
+REAP;
+--connection con2
+REAP;
+SET debug_sync='RESET';
+--save_master_pos
+
+--connection server_2
+--source include/start_slave.inc
+--sync_with_master
+--source include/stop_slave.inc
+
+SELECT * FROM t4 ORDER BY a;
+
+
+# Another example, this one with INSERT vs. DELETE
+--connection server_1
+DELETE FROM t4;
+INSERT INTO t4 VALUES (1,NULL), (2,2), (3,NULL), (4,4), (5, NULL), (6, 6);
+
+# Create a group commit with INSERT and DELETE, in that order.
+# The bug was that while the INSERT's insert intention lock does not block
+# the DELETE, the DELETE's gap lock _does_ block the INSERT. This could cause
+# a deadlock on the slave.
+--connection con1
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
+send INSERT INTO t4 VALUES (7, NULL);
+--connection server_1
+SET debug_sync='now WAIT_FOR master_queued1';
+
+--connection con2
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
+send DELETE FROM t4 WHERE b <= 3;
+
+--connection server_1
+SET debug_sync='now WAIT_FOR master_queued2';
+SET debug_sync='now SIGNAL master_cont1';
+
+--connection con1
+REAP;
+--connection con2
+REAP;
+SET debug_sync='RESET';
+--save_master_pos
+
+--connection server_2
+--source include/start_slave.inc
+--sync_with_master
+--source include/stop_slave.inc
+
+SELECT * FROM t4 ORDER BY a;
+
+
+# Clean up.
+--connection server_2
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+--source include/start_slave.inc
+SET DEBUG_SYNC= 'RESET';
+
+--connection server_1
+--disconnect con1
+--disconnect con2
+DROP TABLE t4;
+SET DEBUG_SYNC= 'RESET';
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/include/rpl_parallel_missed_error_handling.inc b/mysql-test/suite/rpl/include/rpl_parallel_missed_error_handling.inc
new file mode 100644
index 00000000000..33b1bcb11d9
--- /dev/null
+++ b/mysql-test/suite/rpl/include/rpl_parallel_missed_error_handling.inc
@@ -0,0 +1,87 @@
+--echo *** MDEV-5921: In parallel replication, an error is not correctly signalled to the next transaction ***
+
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/have_debug_sync.inc
+--source include/master-slave.inc
+
+--connection server_2
+--source include/stop_slave.inc
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+SET GLOBAL slave_parallel_threads=10;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+CALL mtr.add_suppression("Commit failed due to failure of an earlier commit on which this one depends");
+--source include/start_slave.inc
+
+--connection server_1
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+
+--connection server_1
+INSERT INTO t3 VALUES (110, 1);
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+SELECT * FROM t3 WHERE a >= 110 ORDER BY a;
+# Inject a duplicate key error.
+SET sql_log_bin=0;
+INSERT INTO t3 VALUES (111, 666);
+SET sql_log_bin=1;
+
+--connection server_1
+
+# Create a group commit with two inserts, the first one conflicts with a row on the slave
+--connect (con1,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
+send INSERT INTO t3 VALUES (111, 2);
+--connection server_1
+SET debug_sync='now WAIT_FOR master_queued1';
+
+--connect (con2,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
+send INSERT INTO t3 VALUES (112, 3);
+
+--connection server_1
+SET debug_sync='now WAIT_FOR master_queued2';
+SET debug_sync='now SIGNAL master_cont1';
+
+--connection con1
+REAP;
+--connection con2
+REAP;
+SET debug_sync='RESET';
+--save_master_pos
+
+--connection server_2
+--let $slave_sql_errno= 1062
+--source include/wait_for_slave_sql_error.inc
+--source include/wait_for_slave_sql_to_stop.inc
+# We should not see the row (112,3) here, it should be rolled back due to
+# error signal from the prior transaction.
+SELECT * FROM t3 WHERE a >= 110 ORDER BY a;
+SET sql_log_bin=0;
+DELETE FROM t3 WHERE a=111 AND b=666;
+SET sql_log_bin=1;
+START SLAVE SQL_THREAD;
+--sync_with_master
+SELECT * FROM t3 WHERE a >= 110 ORDER BY a;
+
+# Clean up.
+--connection server_2
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+--source include/start_slave.inc
+SET DEBUG_SYNC= 'RESET';
+
+--connection server_1
+--disconnect con1
+--disconnect con2
+DROP TABLE t3;
+SET DEBUG_SYNC= 'RESET';
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/include/rpl_parallel_mode.inc b/mysql-test/suite/rpl/include/rpl_parallel_mode.inc
new file mode 100644
index 00000000000..67104069e9a
--- /dev/null
+++ b/mysql-test/suite/rpl/include/rpl_parallel_mode.inc
@@ -0,0 +1,87 @@
+--echo *** MDEV-6676 - test syntax of @@slave_parallel_mode ***
+
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/master-slave.inc
+
+--connection server_2
+--source include/stop_slave.inc
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+SET @old_parallel_mode=@@GLOBAL.slave_parallel_mode;
+SET GLOBAL slave_parallel_threads=10;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+--source include/start_slave.inc
+
+--connection server_1
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t2 (a int PRIMARY KEY) ENGINE=InnoDB;
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+
+--let $status_items= Parallel_Mode
+--source include/show_slave_status.inc
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_mode='aggressive';
+--let $status_items= Parallel_Mode
+--source include/show_slave_status.inc
+SET GLOBAL slave_parallel_mode='conservative';
+--let $status_items= Parallel_Mode
+--source include/show_slave_status.inc
+
+--echo *** MDEV-6676 - test that empty parallel_mode does not replicate in parallel ***
+--connection server_1
+INSERT INTO t2 VALUES (1040);
+--source include/save_master_gtid.inc
+
+--connection server_2
+SET GLOBAL slave_parallel_mode='none';
+# Test that we do not use parallel apply, by injecting an unconditional
+# crash in the parallel apply code.
+SET @old_dbug= @@GLOBAL.debug_dbug;
+SET GLOBAL debug_dbug="+d,slave_crash_if_parallel_apply";
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+SELECT * FROM t2 WHERE a >= 1040 ORDER BY a;
+--source include/stop_slave.inc
+SET GLOBAL debug_dbug=@old_dbug;
+
+
+--echo *** MDEV-6676 - test disabling domain-based parallel replication ***
+--connection server_1
+# Let's do a bunch of transactions that will conflict if run out-of-order in
+# domain-based parallel replication mode.
+SET gtid_domain_id = 1;
+INSERT INTO t2 VALUES (1041);
+INSERT INTO t2 VALUES (1042);
+INSERT INTO t2 VALUES (1043);
+INSERT INTO t2 VALUES (1044);
+INSERT INTO t2 VALUES (1045);
+INSERT INTO t2 VALUES (1046);
+DELETE FROM t2 WHERE a >= 1041;
+SET gtid_domain_id = 2;
+INSERT INTO t2 VALUES (1041);
+INSERT INTO t2 VALUES (1042);
+INSERT INTO t2 VALUES (1043);
+INSERT INTO t2 VALUES (1044);
+INSERT INTO t2 VALUES (1045);
+INSERT INTO t2 VALUES (1046);
+SET gtid_domain_id = 0;
+--source include/save_master_gtid.inc
+--connection server_2
+SET GLOBAL slave_parallel_mode=minimal;
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+SELECT * FROM t2 WHERE a >= 1040 ORDER BY a;
+
+# Cleanup
+--source include/stop_slave.inc
+SET GLOBAL debug_dbug=@old_dbug;
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+SET GLOBAL slave_parallel_mode=@old_parallel_mode;
+--source include/start_slave.inc
+
+--connection server_1
+DROP TABLE t2;
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/include/rpl_parallel_partial_binlog_trans.inc b/mysql-test/suite/rpl/include/rpl_parallel_partial_binlog_trans.inc
new file mode 100644
index 00000000000..7247925285f
--- /dev/null
+++ b/mysql-test/suite/rpl/include/rpl_parallel_partial_binlog_trans.inc
@@ -0,0 +1,71 @@
+--echo *** MDEV_6435: Incorrect error handling when query binlogged partially on master with "killed" error ***
+
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/have_debug_sync.inc
+--source include/have_binlog_format_statement.inc
+--source include/master-slave.inc
+
+--connection server_2
+--source include/stop_slave.inc
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+SET GLOBAL slave_parallel_threads=1;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+--source include/start_slave.inc
+
+--connection server_1
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t6 (a INT) ENGINE=MyISAM;
+CREATE TRIGGER tr AFTER INSERT ON t6 FOR EACH ROW SET @a = 1;
+--connect (con1,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
+
+--connection con1
+--let $conid = `SELECT CONNECTION_ID()`
+SET debug_sync='sp_head_execute_before_loop SIGNAL ready WAIT_FOR cont';
+send INSERT INTO t6 VALUES (1), (2), (3);
+
+--connection server_1
+SET debug_sync='now WAIT_FOR ready';
+--replace_result $conid CONID
+eval KILL QUERY $conid;
+SET debug_sync='now SIGNAL cont';
+
+--connection con1
+--error ER_QUERY_INTERRUPTED
+--reap
+SET debug_sync='RESET';
+--let $after_error_gtid_pos= `SELECT @@gtid_binlog_pos`
+
+--connection server_1
+SET debug_sync='RESET';
+
+--connection server_2
+--let $slave_sql_errno= 1317
+--source include/wait_for_slave_sql_error.inc
+STOP SLAVE IO_THREAD;
+--replace_result $after_error_gtid_pos AFTER_ERROR_GTID_POS
+eval SET GLOBAL gtid_slave_pos= '$after_error_gtid_pos';
+--source include/start_slave.inc
+
+--connection server_1
+INSERT INTO t6 VALUES (4);
+SELECT * FROM t6 ORDER BY a;
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+SELECT * FROM t6 ORDER BY a;
+
+# Clean up.
+--connection server_2
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+--source include/start_slave.inc
+SET DEBUG_SYNC= 'RESET';
+
+--connection server_1
+DROP TABLE t6;
+SET DEBUG_SYNC= 'RESET';
+--disconnect con1
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/include/rpl_parallel_record_gtid_wakeup.inc b/mysql-test/suite/rpl/include/rpl_parallel_record_gtid_wakeup.inc
new file mode 100644
index 00000000000..0f94d8f9943
--- /dev/null
+++ b/mysql-test/suite/rpl/include/rpl_parallel_record_gtid_wakeup.inc
@@ -0,0 +1,72 @@
+--echo *** MDEV-7929: record_gtid() for non-transactional event group calls wakeup_subsequent_commits() too early, causing slave hang. ***
+
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/have_debug_sync.inc
+--source include/master-slave.inc
+
+--connection server_2
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=10;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+--source include/start_slave.inc
+
+--connection server_1
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t1 (a int PRIMARY KEY) ENGINE=MyISAM;
+CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+--source include/stop_slave.inc
+SET @old_dbug= @@GLOBAL.debug_dbug;
+SET GLOBAL debug_dbug= '+d,inject_record_gtid_serverid_100_sleep';
+
+--connection server_1
+# Inject two group commits. The bug was that record_gtid for a
+# non-transactional event group would commit its own transaction, which would
+# cause ha_commit_trans() to call wakeup_subsequent_commits() too early. This
+# in turn lead to access to freed group_commit_orderer object, losing a wakeup
+# and causing slave threads to hang.
+# We inject a small sleep in the corresponding record_gtid() to make the race
+# easier to hit.
+
+SET @old_dbug= @@SESSION.debug_dbug;
+SET SESSION debug_dbug="+d,binlog_force_commit_id";
+
+# Group commit with cid=10010, two event groups.
+SET @old_server_id= @@SESSION.server_id;
+SET SESSION server_id= 100;
+SET @commit_id= 10010;
+ALTER TABLE t1 COMMENT "Hulubulu!";
+SET SESSION server_id= @old_server_id;
+INSERT INTO t3 VALUES (130, 0);
+
+# Group commit with cid=10011, one event group.
+SET @commit_id= 10011;
+INSERT INTO t3 VALUES (131, 0);
+
+SET SESSION debug_dbug=@old_dbug;
+
+SELECT * FROM t3 WHERE a >= 130 ORDER BY a;
+--source include/save_master_gtid.inc
+
+--connection server_2
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+
+SELECT * FROM t3 WHERE a >= 130 ORDER BY a;
+
+# Clean up.
+--source include/stop_slave.inc
+SET GLOBAL debug_dbug= @old_dbug;
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+--source include/start_slave.inc
+
+--connection server_1
+DROP TABLE t1,t3;
+
+--source include/rpl_end.inc
+
diff --git a/mysql-test/suite/rpl/include/rpl_parallel_retry_deadlock.inc b/mysql-test/suite/rpl/include/rpl_parallel_retry_deadlock.inc
new file mode 100644
index 00000000000..54ac859bb33
--- /dev/null
+++ b/mysql-test/suite/rpl/include/rpl_parallel_retry_deadlock.inc
@@ -0,0 +1,281 @@
+--echo *** MDEV-7326 Server deadlock in connection with parallel replication ***
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/have_debug_sync.inc
+--source include/master-slave.inc
+
+--connection server_2
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+SET @old_parallel_mode=@@GLOBAL.slave_parallel_mode;
+--source include/stop_slave.inc
+# Test assumes that 'conservative' mode is in effect. i.e
+# Do not start parallel execution of this event group until all prior groups
+# have reached the commit phase. Refer 'rpl_parallel_start_waiting_for_prior'
+# debug simumation.
+SET GLOBAL slave_parallel_mode='conservative';
+SET GLOBAL slave_parallel_threads=10;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+--source include/start_slave.inc
+
+--connection server_1
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t1 (a int PRIMARY KEY) ENGINE=MyISAM;
+CREATE TABLE t2 (a int PRIMARY KEY) ENGINE=InnoDB;
+CREATE TABLE t6 (a INT) ENGINE=MyISAM;
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+
+--connection server_1
+# Use a stored function to inject a debug_sync into the appropriate THD.
+# The function does nothing on the master, and on the slave it injects the
+# desired debug_sync action(s).
+SET sql_log_bin=0;
+--delimiter ||
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+ RETURNS INT DETERMINISTIC
+ BEGIN
+ RETURN x;
+ END
+||
+--delimiter ;
+SET sql_log_bin=1;
+
+--connection server_2
+SET sql_log_bin=0;
+--delimiter ||
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+ RETURNS INT DETERMINISTIC
+ BEGIN
+ IF d1 != '' THEN
+ SET debug_sync = d1;
+ END IF;
+ IF d2 != '' THEN
+ SET debug_sync = d2;
+ END IF;
+ RETURN x;
+ END
+||
+--delimiter ;
+SET sql_log_bin=1;
+
+# We use three transactions, each in a separate group commit.
+# T1 does mark_start_commit(), then gets a deadlock error.
+# T2 wakes up and starts running
+# T1 does unmark_start_commit()
+# T3 goes to wait for T2 to start its commit
+# T2 does mark_start_commit()
+# The bug was that at this point, T3 got deadlocked. Because T1 has unmarked(),
+# T3 did not yet see the count_committing_event_groups reach its target value
+# yet. But when T1 later re-did mark_start_commit(), it failed to send a wakeup
+# to T3.
+
+--connection server_2
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=0;
+SET GLOBAL slave_parallel_threads=3;
+SET GLOBAL debug_dbug="+d,rpl_parallel_simulate_temp_err_xid";
+--source include/start_slave.inc
+
+--connection server_1
+SET @old_format= @@SESSION.binlog_format;
+SET binlog_format= STATEMENT;
+# This debug_sync will linger on and be used to control T3 later.
+INSERT INTO t1 VALUES (foo(50,
+ "rpl_parallel_start_waiting_for_prior SIGNAL t3_ready",
+ "rpl_parallel_end_of_group SIGNAL prep_ready WAIT_FOR prep_cont"));
+--save_master_pos
+--connection server_2
+# Wait for the debug_sync point for T3 to be set. But let the preparation
+# transaction remain hanging, so that T1 and T2 will be scheduled for the
+# remaining two worker threads.
+SET DEBUG_SYNC= "now WAIT_FOR prep_ready";
+
+--connection server_1
+INSERT INTO t2 VALUES (foo(50,
+ "rpl_parallel_simulate_temp_err_xid SIGNAL t1_ready1 WAIT_FOR t1_cont1",
+ "rpl_parallel_retry_after_unmark SIGNAL t1_ready2 WAIT_FOR t1_cont2"));
+--save_master_pos
+
+--connection server_2
+SET DEBUG_SYNC= "now WAIT_FOR t1_ready1";
+# T1 has now done mark_start_commit(). It will later do a rollback and retry.
+
+--connection server_1
+# Use a MyISAM table for T2 and T3, so they do not trigger the
+# rpl_parallel_simulate_temp_err_xid DBUG insertion on XID event.
+INSERT INTO t1 VALUES (foo(51,
+ "rpl_parallel_before_mark_start_commit SIGNAL t2_ready1 WAIT_FOR t2_cont1",
+ "rpl_parallel_after_mark_start_commit SIGNAL t2_ready2"));
+
+--connection server_2
+SET DEBUG_SYNC= "now WAIT_FOR t2_ready1";
+# T2 has now started running, but has not yet done mark_start_commit()
+SET DEBUG_SYNC= "now SIGNAL t1_cont1";
+SET DEBUG_SYNC= "now WAIT_FOR t1_ready2";
+# T1 has now done unmark_start_commit() in preparation for its retry.
+
+--connection server_1
+INSERT INTO t1 VALUES (52);
+SET BINLOG_FORMAT= @old_format;
+SELECT * FROM t2 WHERE a>=50 ORDER BY a;
+SELECT * FROM t1 WHERE a>=50 ORDER BY a;
+
+--connection server_2
+# Let the preparation transaction complete, so that the same worker thread
+# can continue with the transaction T3.
+SET DEBUG_SYNC= "now SIGNAL prep_cont";
+SET DEBUG_SYNC= "now WAIT_FOR t3_ready";
+# T3 has now gone to wait for T2 to start committing
+SET DEBUG_SYNC= "now SIGNAL t2_cont1";
+SET DEBUG_SYNC= "now WAIT_FOR t2_ready2";
+# T2 has now done mark_start_commit().
+# Let things run, and check that T3 does not get deadlocked.
+SET DEBUG_SYNC= "now SIGNAL t1_cont2";
+--sync_with_master
+
+--connection server_1
+--save_master_pos
+--connection server_2
+--sync_with_master
+SELECT * FROM t2 WHERE a>=50 ORDER BY a;
+SELECT * FROM t1 WHERE a>=50 ORDER BY a;
+SET DEBUG_SYNC="reset";
+
+# Re-spawn the worker threads to remove any DBUG injections or DEBUG_SYNC.
+--source include/stop_slave.inc
+SET GLOBAL debug_dbug=@old_dbug;
+SET GLOBAL slave_parallel_mode=@old_parallel_mode;
+SET GLOBAL slave_parallel_threads=0;
+SET GLOBAL slave_parallel_threads=10;
+--source include/start_slave.inc
+
+
+--echo *** MDEV-7326 Server deadlock in connection with parallel replication ***
+# Similar to the previous test, but with T2 and T3 in the same GCO.
+# We use three transactions, T1 in one group commit and T2/T3 in another.
+# T1 does mark_start_commit(), then gets a deadlock error.
+# T2 wakes up and starts running
+# T1 does unmark_start_commit()
+# T3 goes to wait for T1 to start its commit
+# T2 does mark_start_commit()
+# The bug was that at this point, T3 got deadlocked. T2 increments the
+# count_committing_event_groups but does not signal T3, as they are in
+# the same GCO. Then later when T1 increments, it would also not signal
+# T3, because now the count_committing_event_groups is not equal to the
+# wait_count of T3 (it is one larger).
+
+--connect (con_temp3,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
+--connect (con_temp4,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
+
+--connection server_2
+--source include/stop_slave.inc
+SET @old_parallel_mode= @@GLOBAL.slave_parallel_mode;
+SET GLOBAL slave_parallel_mode='conservative';
+SET GLOBAL slave_parallel_threads=0;
+SET GLOBAL slave_parallel_threads=3;
+SET GLOBAL debug_dbug="+d,rpl_parallel_simulate_temp_err_xid";
+--source include/start_slave.inc
+
+--connection server_1
+SET @old_format= @@SESSION.binlog_format;
+SET binlog_format= STATEMENT;
+# This debug_sync will linger on and be used to control T3 later.
+INSERT INTO t1 VALUES (foo(60,
+ "rpl_parallel_start_waiting_for_prior SIGNAL t3_ready",
+ "rpl_parallel_end_of_group SIGNAL prep_ready WAIT_FOR prep_cont"));
+--save_master_pos
+--connection server_2
+# Wait for the debug_sync point for T3 to be set. But let the preparation
+# transaction remain hanging, so that T1 and T2 will be scheduled for the
+# remaining two worker threads.
+SET DEBUG_SYNC= "now WAIT_FOR prep_ready";
+
+--connection server_1
+INSERT INTO t2 VALUES (foo(60,
+ "rpl_parallel_simulate_temp_err_xid SIGNAL t1_ready1 WAIT_FOR t1_cont1",
+ "rpl_parallel_retry_after_unmark SIGNAL t1_ready2 WAIT_FOR t1_cont2"));
+--save_master_pos
+
+--connection server_2
+SET DEBUG_SYNC= "now WAIT_FOR t1_ready1";
+# T1 has now done mark_start_commit(). It will later do a rollback and retry.
+
+# Do T2 and T3 in a single group commit.
+# Use a MyISAM table for T2 and T3, so they do not trigger the
+# rpl_parallel_simulate_temp_err_xid DBUG insertion on XID event.
+--connection con_temp3
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
+SET binlog_format=statement;
+send INSERT INTO t1 VALUES (foo(61,
+ "rpl_parallel_before_mark_start_commit SIGNAL t2_ready1 WAIT_FOR t2_cont1",
+ "rpl_parallel_after_mark_start_commit SIGNAL t2_ready2"));
+
+--connection server_1
+SET debug_sync='now WAIT_FOR master_queued1';
+
+--connection con_temp4
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
+send INSERT INTO t6 VALUES (62);
+
+--connection server_1
+SET debug_sync='now WAIT_FOR master_queued2';
+SET debug_sync='now SIGNAL master_cont1';
+
+--connection con_temp3
+REAP;
+--connection con_temp4
+REAP;
+
+--connection server_1
+SET debug_sync='RESET';
+SET BINLOG_FORMAT= @old_format;
+SELECT * FROM t2 WHERE a>=60 ORDER BY a;
+SELECT * FROM t1 WHERE a>=60 ORDER BY a;
+SELECT * FROM t6 WHERE a>=60 ORDER BY a;
+
+--connection server_2
+SET DEBUG_SYNC= "now WAIT_FOR t2_ready1";
+# T2 has now started running, but has not yet done mark_start_commit()
+SET DEBUG_SYNC= "now SIGNAL t1_cont1";
+SET DEBUG_SYNC= "now WAIT_FOR t1_ready2";
+# T1 has now done unmark_start_commit() in preparation for its retry.
+
+--connection server_2
+# Let the preparation transaction complete, so that the same worker thread
+# can continue with the transaction T3.
+SET DEBUG_SYNC= "now SIGNAL prep_cont";
+SET DEBUG_SYNC= "now WAIT_FOR t3_ready";
+# T3 has now gone to wait for T2 to start committing
+SET DEBUG_SYNC= "now SIGNAL t2_cont1";
+SET DEBUG_SYNC= "now WAIT_FOR t2_ready2";
+# T2 has now done mark_start_commit().
+# Let things run, and check that T3 does not get deadlocked.
+SET DEBUG_SYNC= "now SIGNAL t1_cont2";
+--sync_with_master
+
+--connection server_1
+--save_master_pos
+--connection server_2
+--sync_with_master
+SELECT * FROM t2 WHERE a>=60 ORDER BY a;
+SELECT * FROM t1 WHERE a>=60 ORDER BY a;
+SELECT * FROM t6 WHERE a>=60 ORDER BY a;
+SET DEBUG_SYNC="reset";
+
+# Clean up.
+--source include/stop_slave.inc
+SET GLOBAL debug_dbug=@old_dbug;
+SET GLOBAL slave_parallel_mode=@old_parallel_mode;
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+--source include/start_slave.inc
+
+--connection server_1
+DROP function foo;
+DROP TABLE t1,t2,t6;
+--disconnect con_temp3
+--disconnect con_temp4
+SET DEBUG_SYNC= 'RESET';
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/include/rpl_parallel_rollback_assert.inc b/mysql-test/suite/rpl/include/rpl_parallel_rollback_assert.inc
new file mode 100644
index 00000000000..eec331b3d64
--- /dev/null
+++ b/mysql-test/suite/rpl/include/rpl_parallel_rollback_assert.inc
@@ -0,0 +1,62 @@
+--echo *** MDEV-8725: Assertion on ROLLBACK statement in the binary log ***
+--source include/have_innodb.inc
+--source include/master-slave.inc
+
+--connection server_2
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=10;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+--source include/start_slave.inc
+
+--connection server_1
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t1 (a int PRIMARY KEY) ENGINE=MyISAM;
+CREATE TABLE t2 (a int PRIMARY KEY) ENGINE=InnoDB;
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+
+--connection server_1
+# Inject an event group terminated by ROLLBACK, by mixing MyISAM and InnoDB
+# in a transaction. The bug was an assertion on the ROLLBACK due to
+# mark_start_commit() being already called.
+--disable_warnings
+BEGIN;
+INSERT INTO t2 VALUES (2000);
+INSERT INTO t1 VALUES (2000);
+INSERT INTO t2 VALUES (2001);
+ROLLBACK;
+--enable_warnings
+SELECT * FROM t1 WHERE a>=2000 ORDER BY a;
+SELECT * FROM t2 WHERE a>=2000 ORDER BY a;
+--source include/save_master_gtid.inc
+
+--connection server_2
+--source include/sync_with_master_gtid.inc
+
+--connection server_1
+INSERT INTO t2 VALUES (2020);
+--source include/save_master_gtid.inc
+
+--connection server_2
+--source include/sync_with_master_gtid.inc
+SELECT * FROM t2 WHERE a>=2000 ORDER BY a;
+let $rows_in_t1= `SELECT COUNT(*) FROM t1 WHERE a>=2000 ORDER BY a`;
+if ($rows_in_t1 == 0)
+{
+--query_vertical SHOW SLAVE STATUS
+}
+SELECT * FROM t1 WHERE a>=2000 ORDER BY a;
+
+# Clean up.
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+--source include/start_slave.inc
+
+--connection server_1
+DROP TABLE t1,t2;
+
+--source include/rpl_end.inc
+
diff --git a/mysql-test/suite/rpl/include/rpl_parallel_single_grpcmt.inc b/mysql-test/suite/rpl/include/rpl_parallel_single_grpcmt.inc
new file mode 100644
index 00000000000..cf4c547b73b
--- /dev/null
+++ b/mysql-test/suite/rpl/include/rpl_parallel_single_grpcmt.inc
@@ -0,0 +1,170 @@
+--echo *** Test that group-committed transactions on the master can replicate in parallel on the slave. ***
+
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/have_debug_sync.inc
+--source include/have_binlog_format_statement.inc
+--source include/master-slave.inc
+
+# Test various aspects of parallel replication.
+
+--connection server_1
+# The function does nothing on the master, and on the slave it injects the
+# desired debug_sync action(s).
+SET sql_log_bin=0;
+--delimiter ||
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+ RETURNS INT DETERMINISTIC
+ BEGIN
+ RETURN x;
+ END
+||
+--delimiter ;
+SET sql_log_bin=1;
+
+--connection server_2
+--source include/stop_slave.inc
+SET sql_log_bin=0;
+--delimiter ||
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+ RETURNS INT DETERMINISTIC
+ BEGIN
+ IF d1 != '' THEN
+ SET debug_sync = d1;
+ END IF;
+ IF d2 != '' THEN
+ SET debug_sync = d2;
+ END IF;
+ RETURN x;
+ END
+||
+--delimiter ;
+SET sql_log_bin=1;
+
+# We need to restart all parallel threads for the new global setting to
+# be copied to the session-level values.
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+SET GLOBAL slave_parallel_threads=10;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+--source include/start_slave.inc
+
+--connection server_1
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
+# Create some sentinel rows so that the rows inserted in parallel fall into
+# separate gaps and do not cause gap lock conflicts.
+INSERT INTO t3 VALUES (1,1), (3,3), (5,5), (7,7);
+--save_master_pos
+--connection server_2
+--sync_with_master
+
+
+# We want to test that the transactions can execute out-of-order on
+# the slave, but still end up committing in-order, and in a single
+# group commit.
+#
+# The idea is to group-commit three transactions together on the master:
+# A, B, and C. On the slave, C will execute the insert first, then A,
+# and then B. But B manages to complete before A has time to commit, so
+# all three end up committing together.
+#
+# So we start by setting up some row locks that will block transactions
+# A and B from executing, allowing C to run first.
+
+--connect (con_temp1,127.0.0.1,root,,test,$SERVER_MYPORT_2,)
+BEGIN;
+INSERT INTO t3 VALUES (2,102);
+--connect (con_temp2,127.0.0.1,root,,test,$SERVER_MYPORT_2,)
+BEGIN;
+INSERT INTO t3 VALUES (4,104);
+
+# On the master, queue three INSERT transactions as a single group commit.
+--connect (con_temp3,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
+SET binlog_format=statement;
+send INSERT INTO t3 VALUES (2, foo(12,
+ 'commit_after_release_LOCK_prepare_ordered SIGNAL slave_queued1 WAIT_FOR slave_cont1',
+ ''));
+
+--connection server_1
+SET debug_sync='now WAIT_FOR master_queued1';
+
+--connect (con_temp4,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
+SET binlog_format=statement;
+send INSERT INTO t3 VALUES (4, foo(14,
+ 'commit_after_release_LOCK_prepare_ordered SIGNAL slave_queued2',
+ ''));
+
+--connection server_1
+SET debug_sync='now WAIT_FOR master_queued2';
+
+--connect (con_temp5,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued3';
+SET binlog_format=statement;
+send INSERT INTO t3 VALUES (6, foo(16,
+ 'group_commit_waiting_for_prior SIGNAL slave_queued3',
+ ''));
+
+--connection server_1
+SET debug_sync='now WAIT_FOR master_queued3';
+SET debug_sync='now SIGNAL master_cont1';
+
+--connection con_temp3
+REAP;
+--connection con_temp4
+REAP;
+--connection con_temp5
+REAP;
+SET debug_sync='RESET';
+
+--connection server_1
+SELECT * FROM t3 ORDER BY a;
+--let $binlog_file= master-bin.000001
+--source include/show_binlog_events.inc
+
+# First, wait until insert 3 is ready to queue up for group commit, but is
+# waiting for insert 2 to commit before it can do so itself.
+--connection server_2
+SET debug_sync='now WAIT_FOR slave_queued3';
+
+# Next, let insert 1 proceed, and allow it to queue up as the group commit
+# leader, but let it wait for insert 2 to also queue up before proceeding.
+--connection con_temp1
+ROLLBACK;
+--connection server_2
+SET debug_sync='now WAIT_FOR slave_queued1';
+
+# Now let insert 2 proceed and queue up.
+--connection con_temp2
+ROLLBACK;
+--connection server_2
+SET debug_sync='now WAIT_FOR slave_queued2';
+# And finally, we can let insert 1 proceed and do the group commit with all
+# three insert transactions together.
+SET debug_sync='now SIGNAL slave_cont1';
+
+# Wait for the commit to complete and check that all three transactions
+# group-committed together (will be seen in the binlog as all three having
+# cid=# on their GTID event).
+--let $wait_condition= SELECT COUNT(*) = 3 FROM t3 WHERE a IN (2,4,6)
+--source include/wait_condition.inc
+SELECT * FROM t3 ORDER BY a;
+--let $binlog_file= slave-bin.000001
+--source include/show_binlog_events.inc
+
+
+# Clean up.
+--connection server_2
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+--source include/start_slave.inc
+SET DEBUG_SYNC= 'RESET';
+
+--connection server_1
+DROP function foo;
+DROP TABLE t3;
+SET DEBUG_SYNC= 'RESET';
+
+--disable_connect_log
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/include/rpl_parallel_slave_bgc_kill.inc b/mysql-test/suite/rpl/include/rpl_parallel_slave_bgc_kill.inc
new file mode 100644
index 00000000000..a78dbad052f
--- /dev/null
+++ b/mysql-test/suite/rpl/include/rpl_parallel_slave_bgc_kill.inc
@@ -0,0 +1,454 @@
+--echo *** Test killing slave threads at various wait points ***
+
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/have_debug_sync.inc
+--source include/have_binlog_format_statement.inc
+--source include/master-slave.inc
+
+# Test various aspects of parallel replication.
+
+--connection server_2
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+SET @old_parallel_mode=@@GLOBAL.slave_parallel_mode;
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=10;
+SET GLOBAL slave_parallel_mode='conservative';
+CHANGE MASTER TO master_use_gtid=slave_pos;
+--source include/start_slave.inc
+
+--connection server_1
+--connect (con_temp3,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
+--connect (con_temp4,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
+--connect (con_temp5,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t1 (a int PRIMARY KEY) ENGINE=MyISAM;
+CREATE TABLE t2 (a int PRIMARY KEY) ENGINE=InnoDB;
+CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+
+--connection server_1
+# Use a stored function to inject a debug_sync into the appropriate THD.
+# The function does nothing on the master, and on the slave it injects the
+# desired debug_sync action(s).
+SET sql_log_bin=0;
+--delimiter ||
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+ RETURNS INT DETERMINISTIC
+ BEGIN
+ RETURN x;
+ END
+||
+--delimiter ;
+SET sql_log_bin=1;
+
+--connection server_2
+SET sql_log_bin=0;
+--delimiter ||
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+ RETURNS INT DETERMINISTIC
+ BEGIN
+ IF d1 != '' THEN
+ SET debug_sync = d1;
+ END IF;
+ IF d2 != '' THEN
+ SET debug_sync = d2;
+ END IF;
+ RETURN x;
+ END
+||
+--delimiter ;
+SET sql_log_bin=1;
+
+--echo *** 1. Test killing transaction waiting in commit for previous transaction to commit ***
+
+# Set up three transactions on the master that will be group-committed
+# together so they can be replicated in parallel on the slave.
+--connection con_temp3
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
+send INSERT INTO t3 VALUES (31, foo(31,
+ 'commit_before_prepare_ordered WAIT_FOR t2_waiting',
+ 'commit_after_prepare_ordered SIGNAL t1_ready WAIT_FOR t1_cont'));
+
+--connection server_1
+SET debug_sync='now WAIT_FOR master_queued1';
+
+--connection con_temp4
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
+BEGIN;
+# This insert is just so we can get T2 to wait while a query is running that we
+# can see in SHOW PROCESSLIST so we can get its thread_id to kill later.
+INSERT INTO t3 VALUES (32, foo(32,
+ 'ha_write_row_end SIGNAL t2_query WAIT_FOR t2_cont',
+ ''));
+# This insert sets up debug_sync points so that T2 will tell when it is at its
+# wait point where we want to kill it - and when it has been killed.
+INSERT INTO t3 VALUES (33, foo(33,
+ 'group_commit_waiting_for_prior SIGNAL t2_waiting',
+ 'group_commit_waiting_for_prior_killed SIGNAL t2_killed'));
+send COMMIT;
+
+--connection server_1
+SET debug_sync='now WAIT_FOR master_queued2';
+
+--connection con_temp5
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued3';
+send INSERT INTO t3 VALUES (34, foo(34,
+ '',
+ ''));
+
+--connection server_1
+SET debug_sync='now WAIT_FOR master_queued3';
+SET debug_sync='now SIGNAL master_cont1';
+
+--connection con_temp3
+REAP;
+--connection con_temp4
+REAP;
+--connection con_temp5
+REAP;
+
+--connection server_1
+SELECT * FROM t3 WHERE a >= 30 ORDER BY a;
+SET debug_sync='RESET';
+
+--connection server_2
+SET sql_log_bin=0;
+CALL mtr.add_suppression("Query execution was interrupted");
+CALL mtr.add_suppression("Commit failed due to failure of an earlier commit on which this one depends");
+CALL mtr.add_suppression("Slave: Connection was killed");
+SET sql_log_bin=1;
+# Wait until T2 is inside executing its insert of 32, then find it in SHOW
+# PROCESSLIST to know its thread id for KILL later.
+SET debug_sync='now WAIT_FOR t2_query';
+--let $thd_id= `SELECT ID FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO LIKE '%foo(32%' AND INFO NOT LIKE '%LIKE%'`
+SET debug_sync='now SIGNAL t2_cont';
+
+# Wait until T2 has entered its wait for T1 to commit, and T1 has
+# progressed into its commit phase.
+SET debug_sync='now WAIT_FOR t1_ready';
+
+# Now kill the transaction T2.
+--replace_result $thd_id THD_ID
+eval KILL $thd_id;
+
+# Wait until T2 has reacted on the kill.
+SET debug_sync='now WAIT_FOR t2_killed';
+
+# Now we can allow T1 to proceed.
+SET debug_sync='now SIGNAL t1_cont';
+
+--let $slave_sql_errno= 1317,1927,1964
+--source include/wait_for_slave_sql_error.inc
+STOP SLAVE IO_THREAD;
+SELECT * FROM t3 WHERE a >= 30 ORDER BY a;
+
+# Now we have to disable the debug_sync statements, so they do not trigger
+# when the events are retried.
+SET debug_sync='RESET';
+SET GLOBAL slave_parallel_threads=0;
+SET GLOBAL slave_parallel_threads=10;
+SET sql_log_bin=0;
+DROP FUNCTION foo;
+--delimiter ||
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+ RETURNS INT DETERMINISTIC
+ BEGIN
+ RETURN x;
+ END
+||
+--delimiter ;
+SET sql_log_bin=1;
+
+--connection server_1
+INSERT INTO t3 VALUES (39,0);
+--save_master_pos
+
+--connection server_2
+--source include/start_slave.inc
+--sync_with_master
+SELECT * FROM t3 WHERE a >= 30 ORDER BY a;
+# Restore the foo() function.
+SET sql_log_bin=0;
+DROP FUNCTION foo;
+--delimiter ||
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+ RETURNS INT DETERMINISTIC
+ BEGIN
+ IF d1 != '' THEN
+ SET debug_sync = d1;
+ END IF;
+ IF d2 != '' THEN
+ SET debug_sync = d2;
+ END IF;
+ RETURN x;
+ END
+||
+--delimiter ;
+SET sql_log_bin=1;
+
+
+--connection server_2
+# Respawn all worker threads to clear any left-over debug_sync or other stuff.
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=0;
+SET GLOBAL slave_parallel_threads=10;
+--source include/start_slave.inc
+
+
+--echo *** 2. Same as (1), but without restarting IO thread after kill of SQL threads ***
+
+# Set up three transactions on the master that will be group-committed
+# together so they can be replicated in parallel on the slave.
+--connection con_temp3
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
+send INSERT INTO t3 VALUES (41, foo(41,
+ 'commit_before_prepare_ordered WAIT_FOR t2_waiting',
+ 'commit_after_prepare_ordered SIGNAL t1_ready WAIT_FOR t1_cont'));
+
+--connection server_1
+SET debug_sync='now WAIT_FOR master_queued1';
+
+--connection con_temp4
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
+BEGIN;
+# This insert is just so we can get T2 to wait while a query is running that we
+# can see in SHOW PROCESSLIST so we can get its thread_id to kill later.
+INSERT INTO t3 VALUES (42, foo(42,
+ 'ha_write_row_end SIGNAL t2_query WAIT_FOR t2_cont',
+ ''));
+# This insert sets up debug_sync points so that T2 will tell when it is at its
+# wait point where we want to kill it - and when it has been killed.
+INSERT INTO t3 VALUES (43, foo(43,
+ 'group_commit_waiting_for_prior SIGNAL t2_waiting',
+ 'group_commit_waiting_for_prior_killed SIGNAL t2_killed'));
+send COMMIT;
+
+--connection server_1
+SET debug_sync='now WAIT_FOR master_queued2';
+
+--connection con_temp5
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued3';
+send INSERT INTO t3 VALUES (44, foo(44,
+ '',
+ ''));
+
+--connection server_1
+SET debug_sync='now WAIT_FOR master_queued3';
+SET debug_sync='now SIGNAL master_cont1';
+
+--connection con_temp3
+REAP;
+--connection con_temp4
+REAP;
+--connection con_temp5
+REAP;
+
+--connection server_1
+SELECT * FROM t3 WHERE a >= 40 ORDER BY a;
+SET debug_sync='RESET';
+
+--connection server_2
+# Wait until T2 is inside executing its insert of 42, then find it in SHOW
+# PROCESSLIST to know its thread id for KILL later.
+SET debug_sync='now WAIT_FOR t2_query';
+--let $thd_id= `SELECT ID FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO LIKE '%foo(42%' AND INFO NOT LIKE '%LIKE%'`
+SET debug_sync='now SIGNAL t2_cont';
+
+# Wait until T2 has entered its wait for T1 to commit, and T1 has
+# progressed into its commit phase.
+SET debug_sync='now WAIT_FOR t1_ready';
+
+# Now kill the transaction T2.
+--replace_result $thd_id THD_ID
+eval KILL $thd_id;
+
+# Wait until T2 has reacted on the kill.
+SET debug_sync='now WAIT_FOR t2_killed';
+
+# Now we can allow T1 to proceed.
+SET debug_sync='now SIGNAL t1_cont';
+
+--let $slave_sql_errno= 1317,1927,1964
+--source include/wait_for_slave_sql_error.inc
+
+# Now we have to disable the debug_sync statements, so they do not trigger
+# when the events are retried.
+SET debug_sync='RESET';
+SET GLOBAL slave_parallel_threads=0;
+SET GLOBAL slave_parallel_threads=10;
+SET sql_log_bin=0;
+DROP FUNCTION foo;
+--delimiter ||
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+ RETURNS INT DETERMINISTIC
+ BEGIN
+ RETURN x;
+ END
+||
+--delimiter ;
+SET sql_log_bin=1;
+
+--connection server_1
+INSERT INTO t3 VALUES (49,0);
+--save_master_pos
+
+--connection server_2
+START SLAVE SQL_THREAD;
+--sync_with_master
+SELECT * FROM t3 WHERE a >= 40 ORDER BY a;
+# Restore the foo() function.
+SET sql_log_bin=0;
+DROP FUNCTION foo;
+--delimiter ||
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+ RETURNS INT DETERMINISTIC
+ BEGIN
+ IF d1 != '' THEN
+ SET debug_sync = d1;
+ END IF;
+ IF d2 != '' THEN
+ SET debug_sync = d2;
+ END IF;
+ RETURN x;
+ END
+||
+--delimiter ;
+SET sql_log_bin=1;
+
+
+--connection server_2
+# Respawn all worker threads to clear any left-over debug_sync or other stuff.
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=0;
+SET GLOBAL slave_parallel_threads=10;
+--source include/start_slave.inc
+
+
+--echo *** 3. Same as (2), but not using gtid mode ***
+
+--connection server_2
+--source include/stop_slave.inc
+CHANGE MASTER TO master_use_gtid=no;
+--source include/start_slave.inc
+
+--connection server_1
+# Set up three transactions on the master that will be group-committed
+# together so they can be replicated in parallel on the slave.
+--connection con_temp3
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
+send INSERT INTO t3 VALUES (51, foo(51,
+ 'commit_before_prepare_ordered WAIT_FOR t2_waiting',
+ 'commit_after_prepare_ordered SIGNAL t1_ready WAIT_FOR t1_cont'));
+
+--connection server_1
+SET debug_sync='now WAIT_FOR master_queued1';
+
+--connection con_temp4
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
+BEGIN;
+# This insert is just so we can get T2 to wait while a query is running that we
+# can see in SHOW PROCESSLIST so we can get its thread_id to kill later.
+INSERT INTO t3 VALUES (52, foo(52,
+ 'ha_write_row_end SIGNAL t2_query WAIT_FOR t2_cont',
+ ''));
+# This insert sets up debug_sync points so that T2 will tell when it is at its
+# wait point where we want to kill it - and when it has been killed.
+INSERT INTO t3 VALUES (53, foo(53,
+ 'group_commit_waiting_for_prior SIGNAL t2_waiting',
+ 'group_commit_waiting_for_prior_killed SIGNAL t2_killed'));
+send COMMIT;
+
+--connection server_1
+SET debug_sync='now WAIT_FOR master_queued2';
+
+--connection con_temp5
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued3';
+send INSERT INTO t3 VALUES (54, foo(54,
+ '',
+ ''));
+
+--connection server_1
+SET debug_sync='now WAIT_FOR master_queued3';
+SET debug_sync='now SIGNAL master_cont1';
+
+--connection con_temp3
+REAP;
+--connection con_temp4
+REAP;
+--connection con_temp5
+REAP;
+
+--connection server_1
+SELECT * FROM t3 WHERE a >= 50 ORDER BY a;
+SET debug_sync='RESET';
+
+--connection server_2
+# Wait until T2 is inside executing its insert of 52, then find it in SHOW
+# PROCESSLIST to know its thread id for KILL later.
+SET debug_sync='now WAIT_FOR t2_query';
+--let $thd_id= `SELECT ID FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO LIKE '%foo(52%' AND INFO NOT LIKE '%LIKE%'`
+SET debug_sync='now SIGNAL t2_cont';
+
+# Wait until T2 has entered its wait for T1 to commit, and T1 has
+# progressed into its commit phase.
+SET debug_sync='now WAIT_FOR t1_ready';
+
+# Now kill the transaction T2.
+--replace_result $thd_id THD_ID
+eval KILL $thd_id;
+
+# Wait until T2 has reacted on the kill.
+SET debug_sync='now WAIT_FOR t2_killed';
+
+# Now we can allow T1 to proceed.
+SET debug_sync='now SIGNAL t1_cont';
+
+--let $slave_sql_errno= 1317,1927,1964
+--source include/wait_for_slave_sql_error.inc
+SELECT * FROM t3 WHERE a >= 50 ORDER BY a;
+
+# Now we have to disable the debug_sync statements, so they do not trigger
+# when the events are retried.
+SET debug_sync='RESET';
+SET GLOBAL slave_parallel_threads=0;
+SET GLOBAL slave_parallel_threads=10;
+SET sql_log_bin=0;
+DROP FUNCTION foo;
+--delimiter ||
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+ RETURNS INT DETERMINISTIC
+ BEGIN
+ RETURN x;
+ END
+||
+--delimiter ;
+SET sql_log_bin=1;
+
+--connection server_1
+INSERT INTO t3 VALUES (59,0);
+--save_master_pos
+
+--connection server_2
+START SLAVE SQL_THREAD;
+--sync_with_master
+SELECT * FROM t3 WHERE a >= 50 ORDER BY a;
+
+# Clean up.
+--connection server_2
+--source include/stop_slave.inc
+CHANGE MASTER TO master_use_gtid=slave_pos;
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+SET GLOBAL slave_parallel_mode=@old_parallel_mode;
+--source include/start_slave.inc
+SET DEBUG_SYNC= 'RESET';
+
+--connection server_1
+DROP function foo;
+DROP TABLE t1,t2,t3;
+SET DEBUG_SYNC= 'RESET';
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/include/rpl_parallel_stop_on_con_kill.inc b/mysql-test/suite/rpl/include/rpl_parallel_stop_on_con_kill.inc
new file mode 100644
index 00000000000..63c483ea6ad
--- /dev/null
+++ b/mysql-test/suite/rpl/include/rpl_parallel_stop_on_con_kill.inc
@@ -0,0 +1,129 @@
+--echo *** MDEV-8031: Parallel replication stops on "connection killed" error (probably incorrectly handled deadlock kill) ***
+
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/have_debug_sync.inc
+--source include/master-slave.inc
+
+--connection server_2
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=10;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+--source include/start_slave.inc
+
+--connection server_1
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
+INSERT INTO t3 VALUES (201,0), (202,0);
+--source include/save_master_gtid.inc
+
+--connection server_2
+--source include/sync_with_master_gtid.inc
+--source include/stop_slave.inc
+SET @old_dbug= @@GLOBAL.debug_dbug;
+SET GLOBAL debug_dbug= '+d,inject_mdev8031';
+
+--connection server_1
+# We artificially create a situation that hopefully resembles the original
+# bug which was only seen "in the wild", and only once.
+# Setup a fake group commit with lots of conflicts that will lead to deadloc
+# kill. The slave DBUG injection causes the slave to be deadlock killed at
+# a particular point during the retry, and then later do a small sleep at
+# another critical point where the prior transaction then has a chance to
+# complete. Finally an extra KILL check catches an unhandled, lingering
+# deadlock kill. So rather artificial, but at least it exercises the
+# relevant code paths.
+SET @old_dbug= @@SESSION.debug_dbug;
+SET SESSION debug_dbug="+d,binlog_force_commit_id";
+
+SET @commit_id= 10200;
+INSERT INTO t3 VALUES (203, 1);
+INSERT INTO t3 VALUES (204, 1);
+INSERT INTO t3 VALUES (205, 1);
+UPDATE t3 SET b=b+1 WHERE a=201;
+UPDATE t3 SET b=b+1 WHERE a=201;
+UPDATE t3 SET b=b+1 WHERE a=201;
+UPDATE t3 SET b=b+1 WHERE a=202;
+UPDATE t3 SET b=b+1 WHERE a=202;
+UPDATE t3 SET b=b+1 WHERE a=202;
+UPDATE t3 SET b=b+1 WHERE a=202;
+UPDATE t3 SET b=b+1 WHERE a=203;
+UPDATE t3 SET b=b+1 WHERE a=203;
+UPDATE t3 SET b=b+1 WHERE a=204;
+UPDATE t3 SET b=b+1 WHERE a=204;
+UPDATE t3 SET b=b+1 WHERE a=204;
+UPDATE t3 SET b=b+1 WHERE a=203;
+UPDATE t3 SET b=b+1 WHERE a=205;
+UPDATE t3 SET b=b+1 WHERE a=205;
+SET SESSION debug_dbug=@old_dbug;
+
+SELECT * FROM t3 WHERE a>=200 ORDER BY a;
+--source include/save_master_gtid.inc
+
+--connection server_2
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+
+SELECT * FROM t3 WHERE a>=200 ORDER BY a;
+--source include/stop_slave.inc
+SET GLOBAL debug_dbug= @old_dbug;
+--source include/start_slave.inc
+
+
+--echo *** Check getting deadlock killed inside open_binlog() during retry. ***
+
+--connection server_2
+--source include/stop_slave.inc
+SET @old_dbug= @@GLOBAL.debug_dbug;
+SET GLOBAL debug_dbug= '+d,inject_retry_event_group_open_binlog_kill';
+SET @old_max= @@GLOBAL.max_relay_log_size;
+SET GLOBAL max_relay_log_size= 4096;
+
+--connection server_1
+SET @old_dbug= @@SESSION.debug_dbug;
+SET SESSION debug_dbug="+d,binlog_force_commit_id";
+
+--let $large= `SELECT REPEAT("*", 8192)`
+SET @commit_id= 10210;
+--echo Omit long queries that cause relaylog rotations and transaction retries...
+--disable_query_log
+eval UPDATE t3 SET b=b+1 WHERE a=201 /* $large */;
+eval UPDATE t3 SET b=b+1 WHERE a=201 /* $large */;
+eval UPDATE t3 SET b=b+1 WHERE a=201 /* $large */;
+eval UPDATE t3 SET b=b+1 WHERE a=202 /* $large */;
+eval UPDATE t3 SET b=b+1 WHERE a=202 /* $large */;
+eval UPDATE t3 SET b=b+1 WHERE a=202 /* $large */;
+eval UPDATE t3 SET b=b+1 WHERE a=202 /* $large */;
+eval UPDATE t3 SET b=b+1 WHERE a=203 /* $large */;
+eval UPDATE t3 SET b=b+1 WHERE a=203 /* $large */;
+eval UPDATE t3 SET b=b+1 WHERE a=204 /* $large */;
+eval UPDATE t3 SET b=b+1 WHERE a=204 /* $large */;
+eval UPDATE t3 SET b=b+1 WHERE a=204 /* $large */;
+eval UPDATE t3 SET b=b+1 WHERE a=203 /* $large */;
+eval UPDATE t3 SET b=b+1 WHERE a=205 /* $large */;
+eval UPDATE t3 SET b=b+1 WHERE a=205 /* $large */;
+--enable_query_log
+SET SESSION debug_dbug=@old_dbug;
+
+SELECT * FROM t3 WHERE a>=200 ORDER BY a;
+--source include/save_master_gtid.inc
+
+--connection server_2
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+
+SELECT * FROM t3 WHERE a>=200 ORDER BY a;
+
+# Cleanup
+--source include/stop_slave.inc
+SET GLOBAL debug_dbug= @old_debg;
+SET GLOBAL max_relay_log_size= @old_max;
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+--source include/start_slave.inc
+
+--connection server_1
+DROP TABLE t3;
+
+--source include/rpl_end.inc
+
diff --git a/mysql-test/suite/rpl/include/rpl_parallel_stop_slave.inc b/mysql-test/suite/rpl/include/rpl_parallel_stop_slave.inc
new file mode 100644
index 00000000000..4eeddc927e0
--- /dev/null
+++ b/mysql-test/suite/rpl/include/rpl_parallel_stop_slave.inc
@@ -0,0 +1,114 @@
+--echo *** Test STOP SLAVE in parallel mode ***
+
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/have_debug_sync.inc
+--source include/have_binlog_format_statement.inc
+--source include/master-slave.inc
+
+--connection server_2
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+SET @old_parallel_mode=@@GLOBAL.slave_parallel_mode;
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=10;
+SET GLOBAL slave_parallel_mode='conservative';
+
+CHANGE MASTER TO master_use_gtid=slave_pos;
+--source include/start_slave.inc
+--connect (con_temp1,127.0.0.1,root,,test,$SERVER_MYPORT_2,)
+--connect (con_temp2,127.0.0.1,root,,test,$SERVER_MYPORT_2,)
+
+--connection server_1
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t1 (a int PRIMARY KEY) ENGINE=MyISAM;
+CREATE TABLE t2 (a int PRIMARY KEY) ENGINE=InnoDB;
+CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+--source include/stop_slave.inc
+
+--connection server_1
+# Set up a couple of transactions. The first will be blocked halfway
+# through on a lock, and while it is blocked we initiate STOP SLAVE.
+# We then test that the halfway-initiated transaction is allowed to
+# complete, but no subsequent ones.
+# We have to use statement-based mode and set
+# binlog_direct_non_transactional_updates=0; otherwise the binlog will
+# be split into two event groups, one for the MyISAM part and one for the
+# InnoDB part.
+SET binlog_direct_non_transactional_updates=0;
+SET sql_log_bin=0;
+CALL mtr.add_suppression("Statement is unsafe because it accesses a non-transactional table after accessing a transactional table within the same transaction");
+SET sql_log_bin=1;
+BEGIN;
+INSERT INTO t2 VALUES (20);
+--disable_warnings
+INSERT INTO t1 VALUES (20);
+--enable_warnings
+INSERT INTO t2 VALUES (21);
+INSERT INTO t3 VALUES (20, 20);
+COMMIT;
+INSERT INTO t3 VALUES(21, 21);
+INSERT INTO t3 VALUES(22, 22);
+--save_master_pos
+
+# Start a connection that will block the replicated transaction halfway.
+--connection con_temp1
+BEGIN;
+INSERT INTO t2 VALUES (21);
+
+--connection server_2
+START SLAVE;
+# Wait for the MyISAM change to be visible, after which replication will wait
+# for con_temp1 to roll back.
+--let $wait_condition= SELECT COUNT(*) = 1 FROM t1 WHERE a=20
+--source include/wait_condition.inc
+
+--connection con_temp2
+# Initiate slave stop. It will have to wait for the current event group
+# to complete.
+# The dbug injection causes debug_sync to signal 'wait_for_done_waiting'
+# when the SQL driver thread is ready.
+SET @old_dbug= @@GLOBAL.debug_dbug;
+SET GLOBAL debug_dbug="+d,rpl_parallel_wait_for_done_trigger";
+send STOP SLAVE;
+
+--connection con_temp1
+SET debug_sync='now WAIT_FOR wait_for_done_waiting';
+ROLLBACK;
+
+--connection con_temp2
+reap;
+SET GLOBAL debug_dbug=@old_dbug;
+SET debug_sync='RESET';
+
+--connection server_2
+--source include/wait_for_slave_to_stop.inc
+# We should see the first transaction applied, but not the two others.
+SELECT * FROM t1 WHERE a >= 20 ORDER BY a;
+SELECT * FROM t2 WHERE a >= 20 ORDER BY a;
+SELECT * FROM t3 WHERE a >= 20 ORDER BY a;
+
+--source include/start_slave.inc
+--sync_with_master
+SELECT * FROM t1 WHERE a >= 20 ORDER BY a;
+SELECT * FROM t2 WHERE a >= 20 ORDER BY a;
+SELECT * FROM t3 WHERE a >= 20 ORDER BY a;
+
+--connection server_2
+# Respawn all worker threads to clear any left-over debug_sync or other stuff.
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_mode=@old_parallel_mode;
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+--source include/start_slave.inc
+SET DEBUG_SYNC= 'RESET';
+--disconnect con_temp1
+--disconnect con_temp2
+
+--connection server_1
+DROP TABLE t1,t2,t3;
+SET DEBUG_SYNC= 'RESET';
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/include/rpl_parallel_wrong_binlog_order.inc b/mysql-test/suite/rpl/include/rpl_parallel_wrong_binlog_order.inc
new file mode 100644
index 00000000000..093693d453e
--- /dev/null
+++ b/mysql-test/suite/rpl/include/rpl_parallel_wrong_binlog_order.inc
@@ -0,0 +1,91 @@
+--echo *** MDEV-6775: Wrong binlog order in parallel replication ***
+
+# A bit tricky bug to reproduce. On the master, we binlog in statement-mode
+# two transactions, an UPDATE followed by a DELETE. On the slave, we replicate
+# with binlog-mode set to ROW, which means the DELETE, which modifies no rows,
+# is not binlogged. Then we inject a wait in the group commit code on the
+# slave, shortly before the actual commit of the UPDATE. The bug was that the
+# DELETE could wake up from wait_for_prior_commit() before the commit of the
+# UPDATE. So the test could see the slave position updated to after DELETE,
+# while the UPDATE was still not visible.
+
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/have_debug_sync.inc
+--source include/master-slave.inc
+
+--connection server_2
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=10;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+--source include/start_slave.inc
+
+--connection server_1
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t4 (a INT PRIMARY KEY, b INT, KEY b_idx(b)) ENGINE=InnoDB;
+INSERT INTO t4 VALUES (1,NULL), (3,NULL), (4,4), (5, NULL), (6, 6);
+--connect (con1,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
+--connect (con2,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
+--source include/save_master_gtid.inc
+
+--connection server_2
+--source include/sync_with_master_gtid.inc
+--source include/stop_slave.inc
+SET @old_dbug= @@GLOBAL.debug_dbug;
+SET GLOBAL debug_dbug="+d,inject_binlog_commit_before_get_LOCK_log";
+SET @old_format=@@GLOBAL.binlog_format;
+SET GLOBAL binlog_format=ROW;
+# Re-spawn the worker threads to be sure they pick up the new binlog format
+SET GLOBAL slave_parallel_threads=0;
+SET GLOBAL slave_parallel_threads=10;
+
+--connection con1
+SET @old_format= @@binlog_format;
+SET binlog_format= statement;
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
+send UPDATE t4 SET b=NULL WHERE a=6;
+--connection server_1
+SET debug_sync='now WAIT_FOR master_queued1';
+
+--connection con2
+SET @old_format= @@binlog_format;
+SET binlog_format= statement;
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
+send DELETE FROM t4 WHERE b <= 3;
+
+--connection server_1
+SET debug_sync='now WAIT_FOR master_queued2';
+SET debug_sync='now SIGNAL master_cont1';
+
+--connection con1
+REAP;
+SET binlog_format= @old_format;
+--connection con2
+REAP;
+SET binlog_format= @old_format;
+SET debug_sync='RESET';
+--save_master_pos
+SELECT * FROM t4 ORDER BY a;
+
+--connection server_2
+--source include/start_slave.inc
+SET debug_sync= 'now WAIT_FOR waiting';
+--sync_with_master
+SELECT * FROM t4 ORDER BY a;
+SET debug_sync= 'now SIGNAL cont';
+
+# Re-spawn the worker threads to remove any DBUG injections or DEBUG_SYNC.
+--source include/stop_slave.inc
+SET GLOBAL debug_dbug=@old_dbug;
+SET GLOBAL binlog_format= @old_format;
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+--source include/start_slave.inc
+SET DEBUG_SYNC= 'RESET';
+
+--connection server_1
+DROP TABLE t4;
+SET DEBUG_SYNC= 'RESET';
+--disconnect con1
+--disconnect con2
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/include/rpl_parallel_wrong_exec_master_pos.inc b/mysql-test/suite/rpl/include/rpl_parallel_wrong_exec_master_pos.inc
new file mode 100644
index 00000000000..672ade57ca3
--- /dev/null
+++ b/mysql-test/suite/rpl/include/rpl_parallel_wrong_exec_master_pos.inc
@@ -0,0 +1,56 @@
+--echo *** MDEV-5938: Exec_master_log_pos not updated at log rotate in parallel replication ***
+--source include/have_innodb.inc
+--source include/master-slave.inc
+
+--connection server_2
+--source include/stop_slave.inc
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+SET GLOBAL slave_parallel_threads=1;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+--source include/start_slave.inc
+
+--connection server_1
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t5 (a INT PRIMARY KEY, b INT);
+INSERT INTO t5 VALUES (1,1);
+INSERT INTO t5 VALUES (2,2), (3,8);
+INSERT INTO t5 VALUES (4,16);
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+let $io_file= query_get_value(SHOW SLAVE STATUS, Master_Log_File, 1);
+let $io_pos= query_get_value(SHOW SLAVE STATUS, Read_Master_Log_Pos, 1);
+let $sql_file= query_get_value(SHOW SLAVE STATUS, Relay_Master_Log_File, 1);
+let $sql_pos= query_get_value(SHOW SLAVE STATUS, Exec_Master_Log_Pos, 1);
+--disable_query_log
+eval SELECT IF('$io_file' = '$sql_file', "OK", "Not ok, $io_file <> $sql_file") AS test_check;
+eval SELECT IF('$io_pos' = '$sql_pos', "OK", "Not ok, $io_pos <> $sql_pos") AS test_check;
+--enable_query_log
+
+--connection server_1
+FLUSH LOGS;
+--source include/wait_for_binlog_checkpoint.inc
+--save_master_pos
+
+--connection server_2
+--sync_with_master
+let $io_file= query_get_value(SHOW SLAVE STATUS, Master_Log_File, 1);
+let $io_pos= query_get_value(SHOW SLAVE STATUS, Read_Master_Log_Pos, 1);
+let $sql_file= query_get_value(SHOW SLAVE STATUS, Relay_Master_Log_File, 1);
+let $sql_pos= query_get_value(SHOW SLAVE STATUS, Exec_Master_Log_Pos, 1);
+--disable_query_log
+eval SELECT IF('$io_file' = '$sql_file', "OK", "Not ok, $io_file <> $sql_file") AS test_check;
+eval SELECT IF('$io_pos' = '$sql_pos', "OK", "Not ok, $io_pos <> $sql_pos") AS test_check;
+--enable_query_log
+
+# Clean up.
+--connection server_2
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+--source include/start_slave.inc
+
+--connection server_1
+DROP TABLE t5;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/r/rpl_mdev6386.result b/mysql-test/suite/rpl/r/rpl_mdev6386.result
index 91ba9569343..d0e5144857a 100644
--- a/mysql-test/suite/rpl/r/rpl_mdev6386.result
+++ b/mysql-test/suite/rpl/r/rpl_mdev6386.result
@@ -7,6 +7,7 @@ connection slave;
connection slave;
include/stop_slave.inc
SET sql_log_bin= 0;
+CALL mtr.add_suppression("Commit failed due to failure of an earlier commit on which this one depends");
INSERT INTO t1 VALUES (1, 2);
SET sql_log_bin= 1;
CHANGE MASTER TO master_use_gtid= current_pos;
diff --git a/mysql-test/suite/rpl/r/rpl_parallel.result b/mysql-test/suite/rpl/r/rpl_parallel.result
deleted file mode 100644
index 9258deadaca..00000000000
--- a/mysql-test/suite/rpl/r/rpl_parallel.result
+++ /dev/null
@@ -1,1690 +0,0 @@
-include/master-slave.inc
-[connection master]
-connection server_2;
-SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
-SET GLOBAL slave_parallel_threads=10;
-ERROR HY000: This operation cannot be performed as you have a running slave ''; run STOP SLAVE '' first
-include/stop_slave.inc
-SET GLOBAL slave_parallel_threads=10;
-SELECT IF(COUNT(*) < 10, "OK", CONCAT("Found too many system user processes: ", COUNT(*))) FROM information_schema.processlist WHERE user = "system user";
-IF(COUNT(*) < 10, "OK", CONCAT("Found too many system user processes: ", COUNT(*)))
-OK
-CHANGE MASTER TO master_use_gtid=slave_pos;
-include/start_slave.inc
-SELECT IF(COUNT(*) >= 10, "OK", CONCAT("Found too few system user processes: ", COUNT(*))) FROM information_schema.processlist WHERE user = "system user";
-IF(COUNT(*) >= 10, "OK", CONCAT("Found too few system user processes: ", COUNT(*)))
-OK
-include/stop_slave.inc
-SELECT IF(COUNT(*) < 10, "OK", CONCAT("Found too many system user processes: ", COUNT(*))) FROM information_schema.processlist WHERE user = "system user";
-IF(COUNT(*) < 10, "OK", CONCAT("Found too many system user processes: ", COUNT(*)))
-OK
-include/start_slave.inc
-SELECT IF(COUNT(*) >= 10, "OK", CONCAT("Found too few system user processes: ", COUNT(*))) FROM information_schema.processlist WHERE user = "system user";
-IF(COUNT(*) >= 10, "OK", CONCAT("Found too few system user processes: ", COUNT(*)))
-OK
-*** Test long-running query in domain 1 can run in parallel with short queries in domain 0 ***
-connection server_1;
-ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
-CREATE TABLE t1 (a int PRIMARY KEY) ENGINE=MyISAM;
-CREATE TABLE t2 (a int PRIMARY KEY) ENGINE=InnoDB;
-INSERT INTO t1 VALUES (1);
-INSERT INTO t2 VALUES (1);
-connection server_2;
-connect con_temp1,127.0.0.1,root,,test,$SERVER_MYPORT_2,;
-LOCK TABLE t1 WRITE;
-connection server_1;
-SET gtid_domain_id=1;
-INSERT INTO t1 VALUES (2);
-SET gtid_domain_id=0;
-INSERT INTO t2 VALUES (2);
-INSERT INTO t2 VALUES (3);
-BEGIN;
-INSERT INTO t2 VALUES (4);
-INSERT INTO t2 VALUES (5);
-COMMIT;
-INSERT INTO t2 VALUES (6);
-connection server_2;
-SELECT * FROM t2 ORDER by a;
-a
-1
-2
-3
-4
-5
-6
-connection con_temp1;
-SELECT * FROM t1;
-a
-1
-UNLOCK TABLES;
-connection server_2;
-SELECT * FROM t1 ORDER BY a;
-a
-1
-2
-*** Test two transactions in different domains committed in opposite order on slave but in a single group commit. ***
-connection server_2;
-include/stop_slave.inc
-connection server_1;
-SET sql_log_bin=0;
-CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
-RETURNS INT DETERMINISTIC
-BEGIN
-RETURN x;
-END
-||
-SET sql_log_bin=1;
-SET @old_format= @@SESSION.binlog_format;
-SET binlog_format='statement';
-SET gtid_domain_id=1;
-INSERT INTO t2 VALUES (foo(10,
-'commit_before_enqueue SIGNAL ready1 WAIT_FOR cont1',
-'commit_after_release_LOCK_prepare_ordered SIGNAL ready2'));
-connection server_2;
-FLUSH LOGS;
-SET sql_log_bin=0;
-CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
-RETURNS INT DETERMINISTIC
-BEGIN
-IF d1 != '' THEN
-SET debug_sync = d1;
-END IF;
-IF d2 != '' THEN
-SET debug_sync = d2;
-END IF;
-RETURN x;
-END
-||
-SET sql_log_bin=1;
-SET @old_format=@@GLOBAL.binlog_format;
-SET GLOBAL binlog_format=statement;
-SET GLOBAL slave_parallel_threads=0;
-SET GLOBAL slave_parallel_threads=10;
-include/start_slave.inc
-SET debug_sync='now WAIT_FOR ready1';
-connection server_1;
-SET gtid_domain_id=2;
-INSERT INTO t2 VALUES (foo(11,
-'commit_before_enqueue SIGNAL ready3 WAIT_FOR cont3',
-'commit_after_release_LOCK_prepare_ordered SIGNAL ready4 WAIT_FOR cont4'));
-SET gtid_domain_id=0;
-SELECT * FROM t2 WHERE a >= 10 ORDER BY a;
-a
-10
-11
-connection server_2;
-SET debug_sync='now WAIT_FOR ready3';
-SET debug_sync='now SIGNAL cont3';
-SET debug_sync='now WAIT_FOR ready4';
-SET debug_sync='now SIGNAL cont1';
-SET debug_sync='now WAIT_FOR ready2';
-SET debug_sync='now SIGNAL cont4';
-SELECT * FROM t2 WHERE a >= 10 ORDER BY a;
-a
-10
-11
-include/show_binlog_events.inc
-Log_name Pos Event_type Server_id End_log_pos Info
-slave-bin.000002 # Binlog_checkpoint # # slave-bin.000002
-slave-bin.000002 # Gtid # # BEGIN GTID #-#-# cid=#
-slave-bin.000002 # Query # # use `test`; INSERT INTO t2 VALUES (foo(11,
-'commit_before_enqueue SIGNAL ready3 WAIT_FOR cont3',
-'commit_after_release_LOCK_prepare_ordered SIGNAL ready4 WAIT_FOR cont4'))
-slave-bin.000002 # Xid # # COMMIT /* XID */
-slave-bin.000002 # Gtid # # BEGIN GTID #-#-# cid=#
-slave-bin.000002 # Query # # use `test`; INSERT INTO t2 VALUES (foo(10,
-'commit_before_enqueue SIGNAL ready1 WAIT_FOR cont1',
-'commit_after_release_LOCK_prepare_ordered SIGNAL ready2'))
-slave-bin.000002 # Xid # # COMMIT /* XID */
-FLUSH LOGS;
-connection server_2;
-include/stop_slave.inc
-SET GLOBAL slave_parallel_threads=0;
-SET GLOBAL slave_parallel_threads=10;
-SET debug_sync='RESET';
-include/start_slave.inc
-*** Test that group-committed transactions on the master can replicate in parallel on the slave. ***
-connection server_1;
-SET debug_sync='RESET';
-FLUSH LOGS;
-CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
-INSERT INTO t3 VALUES (1,1), (3,3), (5,5), (7,7);
-connection server_2;
-connection con_temp1;
-BEGIN;
-INSERT INTO t3 VALUES (2,102);
-connect con_temp2,127.0.0.1,root,,test,$SERVER_MYPORT_2,;
-BEGIN;
-INSERT INTO t3 VALUES (4,104);
-connect con_temp3,127.0.0.1,root,,test,$SERVER_MYPORT_1,;
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
-SET binlog_format=statement;
-INSERT INTO t3 VALUES (2, foo(12,
-'commit_after_release_LOCK_prepare_ordered SIGNAL slave_queued1 WAIT_FOR slave_cont1',
-''));
-connection server_1;
-SET debug_sync='now WAIT_FOR master_queued1';
-connect con_temp4,127.0.0.1,root,,test,$SERVER_MYPORT_1,;
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
-SET binlog_format=statement;
-INSERT INTO t3 VALUES (4, foo(14,
-'commit_after_release_LOCK_prepare_ordered SIGNAL slave_queued2',
-''));
-connection server_1;
-SET debug_sync='now WAIT_FOR master_queued2';
-connect con_temp5,127.0.0.1,root,,test,$SERVER_MYPORT_1,;
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued3';
-SET binlog_format=statement;
-INSERT INTO t3 VALUES (6, foo(16,
-'group_commit_waiting_for_prior SIGNAL slave_queued3',
-''));
-connection server_1;
-SET debug_sync='now WAIT_FOR master_queued3';
-SET debug_sync='now SIGNAL master_cont1';
-connection con_temp3;
-connection con_temp4;
-connection con_temp5;
-SET debug_sync='RESET';
-connection server_1;
-SELECT * FROM t3 ORDER BY a;
-a b
-1 1
-2 12
-3 3
-4 14
-5 5
-6 16
-7 7
-include/show_binlog_events.inc
-Log_name Pos Event_type Server_id End_log_pos Info
-master-bin.000002 # Binlog_checkpoint # # master-bin.000002
-master-bin.000002 # Gtid # # GTID #-#-#
-master-bin.000002 # Query # # use `test`; CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB
-master-bin.000002 # Gtid # # BEGIN GTID #-#-#
-master-bin.000002 # Query # # use `test`; INSERT INTO t3 VALUES (1,1), (3,3), (5,5), (7,7)
-master-bin.000002 # Xid # # COMMIT /* XID */
-master-bin.000002 # Gtid # # BEGIN GTID #-#-# cid=#
-master-bin.000002 # Query # # use `test`; INSERT INTO t3 VALUES (2, foo(12,
-'commit_after_release_LOCK_prepare_ordered SIGNAL slave_queued1 WAIT_FOR slave_cont1',
-''))
-master-bin.000002 # Xid # # COMMIT /* XID */
-master-bin.000002 # Gtid # # BEGIN GTID #-#-# cid=#
-master-bin.000002 # Query # # use `test`; INSERT INTO t3 VALUES (4, foo(14,
-'commit_after_release_LOCK_prepare_ordered SIGNAL slave_queued2',
-''))
-master-bin.000002 # Xid # # COMMIT /* XID */
-master-bin.000002 # Gtid # # BEGIN GTID #-#-# cid=#
-master-bin.000002 # Query # # use `test`; INSERT INTO t3 VALUES (6, foo(16,
-'group_commit_waiting_for_prior SIGNAL slave_queued3',
-''))
-master-bin.000002 # Xid # # COMMIT /* XID */
-connection server_2;
-SET debug_sync='now WAIT_FOR slave_queued3';
-connection con_temp1;
-ROLLBACK;
-connection server_2;
-SET debug_sync='now WAIT_FOR slave_queued1';
-connection con_temp2;
-ROLLBACK;
-connection server_2;
-SET debug_sync='now WAIT_FOR slave_queued2';
-SET debug_sync='now SIGNAL slave_cont1';
-SELECT * FROM t3 ORDER BY a;
-a b
-1 1
-2 12
-3 3
-4 14
-5 5
-6 16
-7 7
-include/show_binlog_events.inc
-Log_name Pos Event_type Server_id End_log_pos Info
-slave-bin.000003 # Binlog_checkpoint # # slave-bin.000003
-slave-bin.000003 # Gtid # # GTID #-#-#
-slave-bin.000003 # Query # # use `test`; CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB
-slave-bin.000003 # Gtid # # BEGIN GTID #-#-#
-slave-bin.000003 # Query # # use `test`; INSERT INTO t3 VALUES (1,1), (3,3), (5,5), (7,7)
-slave-bin.000003 # Xid # # COMMIT /* XID */
-slave-bin.000003 # Gtid # # BEGIN GTID #-#-# cid=#
-slave-bin.000003 # Query # # use `test`; INSERT INTO t3 VALUES (2, foo(12,
-'commit_after_release_LOCK_prepare_ordered SIGNAL slave_queued1 WAIT_FOR slave_cont1',
-''))
-slave-bin.000003 # Xid # # COMMIT /* XID */
-slave-bin.000003 # Gtid # # BEGIN GTID #-#-# cid=#
-slave-bin.000003 # Query # # use `test`; INSERT INTO t3 VALUES (4, foo(14,
-'commit_after_release_LOCK_prepare_ordered SIGNAL slave_queued2',
-''))
-slave-bin.000003 # Xid # # COMMIT /* XID */
-slave-bin.000003 # Gtid # # BEGIN GTID #-#-# cid=#
-slave-bin.000003 # Query # # use `test`; INSERT INTO t3 VALUES (6, foo(16,
-'group_commit_waiting_for_prior SIGNAL slave_queued3',
-''))
-slave-bin.000003 # Xid # # COMMIT /* XID */
-*** Test STOP SLAVE in parallel mode ***
-connection server_2;
-include/stop_slave.inc
-SET debug_sync='RESET';
-SET GLOBAL slave_parallel_threads=0;
-SET GLOBAL slave_parallel_threads=10;
-connection server_1;
-SET binlog_direct_non_transactional_updates=0;
-SET sql_log_bin=0;
-CALL mtr.add_suppression("Statement is unsafe because it accesses a non-transactional table after accessing a transactional table within the same transaction");
-SET sql_log_bin=1;
-BEGIN;
-INSERT INTO t2 VALUES (20);
-INSERT INTO t1 VALUES (20);
-INSERT INTO t2 VALUES (21);
-INSERT INTO t3 VALUES (20, 20);
-COMMIT;
-INSERT INTO t3 VALUES(21, 21);
-INSERT INTO t3 VALUES(22, 22);
-SET binlog_format=@old_format;
-connection con_temp1;
-BEGIN;
-INSERT INTO t2 VALUES (21);
-connection server_2;
-START SLAVE;
-connection con_temp2;
-SET @old_dbug= @@GLOBAL.debug_dbug;
-SET GLOBAL debug_dbug="+d,rpl_parallel_wait_for_done_trigger";
-STOP SLAVE;
-connection con_temp1;
-SET debug_sync='now WAIT_FOR wait_for_done_waiting';
-ROLLBACK;
-connection con_temp2;
-SET GLOBAL debug_dbug=@old_dbug;
-SET debug_sync='RESET';
-connection server_2;
-include/wait_for_slave_to_stop.inc
-SELECT * FROM t1 WHERE a >= 20 ORDER BY a;
-a
-20
-SELECT * FROM t2 WHERE a >= 20 ORDER BY a;
-a
-20
-21
-SELECT * FROM t3 WHERE a >= 20 ORDER BY a;
-a b
-20 20
-include/start_slave.inc
-SELECT * FROM t1 WHERE a >= 20 ORDER BY a;
-a
-20
-SELECT * FROM t2 WHERE a >= 20 ORDER BY a;
-a
-20
-21
-SELECT * FROM t3 WHERE a >= 20 ORDER BY a;
-a b
-20 20
-21 21
-22 22
-connection server_2;
-include/stop_slave.inc
-SET GLOBAL binlog_format=@old_format;
-SET GLOBAL slave_parallel_threads=0;
-SET GLOBAL slave_parallel_threads=10;
-include/start_slave.inc
-*** Test killing slave threads at various wait points ***
-*** 1. Test killing transaction waiting in commit for previous transaction to commit ***
-connection con_temp3;
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
-SET binlog_format=statement;
-INSERT INTO t3 VALUES (31, foo(31,
-'commit_before_prepare_ordered WAIT_FOR t2_waiting',
-'commit_after_prepare_ordered SIGNAL t1_ready WAIT_FOR t1_cont'));
-connection server_1;
-SET debug_sync='now WAIT_FOR master_queued1';
-connection con_temp4;
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
-SET binlog_format=statement;
-BEGIN;
-INSERT INTO t3 VALUES (32, foo(32,
-'ha_write_row_end SIGNAL t2_query WAIT_FOR t2_cont',
-''));
-INSERT INTO t3 VALUES (33, foo(33,
-'group_commit_waiting_for_prior SIGNAL t2_waiting',
-'group_commit_waiting_for_prior_killed SIGNAL t2_killed'));
-COMMIT;
-connection server_1;
-SET debug_sync='now WAIT_FOR master_queued2';
-connection con_temp5;
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued3';
-SET binlog_format=statement;
-INSERT INTO t3 VALUES (34, foo(34,
-'',
-''));
-connection server_1;
-SET debug_sync='now WAIT_FOR master_queued3';
-SET debug_sync='now SIGNAL master_cont1';
-connection con_temp3;
-connection con_temp4;
-connection con_temp5;
-connection server_1;
-SELECT * FROM t3 WHERE a >= 30 ORDER BY a;
-a b
-31 31
-32 32
-33 33
-34 34
-SET debug_sync='RESET';
-connection server_2;
-SET sql_log_bin=0;
-CALL mtr.add_suppression("Query execution was interrupted");
-CALL mtr.add_suppression("Commit failed due to failure of an earlier commit on which this one depends");
-CALL mtr.add_suppression("Slave: Connection was killed");
-SET sql_log_bin=1;
-SET debug_sync='now WAIT_FOR t2_query';
-SET debug_sync='now SIGNAL t2_cont';
-SET debug_sync='now WAIT_FOR t1_ready';
-KILL THD_ID;
-SET debug_sync='now WAIT_FOR t2_killed';
-SET debug_sync='now SIGNAL t1_cont';
-include/wait_for_slave_sql_error.inc [errno=1317,1927,1964]
-STOP SLAVE IO_THREAD;
-SELECT * FROM t3 WHERE a >= 30 ORDER BY a;
-a b
-31 31
-SET debug_sync='RESET';
-SET GLOBAL slave_parallel_threads=0;
-SET GLOBAL slave_parallel_threads=10;
-SET sql_log_bin=0;
-DROP FUNCTION foo;
-CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
-RETURNS INT DETERMINISTIC
-BEGIN
-RETURN x;
-END
-||
-SET sql_log_bin=1;
-connection server_1;
-INSERT INTO t3 VALUES (39,0);
-connection server_2;
-include/start_slave.inc
-SELECT * FROM t3 WHERE a >= 30 ORDER BY a;
-a b
-31 31
-32 32
-33 33
-34 34
-39 0
-SET sql_log_bin=0;
-DROP FUNCTION foo;
-CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
-RETURNS INT DETERMINISTIC
-BEGIN
-IF d1 != '' THEN
-SET debug_sync = d1;
-END IF;
-IF d2 != '' THEN
-SET debug_sync = d2;
-END IF;
-RETURN x;
-END
-||
-SET sql_log_bin=1;
-connection server_2;
-include/stop_slave.inc
-SET GLOBAL binlog_format=@old_format;
-SET GLOBAL slave_parallel_threads=0;
-SET GLOBAL slave_parallel_threads=10;
-include/start_slave.inc
-*** 2. Same as (1), but without restarting IO thread after kill of SQL threads ***
-connection con_temp3;
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
-SET binlog_format=statement;
-INSERT INTO t3 VALUES (41, foo(41,
-'commit_before_prepare_ordered WAIT_FOR t2_waiting',
-'commit_after_prepare_ordered SIGNAL t1_ready WAIT_FOR t1_cont'));
-connection server_1;
-SET debug_sync='now WAIT_FOR master_queued1';
-connection con_temp4;
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
-SET binlog_format=statement;
-BEGIN;
-INSERT INTO t3 VALUES (42, foo(42,
-'ha_write_row_end SIGNAL t2_query WAIT_FOR t2_cont',
-''));
-INSERT INTO t3 VALUES (43, foo(43,
-'group_commit_waiting_for_prior SIGNAL t2_waiting',
-'group_commit_waiting_for_prior_killed SIGNAL t2_killed'));
-COMMIT;
-connection server_1;
-SET debug_sync='now WAIT_FOR master_queued2';
-connection con_temp5;
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued3';
-SET binlog_format=statement;
-INSERT INTO t3 VALUES (44, foo(44,
-'',
-''));
-connection server_1;
-SET debug_sync='now WAIT_FOR master_queued3';
-SET debug_sync='now SIGNAL master_cont1';
-connection con_temp3;
-connection con_temp4;
-connection con_temp5;
-connection server_1;
-SELECT * FROM t3 WHERE a >= 40 ORDER BY a;
-a b
-41 41
-42 42
-43 43
-44 44
-SET debug_sync='RESET';
-connection server_2;
-SET debug_sync='now WAIT_FOR t2_query';
-SET debug_sync='now SIGNAL t2_cont';
-SET debug_sync='now WAIT_FOR t1_ready';
-KILL THD_ID;
-SET debug_sync='now WAIT_FOR t2_killed';
-SET debug_sync='now SIGNAL t1_cont';
-include/wait_for_slave_sql_error.inc [errno=1317,1927,1964]
-SET debug_sync='RESET';
-SET GLOBAL slave_parallel_threads=0;
-SET GLOBAL slave_parallel_threads=10;
-SET sql_log_bin=0;
-DROP FUNCTION foo;
-CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
-RETURNS INT DETERMINISTIC
-BEGIN
-RETURN x;
-END
-||
-SET sql_log_bin=1;
-connection server_1;
-INSERT INTO t3 VALUES (49,0);
-connection server_2;
-START SLAVE SQL_THREAD;
-SELECT * FROM t3 WHERE a >= 40 ORDER BY a;
-a b
-41 41
-42 42
-43 43
-44 44
-49 0
-SET sql_log_bin=0;
-DROP FUNCTION foo;
-CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
-RETURNS INT DETERMINISTIC
-BEGIN
-IF d1 != '' THEN
-SET debug_sync = d1;
-END IF;
-IF d2 != '' THEN
-SET debug_sync = d2;
-END IF;
-RETURN x;
-END
-||
-SET sql_log_bin=1;
-connection server_2;
-include/stop_slave.inc
-SET GLOBAL binlog_format=@old_format;
-SET GLOBAL slave_parallel_threads=0;
-SET GLOBAL slave_parallel_threads=10;
-include/start_slave.inc
-*** 3. Same as (2), but not using gtid mode ***
-connection server_2;
-include/stop_slave.inc
-CHANGE MASTER TO master_use_gtid=no;
-include/start_slave.inc
-connection server_1;
-connection con_temp3;
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
-SET binlog_format=statement;
-INSERT INTO t3 VALUES (51, foo(51,
-'commit_before_prepare_ordered WAIT_FOR t2_waiting',
-'commit_after_prepare_ordered SIGNAL t1_ready WAIT_FOR t1_cont'));
-connection server_1;
-SET debug_sync='now WAIT_FOR master_queued1';
-connection con_temp4;
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
-SET binlog_format=statement;
-BEGIN;
-INSERT INTO t3 VALUES (52, foo(52,
-'ha_write_row_end SIGNAL t2_query WAIT_FOR t2_cont',
-''));
-INSERT INTO t3 VALUES (53, foo(53,
-'group_commit_waiting_for_prior SIGNAL t2_waiting',
-'group_commit_waiting_for_prior_killed SIGNAL t2_killed'));
-COMMIT;
-connection server_1;
-SET debug_sync='now WAIT_FOR master_queued2';
-connection con_temp5;
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued3';
-SET binlog_format=statement;
-INSERT INTO t3 VALUES (54, foo(54,
-'',
-''));
-connection server_1;
-SET debug_sync='now WAIT_FOR master_queued3';
-SET debug_sync='now SIGNAL master_cont1';
-connection con_temp3;
-connection con_temp4;
-connection con_temp5;
-connection server_1;
-SELECT * FROM t3 WHERE a >= 50 ORDER BY a;
-a b
-51 51
-52 52
-53 53
-54 54
-SET debug_sync='RESET';
-connection server_2;
-SET debug_sync='now WAIT_FOR t2_query';
-SET debug_sync='now SIGNAL t2_cont';
-SET debug_sync='now WAIT_FOR t1_ready';
-KILL THD_ID;
-SET debug_sync='now WAIT_FOR t2_killed';
-SET debug_sync='now SIGNAL t1_cont';
-include/wait_for_slave_sql_error.inc [errno=1317,1927,1964]
-SELECT * FROM t3 WHERE a >= 50 ORDER BY a;
-a b
-51 51
-SET debug_sync='RESET';
-SET GLOBAL slave_parallel_threads=0;
-SET GLOBAL slave_parallel_threads=10;
-SET sql_log_bin=0;
-DROP FUNCTION foo;
-CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
-RETURNS INT DETERMINISTIC
-BEGIN
-RETURN x;
-END
-||
-SET sql_log_bin=1;
-connection server_1;
-INSERT INTO t3 VALUES (59,0);
-connection server_2;
-START SLAVE SQL_THREAD;
-SELECT * FROM t3 WHERE a >= 50 ORDER BY a;
-a b
-51 51
-52 52
-53 53
-54 54
-59 0
-SET sql_log_bin=0;
-DROP FUNCTION foo;
-CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
-RETURNS INT DETERMINISTIC
-BEGIN
-IF d1 != '' THEN
-SET debug_sync = d1;
-END IF;
-IF d2 != '' THEN
-SET debug_sync = d2;
-END IF;
-RETURN x;
-END
-||
-SET sql_log_bin=1;
-include/stop_slave.inc
-CHANGE MASTER TO master_use_gtid=slave_pos;
-include/start_slave.inc
-connection server_2;
-include/stop_slave.inc
-SET GLOBAL binlog_format=@old_format;
-SET GLOBAL slave_parallel_threads=0;
-SET GLOBAL slave_parallel_threads=4;
-include/start_slave.inc
-*** 4. Test killing thread that is waiting to start transaction until previous transaction commits ***
-connection server_1;
-SET binlog_format=statement;
-SET gtid_domain_id=2;
-BEGIN;
-INSERT INTO t3 VALUES (70, foo(70,
-'rpl_parallel_start_waiting_for_prior SIGNAL t4_waiting', ''));
-INSERT INTO t3 VALUES (60, foo(60,
-'ha_write_row_end SIGNAL d2_query WAIT_FOR d2_cont2',
-'rpl_parallel_end_of_group SIGNAL d2_done WAIT_FOR d2_cont'));
-COMMIT;
-SET gtid_domain_id=0;
-connection server_2;
-SET debug_sync='now WAIT_FOR d2_query';
-connection server_1;
-SET gtid_domain_id=1;
-BEGIN;
-INSERT INTO t3 VALUES (61, foo(61,
-'rpl_parallel_start_waiting_for_prior SIGNAL t3_waiting',
-'rpl_parallel_start_waiting_for_prior_killed SIGNAL t3_killed'));
-INSERT INTO t3 VALUES (62, foo(62,
-'ha_write_row_end SIGNAL d1_query WAIT_FOR d1_cont2',
-'rpl_parallel_end_of_group SIGNAL d1_done WAIT_FOR d1_cont'));
-COMMIT;
-SET gtid_domain_id=0;
-connection server_2;
-SET debug_sync='now WAIT_FOR d1_query';
-connection server_1;
-SET gtid_domain_id=0;
-INSERT INTO t3 VALUES (63, foo(63,
-'ha_write_row_end SIGNAL d0_query WAIT_FOR d0_cont2',
-'rpl_parallel_end_of_group SIGNAL d0_done WAIT_FOR d0_cont'));
-connection server_2;
-SET debug_sync='now WAIT_FOR d0_query';
-connection server_1;
-SET gtid_domain_id=3;
-BEGIN;
-INSERT INTO t3 VALUES (68, foo(68,
-'rpl_parallel_start_waiting_for_prior SIGNAL t2_waiting', ''));
-INSERT INTO t3 VALUES (69, foo(69,
-'ha_write_row_end SIGNAL d3_query WAIT_FOR d3_cont2',
-'rpl_parallel_end_of_group SIGNAL d3_done WAIT_FOR d3_cont'));
-COMMIT;
-SET gtid_domain_id=0;
-connection server_2;
-SET debug_sync='now WAIT_FOR d3_query';
-SET debug_sync='now SIGNAL d2_cont2';
-SET debug_sync='now WAIT_FOR d2_done';
-SET debug_sync='now SIGNAL d1_cont2';
-SET debug_sync='now WAIT_FOR d1_done';
-SET debug_sync='now SIGNAL d0_cont2';
-SET debug_sync='now WAIT_FOR d0_done';
-SET debug_sync='now SIGNAL d3_cont2';
-SET debug_sync='now WAIT_FOR d3_done';
-connection con_temp3;
-SET binlog_format=statement;
-INSERT INTO t3 VALUES (64, foo(64,
-'rpl_parallel_before_mark_start_commit SIGNAL t1_waiting WAIT_FOR t1_cont', ''));
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2 WAIT_FOR master_cont2';
-INSERT INTO t3 VALUES (65, foo(65, '', ''));
-connection server_1;
-SET debug_sync='now WAIT_FOR master_queued2';
-connection con_temp4;
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued3';
-INSERT INTO t3 VALUES (66, foo(66, '', ''));
-connection server_1;
-SET debug_sync='now WAIT_FOR master_queued3';
-connection con_temp5;
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued4';
-INSERT INTO t3 VALUES (67, foo(67, '', ''));
-connection server_1;
-SET debug_sync='now WAIT_FOR master_queued4';
-SET debug_sync='now SIGNAL master_cont2';
-connection con_temp3;
-connection con_temp4;
-connection con_temp5;
-connection server_1;
-SELECT * FROM t3 WHERE a >= 60 ORDER BY a;
-a b
-60 60
-61 61
-62 62
-63 63
-64 64
-65 65
-66 66
-67 67
-68 68
-69 69
-70 70
-SET debug_sync='RESET';
-connection server_2;
-SET debug_sync='now SIGNAL d0_cont';
-SET debug_sync='now WAIT_FOR t1_waiting';
-SET debug_sync='now SIGNAL d3_cont';
-SET debug_sync='now WAIT_FOR t2_waiting';
-SET debug_sync='now SIGNAL d1_cont';
-SET debug_sync='now WAIT_FOR t3_waiting';
-SET debug_sync='now SIGNAL d2_cont';
-SET debug_sync='now WAIT_FOR t4_waiting';
-KILL THD_ID;
-SET debug_sync='now WAIT_FOR t3_killed';
-SET debug_sync='now SIGNAL t1_cont';
-include/wait_for_slave_sql_error.inc [errno=1317,1927,1964]
-STOP SLAVE IO_THREAD;
-SELECT * FROM t3 WHERE a >= 60 AND a != 65 ORDER BY a;
-a b
-60 60
-61 61
-62 62
-63 63
-64 64
-68 68
-69 69
-70 70
-SET debug_sync='RESET';
-SET GLOBAL slave_parallel_threads=0;
-SET GLOBAL slave_parallel_threads=10;
-SET sql_log_bin=0;
-DROP FUNCTION foo;
-CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
-RETURNS INT DETERMINISTIC
-BEGIN
-RETURN x;
-END
-||
-SET sql_log_bin=1;
-connection server_1;
-UPDATE t3 SET b=b+1 WHERE a=60;
-connection server_2;
-include/start_slave.inc
-SELECT * FROM t3 WHERE a >= 60 ORDER BY a;
-a b
-60 61
-61 61
-62 62
-63 63
-64 64
-65 65
-66 66
-67 67
-68 68
-69 69
-70 70
-SET sql_log_bin=0;
-DROP FUNCTION foo;
-CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
-RETURNS INT DETERMINISTIC
-BEGIN
-IF d1 != '' THEN
-SET debug_sync = d1;
-END IF;
-IF d2 != '' THEN
-SET debug_sync = d2;
-END IF;
-RETURN x;
-END
-||
-SET sql_log_bin=1;
-connection server_2;
-include/stop_slave.inc
-SET GLOBAL binlog_format=@old_format;
-SET GLOBAL slave_parallel_threads=0;
-SET GLOBAL slave_parallel_threads=10;
-include/start_slave.inc
-*** 5. Test killing thread that is waiting for queue of max length to shorten ***
-SET @old_max_queued= @@GLOBAL.slave_parallel_max_queued;
-SET GLOBAL slave_parallel_max_queued=9000;
-connection server_1;
-SET binlog_format=statement;
-INSERT INTO t3 VALUES (80, foo(0,
-'ha_write_row_end SIGNAL query_waiting WAIT_FOR query_cont', ''));
-connection server_2;
-SET debug_sync='now WAIT_FOR query_waiting';
-SET @old_dbug= @@GLOBAL.debug_dbug;
-SET GLOBAL debug_dbug="+d,rpl_parallel_wait_queue_max";
-connection server_1;
-SELECT * FROM t3 WHERE a >= 80 ORDER BY a;
-a b
-80 0
-81 10000
-connection server_2;
-SET debug_sync='now WAIT_FOR wait_queue_ready';
-KILL THD_ID;
-SET debug_sync='now WAIT_FOR wait_queue_killed';
-SET debug_sync='now SIGNAL query_cont';
-include/wait_for_slave_sql_error.inc [errno=1317,1927,1964]
-STOP SLAVE IO_THREAD;
-SET GLOBAL debug_dbug=@old_dbug;
-SET GLOBAL slave_parallel_max_queued= @old_max_queued;
-connection server_1;
-INSERT INTO t3 VALUES (82,0);
-SET binlog_format=@old_format;
-connection server_2;
-SET debug_sync='RESET';
-include/start_slave.inc
-SELECT * FROM t3 WHERE a >= 80 ORDER BY a;
-a b
-80 0
-81 10000
-82 0
-connection server_2;
-include/stop_slave.inc
-SET GLOBAL binlog_format=@old_format;
-SET GLOBAL slave_parallel_threads=0;
-SET GLOBAL slave_parallel_threads=10;
-include/start_slave.inc
-*** MDEV-5788 Incorrect free of rgi->deferred_events in parallel replication ***
-connection server_2;
-include/stop_slave.inc
-SET GLOBAL replicate_ignore_table="test.t3";
-SET GLOBAL slave_parallel_threads=2;
-include/start_slave.inc
-connection server_1;
-INSERT INTO t3 VALUES (100, rand());
-INSERT INTO t3 VALUES (101, rand());
-connection server_2;
-connection server_1;
-INSERT INTO t3 VALUES (102, rand());
-INSERT INTO t3 VALUES (103, rand());
-INSERT INTO t3 VALUES (104, rand());
-INSERT INTO t3 VALUES (105, rand());
-connection server_2;
-include/stop_slave.inc
-SET GLOBAL replicate_ignore_table="";
-include/start_slave.inc
-connection server_1;
-INSERT INTO t3 VALUES (106, rand());
-INSERT INTO t3 VALUES (107, rand());
-connection server_2;
-SELECT * FROM t3 WHERE a >= 100 ORDER BY a;
-a b
-106 #
-107 #
-*** MDEV-5921: In parallel replication, an error is not correctly signalled to the next transaction ***
-connection server_2;
-include/stop_slave.inc
-SET GLOBAL slave_parallel_threads=10;
-include/start_slave.inc
-connection server_1;
-INSERT INTO t3 VALUES (110, 1);
-connection server_2;
-SELECT * FROM t3 WHERE a >= 110 ORDER BY a;
-a b
-110 1
-SET sql_log_bin=0;
-INSERT INTO t3 VALUES (111, 666);
-SET sql_log_bin=1;
-connection server_1;
-connect con1,127.0.0.1,root,,test,$SERVER_MYPORT_1,;
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
-INSERT INTO t3 VALUES (111, 2);
-connection server_1;
-SET debug_sync='now WAIT_FOR master_queued1';
-connect con2,127.0.0.1,root,,test,$SERVER_MYPORT_1,;
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
-INSERT INTO t3 VALUES (112, 3);
-connection server_1;
-SET debug_sync='now WAIT_FOR master_queued2';
-SET debug_sync='now SIGNAL master_cont1';
-connection con1;
-connection con2;
-SET debug_sync='RESET';
-connection server_2;
-include/wait_for_slave_sql_error.inc [errno=1062]
-include/wait_for_slave_sql_to_stop.inc
-SELECT * FROM t3 WHERE a >= 110 ORDER BY a;
-a b
-110 1
-111 666
-SET sql_log_bin=0;
-DELETE FROM t3 WHERE a=111 AND b=666;
-SET sql_log_bin=1;
-START SLAVE SQL_THREAD;
-SELECT * FROM t3 WHERE a >= 110 ORDER BY a;
-a b
-110 1
-111 2
-112 3
-***MDEV-5914: Parallel replication deadlock due to InnoDB lock conflicts ***
-connection server_2;
-include/stop_slave.inc
-connection server_1;
-CREATE TABLE t4 (a INT PRIMARY KEY, b INT, KEY b_idx(b)) ENGINE=InnoDB;
-INSERT INTO t4 VALUES (1,NULL), (2,2), (3,NULL), (4,4), (5, NULL), (6, 6);
-connection con1;
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
-UPDATE t4 SET b=NULL WHERE a=6;
-connection server_1;
-SET debug_sync='now WAIT_FOR master_queued1';
-connection con2;
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
-DELETE FROM t4 WHERE b <= 3;
-connection server_1;
-SET debug_sync='now WAIT_FOR master_queued2';
-SET debug_sync='now SIGNAL master_cont1';
-connection con1;
-connection con2;
-SET debug_sync='RESET';
-connection server_2;
-include/start_slave.inc
-include/stop_slave.inc
-SELECT * FROM t4 ORDER BY a;
-a b
-1 NULL
-3 NULL
-4 4
-5 NULL
-6 NULL
-connection server_1;
-DELETE FROM t4;
-INSERT INTO t4 VALUES (1,NULL), (2,2), (3,NULL), (4,4), (5, NULL), (6, 6);
-connection con1;
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
-INSERT INTO t4 VALUES (7, NULL);
-connection server_1;
-SET debug_sync='now WAIT_FOR master_queued1';
-connection con2;
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
-DELETE FROM t4 WHERE b <= 3;
-connection server_1;
-SET debug_sync='now WAIT_FOR master_queued2';
-SET debug_sync='now SIGNAL master_cont1';
-connection con1;
-connection con2;
-SET debug_sync='RESET';
-connection server_2;
-include/start_slave.inc
-include/stop_slave.inc
-SELECT * FROM t4 ORDER BY a;
-a b
-1 NULL
-3 NULL
-4 4
-5 NULL
-6 6
-7 NULL
-connection server_1;
-DELETE FROM t4;
-INSERT INTO t4 VALUES (1,NULL), (2,2), (3,NULL), (4,4), (5, NULL), (6, 6);
-connection con1;
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
-UPDATE t4 SET b=NULL WHERE a=6;
-connection server_1;
-SET debug_sync='now WAIT_FOR master_queued1';
-connection con2;
-SET @old_format= @@SESSION.binlog_format;
-SET binlog_format='statement';
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
-DELETE FROM t4 WHERE b <= 1;
-connection server_1;
-SET debug_sync='now WAIT_FOR master_queued2';
-SET debug_sync='now SIGNAL master_cont1';
-connection con1;
-connection con2;
-SET @old_format=@@GLOBAL.binlog_format;
-SET debug_sync='RESET';
-connection server_2;
-SET @old_dbug= @@GLOBAL.debug_dbug;
-SET GLOBAL debug_dbug="+d,disable_thd_need_ordering_with";
-include/start_slave.inc
-SET GLOBAL debug_dbug=@old_dbug;
-SELECT * FROM t4 ORDER BY a;
-a b
-1 NULL
-2 2
-3 NULL
-4 4
-5 NULL
-6 NULL
-SET @last_gtid= 'GTID';
-SELECT IF(@@gtid_slave_pos LIKE CONCAT('%',@last_gtid,'%'), "GTID found ok",
-CONCAT("GTID ", @last_gtid, " not found in gtid_slave_pos=", @@gtid_slave_pos))
-AS result;
-result
-GTID found ok
-SELECT "ROW FOUND" AS `Is the row found?`
- FROM mysql.gtid_slave_pos
-WHERE CONCAT(domain_id, "-", server_id, "-", seq_no) = @last_gtid;
-Is the row found?
-ROW FOUND
-*** MDEV-5938: Exec_master_log_pos not updated at log rotate in parallel replication ***
-connection server_2;
-include/stop_slave.inc
-SET GLOBAL slave_parallel_threads=1;
-SET DEBUG_SYNC= 'RESET';
-include/start_slave.inc
-connection server_1;
-CREATE TABLE t5 (a INT PRIMARY KEY, b INT);
-INSERT INTO t5 VALUES (1,1);
-INSERT INTO t5 VALUES (2,2), (3,8);
-INSERT INTO t5 VALUES (4,16);
-connection server_2;
-test_check
-OK
-test_check
-OK
-connection server_1;
-FLUSH LOGS;
-connection server_2;
-test_check
-OK
-test_check
-OK
-*** MDEV_6435: Incorrect error handling when query binlogged partially on master with "killed" error ***
-connection server_1;
-CREATE TABLE t6 (a INT) ENGINE=MyISAM;
-CREATE TRIGGER tr AFTER INSERT ON t6 FOR EACH ROW SET @a = 1;
-connection con1;
-SET @old_format= @@binlog_format;
-SET binlog_format= statement;
-SET debug_sync='sp_head_execute_before_loop SIGNAL ready WAIT_FOR cont';
-INSERT INTO t6 VALUES (1), (2), (3);
-connection server_1;
-SET debug_sync='now WAIT_FOR ready';
-KILL QUERY CONID;
-SET debug_sync='now SIGNAL cont';
-connection con1;
-ERROR 70100: Query execution was interrupted
-SET binlog_format= @old_format;
-SET debug_sync='RESET';
-connection server_1;
-SET debug_sync='RESET';
-connection server_2;
-include/wait_for_slave_sql_error.inc [errno=1317]
-STOP SLAVE IO_THREAD;
-SET GLOBAL gtid_slave_pos= 'AFTER_ERROR_GTID_POS';
-include/start_slave.inc
-connection server_1;
-INSERT INTO t6 VALUES (4);
-SELECT * FROM t6 ORDER BY a;
-a
-1
-4
-connection server_2;
-SELECT * FROM t6 ORDER BY a;
-a
-4
-*** MDEV-6551: Some replication errors are ignored if slave_parallel_threads > 0 ***
-connection server_1;
-INSERT INTO t2 VALUES (31);
-include/save_master_gtid.inc
-connection server_2;
-include/sync_with_master_gtid.inc
-include/stop_slave.inc
-SET GLOBAL slave_parallel_threads= 0;
-include/start_slave.inc
-SET sql_log_bin= 0;
-INSERT INTO t2 VALUES (32);
-SET sql_log_bin= 1;
-connection server_1;
-INSERT INTO t2 VALUES (32);
-FLUSH LOGS;
-INSERT INTO t2 VALUES (33);
-INSERT INTO t2 VALUES (34);
-SELECT * FROM t2 WHERE a >= 30 ORDER BY a;
-a
-31
-32
-33
-34
-include/save_master_gtid.inc
-connection server_2;
-include/wait_for_slave_sql_error.inc [errno=1062]
-connection server_2;
-include/stop_slave_io.inc
-SET GLOBAL slave_parallel_threads=10;
-START SLAVE;
-include/wait_for_slave_sql_error.inc [errno=1062]
-START SLAVE SQL_THREAD;
-include/wait_for_slave_sql_error.inc [errno=1062]
-SELECT * FROM t2 WHERE a >= 30 ORDER BY a;
-a
-31
-32
-SET sql_slave_skip_counter= 1;
-ERROR HY000: When using parallel replication and GTID with multiple replication domains, @@sql_slave_skip_counter can not be used. Instead, setting @@gtid_slave_pos explicitly can be used to skip to after a given GTID position
-include/stop_slave_io.inc
-include/start_slave.inc
-include/sync_with_master_gtid.inc
-SELECT * FROM t2 WHERE a >= 30 ORDER BY a;
-a
-31
-32
-33
-34
-*** MDEV-6775: Wrong binlog order in parallel replication ***
-connection server_1;
-DELETE FROM t4;
-INSERT INTO t4 VALUES (1,NULL), (3,NULL), (4,4), (5, NULL), (6, 6);
-include/save_master_gtid.inc
-connection server_2;
-include/sync_with_master_gtid.inc
-include/stop_slave.inc
-SET @old_dbug= @@GLOBAL.debug_dbug;
-SET GLOBAL debug_dbug="+d,inject_binlog_commit_before_get_LOCK_log";
-SET @old_format=@@GLOBAL.binlog_format;
-SET GLOBAL binlog_format=ROW;
-SET GLOBAL slave_parallel_threads=0;
-SET GLOBAL slave_parallel_threads=10;
-connection con1;
-SET @old_format= @@binlog_format;
-SET binlog_format= statement;
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
-UPDATE t4 SET b=NULL WHERE a=6;
-connection server_1;
-SET debug_sync='now WAIT_FOR master_queued1';
-connection con2;
-SET @old_format= @@binlog_format;
-SET binlog_format= statement;
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
-DELETE FROM t4 WHERE b <= 3;
-connection server_1;
-SET debug_sync='now WAIT_FOR master_queued2';
-SET debug_sync='now SIGNAL master_cont1';
-connection con1;
-SET binlog_format= @old_format;
-connection con2;
-SET binlog_format= @old_format;
-SET debug_sync='RESET';
-SELECT * FROM t4 ORDER BY a;
-a b
-1 NULL
-3 NULL
-4 4
-5 NULL
-6 NULL
-connection server_2;
-include/start_slave.inc
-SET debug_sync= 'now WAIT_FOR waiting';
-SELECT * FROM t4 ORDER BY a;
-a b
-1 NULL
-3 NULL
-4 4
-5 NULL
-6 NULL
-SET debug_sync= 'now SIGNAL cont';
-include/stop_slave.inc
-SET GLOBAL debug_dbug=@old_dbug;
-SET GLOBAL binlog_format= @old_format;
-SET GLOBAL slave_parallel_threads=0;
-SET GLOBAL slave_parallel_threads=10;
-include/start_slave.inc
-*** MDEV-7237: Parallel replication: incorrect relaylog position after stop/start the slave ***
-connection server_1;
-INSERT INTO t2 VALUES (40);
-connection server_2;
-include/stop_slave.inc
-CHANGE MASTER TO master_use_gtid=no;
-SET @old_dbug= @@GLOBAL.debug_dbug;
-SET GLOBAL debug_dbug="+d,rpl_parallel_scheduled_gtid_0_x_100";
-SET GLOBAL debug_dbug="+d,rpl_parallel_wait_for_done_trigger";
-SET GLOBAL slave_parallel_threads=0;
-SET GLOBAL slave_parallel_threads=10;
-connection server_1;
-INSERT INTO t2 VALUES (41);
-INSERT INTO t2 VALUES (42);
-SET @old_format= @@binlog_format;
-SET binlog_format= statement;
-DELETE FROM t2 WHERE a=40;
-SET binlog_format= @old_format;
-INSERT INTO t2 VALUES (43);
-INSERT INTO t2 VALUES (44);
-FLUSH LOGS;
-INSERT INTO t2 VALUES (45);
-SET gtid_seq_no=100;
-INSERT INTO t2 VALUES (46);
-connection con_temp2;
-BEGIN;
-SELECT * FROM t2 WHERE a=40 FOR UPDATE;
-a
-40
-connection server_2;
-include/start_slave.inc
-SET debug_sync= 'now WAIT_FOR scheduled_gtid_0_x_100';
-STOP SLAVE;
-connection con_temp2;
-SET debug_sync= 'now WAIT_FOR wait_for_done_waiting';
-ROLLBACK;
-connection server_2;
-include/wait_for_slave_sql_to_stop.inc
-SELECT * FROM t2 WHERE a >= 40 ORDER BY a;
-a
-41
-42
-include/start_slave.inc
-SELECT * FROM t2 WHERE a >= 40 ORDER BY a;
-a
-41
-42
-43
-44
-45
-46
-include/stop_slave.inc
-SET GLOBAL debug_dbug=@old_dbug;
-SET DEBUG_SYNC= 'RESET';
-SET GLOBAL slave_parallel_threads=0;
-SET GLOBAL slave_parallel_threads=10;
-CHANGE MASTER TO master_use_gtid=slave_pos;
-include/start_slave.inc
-*** MDEV-7326 Server deadlock in connection with parallel replication ***
-connection server_2;
-include/stop_slave.inc
-SET GLOBAL slave_parallel_threads=0;
-SET GLOBAL slave_parallel_threads=3;
-SET GLOBAL debug_dbug="+d,rpl_parallel_simulate_temp_err_xid";
-include/start_slave.inc
-connection server_1;
-SET @old_format= @@SESSION.binlog_format;
-SET binlog_format= STATEMENT;
-INSERT INTO t1 VALUES (foo(50,
-"rpl_parallel_start_waiting_for_prior SIGNAL t3_ready",
-"rpl_parallel_end_of_group SIGNAL prep_ready WAIT_FOR prep_cont"));
-connection server_2;
-SET DEBUG_SYNC= "now WAIT_FOR prep_ready";
-connection server_1;
-INSERT INTO t2 VALUES (foo(50,
-"rpl_parallel_simulate_temp_err_xid SIGNAL t1_ready1 WAIT_FOR t1_cont1",
-"rpl_parallel_retry_after_unmark SIGNAL t1_ready2 WAIT_FOR t1_cont2"));
-connection server_2;
-SET DEBUG_SYNC= "now WAIT_FOR t1_ready1";
-connection server_1;
-INSERT INTO t1 VALUES (foo(51,
-"rpl_parallel_before_mark_start_commit SIGNAL t2_ready1 WAIT_FOR t2_cont1",
-"rpl_parallel_after_mark_start_commit SIGNAL t2_ready2"));
-connection server_2;
-SET DEBUG_SYNC= "now WAIT_FOR t2_ready1";
-SET DEBUG_SYNC= "now SIGNAL t1_cont1";
-SET DEBUG_SYNC= "now WAIT_FOR t1_ready2";
-connection server_1;
-INSERT INTO t1 VALUES (52);
-SET BINLOG_FORMAT= @old_format;
-SELECT * FROM t2 WHERE a>=50 ORDER BY a;
-a
-50
-SELECT * FROM t1 WHERE a>=50 ORDER BY a;
-a
-50
-51
-52
-connection server_2;
-SET DEBUG_SYNC= "now SIGNAL prep_cont";
-SET DEBUG_SYNC= "now WAIT_FOR t3_ready";
-SET DEBUG_SYNC= "now SIGNAL t2_cont1";
-SET DEBUG_SYNC= "now WAIT_FOR t2_ready2";
-SET DEBUG_SYNC= "now SIGNAL t1_cont2";
-connection server_1;
-connection server_2;
-SELECT * FROM t2 WHERE a>=50 ORDER BY a;
-a
-50
-SELECT * FROM t1 WHERE a>=50 ORDER BY a;
-a
-50
-51
-52
-SET DEBUG_SYNC="reset";
-include/stop_slave.inc
-SET GLOBAL debug_dbug=@old_dbug;
-SET GLOBAL slave_parallel_threads=0;
-SET GLOBAL slave_parallel_threads=10;
-include/start_slave.inc
-*** MDEV-7326 Server deadlock in connection with parallel replication ***
-connection server_2;
-include/stop_slave.inc
-SET GLOBAL slave_parallel_threads=0;
-SET GLOBAL slave_parallel_threads=3;
-SET GLOBAL debug_dbug="+d,rpl_parallel_simulate_temp_err_xid";
-include/start_slave.inc
-connection server_1;
-SET @old_format= @@SESSION.binlog_format;
-SET binlog_format= STATEMENT;
-INSERT INTO t1 VALUES (foo(60,
-"rpl_parallel_start_waiting_for_prior SIGNAL t3_ready",
-"rpl_parallel_end_of_group SIGNAL prep_ready WAIT_FOR prep_cont"));
-connection server_2;
-SET DEBUG_SYNC= "now WAIT_FOR prep_ready";
-connection server_1;
-INSERT INTO t2 VALUES (foo(60,
-"rpl_parallel_simulate_temp_err_xid SIGNAL t1_ready1 WAIT_FOR t1_cont1",
-"rpl_parallel_retry_after_unmark SIGNAL t1_ready2 WAIT_FOR t1_cont2"));
-connection server_2;
-SET DEBUG_SYNC= "now WAIT_FOR t1_ready1";
-connection con_temp3;
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
-SET binlog_format=statement;
-INSERT INTO t1 VALUES (foo(61,
-"rpl_parallel_before_mark_start_commit SIGNAL t2_ready1 WAIT_FOR t2_cont1",
-"rpl_parallel_after_mark_start_commit SIGNAL t2_ready2"));
-connection server_1;
-SET debug_sync='now WAIT_FOR master_queued1';
-connection con_temp4;
-SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
-INSERT INTO t6 VALUES (62);
-connection server_1;
-SET debug_sync='now WAIT_FOR master_queued2';
-SET debug_sync='now SIGNAL master_cont1';
-connection con_temp3;
-connection con_temp4;
-connection server_1;
-SET debug_sync='RESET';
-SET BINLOG_FORMAT= @old_format;
-SELECT * FROM t2 WHERE a>=60 ORDER BY a;
-a
-60
-SELECT * FROM t1 WHERE a>=60 ORDER BY a;
-a
-60
-61
-SELECT * FROM t6 WHERE a>=60 ORDER BY a;
-a
-62
-connection server_2;
-SET DEBUG_SYNC= "now WAIT_FOR t2_ready1";
-SET DEBUG_SYNC= "now SIGNAL t1_cont1";
-SET DEBUG_SYNC= "now WAIT_FOR t1_ready2";
-connection server_2;
-SET DEBUG_SYNC= "now SIGNAL prep_cont";
-SET DEBUG_SYNC= "now WAIT_FOR t3_ready";
-SET DEBUG_SYNC= "now SIGNAL t2_cont1";
-SET DEBUG_SYNC= "now WAIT_FOR t2_ready2";
-SET DEBUG_SYNC= "now SIGNAL t1_cont2";
-connection server_1;
-connection server_2;
-SELECT * FROM t2 WHERE a>=60 ORDER BY a;
-a
-60
-SELECT * FROM t1 WHERE a>=60 ORDER BY a;
-a
-60
-61
-SELECT * FROM t6 WHERE a>=60 ORDER BY a;
-a
-62
-SET DEBUG_SYNC="reset";
-include/stop_slave.inc
-SET GLOBAL debug_dbug=@old_dbug;
-SET GLOBAL slave_parallel_threads=0;
-SET GLOBAL slave_parallel_threads=10;
-include/start_slave.inc
-*** MDEV-7335: Potential parallel slave deadlock with specific binlog corruption ***
-connection server_2;
-include/stop_slave.inc
-SET GLOBAL slave_parallel_threads=1;
-SET @old_dbug= @@GLOBAL.debug_dbug;
-SET GLOBAL debug_dbug="+d,slave_discard_xid_for_gtid_0_x_1000";
-connection server_1;
-INSERT INTO t2 VALUES (101);
-INSERT INTO t2 VALUES (102);
-INSERT INTO t2 VALUES (103);
-INSERT INTO t2 VALUES (104);
-INSERT INTO t2 VALUES (105);
-SET gtid_seq_no=1000;
-INSERT INTO t2 VALUES (106);
-INSERT INTO t2 VALUES (107);
-INSERT INTO t2 VALUES (108);
-INSERT INTO t2 VALUES (109);
-INSERT INTO t2 VALUES (110);
-INSERT INTO t2 VALUES (111);
-INSERT INTO t2 VALUES (112);
-INSERT INTO t2 VALUES (113);
-INSERT INTO t2 VALUES (114);
-INSERT INTO t2 VALUES (115);
-INSERT INTO t2 VALUES (116);
-INSERT INTO t2 VALUES (117);
-INSERT INTO t2 VALUES (118);
-INSERT INTO t2 VALUES (119);
-INSERT INTO t2 VALUES (120);
-INSERT INTO t2 VALUES (121);
-INSERT INTO t2 VALUES (122);
-INSERT INTO t2 VALUES (123);
-INSERT INTO t2 VALUES (124);
-INSERT INTO t2 VALUES (125);
-INSERT INTO t2 VALUES (126);
-INSERT INTO t2 VALUES (127);
-INSERT INTO t2 VALUES (128);
-INSERT INTO t2 VALUES (129);
-INSERT INTO t2 VALUES (130);
-include/save_master_gtid.inc
-connection server_2;
-include/start_slave.inc
-include/sync_with_master_gtid.inc
-SELECT * FROM t2 WHERE a >= 100 ORDER BY a;
-a
-101
-102
-103
-104
-105
-107
-108
-109
-110
-111
-112
-113
-114
-115
-116
-117
-118
-119
-120
-121
-122
-123
-124
-125
-126
-127
-128
-129
-130
-include/stop_slave.inc
-SET GLOBAL debug_dbug=@old_dbug;
-SET GLOBAL slave_parallel_threads=10;
-include/start_slave.inc
-*** MDEV-6676 - test syntax of @@slave_parallel_mode ***
-connection server_2;
-Parallel_Mode = 'conservative'
-include/stop_slave.inc
-SET GLOBAL slave_parallel_mode='aggressive';
-Parallel_Mode = 'aggressive'
-SET GLOBAL slave_parallel_mode='conservative';
-Parallel_Mode = 'conservative'
-*** MDEV-6676 - test that empty parallel_mode does not replicate in parallel ***
-connection server_1;
-INSERT INTO t2 VALUES (1040);
-include/save_master_gtid.inc
-connection server_2;
-SET GLOBAL slave_parallel_mode='none';
-SET @old_dbug= @@GLOBAL.debug_dbug;
-SET GLOBAL debug_dbug="+d,slave_crash_if_parallel_apply";
-include/start_slave.inc
-include/sync_with_master_gtid.inc
-SELECT * FROM t2 WHERE a >= 1040 ORDER BY a;
-a
-1040
-include/stop_slave.inc
-SET GLOBAL debug_dbug=@old_dbug;
-*** MDEV-6676 - test disabling domain-based parallel replication ***
-connection server_1;
-SET gtid_domain_id = 1;
-INSERT INTO t2 VALUES (1041);
-INSERT INTO t2 VALUES (1042);
-INSERT INTO t2 VALUES (1043);
-INSERT INTO t2 VALUES (1044);
-INSERT INTO t2 VALUES (1045);
-INSERT INTO t2 VALUES (1046);
-DELETE FROM t2 WHERE a >= 1041;
-SET gtid_domain_id = 2;
-INSERT INTO t2 VALUES (1041);
-INSERT INTO t2 VALUES (1042);
-INSERT INTO t2 VALUES (1043);
-INSERT INTO t2 VALUES (1044);
-INSERT INTO t2 VALUES (1045);
-INSERT INTO t2 VALUES (1046);
-SET gtid_domain_id = 0;
-include/save_master_gtid.inc
-connection server_2;
-SET GLOBAL slave_parallel_mode=minimal;
-include/start_slave.inc
-include/sync_with_master_gtid.inc
-SELECT * FROM t2 WHERE a >= 1040 ORDER BY a;
-a
-1040
-1041
-1042
-1043
-1044
-1045
-1046
-*** MDEV-7888: ANALYZE TABLE does wakeup_subsequent_commits(), causing wrong binlog order and parallel replication hang ***
-connection server_2;
-include/stop_slave.inc
-SET GLOBAL slave_parallel_mode='conservative';
-SET GLOBAL slave_parallel_threads=10;
-SET @old_dbug= @@GLOBAL.debug_dbug;
-SET GLOBAL debug_dbug= '+d,inject_analyze_table_sleep';
-connection server_1;
-SET @old_dbug= @@SESSION.debug_dbug;
-SET SESSION debug_dbug="+d,binlog_force_commit_id";
-SET @commit_id= 10000;
-ANALYZE TABLE t2;
-Table Op Msg_type Msg_text
-test.t2 analyze status Engine-independent statistics collected
-test.t2 analyze status OK
-INSERT INTO t3 VALUES (120, 0);
-SET @commit_id= 10001;
-INSERT INTO t3 VALUES (121, 0);
-SET SESSION debug_dbug=@old_dbug;
-SELECT * FROM t3 WHERE a >= 120 ORDER BY a;
-a b
-120 0
-121 0
-include/save_master_gtid.inc
-connection server_2;
-include/start_slave.inc
-include/sync_with_master_gtid.inc
-SELECT * FROM t3 WHERE a >= 120 ORDER BY a;
-a b
-120 0
-121 0
-include/stop_slave.inc
-SET GLOBAL debug_dbug= @old_dbug;
-include/start_slave.inc
-*** MDEV-7929: record_gtid() for non-transactional event group calls wakeup_subsequent_commits() too early, causing slave hang. ***
-connection server_2;
-include/stop_slave.inc
-SET @old_dbug= @@GLOBAL.debug_dbug;
-SET GLOBAL debug_dbug= '+d,inject_record_gtid_serverid_100_sleep';
-connection server_1;
-SET @old_dbug= @@SESSION.debug_dbug;
-SET SESSION debug_dbug="+d,binlog_force_commit_id";
-SET @old_server_id= @@SESSION.server_id;
-SET SESSION server_id= 100;
-SET @commit_id= 10010;
-ALTER TABLE t1 COMMENT "Hulubulu!";
-SET SESSION server_id= @old_server_id;
-INSERT INTO t3 VALUES (130, 0);
-SET @commit_id= 10011;
-INSERT INTO t3 VALUES (131, 0);
-SET SESSION debug_dbug=@old_dbug;
-SELECT * FROM t3 WHERE a >= 130 ORDER BY a;
-a b
-130 0
-131 0
-include/save_master_gtid.inc
-connection server_2;
-include/start_slave.inc
-include/sync_with_master_gtid.inc
-SELECT * FROM t3 WHERE a >= 130 ORDER BY a;
-a b
-130 0
-131 0
-include/stop_slave.inc
-SET GLOBAL debug_dbug= @old_dbug;
-include/start_slave.inc
-*** MDEV-8031: Parallel replication stops on "connection killed" error (probably incorrectly handled deadlock kill) ***
-connection server_1;
-INSERT INTO t3 VALUES (201,0), (202,0);
-include/save_master_gtid.inc
-connection server_2;
-include/sync_with_master_gtid.inc
-include/stop_slave.inc
-SET @old_dbug= @@GLOBAL.debug_dbug;
-SET GLOBAL debug_dbug= '+d,inject_mdev8031';
-connection server_1;
-SET @old_dbug= @@SESSION.debug_dbug;
-SET SESSION debug_dbug="+d,binlog_force_commit_id";
-SET @commit_id= 10200;
-INSERT INTO t3 VALUES (203, 1);
-INSERT INTO t3 VALUES (204, 1);
-INSERT INTO t3 VALUES (205, 1);
-UPDATE t3 SET b=b+1 WHERE a=201;
-UPDATE t3 SET b=b+1 WHERE a=201;
-UPDATE t3 SET b=b+1 WHERE a=201;
-UPDATE t3 SET b=b+1 WHERE a=202;
-UPDATE t3 SET b=b+1 WHERE a=202;
-UPDATE t3 SET b=b+1 WHERE a=202;
-UPDATE t3 SET b=b+1 WHERE a=202;
-UPDATE t3 SET b=b+1 WHERE a=203;
-UPDATE t3 SET b=b+1 WHERE a=203;
-UPDATE t3 SET b=b+1 WHERE a=204;
-UPDATE t3 SET b=b+1 WHERE a=204;
-UPDATE t3 SET b=b+1 WHERE a=204;
-UPDATE t3 SET b=b+1 WHERE a=203;
-UPDATE t3 SET b=b+1 WHERE a=205;
-UPDATE t3 SET b=b+1 WHERE a=205;
-SET SESSION debug_dbug=@old_dbug;
-SELECT * FROM t3 WHERE a>=200 ORDER BY a;
-a b
-201 3
-202 4
-203 4
-204 4
-205 3
-include/save_master_gtid.inc
-connection server_2;
-include/start_slave.inc
-include/sync_with_master_gtid.inc
-SELECT * FROM t3 WHERE a>=200 ORDER BY a;
-a b
-201 3
-202 4
-203 4
-204 4
-205 3
-include/stop_slave.inc
-SET GLOBAL debug_dbug= @old_dbug;
-include/start_slave.inc
-*** Check getting deadlock killed inside open_binlog() during retry. ***
-connection server_2;
-include/stop_slave.inc
-SET @old_dbug= @@GLOBAL.debug_dbug;
-SET GLOBAL debug_dbug= '+d,inject_retry_event_group_open_binlog_kill';
-SET @old_max= @@GLOBAL.max_relay_log_size;
-SET GLOBAL max_relay_log_size= 4096;
-connection server_1;
-SET @old_dbug= @@SESSION.debug_dbug;
-SET SESSION debug_dbug="+d,binlog_force_commit_id";
-SET @commit_id= 10210;
-Omit long queries that cause relaylog rotations and transaction retries...
-SET SESSION debug_dbug=@old_dbug;
-SELECT * FROM t3 WHERE a>=200 ORDER BY a;
-a b
-201 6
-202 8
-203 7
-204 7
-205 5
-include/save_master_gtid.inc
-connection server_2;
-include/start_slave.inc
-include/sync_with_master_gtid.inc
-SELECT * FROM t3 WHERE a>=200 ORDER BY a;
-a b
-201 6
-202 8
-203 7
-204 7
-205 5
-include/stop_slave.inc
-SET GLOBAL debug_dbug= @old_debg;
-SET GLOBAL max_relay_log_size= @old_max;
-include/start_slave.inc
-*** MDEV-8725: Assertion on ROLLBACK statement in the binary log ***
-connection server_1;
-BEGIN;
-INSERT INTO t2 VALUES (2000);
-INSERT INTO t1 VALUES (2000);
-INSERT INTO t2 VALUES (2001);
-ROLLBACK;
-SELECT * FROM t1 WHERE a>=2000 ORDER BY a;
-a
-2000
-SELECT * FROM t2 WHERE a>=2000 ORDER BY a;
-a
-include/save_master_gtid.inc
-connection server_2;
-include/sync_with_master_gtid.inc
-SELECT * FROM t1 WHERE a>=2000 ORDER BY a;
-a
-2000
-SELECT * FROM t2 WHERE a>=2000 ORDER BY a;
-a
-connection server_2;
-include/stop_slave.inc
-SET GLOBAL slave_parallel_threads=@old_parallel_threads;
-include/start_slave.inc
-SET DEBUG_SYNC= 'RESET';
-connection server_1;
-DROP function foo;
-DROP TABLE t1,t2,t3,t4,t5,t6;
-SET DEBUG_SYNC= 'RESET';
-include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/r/rpl_parallel_analyze_table_hang.result b/mysql-test/suite/rpl/r/rpl_parallel_analyze_table_hang.result
new file mode 100644
index 00000000000..3c3cd2601e8
--- /dev/null
+++ b/mysql-test/suite/rpl/r/rpl_parallel_analyze_table_hang.result
@@ -0,0 +1,51 @@
+*** MDEV-7888: ANALYZE TABLE does wakeup_subsequent_commits(), causing wrong binlog order and parallel replication hang ***
+include/master-slave.inc
+[connection master]
+connection server_2;
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+SET @old_parallel_mode=@@GLOBAL.slave_parallel_mode;
+include/stop_slave.inc
+SET GLOBAL slave_parallel_mode='conservative';
+SET GLOBAL slave_parallel_threads=10;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+include/start_slave.inc
+connection server_1;
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t2 (a int PRIMARY KEY) ENGINE=InnoDB;
+CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
+connection server_2;
+include/stop_slave.inc
+SET @old_dbug= @@GLOBAL.debug_dbug;
+SET GLOBAL debug_dbug= '+d,inject_analyze_table_sleep';
+connection server_1;
+SET @old_dbug= @@SESSION.debug_dbug;
+SET SESSION debug_dbug="+d,binlog_force_commit_id";
+SET @commit_id= 10000;
+ANALYZE TABLE t2;
+Table Op Msg_type Msg_text
+test.t2 analyze status Engine-independent statistics collected
+test.t2 analyze status OK
+INSERT INTO t3 VALUES (120, 0);
+SET @commit_id= 10001;
+INSERT INTO t3 VALUES (121, 0);
+SET SESSION debug_dbug=@old_dbug;
+SELECT * FROM t3 WHERE a >= 120 ORDER BY a;
+a b
+120 0
+121 0
+include/save_master_gtid.inc
+connection server_2;
+include/start_slave.inc
+include/sync_with_master_gtid.inc
+SELECT * FROM t3 WHERE a >= 120 ORDER BY a;
+a b
+120 0
+121 0
+include/stop_slave.inc
+SET GLOBAL debug_dbug= @old_dbug;
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+SET GLOBAL slave_parallel_mode=@old_parallel_mode;
+include/start_slave.inc
+connection server_1;
+DROP TABLE t2,t3;
+include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/r/rpl_parallel_conflicts.result b/mysql-test/suite/rpl/r/rpl_parallel_conflicts.result
index b15de6fc215..eeddb89985f 100644
--- a/mysql-test/suite/rpl/r/rpl_parallel_conflicts.result
+++ b/mysql-test/suite/rpl/r/rpl_parallel_conflicts.result
@@ -8,6 +8,12 @@ CREATE TABLE t7 (a int PRIMARY KEY, b INT) ENGINE=InnoDB;
CREATE TABLE t8 (a int PRIMARY KEY, b INT) ENGINE=InnoDB;
connection server_2;
include/stop_slave.inc
+SET @old_mode= @@GLOBAL.slave_parallel_mode;
+SET GLOBAL slave_parallel_mode=conservative;
+SET @old_threads= @@GLOBAL.slave_parallel_threads;
+SET GLOBAL slave_parallel_threads=40;
+SET @old_transaction_retries= @@GLOBAL.slave_transaction_retries;
+SET GLOBAL slave_transaction_retries=5;
connection server_1;
INSERT INTO t7 VALUES (1,1), (2,2), (3,3), (4,4), (5,5);
SET @old_dbug= @@SESSION.debug_dbug;
@@ -325,6 +331,9 @@ a b
104 4
include/stop_slave.inc
SET GLOBAL debug_dbug=@old_dbug;
+SET GLOBAL slave_parallel_mode=@old_mode;
+SET GLOBAL slave_parallel_threads=@old_threads;
+SET GLOBAL slave_transaction_retries=@old_transaction_retries;
include/start_slave.inc
SET DEBUG_SYNC= 'RESET';
connection server_1;
diff --git a/mysql-test/suite/rpl/r/rpl_parallel_deadlock_corrupt_binlog.result b/mysql-test/suite/rpl/r/rpl_parallel_deadlock_corrupt_binlog.result
new file mode 100644
index 00000000000..74d1d53b67c
--- /dev/null
+++ b/mysql-test/suite/rpl/r/rpl_parallel_deadlock_corrupt_binlog.result
@@ -0,0 +1,93 @@
+*** MDEV-7335: Potential parallel slave deadlock with specific binlog corruption ***
+include/master-slave.inc
+[connection master]
+connection server_2;
+include/stop_slave.inc
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+SET GLOBAL slave_parallel_threads=10;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+include/start_slave.inc
+connection server_1;
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t2 (a int PRIMARY KEY) ENGINE=InnoDB;
+connection server_2;
+include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=1;
+SET @old_dbug= @@GLOBAL.debug_dbug;
+SET GLOBAL debug_dbug="+d,slave_discard_xid_for_gtid_0_x_1000";
+connection server_1;
+INSERT INTO t2 VALUES (101);
+INSERT INTO t2 VALUES (102);
+INSERT INTO t2 VALUES (103);
+INSERT INTO t2 VALUES (104);
+INSERT INTO t2 VALUES (105);
+SET gtid_seq_no=1000;
+INSERT INTO t2 VALUES (106);
+INSERT INTO t2 VALUES (107);
+INSERT INTO t2 VALUES (108);
+INSERT INTO t2 VALUES (109);
+INSERT INTO t2 VALUES (110);
+INSERT INTO t2 VALUES (111);
+INSERT INTO t2 VALUES (112);
+INSERT INTO t2 VALUES (113);
+INSERT INTO t2 VALUES (114);
+INSERT INTO t2 VALUES (115);
+INSERT INTO t2 VALUES (116);
+INSERT INTO t2 VALUES (117);
+INSERT INTO t2 VALUES (118);
+INSERT INTO t2 VALUES (119);
+INSERT INTO t2 VALUES (120);
+INSERT INTO t2 VALUES (121);
+INSERT INTO t2 VALUES (122);
+INSERT INTO t2 VALUES (123);
+INSERT INTO t2 VALUES (124);
+INSERT INTO t2 VALUES (125);
+INSERT INTO t2 VALUES (126);
+INSERT INTO t2 VALUES (127);
+INSERT INTO t2 VALUES (128);
+INSERT INTO t2 VALUES (129);
+INSERT INTO t2 VALUES (130);
+include/save_master_gtid.inc
+connection server_2;
+include/start_slave.inc
+include/sync_with_master_gtid.inc
+SELECT * FROM t2 WHERE a >= 100 ORDER BY a;
+a
+101
+102
+103
+104
+105
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+include/stop_slave.inc
+SET GLOBAL debug_dbug=@old_dbug;
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+include/start_slave.inc
+SET DEBUG_SYNC= 'RESET';
+connection server_1;
+DROP TABLE t2;
+SET DEBUG_SYNC= 'RESET';
+include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/r/rpl_parallel_domain.result b/mysql-test/suite/rpl/r/rpl_parallel_domain.result
new file mode 100644
index 00000000000..69b9678d149
--- /dev/null
+++ b/mysql-test/suite/rpl/r/rpl_parallel_domain.result
@@ -0,0 +1,71 @@
+include/master-slave.inc
+[connection master]
+connection server_2;
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+SET GLOBAL slave_parallel_threads=10;
+ERROR HY000: This operation cannot be performed as you have a running slave ''; run STOP SLAVE '' first
+include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=10;
+SELECT IF(COUNT(*) < 10, "OK", CONCAT("Found too many system user processes: ", COUNT(*))) FROM information_schema.processlist WHERE user = "system user";
+IF(COUNT(*) < 10, "OK", CONCAT("Found too many system user processes: ", COUNT(*)))
+OK
+CHANGE MASTER TO master_use_gtid=slave_pos;
+include/start_slave.inc
+SELECT IF(COUNT(*) >= 10, "OK", CONCAT("Found too few system user processes: ", COUNT(*))) FROM information_schema.processlist WHERE user = "system user";
+IF(COUNT(*) >= 10, "OK", CONCAT("Found too few system user processes: ", COUNT(*)))
+OK
+include/stop_slave.inc
+SELECT IF(COUNT(*) < 10, "OK", CONCAT("Found too many system user processes: ", COUNT(*))) FROM information_schema.processlist WHERE user = "system user";
+IF(COUNT(*) < 10, "OK", CONCAT("Found too many system user processes: ", COUNT(*)))
+OK
+include/start_slave.inc
+SELECT IF(COUNT(*) >= 10, "OK", CONCAT("Found too few system user processes: ", COUNT(*))) FROM information_schema.processlist WHERE user = "system user";
+IF(COUNT(*) >= 10, "OK", CONCAT("Found too few system user processes: ", COUNT(*)))
+OK
+*** Test long-running query in domain 1 can run in parallel with short queries in domain 0 ***
+connection server_1;
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t1 (a int PRIMARY KEY) ENGINE=MyISAM;
+CREATE TABLE t2 (a int PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t2 VALUES (1);
+connection server_2;
+connect con_temp1,127.0.0.1,root,,test,$SERVER_MYPORT_2,;
+LOCK TABLE t1 WRITE;
+connection server_1;
+SET gtid_domain_id=1;
+INSERT INTO t1 VALUES (2);
+SET gtid_domain_id=0;
+INSERT INTO t2 VALUES (2);
+INSERT INTO t2 VALUES (3);
+BEGIN;
+INSERT INTO t2 VALUES (4);
+INSERT INTO t2 VALUES (5);
+COMMIT;
+INSERT INTO t2 VALUES (6);
+connection server_2;
+SELECT * FROM t2 ORDER by a;
+a
+1
+2
+3
+4
+5
+6
+connection con_temp1;
+SELECT * FROM t1;
+a
+1
+UNLOCK TABLES;
+connection server_2;
+SELECT * FROM t1 ORDER BY a;
+a
+1
+2
+connection server_2;
+include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+include/start_slave.inc
+connection server_1;
+DROP TABLE t1,t2;
+include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/r/rpl_parallel_domain_slave_single_grp.result b/mysql-test/suite/rpl/r/rpl_parallel_domain_slave_single_grp.result
new file mode 100644
index 00000000000..613aac64487
--- /dev/null
+++ b/mysql-test/suite/rpl/r/rpl_parallel_domain_slave_single_grp.result
@@ -0,0 +1,101 @@
+*** Test two transactions in different domains committed in opposite order on slave but in a single group commit. ***
+include/master-slave.inc
+[connection master]
+connection server_2;
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=10;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+include/start_slave.inc
+connection server_1;
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t1 (a int PRIMARY KEY) ENGINE=MyISAM;
+CREATE TABLE t2 (a int PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t2 VALUES (1);
+connection server_2;
+include/stop_slave.inc
+connection server_1;
+SET sql_log_bin=0;
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+RETURNS INT DETERMINISTIC
+BEGIN
+RETURN x;
+END
+||
+SET sql_log_bin=1;
+SET @old_format= @@SESSION.binlog_format;
+SET binlog_format='statement';
+SET gtid_domain_id=1;
+INSERT INTO t2 VALUES (foo(10,
+'commit_before_enqueue SIGNAL ready1 WAIT_FOR cont1',
+'commit_after_release_LOCK_prepare_ordered SIGNAL ready2'));
+connection server_2;
+FLUSH LOGS;
+SET sql_log_bin=0;
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+RETURNS INT DETERMINISTIC
+BEGIN
+IF d1 != '' THEN
+SET debug_sync = d1;
+END IF;
+IF d2 != '' THEN
+SET debug_sync = d2;
+END IF;
+RETURN x;
+END
+||
+SET sql_log_bin=1;
+SET @old_format=@@GLOBAL.binlog_format;
+SET GLOBAL binlog_format=statement;
+SET GLOBAL slave_parallel_threads=0;
+SET GLOBAL slave_parallel_threads=10;
+include/start_slave.inc
+SET debug_sync='now WAIT_FOR ready1';
+connection server_1;
+SET gtid_domain_id=2;
+INSERT INTO t2 VALUES (foo(11,
+'commit_before_enqueue SIGNAL ready3 WAIT_FOR cont3',
+'commit_after_release_LOCK_prepare_ordered SIGNAL ready4 WAIT_FOR cont4'));
+SET gtid_domain_id=0;
+SELECT * FROM t2 WHERE a >= 10 ORDER BY a;
+a
+10
+11
+connection server_2;
+SET debug_sync='now WAIT_FOR ready3';
+SET debug_sync='now SIGNAL cont3';
+SET debug_sync='now WAIT_FOR ready4';
+SET debug_sync='now SIGNAL cont1';
+SET debug_sync='now WAIT_FOR ready2';
+SET debug_sync='now SIGNAL cont4';
+SELECT * FROM t2 WHERE a >= 10 ORDER BY a;
+a
+10
+11
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+slave-bin.000002 # Binlog_checkpoint # # slave-bin.000002
+slave-bin.000002 # Gtid # # BEGIN GTID #-#-# cid=#
+slave-bin.000002 # Query # # use `test`; INSERT INTO t2 VALUES (foo(11,
+'commit_before_enqueue SIGNAL ready3 WAIT_FOR cont3',
+'commit_after_release_LOCK_prepare_ordered SIGNAL ready4 WAIT_FOR cont4'))
+slave-bin.000002 # Xid # # COMMIT /* XID */
+slave-bin.000002 # Gtid # # BEGIN GTID #-#-# cid=#
+slave-bin.000002 # Query # # use `test`; INSERT INTO t2 VALUES (foo(10,
+'commit_before_enqueue SIGNAL ready1 WAIT_FOR cont1',
+'commit_after_release_LOCK_prepare_ordered SIGNAL ready2'))
+slave-bin.000002 # Xid # # COMMIT /* XID */
+FLUSH LOGS;
+connection server_2;
+include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+include/start_slave.inc
+SET DEBUG_SYNC= 'RESET';
+SET GLOBAL binlog_format=@old_format;
+connection server_1;
+DROP function foo;
+DROP TABLE t1,t2;
+SET DEBUG_SYNC= 'RESET';
+SET GLOBAL binlog_format=@old_format;
+include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/r/rpl_parallel_free_deferred_event.result b/mysql-test/suite/rpl/r/rpl_parallel_free_deferred_event.result
new file mode 100644
index 00000000000..6718561a321
--- /dev/null
+++ b/mysql-test/suite/rpl/r/rpl_parallel_free_deferred_event.result
@@ -0,0 +1,44 @@
+*** MDEV-5788 Incorrect free of rgi->deferred_events in parallel replication ***
+include/master-slave.inc
+[connection master]
+connection server_2;
+include/stop_slave.inc
+CHANGE MASTER TO master_use_gtid=slave_pos;
+include/start_slave.inc
+connection server_1;
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
+connection server_2;
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+include/stop_slave.inc
+SET GLOBAL replicate_ignore_table="test.t3";
+SET GLOBAL slave_parallel_threads=2;
+include/start_slave.inc
+connection server_1;
+INSERT INTO t3 VALUES (100, rand());
+INSERT INTO t3 VALUES (101, rand());
+connection server_2;
+connection server_1;
+INSERT INTO t3 VALUES (102, rand());
+INSERT INTO t3 VALUES (103, rand());
+INSERT INTO t3 VALUES (104, rand());
+INSERT INTO t3 VALUES (105, rand());
+connection server_2;
+include/stop_slave.inc
+SET GLOBAL replicate_ignore_table="";
+include/start_slave.inc
+connection server_1;
+INSERT INTO t3 VALUES (106, rand());
+INSERT INTO t3 VALUES (107, rand());
+connection server_2;
+SELECT * FROM t3 WHERE a >= 100 ORDER BY a;
+a b
+106 #
+107 #
+connection server_2;
+include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+include/start_slave.inc
+connection server_1;
+DROP TABLE t3;
+include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/r/rpl_parallel_gco_wait_kill.result b/mysql-test/suite/rpl/r/rpl_parallel_gco_wait_kill.result
new file mode 100644
index 00000000000..4472550c4f2
--- /dev/null
+++ b/mysql-test/suite/rpl/r/rpl_parallel_gco_wait_kill.result
@@ -0,0 +1,257 @@
+*** Test killing thread that is waiting to start transaction until previous transaction commits ***
+include/master-slave.inc
+[connection master]
+connection server_2;
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+SET @old_parallel_mode= @@GLOBAL.slave_parallel_mode;
+include/stop_slave.inc
+SET sql_log_bin=0;
+CALL mtr.add_suppression("Query execution was interrupted");
+CALL mtr.add_suppression("Slave: Connection was killed");
+CALL mtr.add_suppression("Commit failed due to failure of an earlier commit on which this one depends");
+SET sql_log_bin=1;
+SET GLOBAL slave_parallel_threads=10;
+SET GLOBAL slave_parallel_mode= 'conservative';
+CHANGE MASTER TO master_use_gtid=slave_pos;
+include/start_slave.inc
+connection server_1;
+connect con_temp3,127.0.0.1,root,,test,$SERVER_MYPORT_1,;
+connect con_temp4,127.0.0.1,root,,test,$SERVER_MYPORT_1,;
+connect con_temp5,127.0.0.1,root,,test,$SERVER_MYPORT_1,;
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
+connection server_2;
+connection server_1;
+SET sql_log_bin=0;
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+RETURNS INT DETERMINISTIC
+BEGIN
+RETURN x;
+END
+||
+SET sql_log_bin=1;
+connection server_2;
+SET sql_log_bin=0;
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+RETURNS INT DETERMINISTIC
+BEGIN
+IF d1 != '' THEN
+SET debug_sync = d1;
+END IF;
+IF d2 != '' THEN
+SET debug_sync = d2;
+END IF;
+RETURN x;
+END
+||
+SET sql_log_bin=1;
+include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=0;
+SET GLOBAL slave_parallel_threads=4;
+include/start_slave.inc
+connection server_1;
+SET gtid_domain_id=2;
+BEGIN;
+INSERT INTO t3 VALUES (70, foo(70,
+'rpl_parallel_start_waiting_for_prior SIGNAL t4_waiting', ''));
+INSERT INTO t3 VALUES (60, foo(60,
+'ha_write_row_end SIGNAL d2_query WAIT_FOR d2_cont2',
+'rpl_parallel_end_of_group SIGNAL d2_done WAIT_FOR d2_cont'));
+COMMIT;
+SET gtid_domain_id=0;
+connection server_2;
+SET debug_sync='now WAIT_FOR d2_query';
+connection server_1;
+SET gtid_domain_id=1;
+BEGIN;
+INSERT INTO t3 VALUES (61, foo(61,
+'rpl_parallel_start_waiting_for_prior SIGNAL t3_waiting',
+'rpl_parallel_start_waiting_for_prior_killed SIGNAL t3_killed'));
+INSERT INTO t3 VALUES (62, foo(62,
+'ha_write_row_end SIGNAL d1_query WAIT_FOR d1_cont2',
+'rpl_parallel_end_of_group SIGNAL d1_done WAIT_FOR d1_cont'));
+COMMIT;
+SET gtid_domain_id=0;
+connection server_2;
+SET debug_sync='now WAIT_FOR d1_query';
+connection server_1;
+SET gtid_domain_id=0;
+INSERT INTO t3 VALUES (63, foo(63,
+'ha_write_row_end SIGNAL d0_query WAIT_FOR d0_cont2',
+'rpl_parallel_end_of_group SIGNAL d0_done WAIT_FOR d0_cont'));
+connection server_2;
+SET debug_sync='now WAIT_FOR d0_query';
+connection server_1;
+SET gtid_domain_id=3;
+BEGIN;
+INSERT INTO t3 VALUES (68, foo(68,
+'rpl_parallel_start_waiting_for_prior SIGNAL t2_waiting', ''));
+INSERT INTO t3 VALUES (69, foo(69,
+'ha_write_row_end SIGNAL d3_query WAIT_FOR d3_cont2',
+'rpl_parallel_end_of_group SIGNAL d3_done WAIT_FOR d3_cont'));
+COMMIT;
+SET gtid_domain_id=0;
+connection server_2;
+SET debug_sync='now WAIT_FOR d3_query';
+SET debug_sync='now SIGNAL d2_cont2';
+SET debug_sync='now WAIT_FOR d2_done';
+SET debug_sync='now SIGNAL d1_cont2';
+SET debug_sync='now WAIT_FOR d1_done';
+SET debug_sync='now SIGNAL d0_cont2';
+SET debug_sync='now WAIT_FOR d0_done';
+SET debug_sync='now SIGNAL d3_cont2';
+SET debug_sync='now WAIT_FOR d3_done';
+connection con_temp3;
+INSERT INTO t3 VALUES (64, foo(64,
+'rpl_parallel_before_mark_start_commit SIGNAL t1_waiting WAIT_FOR t1_cont', ''));
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2 WAIT_FOR master_cont2';
+INSERT INTO t3 VALUES (65, foo(65, '', ''));
+connection server_1;
+SET debug_sync='now WAIT_FOR master_queued2';
+connection con_temp4;
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued3';
+INSERT INTO t3 VALUES (66, foo(66, '', ''));
+connection server_1;
+SET debug_sync='now WAIT_FOR master_queued3';
+connection con_temp5;
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued4';
+INSERT INTO t3 VALUES (67, foo(67, '', ''));
+connection server_1;
+SET debug_sync='now WAIT_FOR master_queued4';
+SET debug_sync='now SIGNAL master_cont2';
+connection con_temp3;
+connection con_temp4;
+connection con_temp5;
+connection server_1;
+SELECT * FROM t3 WHERE a >= 60 ORDER BY a;
+a b
+60 60
+61 61
+62 62
+63 63
+64 64
+65 65
+66 66
+67 67
+68 68
+69 69
+70 70
+SET debug_sync='RESET';
+connection server_2;
+SET debug_sync='now SIGNAL d0_cont';
+SET debug_sync='now WAIT_FOR t1_waiting';
+SET debug_sync='now SIGNAL d3_cont';
+SET debug_sync='now WAIT_FOR t2_waiting';
+SET debug_sync='now SIGNAL d1_cont';
+SET debug_sync='now WAIT_FOR t3_waiting';
+SET debug_sync='now SIGNAL d2_cont';
+SET debug_sync='now WAIT_FOR t4_waiting';
+KILL THD_ID;
+SET debug_sync='now WAIT_FOR t3_killed';
+SET debug_sync='now SIGNAL t1_cont';
+include/wait_for_slave_sql_error.inc [errno=1317,1927,1964]
+STOP SLAVE IO_THREAD;
+SELECT * FROM t3 WHERE a >= 60 AND a != 65 ORDER BY a;
+a b
+60 60
+61 61
+62 62
+63 63
+64 64
+68 68
+69 69
+70 70
+SET debug_sync='RESET';
+SET GLOBAL slave_parallel_threads=0;
+SET GLOBAL slave_parallel_threads=10;
+SET sql_log_bin=0;
+DROP FUNCTION foo;
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+RETURNS INT DETERMINISTIC
+BEGIN
+RETURN x;
+END
+||
+SET sql_log_bin=1;
+connection server_1;
+UPDATE t3 SET b=b+1 WHERE a=60;
+connection server_2;
+include/start_slave.inc
+SELECT * FROM t3 WHERE a >= 60 ORDER BY a;
+a b
+60 61
+61 61
+62 62
+63 63
+64 64
+65 65
+66 66
+67 67
+68 68
+69 69
+70 70
+SET sql_log_bin=0;
+DROP FUNCTION foo;
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+RETURNS INT DETERMINISTIC
+BEGIN
+IF d1 != '' THEN
+SET debug_sync = d1;
+END IF;
+IF d2 != '' THEN
+SET debug_sync = d2;
+END IF;
+RETURN x;
+END
+||
+SET sql_log_bin=1;
+connection server_2;
+include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=0;
+SET GLOBAL slave_parallel_threads=10;
+include/start_slave.inc
+*** 5. Test killing thread that is waiting for queue of max length to shorten ***
+SET @old_max_queued= @@GLOBAL.slave_parallel_max_queued;
+SET GLOBAL slave_parallel_max_queued=9000;
+connection server_1;
+INSERT INTO t3 VALUES (80, foo(0,
+'ha_write_row_end SIGNAL query_waiting WAIT_FOR query_cont', ''));
+connection server_2;
+SET debug_sync='now WAIT_FOR query_waiting';
+SET @old_dbug= @@GLOBAL.debug_dbug;
+SET GLOBAL debug_dbug="+d,rpl_parallel_wait_queue_max";
+connection server_1;
+SELECT * FROM t3 WHERE a >= 80 ORDER BY a;
+a b
+80 0
+81 10000
+connection server_2;
+SET debug_sync='now WAIT_FOR wait_queue_ready';
+KILL THD_ID;
+SET debug_sync='now WAIT_FOR wait_queue_killed';
+SET debug_sync='now SIGNAL query_cont';
+include/wait_for_slave_sql_error.inc [errno=1317,1927,1964]
+STOP SLAVE IO_THREAD;
+SET GLOBAL debug_dbug=@old_dbug;
+SET GLOBAL slave_parallel_max_queued= @old_max_queued;
+connection server_1;
+INSERT INTO t3 VALUES (82,0);
+connection server_2;
+SET debug_sync='RESET';
+include/start_slave.inc
+SELECT * FROM t3 WHERE a >= 80 ORDER BY a;
+a b
+80 0
+81 10000
+82 0
+connection server_2;
+include/stop_slave.inc
+SET GLOBAL slave_parallel_mode=@old_parallel_mode;
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+include/start_slave.inc
+SET DEBUG_SYNC= 'RESET';
+connection server_1;
+DROP function foo;
+DROP TABLE t3;
+SET DEBUG_SYNC= 'RESET';
+include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/r/rpl_parallel_gtid_slave_pos_update_fail.result b/mysql-test/suite/rpl/r/rpl_parallel_gtid_slave_pos_update_fail.result
new file mode 100644
index 00000000000..2e7e7f547af
--- /dev/null
+++ b/mysql-test/suite/rpl/r/rpl_parallel_gtid_slave_pos_update_fail.result
@@ -0,0 +1,65 @@
+include/master-slave.inc
+[connection master]
+connection server_2;
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=10;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+include/start_slave.inc
+connection server_1;
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t4 (a INT PRIMARY KEY, b INT, KEY b_idx(b)) ENGINE=InnoDB;
+INSERT INTO t4 VALUES (1,NULL), (2,2), (3,NULL), (4,4), (5, NULL), (6, 6);
+connect con1,127.0.0.1,root,,test,$SERVER_MYPORT_1,;
+connect con2,127.0.0.1,root,,test,$SERVER_MYPORT_1,;
+connection server_2;
+include/stop_slave.inc
+connection con1;
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
+UPDATE t4 SET b=NULL WHERE a=6;
+connection server_1;
+SET debug_sync='now WAIT_FOR master_queued1';
+connection con2;
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
+DELETE FROM t4 WHERE b <= 1;
+connection server_1;
+SET debug_sync='now WAIT_FOR master_queued2';
+SET debug_sync='now SIGNAL master_cont1';
+connection con1;
+connection con2;
+SET debug_sync='RESET';
+connection server_2;
+SET @old_dbug= @@GLOBAL.debug_dbug;
+SET GLOBAL debug_dbug="+d,disable_thd_need_ordering_with";
+include/start_slave.inc
+SET GLOBAL debug_dbug=@old_dbug;
+SELECT * FROM t4 ORDER BY a;
+a b
+1 NULL
+2 2
+3 NULL
+4 4
+5 NULL
+6 NULL
+SET @last_gtid= 'GTID';
+SELECT IF(@@gtid_slave_pos LIKE CONCAT('%',@last_gtid,'%'), "GTID found ok",
+CONCAT("GTID ", @last_gtid, " not found in gtid_slave_pos=", @@gtid_slave_pos))
+AS result;
+result
+GTID found ok
+SELECT "ROW FOUND" AS `Is the row found?`
+ FROM mysql.gtid_slave_pos
+WHERE CONCAT(domain_id, "-", server_id, "-", seq_no) = @last_gtid;
+Is the row found?
+ROW FOUND
+connection server_2;
+include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+include/start_slave.inc
+SET DEBUG_SYNC= 'RESET';
+connection server_1;
+DROP TABLE t4;
+SET DEBUG_SYNC= 'RESET';
+disconnect con1;
+disconnect con2;
+include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/r/rpl_parallel_ignored_errors.result b/mysql-test/suite/rpl/r/rpl_parallel_ignored_errors.result
new file mode 100644
index 00000000000..d00740dba3d
--- /dev/null
+++ b/mysql-test/suite/rpl/r/rpl_parallel_ignored_errors.result
@@ -0,0 +1,74 @@
+*** MDEV-6551: Some replication errors are ignored if slave_parallel_threads > 0 ***
+include/master-slave.inc
+[connection master]
+connection server_2;
+include/stop_slave.inc
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+SET @old_parallel_mode=@@GLOBAL.slave_parallel_mode;
+SET GLOBAL slave_parallel_threads=1;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+CALL mtr.add_suppression("Commit failed due to failure of an earlier commit on which this one depends");
+include/start_slave.inc
+connection server_1;
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t2 (a int PRIMARY KEY) ENGINE=InnoDB;
+SET gtid_domain_id=1;
+INSERT INTO t2 VALUES (1);
+SET gtid_domain_id=0;
+SET gtid_domain_id=2;
+INSERT INTO t2 VALUES (2);
+SET gtid_domain_id=0;
+INSERT INTO t2 VALUES (31);
+include/save_master_gtid.inc
+connection server_2;
+include/sync_with_master_gtid.inc
+include/stop_slave.inc
+SET GLOBAL slave_parallel_threads= 0;
+include/start_slave.inc
+SET sql_log_bin= 0;
+INSERT INTO t2 VALUES (32);
+SET sql_log_bin= 1;
+connection server_1;
+INSERT INTO t2 VALUES (32);
+FLUSH LOGS;
+INSERT INTO t2 VALUES (33);
+INSERT INTO t2 VALUES (34);
+SELECT * FROM t2 WHERE a >= 30 ORDER BY a;
+a
+31
+32
+33
+34
+include/save_master_gtid.inc
+connection server_2;
+include/wait_for_slave_sql_error.inc [errno=1062]
+connection server_2;
+include/stop_slave_io.inc
+SET GLOBAL slave_parallel_threads=10;
+START SLAVE;
+include/wait_for_slave_sql_error.inc [errno=1062]
+START SLAVE SQL_THREAD;
+include/wait_for_slave_sql_error.inc [errno=1062]
+SELECT * FROM t2 WHERE a >= 30 ORDER BY a;
+a
+31
+32
+SET sql_slave_skip_counter= 1;
+ERROR HY000: When using parallel replication and GTID with multiple replication domains, @@sql_slave_skip_counter can not be used. Instead, setting @@gtid_slave_pos explicitly can be used to skip to after a given GTID position
+include/stop_slave_io.inc
+include/start_slave.inc
+include/sync_with_master_gtid.inc
+SELECT * FROM t2 WHERE a >= 30 ORDER BY a;
+a
+31
+32
+33
+34
+connection server_2;
+include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+SET GLOBAL slave_parallel_mode=@old_parallel_mode;
+include/start_slave.inc
+connection server_1;
+DROP TABLE t2;
+include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/r/rpl_parallel_incorrect_relay_pos.result b/mysql-test/suite/rpl/r/rpl_parallel_incorrect_relay_pos.result
new file mode 100644
index 00000000000..6ca7f2b68e8
--- /dev/null
+++ b/mysql-test/suite/rpl/r/rpl_parallel_incorrect_relay_pos.result
@@ -0,0 +1,75 @@
+*** MDEV-7237: Parallel replication: incorrect relaylog position after stop/start the slave ***
+include/master-slave.inc
+[connection master]
+connection server_2;
+include/stop_slave.inc
+CALL mtr.add_suppression("Commit failed due to failure of an earlier commit on which this one depends");
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+SET @old_parallel_mode=@@GLOBAL.slave_parallel_mode;
+SET GLOBAL slave_parallel_threads=10;
+SET GLOBAL slave_parallel_mode='conservative';
+CHANGE MASTER TO master_use_gtid=slave_pos;
+include/start_slave.inc
+connection server_1;
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t2 (a int PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t2 VALUES (40);
+connection server_2;
+connect con_temp2,127.0.0.1,root,,test,$SERVER_MYPORT_2,;
+include/stop_slave.inc
+CHANGE MASTER TO master_use_gtid=no;
+SET @old_dbug= @@GLOBAL.debug_dbug;
+SET GLOBAL debug_dbug="+d,rpl_parallel_scheduled_gtid_0_x_100";
+SET GLOBAL debug_dbug="+d,rpl_parallel_wait_for_done_trigger";
+SET GLOBAL slave_parallel_threads=0;
+SET GLOBAL slave_parallel_threads=10;
+connection server_1;
+INSERT INTO t2 VALUES (41);
+INSERT INTO t2 VALUES (42);
+SET @old_format= @@binlog_format;
+SET binlog_format= statement;
+DELETE FROM t2 WHERE a=40;
+SET binlog_format= @old_format;
+INSERT INTO t2 VALUES (43);
+INSERT INTO t2 VALUES (44);
+FLUSH LOGS;
+INSERT INTO t2 VALUES (45);
+SET gtid_seq_no=100;
+INSERT INTO t2 VALUES (46);
+connection con_temp2;
+BEGIN;
+SELECT * FROM t2 WHERE a=40 FOR UPDATE;
+a
+40
+connection server_2;
+include/start_slave.inc
+SET debug_sync= 'now WAIT_FOR scheduled_gtid_0_x_100';
+STOP SLAVE;
+connection con_temp2;
+SET debug_sync= 'now WAIT_FOR wait_for_done_waiting';
+ROLLBACK;
+connection server_2;
+include/wait_for_slave_sql_to_stop.inc
+SELECT * FROM t2 WHERE a >= 40 ORDER BY a;
+a
+41
+42
+include/start_slave.inc
+SELECT * FROM t2 WHERE a >= 40 ORDER BY a;
+a
+41
+42
+43
+44
+45
+46
+include/stop_slave.inc
+SET GLOBAL debug_dbug=@old_dbug;
+SET DEBUG_SYNC= 'RESET';
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+SET GLOBAL slave_parallel_mode=@old_parallel_mode;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+include/start_slave.inc
+connection server_1;
+DROP TABLE t2;
+include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/r/rpl_parallel_innodb_lock_conflict.result b/mysql-test/suite/rpl/r/rpl_parallel_innodb_lock_conflict.result
new file mode 100644
index 00000000000..1411db16af6
--- /dev/null
+++ b/mysql-test/suite/rpl/r/rpl_parallel_innodb_lock_conflict.result
@@ -0,0 +1,79 @@
+***MDEV-5914: Parallel replication deadlock due to InnoDB lock conflicts ***
+include/master-slave.inc
+[connection master]
+connection server_2;
+SET sql_log_bin=0;
+CALL mtr.add_suppression("Commit failed due to failure of an earlier commit on which this one depends");
+SET sql_log_bin=1;
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=10;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+connection server_1;
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t4 (a INT PRIMARY KEY, b INT, KEY b_idx(b)) ENGINE=InnoDB;
+INSERT INTO t4 VALUES (1,NULL), (2,2), (3,NULL), (4,4), (5, NULL), (6, 6);
+connect con1,127.0.0.1,root,,test,$SERVER_MYPORT_1,;
+connect con2,127.0.0.1,root,,test,$SERVER_MYPORT_1,;
+connection con1;
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
+UPDATE t4 SET b=NULL WHERE a=6;
+connection server_1;
+SET debug_sync='now WAIT_FOR master_queued1';
+connection con2;
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
+DELETE FROM t4 WHERE b <= 3;
+connection server_1;
+SET debug_sync='now WAIT_FOR master_queued2';
+SET debug_sync='now SIGNAL master_cont1';
+connection con1;
+connection con2;
+SET debug_sync='RESET';
+connection server_2;
+include/start_slave.inc
+include/stop_slave.inc
+SELECT * FROM t4 ORDER BY a;
+a b
+1 NULL
+3 NULL
+4 4
+5 NULL
+6 NULL
+connection server_1;
+DELETE FROM t4;
+INSERT INTO t4 VALUES (1,NULL), (2,2), (3,NULL), (4,4), (5, NULL), (6, 6);
+connection con1;
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
+INSERT INTO t4 VALUES (7, NULL);
+connection server_1;
+SET debug_sync='now WAIT_FOR master_queued1';
+connection con2;
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
+DELETE FROM t4 WHERE b <= 3;
+connection server_1;
+SET debug_sync='now WAIT_FOR master_queued2';
+SET debug_sync='now SIGNAL master_cont1';
+connection con1;
+connection con2;
+SET debug_sync='RESET';
+connection server_2;
+include/start_slave.inc
+include/stop_slave.inc
+SELECT * FROM t4 ORDER BY a;
+a b
+1 NULL
+3 NULL
+4 4
+5 NULL
+6 6
+7 NULL
+connection server_2;
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+include/start_slave.inc
+SET DEBUG_SYNC= 'RESET';
+connection server_1;
+disconnect con1;
+disconnect con2;
+DROP TABLE t4;
+SET DEBUG_SYNC= 'RESET';
+include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/r/rpl_parallel_mdev6589.result b/mysql-test/suite/rpl/r/rpl_parallel_mdev6589.result
index e05e824eed3..47cdb3496da 100644
--- a/mysql-test/suite/rpl/r/rpl_parallel_mdev6589.result
+++ b/mysql-test/suite/rpl/r/rpl_parallel_mdev6589.result
@@ -92,6 +92,7 @@ MASTER_GTID_WAIT('WAIT_POS')
0
connection con_temp1;
COMMIT;
+CALL mtr.add_suppression("Commit failed due to failure of an earlier commit on which this one depends");
SET sql_log_bin=1;
connection server_2;
include/wait_for_slave_sql_error.inc [errno=1062]
diff --git a/mysql-test/suite/rpl/r/rpl_parallel_missed_error_handling.result b/mysql-test/suite/rpl/r/rpl_parallel_missed_error_handling.result
new file mode 100644
index 00000000000..e9d04c02d7a
--- /dev/null
+++ b/mysql-test/suite/rpl/r/rpl_parallel_missed_error_handling.result
@@ -0,0 +1,65 @@
+*** MDEV-5921: In parallel replication, an error is not correctly signalled to the next transaction ***
+include/master-slave.inc
+[connection master]
+connection server_2;
+include/stop_slave.inc
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+SET GLOBAL slave_parallel_threads=10;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+CALL mtr.add_suppression("Commit failed due to failure of an earlier commit on which this one depends");
+include/start_slave.inc
+connection server_1;
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
+connection server_2;
+connection server_1;
+INSERT INTO t3 VALUES (110, 1);
+connection server_2;
+SELECT * FROM t3 WHERE a >= 110 ORDER BY a;
+a b
+110 1
+SET sql_log_bin=0;
+INSERT INTO t3 VALUES (111, 666);
+SET sql_log_bin=1;
+connection server_1;
+connect con1,127.0.0.1,root,,test,$SERVER_MYPORT_1,;
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
+INSERT INTO t3 VALUES (111, 2);
+connection server_1;
+SET debug_sync='now WAIT_FOR master_queued1';
+connect con2,127.0.0.1,root,,test,$SERVER_MYPORT_1,;
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
+INSERT INTO t3 VALUES (112, 3);
+connection server_1;
+SET debug_sync='now WAIT_FOR master_queued2';
+SET debug_sync='now SIGNAL master_cont1';
+connection con1;
+connection con2;
+SET debug_sync='RESET';
+connection server_2;
+include/wait_for_slave_sql_error.inc [errno=1062]
+include/wait_for_slave_sql_to_stop.inc
+SELECT * FROM t3 WHERE a >= 110 ORDER BY a;
+a b
+110 1
+111 666
+SET sql_log_bin=0;
+DELETE FROM t3 WHERE a=111 AND b=666;
+SET sql_log_bin=1;
+START SLAVE SQL_THREAD;
+SELECT * FROM t3 WHERE a >= 110 ORDER BY a;
+a b
+110 1
+111 2
+112 3
+connection server_2;
+include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+include/start_slave.inc
+SET DEBUG_SYNC= 'RESET';
+connection server_1;
+disconnect con1;
+disconnect con2;
+DROP TABLE t3;
+SET DEBUG_SYNC= 'RESET';
+include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/r/rpl_parallel_mode.result b/mysql-test/suite/rpl/r/rpl_parallel_mode.result
new file mode 100644
index 00000000000..313290b1fd2
--- /dev/null
+++ b/mysql-test/suite/rpl/r/rpl_parallel_mode.result
@@ -0,0 +1,75 @@
+*** MDEV-6676 - test syntax of @@slave_parallel_mode ***
+include/master-slave.inc
+[connection master]
+connection server_2;
+include/stop_slave.inc
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+SET @old_parallel_mode=@@GLOBAL.slave_parallel_mode;
+SET GLOBAL slave_parallel_threads=10;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+include/start_slave.inc
+connection server_1;
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t2 (a int PRIMARY KEY) ENGINE=InnoDB;
+connection server_2;
+Parallel_Mode = 'optimistic'
+include/stop_slave.inc
+SET GLOBAL slave_parallel_mode='aggressive';
+Parallel_Mode = 'aggressive'
+SET GLOBAL slave_parallel_mode='conservative';
+Parallel_Mode = 'conservative'
+*** MDEV-6676 - test that empty parallel_mode does not replicate in parallel ***
+connection server_1;
+INSERT INTO t2 VALUES (1040);
+include/save_master_gtid.inc
+connection server_2;
+SET GLOBAL slave_parallel_mode='none';
+SET @old_dbug= @@GLOBAL.debug_dbug;
+SET GLOBAL debug_dbug="+d,slave_crash_if_parallel_apply";
+include/start_slave.inc
+include/sync_with_master_gtid.inc
+SELECT * FROM t2 WHERE a >= 1040 ORDER BY a;
+a
+1040
+include/stop_slave.inc
+SET GLOBAL debug_dbug=@old_dbug;
+*** MDEV-6676 - test disabling domain-based parallel replication ***
+connection server_1;
+SET gtid_domain_id = 1;
+INSERT INTO t2 VALUES (1041);
+INSERT INTO t2 VALUES (1042);
+INSERT INTO t2 VALUES (1043);
+INSERT INTO t2 VALUES (1044);
+INSERT INTO t2 VALUES (1045);
+INSERT INTO t2 VALUES (1046);
+DELETE FROM t2 WHERE a >= 1041;
+SET gtid_domain_id = 2;
+INSERT INTO t2 VALUES (1041);
+INSERT INTO t2 VALUES (1042);
+INSERT INTO t2 VALUES (1043);
+INSERT INTO t2 VALUES (1044);
+INSERT INTO t2 VALUES (1045);
+INSERT INTO t2 VALUES (1046);
+SET gtid_domain_id = 0;
+include/save_master_gtid.inc
+connection server_2;
+SET GLOBAL slave_parallel_mode=minimal;
+include/start_slave.inc
+include/sync_with_master_gtid.inc
+SELECT * FROM t2 WHERE a >= 1040 ORDER BY a;
+a
+1040
+1041
+1042
+1043
+1044
+1045
+1046
+include/stop_slave.inc
+SET GLOBAL debug_dbug=@old_dbug;
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+SET GLOBAL slave_parallel_mode=@old_parallel_mode;
+include/start_slave.inc
+connection server_1;
+DROP TABLE t2;
+include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/r/rpl_parallel_partial_binlog_trans.result b/mysql-test/suite/rpl/r/rpl_parallel_partial_binlog_trans.result
new file mode 100644
index 00000000000..ab1cac692a0
--- /dev/null
+++ b/mysql-test/suite/rpl/r/rpl_parallel_partial_binlog_trans.result
@@ -0,0 +1,51 @@
+*** MDEV_6435: Incorrect error handling when query binlogged partially on master with "killed" error ***
+include/master-slave.inc
+[connection master]
+connection server_2;
+include/stop_slave.inc
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+SET GLOBAL slave_parallel_threads=1;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+include/start_slave.inc
+connection server_1;
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t6 (a INT) ENGINE=MyISAM;
+CREATE TRIGGER tr AFTER INSERT ON t6 FOR EACH ROW SET @a = 1;
+connect con1,127.0.0.1,root,,test,$SERVER_MYPORT_1,;
+connection con1;
+SET debug_sync='sp_head_execute_before_loop SIGNAL ready WAIT_FOR cont';
+INSERT INTO t6 VALUES (1), (2), (3);
+connection server_1;
+SET debug_sync='now WAIT_FOR ready';
+KILL QUERY CONID;
+SET debug_sync='now SIGNAL cont';
+connection con1;
+ERROR 70100: Query execution was interrupted
+SET debug_sync='RESET';
+connection server_1;
+SET debug_sync='RESET';
+connection server_2;
+include/wait_for_slave_sql_error.inc [errno=1317]
+STOP SLAVE IO_THREAD;
+SET GLOBAL gtid_slave_pos= 'AFTER_ERROR_GTID_POS';
+include/start_slave.inc
+connection server_1;
+INSERT INTO t6 VALUES (4);
+SELECT * FROM t6 ORDER BY a;
+a
+1
+4
+connection server_2;
+SELECT * FROM t6 ORDER BY a;
+a
+4
+connection server_2;
+include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+include/start_slave.inc
+SET DEBUG_SYNC= 'RESET';
+connection server_1;
+DROP TABLE t6;
+SET DEBUG_SYNC= 'RESET';
+disconnect con1;
+include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/r/rpl_parallel_record_gtid_wakeup.result b/mysql-test/suite/rpl/r/rpl_parallel_record_gtid_wakeup.result
new file mode 100644
index 00000000000..cbe53e4f623
--- /dev/null
+++ b/mysql-test/suite/rpl/r/rpl_parallel_record_gtid_wakeup.result
@@ -0,0 +1,48 @@
+*** MDEV-7929: record_gtid() for non-transactional event group calls wakeup_subsequent_commits() too early, causing slave hang. ***
+include/master-slave.inc
+[connection master]
+connection server_2;
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=10;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+include/start_slave.inc
+connection server_1;
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t1 (a int PRIMARY KEY) ENGINE=MyISAM;
+CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
+connection server_2;
+include/stop_slave.inc
+SET @old_dbug= @@GLOBAL.debug_dbug;
+SET GLOBAL debug_dbug= '+d,inject_record_gtid_serverid_100_sleep';
+connection server_1;
+SET @old_dbug= @@SESSION.debug_dbug;
+SET SESSION debug_dbug="+d,binlog_force_commit_id";
+SET @old_server_id= @@SESSION.server_id;
+SET SESSION server_id= 100;
+SET @commit_id= 10010;
+ALTER TABLE t1 COMMENT "Hulubulu!";
+SET SESSION server_id= @old_server_id;
+INSERT INTO t3 VALUES (130, 0);
+SET @commit_id= 10011;
+INSERT INTO t3 VALUES (131, 0);
+SET SESSION debug_dbug=@old_dbug;
+SELECT * FROM t3 WHERE a >= 130 ORDER BY a;
+a b
+130 0
+131 0
+include/save_master_gtid.inc
+connection server_2;
+include/start_slave.inc
+include/sync_with_master_gtid.inc
+SELECT * FROM t3 WHERE a >= 130 ORDER BY a;
+a b
+130 0
+131 0
+include/stop_slave.inc
+SET GLOBAL debug_dbug= @old_dbug;
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+include/start_slave.inc
+connection server_1;
+DROP TABLE t1,t3;
+include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/r/rpl_parallel_retry_deadlock.result b/mysql-test/suite/rpl/r/rpl_parallel_retry_deadlock.result
new file mode 100644
index 00000000000..1f5a23db848
--- /dev/null
+++ b/mysql-test/suite/rpl/r/rpl_parallel_retry_deadlock.result
@@ -0,0 +1,192 @@
+*** MDEV-7326 Server deadlock in connection with parallel replication ***
+include/master-slave.inc
+[connection master]
+connection server_2;
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+SET @old_parallel_mode=@@GLOBAL.slave_parallel_mode;
+include/stop_slave.inc
+SET GLOBAL slave_parallel_mode='conservative';
+SET GLOBAL slave_parallel_threads=10;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+include/start_slave.inc
+connection server_1;
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t1 (a int PRIMARY KEY) ENGINE=MyISAM;
+CREATE TABLE t2 (a int PRIMARY KEY) ENGINE=InnoDB;
+CREATE TABLE t6 (a INT) ENGINE=MyISAM;
+connection server_2;
+connection server_1;
+SET sql_log_bin=0;
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+RETURNS INT DETERMINISTIC
+BEGIN
+RETURN x;
+END
+||
+SET sql_log_bin=1;
+connection server_2;
+SET sql_log_bin=0;
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+RETURNS INT DETERMINISTIC
+BEGIN
+IF d1 != '' THEN
+SET debug_sync = d1;
+END IF;
+IF d2 != '' THEN
+SET debug_sync = d2;
+END IF;
+RETURN x;
+END
+||
+SET sql_log_bin=1;
+connection server_2;
+include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=0;
+SET GLOBAL slave_parallel_threads=3;
+SET GLOBAL debug_dbug="+d,rpl_parallel_simulate_temp_err_xid";
+include/start_slave.inc
+connection server_1;
+SET @old_format= @@SESSION.binlog_format;
+SET binlog_format= STATEMENT;
+INSERT INTO t1 VALUES (foo(50,
+"rpl_parallel_start_waiting_for_prior SIGNAL t3_ready",
+"rpl_parallel_end_of_group SIGNAL prep_ready WAIT_FOR prep_cont"));
+connection server_2;
+SET DEBUG_SYNC= "now WAIT_FOR prep_ready";
+connection server_1;
+INSERT INTO t2 VALUES (foo(50,
+"rpl_parallel_simulate_temp_err_xid SIGNAL t1_ready1 WAIT_FOR t1_cont1",
+"rpl_parallel_retry_after_unmark SIGNAL t1_ready2 WAIT_FOR t1_cont2"));
+connection server_2;
+SET DEBUG_SYNC= "now WAIT_FOR t1_ready1";
+connection server_1;
+INSERT INTO t1 VALUES (foo(51,
+"rpl_parallel_before_mark_start_commit SIGNAL t2_ready1 WAIT_FOR t2_cont1",
+"rpl_parallel_after_mark_start_commit SIGNAL t2_ready2"));
+connection server_2;
+SET DEBUG_SYNC= "now WAIT_FOR t2_ready1";
+SET DEBUG_SYNC= "now SIGNAL t1_cont1";
+SET DEBUG_SYNC= "now WAIT_FOR t1_ready2";
+connection server_1;
+INSERT INTO t1 VALUES (52);
+SET BINLOG_FORMAT= @old_format;
+SELECT * FROM t2 WHERE a>=50 ORDER BY a;
+a
+50
+SELECT * FROM t1 WHERE a>=50 ORDER BY a;
+a
+50
+51
+52
+connection server_2;
+SET DEBUG_SYNC= "now SIGNAL prep_cont";
+SET DEBUG_SYNC= "now WAIT_FOR t3_ready";
+SET DEBUG_SYNC= "now SIGNAL t2_cont1";
+SET DEBUG_SYNC= "now WAIT_FOR t2_ready2";
+SET DEBUG_SYNC= "now SIGNAL t1_cont2";
+connection server_1;
+connection server_2;
+SELECT * FROM t2 WHERE a>=50 ORDER BY a;
+a
+50
+SELECT * FROM t1 WHERE a>=50 ORDER BY a;
+a
+50
+51
+52
+SET DEBUG_SYNC="reset";
+include/stop_slave.inc
+SET GLOBAL debug_dbug=@old_dbug;
+SET GLOBAL slave_parallel_mode=@old_parallel_mode;
+SET GLOBAL slave_parallel_threads=0;
+SET GLOBAL slave_parallel_threads=10;
+include/start_slave.inc
+*** MDEV-7326 Server deadlock in connection with parallel replication ***
+connect con_temp3,127.0.0.1,root,,test,$SERVER_MYPORT_1,;
+connect con_temp4,127.0.0.1,root,,test,$SERVER_MYPORT_1,;
+connection server_2;
+include/stop_slave.inc
+SET @old_parallel_mode= @@GLOBAL.slave_parallel_mode;
+SET GLOBAL slave_parallel_mode='conservative';
+SET GLOBAL slave_parallel_threads=0;
+SET GLOBAL slave_parallel_threads=3;
+SET GLOBAL debug_dbug="+d,rpl_parallel_simulate_temp_err_xid";
+include/start_slave.inc
+connection server_1;
+SET @old_format= @@SESSION.binlog_format;
+SET binlog_format= STATEMENT;
+INSERT INTO t1 VALUES (foo(60,
+"rpl_parallel_start_waiting_for_prior SIGNAL t3_ready",
+"rpl_parallel_end_of_group SIGNAL prep_ready WAIT_FOR prep_cont"));
+connection server_2;
+SET DEBUG_SYNC= "now WAIT_FOR prep_ready";
+connection server_1;
+INSERT INTO t2 VALUES (foo(60,
+"rpl_parallel_simulate_temp_err_xid SIGNAL t1_ready1 WAIT_FOR t1_cont1",
+"rpl_parallel_retry_after_unmark SIGNAL t1_ready2 WAIT_FOR t1_cont2"));
+connection server_2;
+SET DEBUG_SYNC= "now WAIT_FOR t1_ready1";
+connection con_temp3;
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
+SET binlog_format=statement;
+INSERT INTO t1 VALUES (foo(61,
+"rpl_parallel_before_mark_start_commit SIGNAL t2_ready1 WAIT_FOR t2_cont1",
+"rpl_parallel_after_mark_start_commit SIGNAL t2_ready2"));
+connection server_1;
+SET debug_sync='now WAIT_FOR master_queued1';
+connection con_temp4;
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
+INSERT INTO t6 VALUES (62);
+connection server_1;
+SET debug_sync='now WAIT_FOR master_queued2';
+SET debug_sync='now SIGNAL master_cont1';
+connection con_temp3;
+connection con_temp4;
+connection server_1;
+SET debug_sync='RESET';
+SET BINLOG_FORMAT= @old_format;
+SELECT * FROM t2 WHERE a>=60 ORDER BY a;
+a
+60
+SELECT * FROM t1 WHERE a>=60 ORDER BY a;
+a
+60
+61
+SELECT * FROM t6 WHERE a>=60 ORDER BY a;
+a
+62
+connection server_2;
+SET DEBUG_SYNC= "now WAIT_FOR t2_ready1";
+SET DEBUG_SYNC= "now SIGNAL t1_cont1";
+SET DEBUG_SYNC= "now WAIT_FOR t1_ready2";
+connection server_2;
+SET DEBUG_SYNC= "now SIGNAL prep_cont";
+SET DEBUG_SYNC= "now WAIT_FOR t3_ready";
+SET DEBUG_SYNC= "now SIGNAL t2_cont1";
+SET DEBUG_SYNC= "now WAIT_FOR t2_ready2";
+SET DEBUG_SYNC= "now SIGNAL t1_cont2";
+connection server_1;
+connection server_2;
+SELECT * FROM t2 WHERE a>=60 ORDER BY a;
+a
+60
+SELECT * FROM t1 WHERE a>=60 ORDER BY a;
+a
+60
+61
+SELECT * FROM t6 WHERE a>=60 ORDER BY a;
+a
+62
+SET DEBUG_SYNC="reset";
+include/stop_slave.inc
+SET GLOBAL debug_dbug=@old_dbug;
+SET GLOBAL slave_parallel_mode=@old_parallel_mode;
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+include/start_slave.inc
+connection server_1;
+DROP function foo;
+DROP TABLE t1,t2,t6;
+disconnect con_temp3;
+disconnect con_temp4;
+SET DEBUG_SYNC= 'RESET';
+include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/r/rpl_parallel_rollback_assert.result b/mysql-test/suite/rpl/r/rpl_parallel_rollback_assert.result
new file mode 100644
index 00000000000..af9c5f14687
--- /dev/null
+++ b/mysql-test/suite/rpl/r/rpl_parallel_rollback_assert.result
@@ -0,0 +1,45 @@
+*** MDEV-8725: Assertion on ROLLBACK statement in the binary log ***
+include/master-slave.inc
+[connection master]
+connection server_2;
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=10;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+include/start_slave.inc
+connection server_1;
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t1 (a int PRIMARY KEY) ENGINE=MyISAM;
+CREATE TABLE t2 (a int PRIMARY KEY) ENGINE=InnoDB;
+connection server_2;
+connection server_1;
+BEGIN;
+INSERT INTO t2 VALUES (2000);
+INSERT INTO t1 VALUES (2000);
+INSERT INTO t2 VALUES (2001);
+ROLLBACK;
+SELECT * FROM t1 WHERE a>=2000 ORDER BY a;
+a
+2000
+SELECT * FROM t2 WHERE a>=2000 ORDER BY a;
+a
+include/save_master_gtid.inc
+connection server_2;
+include/sync_with_master_gtid.inc
+connection server_1;
+INSERT INTO t2 VALUES (2020);
+include/save_master_gtid.inc
+connection server_2;
+include/sync_with_master_gtid.inc
+SELECT * FROM t2 WHERE a>=2000 ORDER BY a;
+a
+2020
+SELECT * FROM t1 WHERE a>=2000 ORDER BY a;
+a
+2000
+include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+include/start_slave.inc
+connection server_1;
+DROP TABLE t1,t2;
+include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/r/rpl_parallel_single_grpcmt.result b/mysql-test/suite/rpl/r/rpl_parallel_single_grpcmt.result
new file mode 100644
index 00000000000..18ffac4fa5d
--- /dev/null
+++ b/mysql-test/suite/rpl/r/rpl_parallel_single_grpcmt.result
@@ -0,0 +1,160 @@
+*** Test that group-committed transactions on the master can replicate in parallel on the slave. ***
+include/master-slave.inc
+[connection master]
+connection server_1;
+SET sql_log_bin=0;
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+RETURNS INT DETERMINISTIC
+BEGIN
+RETURN x;
+END
+||
+SET sql_log_bin=1;
+connection server_2;
+include/stop_slave.inc
+SET sql_log_bin=0;
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+RETURNS INT DETERMINISTIC
+BEGIN
+IF d1 != '' THEN
+SET debug_sync = d1;
+END IF;
+IF d2 != '' THEN
+SET debug_sync = d2;
+END IF;
+RETURN x;
+END
+||
+SET sql_log_bin=1;
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+SET GLOBAL slave_parallel_threads=10;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+include/start_slave.inc
+connection server_1;
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
+INSERT INTO t3 VALUES (1,1), (3,3), (5,5), (7,7);
+connection server_2;
+connect con_temp1,127.0.0.1,root,,test,$SERVER_MYPORT_2,;
+BEGIN;
+INSERT INTO t3 VALUES (2,102);
+connect con_temp2,127.0.0.1,root,,test,$SERVER_MYPORT_2,;
+BEGIN;
+INSERT INTO t3 VALUES (4,104);
+connect con_temp3,127.0.0.1,root,,test,$SERVER_MYPORT_1,;
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
+SET binlog_format=statement;
+INSERT INTO t3 VALUES (2, foo(12,
+'commit_after_release_LOCK_prepare_ordered SIGNAL slave_queued1 WAIT_FOR slave_cont1',
+''));
+connection server_1;
+SET debug_sync='now WAIT_FOR master_queued1';
+connect con_temp4,127.0.0.1,root,,test,$SERVER_MYPORT_1,;
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
+SET binlog_format=statement;
+INSERT INTO t3 VALUES (4, foo(14,
+'commit_after_release_LOCK_prepare_ordered SIGNAL slave_queued2',
+''));
+connection server_1;
+SET debug_sync='now WAIT_FOR master_queued2';
+connect con_temp5,127.0.0.1,root,,test,$SERVER_MYPORT_1,;
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued3';
+SET binlog_format=statement;
+INSERT INTO t3 VALUES (6, foo(16,
+'group_commit_waiting_for_prior SIGNAL slave_queued3',
+''));
+connection server_1;
+SET debug_sync='now WAIT_FOR master_queued3';
+SET debug_sync='now SIGNAL master_cont1';
+connection con_temp3;
+connection con_temp4;
+connection con_temp5;
+SET debug_sync='RESET';
+connection server_1;
+SELECT * FROM t3 ORDER BY a;
+a b
+1 1
+2 12
+3 3
+4 14
+5 5
+6 16
+7 7
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Gtid # # GTID #-#-#
+master-bin.000001 # Query # # use `test`; ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB
+master-bin.000001 # Gtid # # GTID #-#-#
+master-bin.000001 # Query # # use `test`; CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t3 VALUES (1,1), (3,3), (5,5), (7,7)
+master-bin.000001 # Xid # # COMMIT /* XID */
+master-bin.000001 # Gtid # # BEGIN GTID #-#-# cid=#
+master-bin.000001 # Query # # use `test`; INSERT INTO t3 VALUES (2, foo(12,
+'commit_after_release_LOCK_prepare_ordered SIGNAL slave_queued1 WAIT_FOR slave_cont1',
+''))
+master-bin.000001 # Xid # # COMMIT /* XID */
+master-bin.000001 # Gtid # # BEGIN GTID #-#-# cid=#
+master-bin.000001 # Query # # use `test`; INSERT INTO t3 VALUES (4, foo(14,
+'commit_after_release_LOCK_prepare_ordered SIGNAL slave_queued2',
+''))
+master-bin.000001 # Xid # # COMMIT /* XID */
+master-bin.000001 # Gtid # # BEGIN GTID #-#-# cid=#
+master-bin.000001 # Query # # use `test`; INSERT INTO t3 VALUES (6, foo(16,
+'group_commit_waiting_for_prior SIGNAL slave_queued3',
+''))
+master-bin.000001 # Xid # # COMMIT /* XID */
+connection server_2;
+SET debug_sync='now WAIT_FOR slave_queued3';
+connection con_temp1;
+ROLLBACK;
+connection server_2;
+SET debug_sync='now WAIT_FOR slave_queued1';
+connection con_temp2;
+ROLLBACK;
+connection server_2;
+SET debug_sync='now WAIT_FOR slave_queued2';
+SET debug_sync='now SIGNAL slave_cont1';
+SELECT * FROM t3 ORDER BY a;
+a b
+1 1
+2 12
+3 3
+4 14
+5 5
+6 16
+7 7
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+slave-bin.000001 # Gtid # # GTID #-#-#
+slave-bin.000001 # Query # # use `test`; ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB
+slave-bin.000001 # Gtid # # GTID #-#-#
+slave-bin.000001 # Query # # use `test`; CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB
+slave-bin.000001 # Gtid # # BEGIN GTID #-#-#
+slave-bin.000001 # Query # # use `test`; INSERT INTO t3 VALUES (1,1), (3,3), (5,5), (7,7)
+slave-bin.000001 # Xid # # COMMIT /* XID */
+slave-bin.000001 # Gtid # # BEGIN GTID #-#-# cid=#
+slave-bin.000001 # Query # # use `test`; INSERT INTO t3 VALUES (2, foo(12,
+'commit_after_release_LOCK_prepare_ordered SIGNAL slave_queued1 WAIT_FOR slave_cont1',
+''))
+slave-bin.000001 # Xid # # COMMIT /* XID */
+slave-bin.000001 # Gtid # # BEGIN GTID #-#-# cid=#
+slave-bin.000001 # Query # # use `test`; INSERT INTO t3 VALUES (4, foo(14,
+'commit_after_release_LOCK_prepare_ordered SIGNAL slave_queued2',
+''))
+slave-bin.000001 # Xid # # COMMIT /* XID */
+slave-bin.000001 # Gtid # # BEGIN GTID #-#-# cid=#
+slave-bin.000001 # Query # # use `test`; INSERT INTO t3 VALUES (6, foo(16,
+'group_commit_waiting_for_prior SIGNAL slave_queued3',
+''))
+slave-bin.000001 # Xid # # COMMIT /* XID */
+connection server_2;
+include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+include/start_slave.inc
+SET DEBUG_SYNC= 'RESET';
+connection server_1;
+DROP function foo;
+DROP TABLE t3;
+SET DEBUG_SYNC= 'RESET';
+include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/r/rpl_parallel_slave_bgc_kill.result b/mysql-test/suite/rpl/r/rpl_parallel_slave_bgc_kill.result
new file mode 100644
index 00000000000..320bf0e49f8
--- /dev/null
+++ b/mysql-test/suite/rpl/r/rpl_parallel_slave_bgc_kill.result
@@ -0,0 +1,323 @@
+*** Test killing slave threads at various wait points ***
+include/master-slave.inc
+[connection master]
+connection server_2;
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+SET @old_parallel_mode=@@GLOBAL.slave_parallel_mode;
+include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=10;
+SET GLOBAL slave_parallel_mode='conservative';
+CHANGE MASTER TO master_use_gtid=slave_pos;
+include/start_slave.inc
+connection server_1;
+connect con_temp3,127.0.0.1,root,,test,$SERVER_MYPORT_1,;
+connect con_temp4,127.0.0.1,root,,test,$SERVER_MYPORT_1,;
+connect con_temp5,127.0.0.1,root,,test,$SERVER_MYPORT_1,;
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t1 (a int PRIMARY KEY) ENGINE=MyISAM;
+CREATE TABLE t2 (a int PRIMARY KEY) ENGINE=InnoDB;
+CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
+connection server_2;
+connection server_1;
+SET sql_log_bin=0;
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+RETURNS INT DETERMINISTIC
+BEGIN
+RETURN x;
+END
+||
+SET sql_log_bin=1;
+connection server_2;
+SET sql_log_bin=0;
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+RETURNS INT DETERMINISTIC
+BEGIN
+IF d1 != '' THEN
+SET debug_sync = d1;
+END IF;
+IF d2 != '' THEN
+SET debug_sync = d2;
+END IF;
+RETURN x;
+END
+||
+SET sql_log_bin=1;
+*** 1. Test killing transaction waiting in commit for previous transaction to commit ***
+connection con_temp3;
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
+INSERT INTO t3 VALUES (31, foo(31,
+'commit_before_prepare_ordered WAIT_FOR t2_waiting',
+'commit_after_prepare_ordered SIGNAL t1_ready WAIT_FOR t1_cont'));
+connection server_1;
+SET debug_sync='now WAIT_FOR master_queued1';
+connection con_temp4;
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
+BEGIN;
+INSERT INTO t3 VALUES (32, foo(32,
+'ha_write_row_end SIGNAL t2_query WAIT_FOR t2_cont',
+''));
+INSERT INTO t3 VALUES (33, foo(33,
+'group_commit_waiting_for_prior SIGNAL t2_waiting',
+'group_commit_waiting_for_prior_killed SIGNAL t2_killed'));
+COMMIT;
+connection server_1;
+SET debug_sync='now WAIT_FOR master_queued2';
+connection con_temp5;
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued3';
+INSERT INTO t3 VALUES (34, foo(34,
+'',
+''));
+connection server_1;
+SET debug_sync='now WAIT_FOR master_queued3';
+SET debug_sync='now SIGNAL master_cont1';
+connection con_temp3;
+connection con_temp4;
+connection con_temp5;
+connection server_1;
+SELECT * FROM t3 WHERE a >= 30 ORDER BY a;
+a b
+31 31
+32 32
+33 33
+34 34
+SET debug_sync='RESET';
+connection server_2;
+SET sql_log_bin=0;
+CALL mtr.add_suppression("Query execution was interrupted");
+CALL mtr.add_suppression("Commit failed due to failure of an earlier commit on which this one depends");
+CALL mtr.add_suppression("Slave: Connection was killed");
+SET sql_log_bin=1;
+SET debug_sync='now WAIT_FOR t2_query';
+SET debug_sync='now SIGNAL t2_cont';
+SET debug_sync='now WAIT_FOR t1_ready';
+KILL THD_ID;
+SET debug_sync='now WAIT_FOR t2_killed';
+SET debug_sync='now SIGNAL t1_cont';
+include/wait_for_slave_sql_error.inc [errno=1317,1927,1964]
+STOP SLAVE IO_THREAD;
+SELECT * FROM t3 WHERE a >= 30 ORDER BY a;
+a b
+31 31
+SET debug_sync='RESET';
+SET GLOBAL slave_parallel_threads=0;
+SET GLOBAL slave_parallel_threads=10;
+SET sql_log_bin=0;
+DROP FUNCTION foo;
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+RETURNS INT DETERMINISTIC
+BEGIN
+RETURN x;
+END
+||
+SET sql_log_bin=1;
+connection server_1;
+INSERT INTO t3 VALUES (39,0);
+connection server_2;
+include/start_slave.inc
+SELECT * FROM t3 WHERE a >= 30 ORDER BY a;
+a b
+31 31
+32 32
+33 33
+34 34
+39 0
+SET sql_log_bin=0;
+DROP FUNCTION foo;
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+RETURNS INT DETERMINISTIC
+BEGIN
+IF d1 != '' THEN
+SET debug_sync = d1;
+END IF;
+IF d2 != '' THEN
+SET debug_sync = d2;
+END IF;
+RETURN x;
+END
+||
+SET sql_log_bin=1;
+connection server_2;
+include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=0;
+SET GLOBAL slave_parallel_threads=10;
+include/start_slave.inc
+*** 2. Same as (1), but without restarting IO thread after kill of SQL threads ***
+connection con_temp3;
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
+INSERT INTO t3 VALUES (41, foo(41,
+'commit_before_prepare_ordered WAIT_FOR t2_waiting',
+'commit_after_prepare_ordered SIGNAL t1_ready WAIT_FOR t1_cont'));
+connection server_1;
+SET debug_sync='now WAIT_FOR master_queued1';
+connection con_temp4;
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
+BEGIN;
+INSERT INTO t3 VALUES (42, foo(42,
+'ha_write_row_end SIGNAL t2_query WAIT_FOR t2_cont',
+''));
+INSERT INTO t3 VALUES (43, foo(43,
+'group_commit_waiting_for_prior SIGNAL t2_waiting',
+'group_commit_waiting_for_prior_killed SIGNAL t2_killed'));
+COMMIT;
+connection server_1;
+SET debug_sync='now WAIT_FOR master_queued2';
+connection con_temp5;
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued3';
+INSERT INTO t3 VALUES (44, foo(44,
+'',
+''));
+connection server_1;
+SET debug_sync='now WAIT_FOR master_queued3';
+SET debug_sync='now SIGNAL master_cont1';
+connection con_temp3;
+connection con_temp4;
+connection con_temp5;
+connection server_1;
+SELECT * FROM t3 WHERE a >= 40 ORDER BY a;
+a b
+41 41
+42 42
+43 43
+44 44
+SET debug_sync='RESET';
+connection server_2;
+SET debug_sync='now WAIT_FOR t2_query';
+SET debug_sync='now SIGNAL t2_cont';
+SET debug_sync='now WAIT_FOR t1_ready';
+KILL THD_ID;
+SET debug_sync='now WAIT_FOR t2_killed';
+SET debug_sync='now SIGNAL t1_cont';
+include/wait_for_slave_sql_error.inc [errno=1317,1927,1964]
+SET debug_sync='RESET';
+SET GLOBAL slave_parallel_threads=0;
+SET GLOBAL slave_parallel_threads=10;
+SET sql_log_bin=0;
+DROP FUNCTION foo;
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+RETURNS INT DETERMINISTIC
+BEGIN
+RETURN x;
+END
+||
+SET sql_log_bin=1;
+connection server_1;
+INSERT INTO t3 VALUES (49,0);
+connection server_2;
+START SLAVE SQL_THREAD;
+SELECT * FROM t3 WHERE a >= 40 ORDER BY a;
+a b
+41 41
+42 42
+43 43
+44 44
+49 0
+SET sql_log_bin=0;
+DROP FUNCTION foo;
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+RETURNS INT DETERMINISTIC
+BEGIN
+IF d1 != '' THEN
+SET debug_sync = d1;
+END IF;
+IF d2 != '' THEN
+SET debug_sync = d2;
+END IF;
+RETURN x;
+END
+||
+SET sql_log_bin=1;
+connection server_2;
+include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=0;
+SET GLOBAL slave_parallel_threads=10;
+include/start_slave.inc
+*** 3. Same as (2), but not using gtid mode ***
+connection server_2;
+include/stop_slave.inc
+CHANGE MASTER TO master_use_gtid=no;
+include/start_slave.inc
+connection server_1;
+connection con_temp3;
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
+INSERT INTO t3 VALUES (51, foo(51,
+'commit_before_prepare_ordered WAIT_FOR t2_waiting',
+'commit_after_prepare_ordered SIGNAL t1_ready WAIT_FOR t1_cont'));
+connection server_1;
+SET debug_sync='now WAIT_FOR master_queued1';
+connection con_temp4;
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
+BEGIN;
+INSERT INTO t3 VALUES (52, foo(52,
+'ha_write_row_end SIGNAL t2_query WAIT_FOR t2_cont',
+''));
+INSERT INTO t3 VALUES (53, foo(53,
+'group_commit_waiting_for_prior SIGNAL t2_waiting',
+'group_commit_waiting_for_prior_killed SIGNAL t2_killed'));
+COMMIT;
+connection server_1;
+SET debug_sync='now WAIT_FOR master_queued2';
+connection con_temp5;
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued3';
+INSERT INTO t3 VALUES (54, foo(54,
+'',
+''));
+connection server_1;
+SET debug_sync='now WAIT_FOR master_queued3';
+SET debug_sync='now SIGNAL master_cont1';
+connection con_temp3;
+connection con_temp4;
+connection con_temp5;
+connection server_1;
+SELECT * FROM t3 WHERE a >= 50 ORDER BY a;
+a b
+51 51
+52 52
+53 53
+54 54
+SET debug_sync='RESET';
+connection server_2;
+SET debug_sync='now WAIT_FOR t2_query';
+SET debug_sync='now SIGNAL t2_cont';
+SET debug_sync='now WAIT_FOR t1_ready';
+KILL THD_ID;
+SET debug_sync='now WAIT_FOR t2_killed';
+SET debug_sync='now SIGNAL t1_cont';
+include/wait_for_slave_sql_error.inc [errno=1317,1927,1964]
+SELECT * FROM t3 WHERE a >= 50 ORDER BY a;
+a b
+51 51
+SET debug_sync='RESET';
+SET GLOBAL slave_parallel_threads=0;
+SET GLOBAL slave_parallel_threads=10;
+SET sql_log_bin=0;
+DROP FUNCTION foo;
+CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500))
+RETURNS INT DETERMINISTIC
+BEGIN
+RETURN x;
+END
+||
+SET sql_log_bin=1;
+connection server_1;
+INSERT INTO t3 VALUES (59,0);
+connection server_2;
+START SLAVE SQL_THREAD;
+SELECT * FROM t3 WHERE a >= 50 ORDER BY a;
+a b
+51 51
+52 52
+53 53
+54 54
+59 0
+connection server_2;
+include/stop_slave.inc
+CHANGE MASTER TO master_use_gtid=slave_pos;
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+SET GLOBAL slave_parallel_mode=@old_parallel_mode;
+include/start_slave.inc
+SET DEBUG_SYNC= 'RESET';
+connection server_1;
+DROP function foo;
+DROP TABLE t1,t2,t3;
+SET DEBUG_SYNC= 'RESET';
+include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/r/rpl_parallel_stop_on_con_kill.result b/mysql-test/suite/rpl/r/rpl_parallel_stop_on_con_kill.result
new file mode 100644
index 00000000000..bf0ed9e4374
--- /dev/null
+++ b/mysql-test/suite/rpl/r/rpl_parallel_stop_on_con_kill.result
@@ -0,0 +1,102 @@
+*** MDEV-8031: Parallel replication stops on "connection killed" error (probably incorrectly handled deadlock kill) ***
+include/master-slave.inc
+[connection master]
+connection server_2;
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=10;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+include/start_slave.inc
+connection server_1;
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
+INSERT INTO t3 VALUES (201,0), (202,0);
+include/save_master_gtid.inc
+connection server_2;
+include/sync_with_master_gtid.inc
+include/stop_slave.inc
+SET @old_dbug= @@GLOBAL.debug_dbug;
+SET GLOBAL debug_dbug= '+d,inject_mdev8031';
+connection server_1;
+SET @old_dbug= @@SESSION.debug_dbug;
+SET SESSION debug_dbug="+d,binlog_force_commit_id";
+SET @commit_id= 10200;
+INSERT INTO t3 VALUES (203, 1);
+INSERT INTO t3 VALUES (204, 1);
+INSERT INTO t3 VALUES (205, 1);
+UPDATE t3 SET b=b+1 WHERE a=201;
+UPDATE t3 SET b=b+1 WHERE a=201;
+UPDATE t3 SET b=b+1 WHERE a=201;
+UPDATE t3 SET b=b+1 WHERE a=202;
+UPDATE t3 SET b=b+1 WHERE a=202;
+UPDATE t3 SET b=b+1 WHERE a=202;
+UPDATE t3 SET b=b+1 WHERE a=202;
+UPDATE t3 SET b=b+1 WHERE a=203;
+UPDATE t3 SET b=b+1 WHERE a=203;
+UPDATE t3 SET b=b+1 WHERE a=204;
+UPDATE t3 SET b=b+1 WHERE a=204;
+UPDATE t3 SET b=b+1 WHERE a=204;
+UPDATE t3 SET b=b+1 WHERE a=203;
+UPDATE t3 SET b=b+1 WHERE a=205;
+UPDATE t3 SET b=b+1 WHERE a=205;
+SET SESSION debug_dbug=@old_dbug;
+SELECT * FROM t3 WHERE a>=200 ORDER BY a;
+a b
+201 3
+202 4
+203 4
+204 4
+205 3
+include/save_master_gtid.inc
+connection server_2;
+include/start_slave.inc
+include/sync_with_master_gtid.inc
+SELECT * FROM t3 WHERE a>=200 ORDER BY a;
+a b
+201 3
+202 4
+203 4
+204 4
+205 3
+include/stop_slave.inc
+SET GLOBAL debug_dbug= @old_dbug;
+include/start_slave.inc
+*** Check getting deadlock killed inside open_binlog() during retry. ***
+connection server_2;
+include/stop_slave.inc
+SET @old_dbug= @@GLOBAL.debug_dbug;
+SET GLOBAL debug_dbug= '+d,inject_retry_event_group_open_binlog_kill';
+SET @old_max= @@GLOBAL.max_relay_log_size;
+SET GLOBAL max_relay_log_size= 4096;
+connection server_1;
+SET @old_dbug= @@SESSION.debug_dbug;
+SET SESSION debug_dbug="+d,binlog_force_commit_id";
+SET @commit_id= 10210;
+Omit long queries that cause relaylog rotations and transaction retries...
+SET SESSION debug_dbug=@old_dbug;
+SELECT * FROM t3 WHERE a>=200 ORDER BY a;
+a b
+201 6
+202 8
+203 7
+204 7
+205 5
+include/save_master_gtid.inc
+connection server_2;
+include/start_slave.inc
+include/sync_with_master_gtid.inc
+SELECT * FROM t3 WHERE a>=200 ORDER BY a;
+a b
+201 6
+202 8
+203 7
+204 7
+205 5
+include/stop_slave.inc
+SET GLOBAL debug_dbug= @old_debg;
+SET GLOBAL max_relay_log_size= @old_max;
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+include/start_slave.inc
+connection server_1;
+DROP TABLE t3;
+include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/r/rpl_parallel_stop_slave.result b/mysql-test/suite/rpl/r/rpl_parallel_stop_slave.result
new file mode 100644
index 00000000000..6c9fd168e73
--- /dev/null
+++ b/mysql-test/suite/rpl/r/rpl_parallel_stop_slave.result
@@ -0,0 +1,85 @@
+*** Test STOP SLAVE in parallel mode ***
+include/master-slave.inc
+[connection master]
+connection server_2;
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+SET @old_parallel_mode=@@GLOBAL.slave_parallel_mode;
+include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=10;
+SET GLOBAL slave_parallel_mode='conservative';
+CHANGE MASTER TO master_use_gtid=slave_pos;
+include/start_slave.inc
+connect con_temp1,127.0.0.1,root,,test,$SERVER_MYPORT_2,;
+connect con_temp2,127.0.0.1,root,,test,$SERVER_MYPORT_2,;
+connection server_1;
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t1 (a int PRIMARY KEY) ENGINE=MyISAM;
+CREATE TABLE t2 (a int PRIMARY KEY) ENGINE=InnoDB;
+CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
+connection server_2;
+include/stop_slave.inc
+connection server_1;
+SET binlog_direct_non_transactional_updates=0;
+SET sql_log_bin=0;
+CALL mtr.add_suppression("Statement is unsafe because it accesses a non-transactional table after accessing a transactional table within the same transaction");
+SET sql_log_bin=1;
+BEGIN;
+INSERT INTO t2 VALUES (20);
+INSERT INTO t1 VALUES (20);
+INSERT INTO t2 VALUES (21);
+INSERT INTO t3 VALUES (20, 20);
+COMMIT;
+INSERT INTO t3 VALUES(21, 21);
+INSERT INTO t3 VALUES(22, 22);
+connection con_temp1;
+BEGIN;
+INSERT INTO t2 VALUES (21);
+connection server_2;
+START SLAVE;
+connection con_temp2;
+SET @old_dbug= @@GLOBAL.debug_dbug;
+SET GLOBAL debug_dbug="+d,rpl_parallel_wait_for_done_trigger";
+STOP SLAVE;
+connection con_temp1;
+SET debug_sync='now WAIT_FOR wait_for_done_waiting';
+ROLLBACK;
+connection con_temp2;
+SET GLOBAL debug_dbug=@old_dbug;
+SET debug_sync='RESET';
+connection server_2;
+include/wait_for_slave_to_stop.inc
+SELECT * FROM t1 WHERE a >= 20 ORDER BY a;
+a
+20
+SELECT * FROM t2 WHERE a >= 20 ORDER BY a;
+a
+20
+21
+SELECT * FROM t3 WHERE a >= 20 ORDER BY a;
+a b
+20 20
+include/start_slave.inc
+SELECT * FROM t1 WHERE a >= 20 ORDER BY a;
+a
+20
+SELECT * FROM t2 WHERE a >= 20 ORDER BY a;
+a
+20
+21
+SELECT * FROM t3 WHERE a >= 20 ORDER BY a;
+a b
+20 20
+21 21
+22 22
+connection server_2;
+include/stop_slave.inc
+SET GLOBAL slave_parallel_mode=@old_parallel_mode;
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+include/start_slave.inc
+SET DEBUG_SYNC= 'RESET';
+disconnect con_temp1;
+disconnect con_temp2;
+connection server_1;
+DROP TABLE t1,t2,t3;
+SET DEBUG_SYNC= 'RESET';
+include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/r/rpl_parallel_wrong_binlog_order.result b/mysql-test/suite/rpl/r/rpl_parallel_wrong_binlog_order.result
new file mode 100644
index 00000000000..f6781f64d30
--- /dev/null
+++ b/mysql-test/suite/rpl/r/rpl_parallel_wrong_binlog_order.result
@@ -0,0 +1,75 @@
+*** MDEV-6775: Wrong binlog order in parallel replication ***
+include/master-slave.inc
+[connection master]
+connection server_2;
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=10;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+include/start_slave.inc
+connection server_1;
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t4 (a INT PRIMARY KEY, b INT, KEY b_idx(b)) ENGINE=InnoDB;
+INSERT INTO t4 VALUES (1,NULL), (3,NULL), (4,4), (5, NULL), (6, 6);
+connect con1,127.0.0.1,root,,test,$SERVER_MYPORT_1,;
+connect con2,127.0.0.1,root,,test,$SERVER_MYPORT_1,;
+include/save_master_gtid.inc
+connection server_2;
+include/sync_with_master_gtid.inc
+include/stop_slave.inc
+SET @old_dbug= @@GLOBAL.debug_dbug;
+SET GLOBAL debug_dbug="+d,inject_binlog_commit_before_get_LOCK_log";
+SET @old_format=@@GLOBAL.binlog_format;
+SET GLOBAL binlog_format=ROW;
+SET GLOBAL slave_parallel_threads=0;
+SET GLOBAL slave_parallel_threads=10;
+connection con1;
+SET @old_format= @@binlog_format;
+SET binlog_format= statement;
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
+UPDATE t4 SET b=NULL WHERE a=6;
+connection server_1;
+SET debug_sync='now WAIT_FOR master_queued1';
+connection con2;
+SET @old_format= @@binlog_format;
+SET binlog_format= statement;
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
+DELETE FROM t4 WHERE b <= 3;
+connection server_1;
+SET debug_sync='now WAIT_FOR master_queued2';
+SET debug_sync='now SIGNAL master_cont1';
+connection con1;
+SET binlog_format= @old_format;
+connection con2;
+SET binlog_format= @old_format;
+SET debug_sync='RESET';
+SELECT * FROM t4 ORDER BY a;
+a b
+1 NULL
+3 NULL
+4 4
+5 NULL
+6 NULL
+connection server_2;
+include/start_slave.inc
+SET debug_sync= 'now WAIT_FOR waiting';
+SELECT * FROM t4 ORDER BY a;
+a b
+1 NULL
+3 NULL
+4 4
+5 NULL
+6 NULL
+SET debug_sync= 'now SIGNAL cont';
+include/stop_slave.inc
+SET GLOBAL debug_dbug=@old_dbug;
+SET GLOBAL binlog_format= @old_format;
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+include/start_slave.inc
+SET DEBUG_SYNC= 'RESET';
+connection server_1;
+DROP TABLE t4;
+SET DEBUG_SYNC= 'RESET';
+disconnect con1;
+disconnect con2;
+include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/r/rpl_parallel_wrong_exec_master_pos.result b/mysql-test/suite/rpl/r/rpl_parallel_wrong_exec_master_pos.result
new file mode 100644
index 00000000000..47cfa5e08e2
--- /dev/null
+++ b/mysql-test/suite/rpl/r/rpl_parallel_wrong_exec_master_pos.result
@@ -0,0 +1,34 @@
+*** MDEV-5938: Exec_master_log_pos not updated at log rotate in parallel replication ***
+include/master-slave.inc
+[connection master]
+connection server_2;
+include/stop_slave.inc
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+SET GLOBAL slave_parallel_threads=1;
+CHANGE MASTER TO master_use_gtid=slave_pos;
+include/start_slave.inc
+connection server_1;
+ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
+CREATE TABLE t5 (a INT PRIMARY KEY, b INT);
+INSERT INTO t5 VALUES (1,1);
+INSERT INTO t5 VALUES (2,2), (3,8);
+INSERT INTO t5 VALUES (4,16);
+connection server_2;
+test_check
+OK
+test_check
+OK
+connection server_1;
+FLUSH LOGS;
+connection server_2;
+test_check
+OK
+test_check
+OK
+connection server_2;
+include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+include/start_slave.inc
+connection server_1;
+DROP TABLE t5;
+include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_mdev6386.test b/mysql-test/suite/rpl/t/rpl_mdev6386.test
index e85b1ae0132..e6fb72dc788 100644
--- a/mysql-test/suite/rpl/t/rpl_mdev6386.test
+++ b/mysql-test/suite/rpl/t/rpl_mdev6386.test
@@ -10,6 +10,7 @@ CREATE TABLE t1 (a INT PRIMARY KEY, b INT) Engine=InnoDB;
--source include/stop_slave.inc
# Provoke a duplicate key error on replication.
SET sql_log_bin= 0;
+CALL mtr.add_suppression("Commit failed due to failure of an earlier commit on which this one depends");
INSERT INTO t1 VALUES (1, 2);
SET sql_log_bin= 1;
CHANGE MASTER TO master_use_gtid= current_pos;
diff --git a/mysql-test/suite/rpl/t/rpl_parallel.test b/mysql-test/suite/rpl/t/rpl_parallel.test
deleted file mode 100644
index ee39bfa7a39..00000000000
--- a/mysql-test/suite/rpl/t/rpl_parallel.test
+++ /dev/null
@@ -1 +0,0 @@
---source include/rpl_parallel.inc
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_analyze_table_hang.test b/mysql-test/suite/rpl/t/rpl_parallel_analyze_table_hang.test
new file mode 100644
index 00000000000..c1f1b9bac43
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_analyze_table_hang.test
@@ -0,0 +1 @@
+--source include/rpl_parallel_analyze_table_hang.inc
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_conflicts-slave.opt b/mysql-test/suite/rpl/t/rpl_parallel_conflicts-slave.opt
deleted file mode 100644
index af7bd138793..00000000000
--- a/mysql-test/suite/rpl/t/rpl_parallel_conflicts-slave.opt
+++ /dev/null
@@ -1 +0,0 @@
---slave_parallel_threads=40 --slave_parallel_mode=conservative --slave_transaction_retries=5
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_conflicts.test b/mysql-test/suite/rpl/t/rpl_parallel_conflicts.test
index fc294f68197..a3c3f9a9e04 100644
--- a/mysql-test/suite/rpl/t/rpl_parallel_conflicts.test
+++ b/mysql-test/suite/rpl/t/rpl_parallel_conflicts.test
@@ -15,7 +15,12 @@ CREATE TABLE t8 (a int PRIMARY KEY, b INT) ENGINE=InnoDB;
--connection server_2
--sync_with_master
--source include/stop_slave.inc
-
+SET @old_mode= @@GLOBAL.slave_parallel_mode;
+SET GLOBAL slave_parallel_mode=conservative;
+SET @old_threads= @@GLOBAL.slave_parallel_threads;
+SET GLOBAL slave_parallel_threads=40;
+SET @old_transaction_retries= @@GLOBAL.slave_transaction_retries;
+SET GLOBAL slave_transaction_retries=5;
# Using dbug error injection, we artificially create event groups with a lot of
# conflicting transactions in each event group. The bugs were originally seen
@@ -249,6 +254,9 @@ SELECT * FROM t7 ORDER BY a;
--source include/stop_slave.inc
SET GLOBAL debug_dbug=@old_dbug;
+SET GLOBAL slave_parallel_mode=@old_mode;
+SET GLOBAL slave_parallel_threads=@old_threads;
+SET GLOBAL slave_transaction_retries=@old_transaction_retries;
# Clean up.
--source include/start_slave.inc
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_deadlock_corrupt_binlog.test b/mysql-test/suite/rpl/t/rpl_parallel_deadlock_corrupt_binlog.test
new file mode 100644
index 00000000000..9ee06f59858
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_deadlock_corrupt_binlog.test
@@ -0,0 +1 @@
+--source include/rpl_parallel_deadlock_corrupt_binlog.inc
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_domain.test b/mysql-test/suite/rpl/t/rpl_parallel_domain.test
new file mode 100644
index 00000000000..f5864380f02
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_domain.test
@@ -0,0 +1 @@
+--source include/rpl_parallel_domain.inc
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_domain_slave_single_grp.test b/mysql-test/suite/rpl/t/rpl_parallel_domain_slave_single_grp.test
new file mode 100644
index 00000000000..5ddd2af323c
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_domain_slave_single_grp.test
@@ -0,0 +1 @@
+--source include/rpl_parallel_domain_slave_single_grp.inc
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_free_deferred_event.test b/mysql-test/suite/rpl/t/rpl_parallel_free_deferred_event.test
new file mode 100644
index 00000000000..e2a41d0db7e
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_free_deferred_event.test
@@ -0,0 +1 @@
+--source include/rpl_parallel_free_deferred_event.inc
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_gco_wait_kill.test b/mysql-test/suite/rpl/t/rpl_parallel_gco_wait_kill.test
new file mode 100644
index 00000000000..d9dc4dfd293
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_gco_wait_kill.test
@@ -0,0 +1 @@
+--source include/rpl_parallel_gco_wait_kill.inc
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_gtid_slave_pos_update_fail.test b/mysql-test/suite/rpl/t/rpl_parallel_gtid_slave_pos_update_fail.test
new file mode 100644
index 00000000000..0756caca084
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_gtid_slave_pos_update_fail.test
@@ -0,0 +1 @@
+--source include/rpl_parallel_gtid_slave_pos_update_fail.inc
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_ignored_errors.test b/mysql-test/suite/rpl/t/rpl_parallel_ignored_errors.test
new file mode 100644
index 00000000000..90f09a76546
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_ignored_errors.test
@@ -0,0 +1 @@
+--source include/rpl_parallel_ignored_errors.inc
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_incorrect_relay_pos.test b/mysql-test/suite/rpl/t/rpl_parallel_incorrect_relay_pos.test
new file mode 100644
index 00000000000..e0226d9453e
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_incorrect_relay_pos.test
@@ -0,0 +1 @@
+--source include/rpl_parallel_incorrect_relay_pos.inc
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_innodb_lock_conflict.test b/mysql-test/suite/rpl/t/rpl_parallel_innodb_lock_conflict.test
new file mode 100644
index 00000000000..3838973c201
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_innodb_lock_conflict.test
@@ -0,0 +1 @@
+--source include/rpl_parallel_innodb_lock_conflict.inc
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_mdev6589.test b/mysql-test/suite/rpl/t/rpl_parallel_mdev6589.test
index 5929fad71df..981c6216376 100644
--- a/mysql-test/suite/rpl/t/rpl_parallel_mdev6589.test
+++ b/mysql-test/suite/rpl/t/rpl_parallel_mdev6589.test
@@ -99,6 +99,7 @@ eval SELECT MASTER_GTID_WAIT('$wait_pos');
# duplicate key error.
--connection con_temp1
COMMIT;
+CALL mtr.add_suppression("Commit failed due to failure of an earlier commit on which this one depends");
SET sql_log_bin=1;
--connection server_2
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_missed_error_handling.test b/mysql-test/suite/rpl/t/rpl_parallel_missed_error_handling.test
new file mode 100644
index 00000000000..de9dc7f782a
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_missed_error_handling.test
@@ -0,0 +1 @@
+--source include/rpl_parallel_missed_error_handling.inc
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_mode.test b/mysql-test/suite/rpl/t/rpl_parallel_mode.test
new file mode 100644
index 00000000000..afd9e038912
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_mode.test
@@ -0,0 +1 @@
+--source include/rpl_parallel_mode.inc
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_partial_binlog_trans.test b/mysql-test/suite/rpl/t/rpl_parallel_partial_binlog_trans.test
new file mode 100644
index 00000000000..7be26edabb8
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_partial_binlog_trans.test
@@ -0,0 +1 @@
+--source include/rpl_parallel_partial_binlog_trans.inc
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_record_gtid_wakeup.test b/mysql-test/suite/rpl/t/rpl_parallel_record_gtid_wakeup.test
new file mode 100644
index 00000000000..4529a268103
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_record_gtid_wakeup.test
@@ -0,0 +1 @@
+--source include/rpl_parallel_record_gtid_wakeup.inc
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_retry_deadlock.test b/mysql-test/suite/rpl/t/rpl_parallel_retry_deadlock.test
new file mode 100644
index 00000000000..50b216b6f58
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_retry_deadlock.test
@@ -0,0 +1 @@
+--source include/rpl_parallel_retry_deadlock.inc
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_rollback_assert.test b/mysql-test/suite/rpl/t/rpl_parallel_rollback_assert.test
new file mode 100644
index 00000000000..f66375b7fb4
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_rollback_assert.test
@@ -0,0 +1 @@
+--source include/rpl_parallel_rollback_assert.inc
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_single_grpcmt.test b/mysql-test/suite/rpl/t/rpl_parallel_single_grpcmt.test
new file mode 100644
index 00000000000..20919823945
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_single_grpcmt.test
@@ -0,0 +1 @@
+--source include/rpl_parallel_single_grpcmt.inc
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_slave_bgc_kill.test b/mysql-test/suite/rpl/t/rpl_parallel_slave_bgc_kill.test
new file mode 100644
index 00000000000..7b0f9485e5e
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_slave_bgc_kill.test
@@ -0,0 +1 @@
+--source include/rpl_parallel_slave_bgc_kill.inc
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_stop_on_con_kill.test b/mysql-test/suite/rpl/t/rpl_parallel_stop_on_con_kill.test
new file mode 100644
index 00000000000..64b4cb77dd4
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_stop_on_con_kill.test
@@ -0,0 +1 @@
+--source include/rpl_parallel_stop_on_con_kill.inc
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_stop_slave.test b/mysql-test/suite/rpl/t/rpl_parallel_stop_slave.test
new file mode 100644
index 00000000000..131ddc2efd9
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_stop_slave.test
@@ -0,0 +1 @@
+--source include/rpl_parallel_stop_slave.inc
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_wrong_binlog_order.test b/mysql-test/suite/rpl/t/rpl_parallel_wrong_binlog_order.test
new file mode 100644
index 00000000000..3c920e1539a
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_wrong_binlog_order.test
@@ -0,0 +1 @@
+--source include/rpl_parallel_wrong_binlog_order.inc
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_wrong_exec_master_pos.test b/mysql-test/suite/rpl/t/rpl_parallel_wrong_exec_master_pos.test
new file mode 100644
index 00000000000..9cd700f57fa
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_wrong_exec_master_pos.test
@@ -0,0 +1 @@
+--source include/rpl_parallel_wrong_exec_master_pos.inc
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 9988cdeab74..0d96c4216d3 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -549,7 +549,7 @@ ulong stored_program_cache_size= 0;
ulong opt_slave_parallel_threads= 0;
ulong opt_slave_domain_parallel_threads= 0;
-ulong opt_slave_parallel_mode= SLAVE_PARALLEL_CONSERVATIVE;
+ulong opt_slave_parallel_mode;
ulong opt_binlog_commit_wait_count= 0;
ulong opt_binlog_commit_wait_usec= 0;
ulong opt_slave_parallel_max_queued= 131072;
diff --git a/sql/rpl_filter.cc b/sql/rpl_filter.cc
index b167b849923..5d10cc661ca 100644
--- a/sql/rpl_filter.cc
+++ b/sql/rpl_filter.cc
@@ -24,7 +24,7 @@
#define TABLE_RULE_ARR_SIZE 16
Rpl_filter::Rpl_filter() :
- parallel_mode(SLAVE_PARALLEL_CONSERVATIVE),
+ parallel_mode(SLAVE_PARALLEL_OPTIMISTIC),
table_rules_on(0),
do_table_inited(0), ignore_table_inited(0),
wild_do_table_inited(0), wild_ignore_table_inited(0)
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 4eab241232b..5ba9c5fe456 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -7365,6 +7365,33 @@ wait_for_commit::register_wait_for_prior_commit(wait_for_commit *waitee)
}
+int wait_for_commit::wait_for_prior_commit(THD *thd)
+{
+ /*
+ Quick inline check, to avoid function call and locking in the common case
+ where no wakeup is registered, or a registered wait was already signalled.
+ */
+ if (waitee)
+ return wait_for_prior_commit2(thd);
+ else
+ {
+ if (wakeup_error)
+ my_error(ER_PRIOR_COMMIT_FAILED, MYF(0));
+ else
+ {
+ rpl_group_info* rgi= thd->rgi_slave;
+ if (rgi && rgi->is_parallel_exec &&
+ rgi->parallel_entry->stop_on_error_sub_id < (uint64)ULONGLONG_MAX &&
+ rgi->gtid_sub_id >= rgi->parallel_entry->stop_on_error_sub_id)
+ {
+ my_error(ER_PRIOR_COMMIT_FAILED, MYF(0));
+ wakeup_error= ER_PRIOR_COMMIT_FAILED;
+ }
+ }
+ return wakeup_error;
+ }
+}
+
/*
Wait for commit of another transaction to complete, as already registered
with register_wait_for_prior_commit(). If the commit already completed,
@@ -7387,6 +7414,17 @@ wait_for_commit::wait_for_prior_commit2(THD *thd)
{
if (wakeup_error)
my_error(ER_PRIOR_COMMIT_FAILED, MYF(0));
+ else
+ {
+ rpl_group_info* rgi= thd->rgi_slave;
+ if (rgi && rgi->is_parallel_exec &&
+ rgi->parallel_entry->stop_on_error_sub_id < (uint64)ULONGLONG_MAX &&
+ rgi->gtid_sub_id >= rgi->parallel_entry->stop_on_error_sub_id)
+ {
+ my_error(ER_PRIOR_COMMIT_FAILED, MYF(0));
+ wakeup_error= ER_PRIOR_COMMIT_FAILED;
+ }
+ }
goto end;
}
/*
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 72cb8148895..0a0a1aa9fa1 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -2062,21 +2062,6 @@ struct wait_for_commit
bool commit_started;
void register_wait_for_prior_commit(wait_for_commit *waitee);
- int wait_for_prior_commit(THD *thd)
- {
- /*
- Quick inline check, to avoid function call and locking in the common case
- where no wakeup is registered, or a registered wait was already signalled.
- */
- if (waitee)
- return wait_for_prior_commit2(thd);
- else
- {
- if (wakeup_error)
- my_error(ER_PRIOR_COMMIT_FAILED, MYF(0));
- return wakeup_error;
- }
- }
void wakeup_subsequent_commits(int wakeup_error_arg)
{
/*
@@ -2123,6 +2108,7 @@ struct wait_for_commit
void wakeup(int wakeup_error);
+ int wait_for_prior_commit(THD *thd);
int wait_for_prior_commit2(THD *thd);
void wakeup_subsequent_commits2(int wakeup_error);
void unregister_wait_for_prior_commit2();
diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc
index 1ba58bf71c4..10fc6ff4057 100644
--- a/sql/sys_vars.cc
+++ b/sql/sys_vars.cc
@@ -2221,7 +2221,7 @@ static Sys_var_slave_parallel_mode Sys_slave_parallel_mode(
"\"minimal\" only parallelizes the commit steps of transactions. "
"\"none\" disables parallel apply completely.",
GLOBAL_VAR(opt_slave_parallel_mode), NO_CMD_LINE,
- slave_parallel_mode_names, DEFAULT(SLAVE_PARALLEL_CONSERVATIVE));
+ slave_parallel_mode_names, DEFAULT(SLAVE_PARALLEL_OPTIMISTIC));
static Sys_var_bit Sys_skip_parallel_replication(
1
0
[Commits] 90a9c4cae74: MDEV-20217: Semi_sync: Last_IO_Error: Fatal error: Failed to run 'after_queue_event' hook
by sujatha 17 Sep '19
by sujatha 17 Sep '19
17 Sep '19
revision-id: 90a9c4cae74d2ef1008e3f216026b7fd2697e46b (mariadb-10.3.18-15-g90a9c4cae74)
parent(s): bfbf0f225179d79c1c568b93ddc8b5dd6a670072
author: Sujatha
committer: Sujatha
timestamp: 2019-09-16 15:45:24 +0530
message:
MDEV-20217: Semi_sync: Last_IO_Error: Fatal error: Failed to run 'after_queue_event' hook
Fix:
===
Implemented upstream fix.
commit 7d3d0fc303183ef50a343680ce70df71d5675cd1
Author: He Zhenxing <zhenxing.he(a)sun.com>
Backport Bug#45852 Semisynch: Last_IO_Error: Fatal error: Failed
to run 'after_queue_event' hook
Errors when send reply to master should never cause the IO thread
to stop, because master can fall back to async replication if it
does not get reply from slave.
The problem is fixed by deliberately ignoring the return value of
slave_reply.
---
.../rpl/r/rpl_semi_sync_slave_reply_fail.result | 40 ++++++++++
.../rpl/t/rpl_semi_sync_slave_reply_fail.test | 87 ++++++++++++++++++++++
sql/slave.cc | 13 ++--
3 files changed, 134 insertions(+), 6 deletions(-)
diff --git a/mysql-test/suite/rpl/r/rpl_semi_sync_slave_reply_fail.result b/mysql-test/suite/rpl/r/rpl_semi_sync_slave_reply_fail.result
new file mode 100644
index 00000000000..6b39b296cdf
--- /dev/null
+++ b/mysql-test/suite/rpl/r/rpl_semi_sync_slave_reply_fail.result
@@ -0,0 +1,40 @@
+include/master-slave.inc
+[connection master]
+connection slave;
+include/stop_slave.inc
+connection master;
+call mtr.add_suppression("Timeout waiting for reply of binlog*");
+set global rpl_semi_sync_master_enabled = ON;
+SET @@GLOBAL.rpl_semi_sync_master_timeout=100;
+create table t1 (i int);
+connection slave;
+set global rpl_semi_sync_slave_enabled = ON;
+CALL mtr.add_suppression("Semi-sync slave net_flush*");
+SET @save_debug= @@global.debug;
+SET GLOBAL debug_dbug="+d,semislave_failed_net_flush";
+include/start_slave.inc
+connection master;
+connection slave;
+"Assert that the net_fulsh() reply failed is present in slave error log.
+FOUND 1 /Semi-sync slave net_flush\(\) reply failed/ in mysqld.2.err
+"Assert that Slave IO thread is up and running."
+SHOW STATUS LIKE 'Slave_running';
+Variable_name Value
+Slave_running ON
+Slave_IO_Running= Yes
+"Clear the network failure simulation."
+SET GLOBAL debug_dbug= @save_debug;
+connection master;
+insert into t1 values (10);
+connection slave;
+connection slave;
+# Compare the tables on master and slave.
+include/diff_tables.inc [master:t1, slave:t1]
+connection master;
+drop table t1;
+connection slave;
+set global rpl_semi_sync_slave_enabled = OFF;
+connection master;
+set global rpl_semi_sync_master_enabled = OFF;
+SET @@GLOBAL.rpl_semi_sync_master_timeout = 10000;
+include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_slave_reply_fail.test b/mysql-test/suite/rpl/t/rpl_semi_sync_slave_reply_fail.test
new file mode 100644
index 00000000000..f0eb474f00e
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_semi_sync_slave_reply_fail.test
@@ -0,0 +1,87 @@
+# ==== Purpose ====
+#
+# Test verifies that slave IO thread doesn't report an error, when slave fails
+# to send an acknowledgment to master with semi sync replication in use.
+#
+# ==== Implementation ====
+#
+# Steps:
+# 0 - Have semi synchronous replication in use.
+# 1 - Enable a debug simulation point which simulates network flush failure
+# at the time of slave reply operation.
+# 2 - Do some operation on master and wait for it to be replicated. Master
+# will timeout waiting for reply from slave.
+# 3 - Check the slave error log for appropriate error message regarding
+# net_flush operation failure.
+# 4 - Remove the debug simulation and do some more DML operations on master
+# and wait for them to be replicated.
+# 5 - Slave will be able to replicate and data is consistent on both master
+# and slave. Semi sync will be automatically turned on.
+#
+# ==== References ====
+#
+# MDEV-20217: Semi_sync: Last_IO_Error: Fatal error: Failed to run
+# 'after_queue_event' hook
+#
+--source include/have_debug.inc
+--source include/master-slave.inc
+
+--connection slave
+--source include/stop_slave.inc
+
+--connection master
+call mtr.add_suppression("Timeout waiting for reply of binlog*");
+--let $sav_timeout_master=`SELECT @@GLOBAL.rpl_semi_sync_master_timeout`
+set global rpl_semi_sync_master_enabled = ON;
+SET @@GLOBAL.rpl_semi_sync_master_timeout=100;
+create table t1 (i int);
+
+--connection slave
+set global rpl_semi_sync_slave_enabled = ON;
+CALL mtr.add_suppression("Semi-sync slave net_flush*");
+SET @save_debug= @@global.debug;
+SET GLOBAL debug_dbug="+d,semislave_failed_net_flush";
+--source include/start_slave.inc
+
+--connection master
+--sync_slave_with_master
+
+# Check error log for correct messages.
+let $log_error_= `SELECT @@GLOBAL.log_error`;
+if(!$log_error_)
+{
+ # MySQL Server on windows is started with --console and thus
+ # does not know the location of its .err log, use default location
+ let $log_error_ = $MYSQLTEST_VARDIR/log/mysqld.2.err;
+}
+--echo "Assert that the net_fulsh() reply failed is present in slave error log.
+--let SEARCH_FILE=$log_error_
+--let SEARCH_PATTERN=Semi-sync slave net_flush\(\) reply failed
+--source include/search_pattern_in_file.inc
+
+--echo "Assert that Slave IO thread is up and running."
+SHOW STATUS LIKE 'Slave_running';
+let $status= query_get_value("show slave status", Slave_IO_Running, 1);
+echo Slave_IO_Running= $status;
+
+--echo "Clear the network failure simulation."
+SET GLOBAL debug_dbug= @save_debug;
+
+--connection master
+insert into t1 values (10);
+--sync_slave_with_master
+
+--connection slave
+--echo # Compare the tables on master and slave.
+--let $diff_tables= master:t1, slave:t1
+--source include/diff_tables.inc
+
+--connection master
+drop table t1;
+--sync_slave_with_master
+set global rpl_semi_sync_slave_enabled = OFF;
+
+--connection master
+set global rpl_semi_sync_master_enabled = OFF;
+--eval SET @@GLOBAL.rpl_semi_sync_master_timeout = $sav_timeout_master
+--source include/rpl_end.inc
diff --git a/sql/slave.cc b/sql/slave.cc
index 4007f323a6e..165aa20b1ee 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -4911,13 +4911,14 @@ Stopping slave I/O thread due to out-of-memory error from master");
goto err;
}
- if (rpl_semi_sync_slave_status && (mi->semi_ack & SEMI_SYNC_NEED_ACK) &&
- repl_semisync_slave.slave_reply(mi))
+ if (rpl_semi_sync_slave_status && (mi->semi_ack & SEMI_SYNC_NEED_ACK))
{
- mi->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR, NULL,
- ER_THD(thd, ER_SLAVE_FATAL_ERROR),
- "Failed to run 'after_queue_event' hook");
- goto err;
+ /*
+ We deliberately ignore the error in slave_reply, such error should
+ not cause the slave IO thread to stop, and the error messages are
+ already reported.
+ */
+ (void)repl_semisync_slave.slave_reply(mi);
}
if (mi->using_gtid == Master_info::USE_GTID_NO &&
1
0
[Commits] 0ae0f6571c2: Issue #790, MyRocks/MRR: make ref(const) access switch to MRR
by Sergei Petrunia 16 Sep '19
by Sergei Petrunia 16 Sep '19
16 Sep '19
revision-id: 0ae0f6571c234ab00a16005da0db15fafc6fe98c (fb-prod201903-165-g0ae0f6571c2)
parent(s): 803de702568dc7867075a434cbeca1e3c7e2782a
author: Sergei Petrunia
committer: Sergei Petrunia
timestamp: 2019-09-16 23:30:13 +0300
message:
Issue #790, MyRocks/MRR: make ref(const) access switch to MRR
Do the switch only if the storage engine requests it by setting
the HA_MRR_CONVERT_REF_TO_RANGE flag.
---
sql/handler.h | 13 +++++++++++++
sql/sql_optimizer.cc | 21 ++++++++++++++++-----
storage/rocksdb/ha_rocksdb.cc | 4 ++++
3 files changed, 33 insertions(+), 5 deletions(-)
diff --git a/sql/handler.h b/sql/handler.h
index 3dd40c88881..4f68fcb6bcc 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -1834,8 +1834,21 @@ void get_sweep_read_cost(TABLE *table, ha_rows nrows, bool interrupted,
*/
#define HA_MRR_SUPPORT_SORTED 256
+/*
+ SQL layer passes this as an argument to multi_range_read_info() to indicate
+ that the lookup keys are full extended keys for the index
+*/
#define HA_MRR_FULL_EXTENDED_KEYS 512
+/*
+ MRR implementation returns this flag to indicate that when the optimizer has
+ a choice between
+ - ref(const) access (which doesnt use the MRR interface)
+ - range access (which does use MRR interface)
+ the latter should be preferred.
+*/
+#define HA_MRR_CONVERT_REF_TO_RANGE 1024
+
class ha_statistics
{
public:
diff --git a/sql/sql_optimizer.cc b/sql/sql_optimizer.cc
index 219ddc5d50f..e170e674e08 100644
--- a/sql/sql_optimizer.cc
+++ b/sql/sql_optimizer.cc
@@ -8324,7 +8324,9 @@ only_eq_ref_tables(JOIN *join, ORDER *order, table_map tables,
@param thd THD To re-run range optimizer.
@param tab JOIN_TAB To check the above conditions.
- @return Pointer Range is better than ref
+ @return Pointer Range is better than ref. The pointer points to a string
+ describing why (the string is intended to be used in the
+ optimizer trace)
@return nullptr Ref is better or switch isn't possible
@todo: This decision should rather be made in best_access_path()
@@ -8334,13 +8336,22 @@ static const char* can_switch_from_ref_to_range(THD *thd, JOIN_TAB *tab)
if (!tab->ref.depend_map && // 1)
tab->quick) // 2)
{
- // MRR use: TODO: check if quick would have used MRR:
+ /*
+ If there was a quick select that
+ - was scanning the same range
+ - used MRR
+ - MRR implementation indicated that it's preferred to use MRR over
+ ref(const).
+ then switch to range access as it will read rows using the MRR interface
+ */
if ((uint) tab->ref.key == tab->quick->index &&
tab->ref.key_length == tab->quick->max_used_key_length &&
- tab->quick->get_type() == QUICK_SELECT_I::QS_TYPE_RANGE &&
- !(((QUICK_RANGE_SELECT*)tab->quick)->mrr_flags &
- HA_MRR_USE_DEFAULT_IMPL))
+ tab->quick->get_type() == QUICK_SELECT_I::QS_TYPE_RANGE) {
+ QUICK_RANGE_SELECT *qr = (QUICK_RANGE_SELECT*)tab->quick;
+ if (!(qr->mrr_flags & HA_MRR_USE_DEFAULT_IMPL) &&
+ (qr->mrr_flags & HA_MRR_CONVERT_REF_TO_RANGE))
return "uses_mrr";
+ }
if ((uint) tab->ref.key == tab->quick->index && // 3a)
tab->ref.key_length < tab->quick->max_used_key_length) // 3b)
diff --git a/storage/rocksdb/ha_rocksdb.cc b/storage/rocksdb/ha_rocksdb.cc
index 94b8c3741f3..993cfe1abce 100644
--- a/storage/rocksdb/ha_rocksdb.cc
+++ b/storage/rocksdb/ha_rocksdb.cc
@@ -15175,6 +15175,7 @@ ha_rows ha_rocksdb::multi_range_read_info_const(uint keyno, RANGE_SEQ_IF *seq,
if (all_eq_ranges) {
// Indicate that we will use Mutlit-Get MRR
*flags &= ~HA_MRR_USE_DEFAULT_IMPL;
+ *flags |= HA_MRR_CONVERT_REF_TO_RANGE;
*flags |= HA_MRR_SUPPORT_SORTED;
*bufsz = mrr_get_length_per_rec() * res * 1.1 + 1;
}
@@ -15184,6 +15185,7 @@ ha_rows ha_rocksdb::multi_range_read_info_const(uint keyno, RANGE_SEQ_IF *seq,
if (!(*flags & HA_MRR_INDEX_ONLY)) {
*flags &= ~HA_MRR_SUPPORT_SORTED; // Non-sorted mode
*flags &= ~HA_MRR_USE_DEFAULT_IMPL;
+ *flags |= HA_MRR_CONVERT_REF_TO_RANGE;
*bufsz = mrr_get_length_per_rec() * res * 1.1 + 1;
}
}
@@ -15207,11 +15209,13 @@ ha_rows ha_rocksdb::multi_range_read_info(uint keyno, uint n_ranges, uint keys,
if (keyno == table->s->primary_key && (*flags & HA_MRR_FULL_EXTENDED_KEYS)) {
*flags &= ~HA_MRR_USE_DEFAULT_IMPL;
+ *flags |= HA_MRR_CONVERT_REF_TO_RANGE;
*flags |= HA_MRR_SUPPORT_SORTED;
}
if (keyno != table->s->primary_key && !(*flags & HA_MRR_INDEX_ONLY)) {
*flags &= ~HA_MRR_USE_DEFAULT_IMPL;
+ *flags |= HA_MRR_CONVERT_REF_TO_RANGE;
*flags &= ~HA_MRR_SUPPORT_SORTED; // Non-sorted mode
}
1
0
[Commits] 803de702568: Issue #790, MyRocks/MRR: make ref(const) access switch to MRR
by Sergei Petrunia 16 Sep '19
by Sergei Petrunia 16 Sep '19
16 Sep '19
revision-id: 803de702568dc7867075a434cbeca1e3c7e2782a (fb-prod201903-164-g803de702568)
parent(s): ff51e6038a6d64cf596f0ecda6c28aaf3dcfa3bf
author: Sergei Petrunia
committer: Sergei Petrunia
timestamp: 2019-09-16 23:12:27 +0300
message:
Issue #790, MyRocks/MRR: make ref(const) access switch to MRR
Revert this (as a different solution will be used):
Followup patch: update test results:
- index_merge_innodb uses a table that's large enough so that the
choice to use MRR is cost-based
- Other tests set mrr=on,mrr_cost_based=off, which forces MRR to be used.
---
mysql-test/r/index_merge_innodb.result | 2 +-
.../r/innodb_explain_json_non_select_all.result | 18 +++++++----
mysql-test/r/innodb_explain_non_select_all.result | 4 +--
mysql-test/r/join_cache_bka.result | 6 ++--
mysql-test/r/join_cache_bka_nixbnl.result | 6 ++--
mysql-test/r/join_cache_bnl.result | 6 ++--
mysql-test/r/join_cache_nojb.result | 6 ++--
mysql-test/r/join_nested_bka.result | 2 +-
mysql-test/r/join_nested_bka_nixbnl.result | 2 +-
.../r/myisam_explain_json_non_select_all.result | 18 +++++++----
mysql-test/r/myisam_explain_non_select_all.result | 4 +--
mysql-test/r/myisam_mrr.result | 2 +-
mysql-test/r/myisam_mrr_all.result | 2 +-
mysql-test/r/myisam_mrr_icp.result | 2 +-
mysql-test/r/order_by_all.result | 8 ++---
mysql-test/r/order_by_icp_mrr.result | 8 ++---
mysql-test/r/range_all.result | 28 ++++++++---------
mysql-test/r/range_icp_mrr.result | 28 ++++++++---------
mysql-test/r/range_mrr.result | 28 ++++++++---------
mysql-test/r/select_all.result | 26 ++++++++--------
mysql-test/r/select_all_bka.result | 26 ++++++++--------
mysql-test/r/select_all_bka_nixbnl.result | 26 ++++++++--------
mysql-test/r/select_icp_mrr.result | 26 ++++++++--------
mysql-test/r/select_icp_mrr_bka.result | 26 ++++++++--------
mysql-test/r/select_icp_mrr_bka_nixbnl.result | 26 ++++++++--------
mysql-test/r/subquery_all.result | 8 ++---
mysql-test/r/subquery_all_bka.result | 8 ++---
mysql-test/r/subquery_all_bka_nixbnl.result | 8 ++---
mysql-test/r/subquery_nomat_nosj.result | 8 ++---
mysql-test/r/subquery_nomat_nosj_bka.result | 8 ++---
mysql-test/r/subquery_nomat_nosj_bka_nixbnl.result | 8 ++---
mysql-test/r/subquery_sj_all.result | 35 ++++++++++++----------
mysql-test/r/subquery_sj_all_bka.result | 35 ++++++++++++----------
mysql-test/r/subquery_sj_all_bka_nixbnl.result | 35 ++++++++++++----------
34 files changed, 255 insertions(+), 234 deletions(-)
diff --git a/mysql-test/r/index_merge_innodb.result b/mysql-test/r/index_merge_innodb.result
index f55b26ab31c..98d69097140 100644
--- a/mysql-test/r/index_merge_innodb.result
+++ b/mysql-test/r/index_merge_innodb.result
@@ -746,7 +746,7 @@ key1 key2 key3 key4 filler1
-1 -1 200 -1 key3
explain select * from t1 where st_a=1 and swt1a=1 and swt2a=1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range sta_swt12a,sta_swt1a,sta_swt2a,sta_swt21a,st_a sta_swt21a 12 NULL 999 Using index condition; Using MRR
+1 SIMPLE t1 ref sta_swt12a,sta_swt1a,sta_swt2a,sta_swt21a,st_a sta_swt21a 12 const,const,const 999 NULL
explain select * from t1 where st_b=1 and swt1b=1 and swt2b=1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref stb_swt1a_2b,stb_swt1b,st_b stb_swt1a_2b 8 const,const 3999 Using where
diff --git a/mysql-test/r/innodb_explain_json_non_select_all.result b/mysql-test/r/innodb_explain_json_non_select_all.result
index 800f6763b78..6729e40dd9a 100644
--- a/mysql-test/r/innodb_explain_json_non_select_all.result
+++ b/mysql-test/r/innodb_explain_json_non_select_all.result
@@ -4699,7 +4699,7 @@ FLUSH STATUS;
FLUSH TABLES;
EXPLAIN EXTENDED SELECT * FROM t1 WHERE c1_idx = 'y' ORDER BY pk DESC LIMIT 2;
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 SIMPLE t1 range c1_idx c1_idx 2 NULL 2 100.00 Using index condition
+1 SIMPLE t1 ref c1_idx c1_idx 2 const 2 100.00 Using where
Warnings:
Note 1003 /* select#1 */ select `test`.`t1`.`pk` AS `pk`,`test`.`t1`.`c1_idx` AS `c1_idx`,`test`.`t1`.`c2` AS `c2` from `test`.`t1` where (`test`.`t1`.`c1_idx` = 'y') order by `test`.`t1`.`pk` desc limit 2
# Status of EXPLAIN EXTENDED "equivalent" SELECT query execution
@@ -4713,7 +4713,7 @@ EXPLAIN
"using_filesort": false,
"table": {
"table_name": "t1",
- "access_type": "range",
+ "access_type": "ref",
"possible_keys": [
"c1_idx"
] /* possible_keys */,
@@ -4722,9 +4722,12 @@ EXPLAIN
"c1_idx"
] /* used_key_parts */,
"key_length": "2",
+ "ref": [
+ "const"
+ ] /* ref */,
"rows": 2,
"filtered": 100,
- "index_condition": "(`test`.`t1`.`c1_idx` = 'y')"
+ "attached_condition": "((`test`.`t1`.`c1_idx` <=> 'y') and (`test`.`t1`.`c1_idx` = 'y'))"
} /* table */
} /* ordering_operation */
} /* query_block */
@@ -4789,7 +4792,7 @@ FLUSH STATUS;
FLUSH TABLES;
EXPLAIN EXTENDED SELECT * FROM t1 WHERE c1_idx = 'y' ORDER BY pk DESC LIMIT 2;
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 SIMPLE t1 range c1_idx c1_idx 2 NULL 2 100.00 Using index condition
+1 SIMPLE t1 ref c1_idx c1_idx 2 const 2 100.00 Using where
Warnings:
Note 1003 /* select#1 */ select `test`.`t1`.`pk` AS `pk`,`test`.`t1`.`c1_idx` AS `c1_idx`,`test`.`t1`.`c2` AS `c2` from `test`.`t1` where (`test`.`t1`.`c1_idx` = 'y') order by `test`.`t1`.`pk` desc limit 2
# Status of EXPLAIN EXTENDED "equivalent" SELECT query execution
@@ -4803,7 +4806,7 @@ EXPLAIN
"using_filesort": false,
"table": {
"table_name": "t1",
- "access_type": "range",
+ "access_type": "ref",
"possible_keys": [
"c1_idx"
] /* possible_keys */,
@@ -4812,9 +4815,12 @@ EXPLAIN
"c1_idx"
] /* used_key_parts */,
"key_length": "2",
+ "ref": [
+ "const"
+ ] /* ref */,
"rows": 2,
"filtered": 100,
- "index_condition": "(`test`.`t1`.`c1_idx` = 'y')"
+ "attached_condition": "((`test`.`t1`.`c1_idx` <=> 'y') and (`test`.`t1`.`c1_idx` = 'y'))"
} /* table */
} /* ordering_operation */
} /* query_block */
diff --git a/mysql-test/r/innodb_explain_non_select_all.result b/mysql-test/r/innodb_explain_non_select_all.result
index 945a9d3fde3..9b80213dd12 100644
--- a/mysql-test/r/innodb_explain_non_select_all.result
+++ b/mysql-test/r/innodb_explain_non_select_all.result
@@ -2211,7 +2211,7 @@ FLUSH STATUS;
FLUSH TABLES;
EXPLAIN EXTENDED SELECT * FROM t1 WHERE c1_idx = 'y' ORDER BY pk DESC LIMIT 2;
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 SIMPLE t1 range c1_idx c1_idx 2 NULL 2 100.00 Using index condition
+1 SIMPLE t1 ref c1_idx c1_idx 2 const 2 100.00 Using where
Warnings:
Note 1003 /* select#1 */ select `test`.`t1`.`pk` AS `pk`,`test`.`t1`.`c1_idx` AS `c1_idx`,`test`.`t1`.`c2` AS `c2` from `test`.`t1` where (`test`.`t1`.`c1_idx` = 'y') order by `test`.`t1`.`pk` desc limit 2
# Status of EXPLAIN EXTENDED "equivalent" SELECT query execution
@@ -2245,7 +2245,7 @@ FLUSH STATUS;
FLUSH TABLES;
EXPLAIN EXTENDED SELECT * FROM t1 WHERE c1_idx = 'y' ORDER BY pk DESC LIMIT 2;
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 SIMPLE t1 range c1_idx c1_idx 2 NULL 2 100.00 Using index condition
+1 SIMPLE t1 ref c1_idx c1_idx 2 const 2 100.00 Using where
Warnings:
Note 1003 /* select#1 */ select `test`.`t1`.`pk` AS `pk`,`test`.`t1`.`c1_idx` AS `c1_idx`,`test`.`t1`.`c2` AS `c2` from `test`.`t1` where (`test`.`t1`.`c1_idx` = 'y') order by `test`.`t1`.`pk` desc limit 2
# Status of EXPLAIN EXTENDED "equivalent" SELECT query execution
diff --git a/mysql-test/r/join_cache_bka.result b/mysql-test/r/join_cache_bka.result
index cab5504b367..89177082752 100644
--- a/mysql-test/r/join_cache_bka.result
+++ b/mysql-test/r/join_cache_bka.result
@@ -1302,8 +1302,8 @@ t6.formattypeid IN (2) AND (t3.formatid IN (31, 8, 76)) AND
t1.metaid = t2.metaid AND t1.affiliateid = '2';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t6 system PRIMARY NULL NULL NULL 1 NULL
-1 SIMPLE t1 range t1_affiliateid,t1_metaid t1_affiliateid 4 NULL 1 Using index condition; Using MRR
-1 SIMPLE t4 range PRIMARY,t4_formatclassid,t4_formats_idx t4_formats_idx 1 NULL 1 Using index condition; Using where; Using MRR; Using join buffer (Block Nested Loop)
+1 SIMPLE t1 ref t1_affiliateid,t1_metaid t1_affiliateid 4 const 1 NULL
+1 SIMPLE t4 ref PRIMARY,t4_formatclassid,t4_formats_idx t4_formats_idx 1 const 1 Using index condition; Using where; Using join buffer (Batched Key Access)
1 SIMPLE t5 eq_ref PRIMARY,t5_formattypeid PRIMARY 4 test.t4.formatclassid 1 Using where; Using join buffer (Batched Key Access)
1 SIMPLE t2 eq_ref PRIMARY PRIMARY 4 test.t1.metaid 1 Using join buffer (Batched Key Access)
1 SIMPLE t7 ref PRIMARY PRIMARY 4 test.t1.metaid 1 Using index
@@ -2216,7 +2216,7 @@ ORDER BY t1.col_int_key, t1.col_datetime
LIMIT 2;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL col_int_key NULL NULL NULL 3 Using temporary; Using filesort
-1 SIMPLE t2 range col_int_key col_int_key 5 NULL 1 Using index condition; Using where; Using MRR; Using join buffer (Block Nested Loop)
+1 SIMPLE t2 ref col_int_key col_int_key 5 const 1 Using where; Using join buffer (Batched Key Access)
SELECT t1.col_int_key, t1.col_datetime
FROM t1,t2
WHERE t2.col_int_key = 1 AND t2.col_int >= 3
diff --git a/mysql-test/r/join_cache_bka_nixbnl.result b/mysql-test/r/join_cache_bka_nixbnl.result
index b27e9675112..3d89af07b57 100644
--- a/mysql-test/r/join_cache_bka_nixbnl.result
+++ b/mysql-test/r/join_cache_bka_nixbnl.result
@@ -1302,8 +1302,8 @@ t6.formattypeid IN (2) AND (t3.formatid IN (31, 8, 76)) AND
t1.metaid = t2.metaid AND t1.affiliateid = '2';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t6 system PRIMARY NULL NULL NULL 1 NULL
-1 SIMPLE t1 range t1_affiliateid,t1_metaid t1_affiliateid 4 NULL 1 Using index condition; Using MRR
-1 SIMPLE t4 range PRIMARY,t4_formatclassid,t4_formats_idx t4_formats_idx 1 NULL 1 Using index condition; Using where; Using MRR
+1 SIMPLE t1 ref t1_affiliateid,t1_metaid t1_affiliateid 4 const 1 NULL
+1 SIMPLE t4 ref PRIMARY,t4_formatclassid,t4_formats_idx t4_formats_idx 1 const 1 Using index condition; Using where; Using join buffer (Batched Key Access)
1 SIMPLE t5 eq_ref PRIMARY,t5_formattypeid PRIMARY 4 test.t4.formatclassid 1 Using where; Using join buffer (Batched Key Access)
1 SIMPLE t2 eq_ref PRIMARY PRIMARY 4 test.t1.metaid 1 Using join buffer (Batched Key Access)
1 SIMPLE t7 ref PRIMARY PRIMARY 4 test.t1.metaid 1 Using index
@@ -2216,7 +2216,7 @@ ORDER BY t1.col_int_key, t1.col_datetime
LIMIT 2;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL col_int_key NULL NULL NULL 3 Using temporary; Using filesort
-1 SIMPLE t2 range col_int_key col_int_key 5 NULL 1 Using index condition; Using where; Using MRR
+1 SIMPLE t2 ref col_int_key col_int_key 5 const 1 Using where; Using join buffer (Batched Key Access)
SELECT t1.col_int_key, t1.col_datetime
FROM t1,t2
WHERE t2.col_int_key = 1 AND t2.col_int >= 3
diff --git a/mysql-test/r/join_cache_bnl.result b/mysql-test/r/join_cache_bnl.result
index 853a2f8a225..1ebf6f8bd71 100644
--- a/mysql-test/r/join_cache_bnl.result
+++ b/mysql-test/r/join_cache_bnl.result
@@ -1303,8 +1303,8 @@ t6.formattypeid IN (2) AND (t3.formatid IN (31, 8, 76)) AND
t1.metaid = t2.metaid AND t1.affiliateid = '2';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t6 system PRIMARY NULL NULL NULL 1 NULL
-1 SIMPLE t1 range t1_affiliateid,t1_metaid t1_affiliateid 4 NULL 1 Using index condition; Using MRR
-1 SIMPLE t4 range PRIMARY,t4_formatclassid,t4_formats_idx t4_formats_idx 1 NULL 1 Using index condition; Using where; Using MRR; Using join buffer (Block Nested Loop)
+1 SIMPLE t1 ref t1_affiliateid,t1_metaid t1_affiliateid 4 const 1 NULL
+1 SIMPLE t4 ref PRIMARY,t4_formatclassid,t4_formats_idx t4_formats_idx 1 const 1 Using index condition; Using where
1 SIMPLE t5 eq_ref PRIMARY,t5_formattypeid PRIMARY 4 test.t4.formatclassid 1 Using where
1 SIMPLE t2 eq_ref PRIMARY PRIMARY 4 test.t1.metaid 1 NULL
1 SIMPLE t7 ref PRIMARY PRIMARY 4 test.t1.metaid 1 Using index
@@ -2217,7 +2217,7 @@ ORDER BY t1.col_int_key, t1.col_datetime
LIMIT 2;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL col_int_key NULL NULL NULL 3 Using temporary; Using filesort
-1 SIMPLE t2 range col_int_key col_int_key 5 NULL 1 Using index condition; Using where; Using MRR; Using join buffer (Block Nested Loop)
+1 SIMPLE t2 ref col_int_key col_int_key 5 const 1 Using where
SELECT t1.col_int_key, t1.col_datetime
FROM t1,t2
WHERE t2.col_int_key = 1 AND t2.col_int >= 3
diff --git a/mysql-test/r/join_cache_nojb.result b/mysql-test/r/join_cache_nojb.result
index a045c4d890a..e7982de302c 100644
--- a/mysql-test/r/join_cache_nojb.result
+++ b/mysql-test/r/join_cache_nojb.result
@@ -1303,8 +1303,8 @@ t6.formattypeid IN (2) AND (t3.formatid IN (31, 8, 76)) AND
t1.metaid = t2.metaid AND t1.affiliateid = '2';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t6 system PRIMARY NULL NULL NULL 1 NULL
-1 SIMPLE t1 range t1_affiliateid,t1_metaid t1_affiliateid 4 NULL 1 Using index condition; Using MRR
-1 SIMPLE t4 range PRIMARY,t4_formatclassid,t4_formats_idx t4_formats_idx 1 NULL 1 Using index condition; Using where; Using MRR
+1 SIMPLE t1 ref t1_affiliateid,t1_metaid t1_affiliateid 4 const 1 NULL
+1 SIMPLE t4 ref PRIMARY,t4_formatclassid,t4_formats_idx t4_formats_idx 1 const 1 Using index condition; Using where
1 SIMPLE t5 eq_ref PRIMARY,t5_formattypeid PRIMARY 4 test.t4.formatclassid 1 Using where
1 SIMPLE t2 eq_ref PRIMARY PRIMARY 4 test.t1.metaid 1 NULL
1 SIMPLE t7 ref PRIMARY PRIMARY 4 test.t1.metaid 1 Using index
@@ -2217,7 +2217,7 @@ ORDER BY t1.col_int_key, t1.col_datetime
LIMIT 2;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL col_int_key NULL NULL NULL 3 Using temporary; Using filesort
-1 SIMPLE t2 range col_int_key col_int_key 5 NULL 1 Using index condition; Using where; Using MRR
+1 SIMPLE t2 ref col_int_key col_int_key 5 const 1 Using where
SELECT t1.col_int_key, t1.col_datetime
FROM t1,t2
WHERE t2.col_int_key = 1 AND t2.col_int >= 3
diff --git a/mysql-test/r/join_nested_bka.result b/mysql-test/r/join_nested_bka.result
index 5bdffe0a7c7..bf1bc232c04 100644
--- a/mysql-test/r/join_nested_bka.result
+++ b/mysql-test/r/join_nested_bka.result
@@ -1055,7 +1055,7 @@ t0.b=t1.b AND
(t8.b=t9.b OR t8.c IS NULL) AND
(t9.a=1);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 SIMPLE t0 range idx_a idx_a 5 NULL 1 100.00 Using index condition; Using where; Using MRR
+1 SIMPLE t0 ref idx_a idx_a 5 const 1 100.00 Using where
1 SIMPLE t1 ref idx_b idx_b 5 test.t0.b 2 100.00 Using join buffer (Batched Key Access)
1 SIMPLE t2 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (Block Nested Loop)
1 SIMPLE t3 ALL NULL NULL NULL NULL 2 100.00 Using where; Using join buffer (Block Nested Loop)
diff --git a/mysql-test/r/join_nested_bka_nixbnl.result b/mysql-test/r/join_nested_bka_nixbnl.result
index f7827381b2f..895435deb26 100644
--- a/mysql-test/r/join_nested_bka_nixbnl.result
+++ b/mysql-test/r/join_nested_bka_nixbnl.result
@@ -1055,7 +1055,7 @@ t0.b=t1.b AND
(t8.b=t9.b OR t8.c IS NULL) AND
(t9.a=1);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 SIMPLE t0 range idx_a idx_a 5 NULL 1 100.00 Using index condition; Using where; Using MRR
+1 SIMPLE t0 ref idx_a idx_a 5 const 1 100.00 Using where
1 SIMPLE t1 ref idx_b idx_b 5 test.t0.b 2 100.00 Using join buffer (Batched Key Access)
1 SIMPLE t2 ALL NULL NULL NULL NULL 3 100.00 Using where
1 SIMPLE t3 ALL NULL NULL NULL NULL 2 100.00 Using where
diff --git a/mysql-test/r/myisam_explain_json_non_select_all.result b/mysql-test/r/myisam_explain_json_non_select_all.result
index e0443347640..9b72fcea450 100644
--- a/mysql-test/r/myisam_explain_json_non_select_all.result
+++ b/mysql-test/r/myisam_explain_json_non_select_all.result
@@ -4556,7 +4556,7 @@ FLUSH STATUS;
FLUSH TABLES;
EXPLAIN EXTENDED SELECT * FROM t1 WHERE c1_idx = 'y' ORDER BY pk DESC LIMIT 2;
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 SIMPLE t1 range c1_idx c1_idx 2 NULL 2 100.00 Using index condition; Using MRR; Using filesort
+1 SIMPLE t1 ref c1_idx c1_idx 2 const 2 100.00 Using index condition; Using where; Using filesort
Warnings:
Note 1003 /* select#1 */ select `test`.`t1`.`pk` AS `pk`,`test`.`t1`.`c1_idx` AS `c1_idx`,`test`.`t1`.`c2` AS `c2` from `test`.`t1` where (`test`.`t1`.`c1_idx` = 'y') order by `test`.`t1`.`pk` desc limit 2
# Status of EXPLAIN EXTENDED "equivalent" SELECT query execution
@@ -4570,7 +4570,7 @@ EXPLAIN
"using_filesort": true,
"table": {
"table_name": "t1",
- "access_type": "range",
+ "access_type": "ref",
"possible_keys": [
"c1_idx"
] /* possible_keys */,
@@ -4579,10 +4579,13 @@ EXPLAIN
"c1_idx"
] /* used_key_parts */,
"key_length": "2",
+ "ref": [
+ "const"
+ ] /* ref */,
"rows": 2,
"filtered": 100,
"index_condition": "(`test`.`t1`.`c1_idx` = 'y')",
- "using_MRR": true
+ "attached_condition": "((`test`.`t1`.`c1_idx` <=> 'y'))"
} /* table */
} /* ordering_operation */
} /* query_block */
@@ -4652,7 +4655,7 @@ FLUSH STATUS;
FLUSH TABLES;
EXPLAIN EXTENDED SELECT * FROM t1 WHERE c1_idx = 'y' ORDER BY pk DESC LIMIT 2;
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 SIMPLE t1 range c1_idx c1_idx 2 NULL 2 100.00 Using index condition; Using MRR; Using filesort
+1 SIMPLE t1 ref c1_idx c1_idx 2 const 2 100.00 Using index condition; Using where; Using filesort
Warnings:
Note 1003 /* select#1 */ select `test`.`t1`.`pk` AS `pk`,`test`.`t1`.`c1_idx` AS `c1_idx`,`test`.`t1`.`c2` AS `c2` from `test`.`t1` where (`test`.`t1`.`c1_idx` = 'y') order by `test`.`t1`.`pk` desc limit 2
# Status of EXPLAIN EXTENDED "equivalent" SELECT query execution
@@ -4666,7 +4669,7 @@ EXPLAIN
"using_filesort": true,
"table": {
"table_name": "t1",
- "access_type": "range",
+ "access_type": "ref",
"possible_keys": [
"c1_idx"
] /* possible_keys */,
@@ -4675,10 +4678,13 @@ EXPLAIN
"c1_idx"
] /* used_key_parts */,
"key_length": "2",
+ "ref": [
+ "const"
+ ] /* ref */,
"rows": 2,
"filtered": 100,
"index_condition": "(`test`.`t1`.`c1_idx` = 'y')",
- "using_MRR": true
+ "attached_condition": "((`test`.`t1`.`c1_idx` <=> 'y'))"
} /* table */
} /* ordering_operation */
} /* query_block */
diff --git a/mysql-test/r/myisam_explain_non_select_all.result b/mysql-test/r/myisam_explain_non_select_all.result
index ba36f354ee2..330713ddef3 100644
--- a/mysql-test/r/myisam_explain_non_select_all.result
+++ b/mysql-test/r/myisam_explain_non_select_all.result
@@ -2085,7 +2085,7 @@ FLUSH STATUS;
FLUSH TABLES;
EXPLAIN EXTENDED SELECT * FROM t1 WHERE c1_idx = 'y' ORDER BY pk DESC LIMIT 2;
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 SIMPLE t1 range c1_idx c1_idx 2 NULL 2 100.00 Using index condition; Using MRR; Using filesort
+1 SIMPLE t1 ref c1_idx c1_idx 2 const 2 100.00 Using index condition; Using where; Using filesort
Warnings:
Note 1003 /* select#1 */ select `test`.`t1`.`pk` AS `pk`,`test`.`t1`.`c1_idx` AS `c1_idx`,`test`.`t1`.`c2` AS `c2` from `test`.`t1` where (`test`.`t1`.`c1_idx` = 'y') order by `test`.`t1`.`pk` desc limit 2
# Status of EXPLAIN EXTENDED "equivalent" SELECT query execution
@@ -2124,7 +2124,7 @@ FLUSH STATUS;
FLUSH TABLES;
EXPLAIN EXTENDED SELECT * FROM t1 WHERE c1_idx = 'y' ORDER BY pk DESC LIMIT 2;
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 SIMPLE t1 range c1_idx c1_idx 2 NULL 2 100.00 Using index condition; Using MRR; Using filesort
+1 SIMPLE t1 ref c1_idx c1_idx 2 const 2 100.00 Using index condition; Using where; Using filesort
Warnings:
Note 1003 /* select#1 */ select `test`.`t1`.`pk` AS `pk`,`test`.`t1`.`c1_idx` AS `c1_idx`,`test`.`t1`.`c2` AS `c2` from `test`.`t1` where (`test`.`t1`.`c1_idx` = 'y') order by `test`.`t1`.`pk` desc limit 2
# Status of EXPLAIN EXTENDED "equivalent" SELECT query execution
diff --git a/mysql-test/r/myisam_mrr.result b/mysql-test/r/myisam_mrr.result
index a2ea0318800..bf0485383b8 100644
--- a/mysql-test/r/myisam_mrr.result
+++ b/mysql-test/r/myisam_mrr.result
@@ -347,7 +347,7 @@ GROUP BY t2.pk
);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
-2 SUBQUERY t2 range int_key int_key 5 NULL 1 100.00 Using where; Using MRR
+2 SUBQUERY t2 ref int_key int_key 5 const 1 100.00 Using where
Warnings:
Note 1003 /* select#1 */ select min(`test`.`t1`.`pk`) AS `MIN(t1.pk)` from `test`.`t1` where 0
DROP TABLE t1, t2;
diff --git a/mysql-test/r/myisam_mrr_all.result b/mysql-test/r/myisam_mrr_all.result
index 37e1e3d573a..8eda02da1d1 100644
--- a/mysql-test/r/myisam_mrr_all.result
+++ b/mysql-test/r/myisam_mrr_all.result
@@ -347,7 +347,7 @@ GROUP BY t2.pk
);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
-2 SUBQUERY t2 range int_key int_key 5 NULL 1 100.00 Using index condition; Using MRR
+2 SUBQUERY t2 ref int_key int_key 5 const 1 100.00 Using index condition
Warnings:
Note 1003 /* select#1 */ select min(`test`.`t1`.`pk`) AS `MIN(t1.pk)` from `test`.`t1` where 0
DROP TABLE t1, t2;
diff --git a/mysql-test/r/myisam_mrr_icp.result b/mysql-test/r/myisam_mrr_icp.result
index fe637227b4a..de98834f39c 100644
--- a/mysql-test/r/myisam_mrr_icp.result
+++ b/mysql-test/r/myisam_mrr_icp.result
@@ -347,7 +347,7 @@ GROUP BY t2.pk
);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
-2 SUBQUERY t2 range int_key int_key 5 NULL 1 100.00 Using index condition; Using MRR
+2 SUBQUERY t2 ref int_key int_key 5 const 1 100.00 Using index condition
Warnings:
Note 1003 /* select#1 */ select min(`test`.`t1`.`pk`) AS `MIN(t1.pk)` from `test`.`t1` where 0
DROP TABLE t1, t2;
diff --git a/mysql-test/r/order_by_all.result b/mysql-test/r/order_by_all.result
index c50053bab4f..3389f44979c 100644
--- a/mysql-test/r/order_by_all.result
+++ b/mysql-test/r/order_by_all.result
@@ -602,7 +602,7 @@ KEY StringField (FieldKey,StringVal(32))
INSERT INTO t1 VALUES ('0',3,'0'),('0',2,'1'),('0',1,'2'),('1',2,'1'),('1',1,'3'), ('1',0,'2'),('2',3,'0'),('2',2,'1'),('2',1,'2'),('2',3,'0'),('2',2,'1'),('2',1,'2'),('3',2,'1'),('3',1,'2'),('3','3','3');
EXPLAIN SELECT * FROM t1 WHERE FieldKey = '1' ORDER BY LongVal;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range FieldKey,LongField,StringField LongField 38 NULL 3 Using where
+1 SIMPLE t1 ref FieldKey,LongField,StringField LongField 38 const 3 Using where
SELECT * FROM t1 WHERE FieldKey = '1' ORDER BY LongVal;
FieldKey LongVal StringVal
1 0 2
@@ -683,10 +683,10 @@ a b c d
1 1 92 -9
select * from t1 where a=1 and b in (1);
a b c d
-1 1 2 0
1 1 92 -9
1 1 52 -5
1 1 12 -1
+1 1 2 0
drop table t1, t2;
create table t1 (col1 int, col int);
create table t2 (col2 int, col int);
@@ -1102,7 +1102,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 index k2 k3 5 NULL 111 Using where
EXPLAIN SELECT id,c3 FROM t2 WHERE c2=11 ORDER BY c3 LIMIT 4000;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range k2 k2 5 NULL 7341 Using index condition; Using MRR; Using filesort
+1 SIMPLE t2 ref k2 k2 5 const 7341 Using where; Using filesort
EXPLAIN SELECT id,c3 FROM t2 WHERE c2 BETWEEN 10 AND 12 ORDER BY c3 LIMIT 20;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 index k2 k3 5 NULL 73 Using where
@@ -1487,7 +1487,7 @@ SELECT d FROM t1, t2
WHERE t2.b=14 AND t2.a=t1.a AND 5.1<t2.c AND t1.b='DE'
ORDER BY t2.c LIMIT 1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range a,b b 4 NULL 4 Using index condition; Using where; Using MRR; Using temporary; Using filesort
+1 SIMPLE t1 ref a,b b 4 const 4 Using index condition; Using where; Using temporary; Using filesort
1 SIMPLE t2 ref a,b,c a 40 test.t1.a,const 11 Using index condition
SELECT d FROM t1, t2
WHERE t2.b=14 AND t2.a=t1.a AND 5.1<t2.c AND t1.b='DE'
diff --git a/mysql-test/r/order_by_icp_mrr.result b/mysql-test/r/order_by_icp_mrr.result
index 18595dfeb98..de8c9858994 100644
--- a/mysql-test/r/order_by_icp_mrr.result
+++ b/mysql-test/r/order_by_icp_mrr.result
@@ -602,7 +602,7 @@ KEY StringField (FieldKey,StringVal(32))
INSERT INTO t1 VALUES ('0',3,'0'),('0',2,'1'),('0',1,'2'),('1',2,'1'),('1',1,'3'), ('1',0,'2'),('2',3,'0'),('2',2,'1'),('2',1,'2'),('2',3,'0'),('2',2,'1'),('2',1,'2'),('3',2,'1'),('3',1,'2'),('3','3','3');
EXPLAIN SELECT * FROM t1 WHERE FieldKey = '1' ORDER BY LongVal;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range FieldKey,LongField,StringField LongField 38 NULL 3 Using where
+1 SIMPLE t1 ref FieldKey,LongField,StringField LongField 38 const 3 Using where
SELECT * FROM t1 WHERE FieldKey = '1' ORDER BY LongVal;
FieldKey LongVal StringVal
1 0 2
@@ -683,10 +683,10 @@ a b c d
1 1 92 -9
select * from t1 where a=1 and b in (1);
a b c d
-1 1 2 0
1 1 92 -9
1 1 52 -5
1 1 12 -1
+1 1 2 0
drop table t1, t2;
create table t1 (col1 int, col int);
create table t2 (col2 int, col int);
@@ -1102,7 +1102,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 index k2 k3 5 NULL 111 Using where
EXPLAIN SELECT id,c3 FROM t2 WHERE c2=11 ORDER BY c3 LIMIT 4000;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range k2 k2 5 NULL 7341 Using index condition; Using MRR; Using filesort
+1 SIMPLE t2 ref k2 k2 5 const 7341 Using where; Using filesort
EXPLAIN SELECT id,c3 FROM t2 WHERE c2 BETWEEN 10 AND 12 ORDER BY c3 LIMIT 20;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 index k2 k3 5 NULL 73 Using where
@@ -1487,7 +1487,7 @@ SELECT d FROM t1, t2
WHERE t2.b=14 AND t2.a=t1.a AND 5.1<t2.c AND t1.b='DE'
ORDER BY t2.c LIMIT 1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range a,b b 4 NULL 4 Using index condition; Using where; Using MRR; Using temporary; Using filesort
+1 SIMPLE t1 ref a,b b 4 const 4 Using index condition; Using where; Using temporary; Using filesort
1 SIMPLE t2 ref a,b,c a 40 test.t1.a,const 11 Using index condition
SELECT d FROM t1, t2
WHERE t2.b=14 AND t2.a=t1.a AND 5.1<t2.c AND t1.b='DE'
diff --git a/mysql-test/r/range_all.result b/mysql-test/r/range_all.result
index 3032dd19893..629fe9b1ec4 100644
--- a/mysql-test/r/range_all.result
+++ b/mysql-test/r/range_all.result
@@ -224,27 +224,27 @@ Table Op Msg_type Msg_text
test.t1 analyze status OK
explain select * from t1, t1 t2 where t1.y = 8 and t2.x between 7 and t1.y+0;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range y y 5 NULL 1 Using index condition; Using MRR
+1 SIMPLE t1 ref y y 5 const 1 NULL
1 SIMPLE t2 range x x 5 NULL 2 Using index condition; Using MRR; Using join buffer (Block Nested Loop)
explain select * from t1, t1 t2 where t1.y = 8 and t2.x >= 7 and t2.x <= t1.y+0;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range y y 5 NULL 1 Using index condition; Using MRR
+1 SIMPLE t1 ref y y 5 const 1 NULL
1 SIMPLE t2 range x x 5 NULL 2 Using index condition; Using MRR; Using join buffer (Block Nested Loop)
explain select * from t1, t1 t2 where t1.y = 2 and t2.x between t1.y-1 and t1.y+1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range y y 5 NULL 1 Using index condition; Using MRR
+1 SIMPLE t1 ref y y 5 const 1 NULL
1 SIMPLE t2 range x x 5 NULL 3 Using index condition; Using MRR; Using join buffer (Block Nested Loop)
explain select * from t1, t1 t2 where t1.y = 2 and t2.x >= t1.y-1 and t2.x <= t1.y+1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range y y 5 NULL 1 Using index condition; Using MRR
+1 SIMPLE t1 ref y y 5 const 1 NULL
1 SIMPLE t2 range x x 5 NULL 3 Using index condition; Using MRR; Using join buffer (Block Nested Loop)
explain select * from t1, t1 t2 where t1.y = 2 and t2.x between 0 and t1.y;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range y y 5 NULL 1 Using index condition; Using MRR
+1 SIMPLE t1 ref y y 5 const 1 NULL
1 SIMPLE t2 range x x 5 NULL 2 Using index condition; Using MRR; Using join buffer (Block Nested Loop)
explain select * from t1, t1 t2 where t1.y = 2 and t2.x >= 0 and t2.x <= t1.y;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range y y 5 NULL 1 Using index condition; Using MRR
+1 SIMPLE t1 ref y y 5 const 1 NULL
1 SIMPLE t2 range x x 5 NULL 2 Using index condition; Using MRR; Using join buffer (Block Nested Loop)
explain select count(*) from t1 where x in (1);
id select_type table type possible_keys key key_len ref rows Extra
@@ -326,8 +326,8 @@ KEY recount( owner, line )
INSERT into t1 (owner,id,columnid,line) values (11,15,15,1),(11,13,13,5);
SELECT id, columnid, tableid, content, showid, line, ordinal FROM t1 WHERE owner=11 AND ((columnid IN ( 15, 13, 14 ) AND line IN ( 1, 2, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 31 )) OR (columnid IN ( 13, 14 ) AND line IN ( 15 ))) LIMIT 0 , 30;
id columnid tableid content showid line ordinal
-15 15 1 188 1 1 0
13 13 1 188 1 5 0
+15 15 1 188 1 1 0
drop table t1;
create table t1 (id int(10) primary key);
insert into t1 values (1),(2),(3),(4),(5),(6),(7),(8),(9);
@@ -619,7 +619,7 @@ INSERT INTO t1 (a) VALUES
('111'),('222'),('222'),('222'),('222'),('444'),('aaa'),('AAA'),('bbb');
explain select * from t1 where a='aaa';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range a a 11 NULL 2 Using index condition; Using MRR
+1 SIMPLE t1 ref a a 11 const 2 Using index condition
explain select * from t1 where a=binary 'aaa';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range a a 11 NULL 2 Using index condition; Using MRR
@@ -708,8 +708,8 @@ WHERE s.oxrootid = 'd8c4177d09f8b11f5.52725521' AND
v.oxrootid ='d8c4177d09f8b11f5.52725521' AND
s.oxleft > v.oxleft AND s.oxleft < v.oxright;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE v range OXLEFT,OXRIGHT,OXROOTID OXROOTID 34 NULL 5 Using index condition; Using MRR
-1 SIMPLE s range OXLEFT,OXROOTID OXROOTID 34 NULL 5 Using index condition; Using where; Using MRR; Using join buffer (Block Nested Loop)
+1 SIMPLE v ref OXLEFT,OXRIGHT,OXROOTID OXROOTID 34 const 5 Using index condition
+1 SIMPLE s ref OXLEFT,OXROOTID OXROOTID 34 const 5 Using index condition; Using where
SELECT s.oxid FROM t1 v, t1 s
WHERE s.oxrootid = 'd8c4177d09f8b11f5.52725521' AND
v.oxrootid ='d8c4177d09f8b11f5.52725521' AND
@@ -1026,10 +1026,10 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range a a 13 NULL # Using index condition; Using MRR
explain select * from t2 where a between 'a' and 'a ';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range a a 13 NULL # Using index condition; Using MRR
+1 SIMPLE t2 ref a a 13 const # Using index condition
explain select * from t2 where a = 'a' or a='a ';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range a a 13 NULL # Using index condition; Using MRR
+1 SIMPLE t2 ref a a 13 const # Using index condition
update t1 set a='b' where a<>'a';
explain select * from t1 where a not between 'b' and 'b';
id select_type table type possible_keys key key_len ref rows Extra
@@ -1115,7 +1115,7 @@ Table Op Msg_type Msg_text
test.t1 analyze status OK
EXPLAIN SELECT * FROM t1 WHERE item='A1' AND started<='2005-12-01 24:00:00';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range PRIMARY PRIMARY 20 NULL 2 Using index condition; Using MRR
+1 SIMPLE t1 ref PRIMARY PRIMARY 20 const 2 Using index condition
Warnings:
Warning 1292 Incorrect datetime value: '2005-12-01 24:00:00' for column 'started' at row 1
Warning 1292 Incorrect datetime value: '2005-12-01 24:00:00' for column 'started' at row 1
@@ -1983,7 +1983,7 @@ INSERT INTO t2 VALUES (1, 1, 2);
# range estimates k is selected.
EXPLAIN SELECT * FROM t2 WHERE a = 1 AND b >= 2 AND c >= 2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range k,l,m,n k 5 NULL 66 Using index condition; Using where; Using MRR
+1 SIMPLE t2 ref k,l,m,n k 5 const 66 Using where
DROP TABLE t1, t2;
#
# BUG#11765831: 'RANGE ACCESS' MAY INCORRECTLY FILTER
diff --git a/mysql-test/r/range_icp_mrr.result b/mysql-test/r/range_icp_mrr.result
index 4a7b4a22205..a21557d4f3c 100644
--- a/mysql-test/r/range_icp_mrr.result
+++ b/mysql-test/r/range_icp_mrr.result
@@ -224,27 +224,27 @@ Table Op Msg_type Msg_text
test.t1 analyze status OK
explain select * from t1, t1 t2 where t1.y = 8 and t2.x between 7 and t1.y+0;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range y y 5 NULL 1 Using index condition; Using MRR
+1 SIMPLE t1 ref y y 5 const 1 NULL
1 SIMPLE t2 range x x 5 NULL 2 Using index condition; Using MRR; Using join buffer (Block Nested Loop)
explain select * from t1, t1 t2 where t1.y = 8 and t2.x >= 7 and t2.x <= t1.y+0;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range y y 5 NULL 1 Using index condition; Using MRR
+1 SIMPLE t1 ref y y 5 const 1 NULL
1 SIMPLE t2 range x x 5 NULL 2 Using index condition; Using MRR; Using join buffer (Block Nested Loop)
explain select * from t1, t1 t2 where t1.y = 2 and t2.x between t1.y-1 and t1.y+1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range y y 5 NULL 1 Using index condition; Using MRR
+1 SIMPLE t1 ref y y 5 const 1 NULL
1 SIMPLE t2 range x x 5 NULL 3 Using index condition; Using MRR; Using join buffer (Block Nested Loop)
explain select * from t1, t1 t2 where t1.y = 2 and t2.x >= t1.y-1 and t2.x <= t1.y+1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range y y 5 NULL 1 Using index condition; Using MRR
+1 SIMPLE t1 ref y y 5 const 1 NULL
1 SIMPLE t2 range x x 5 NULL 3 Using index condition; Using MRR; Using join buffer (Block Nested Loop)
explain select * from t1, t1 t2 where t1.y = 2 and t2.x between 0 and t1.y;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range y y 5 NULL 1 Using index condition; Using MRR
+1 SIMPLE t1 ref y y 5 const 1 NULL
1 SIMPLE t2 range x x 5 NULL 2 Using index condition; Using MRR; Using join buffer (Block Nested Loop)
explain select * from t1, t1 t2 where t1.y = 2 and t2.x >= 0 and t2.x <= t1.y;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range y y 5 NULL 1 Using index condition; Using MRR
+1 SIMPLE t1 ref y y 5 const 1 NULL
1 SIMPLE t2 range x x 5 NULL 2 Using index condition; Using MRR; Using join buffer (Block Nested Loop)
explain select count(*) from t1 where x in (1);
id select_type table type possible_keys key key_len ref rows Extra
@@ -326,8 +326,8 @@ KEY recount( owner, line )
INSERT into t1 (owner,id,columnid,line) values (11,15,15,1),(11,13,13,5);
SELECT id, columnid, tableid, content, showid, line, ordinal FROM t1 WHERE owner=11 AND ((columnid IN ( 15, 13, 14 ) AND line IN ( 1, 2, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 31 )) OR (columnid IN ( 13, 14 ) AND line IN ( 15 ))) LIMIT 0 , 30;
id columnid tableid content showid line ordinal
-15 15 1 188 1 1 0
13 13 1 188 1 5 0
+15 15 1 188 1 1 0
drop table t1;
create table t1 (id int(10) primary key);
insert into t1 values (1),(2),(3),(4),(5),(6),(7),(8),(9);
@@ -619,7 +619,7 @@ INSERT INTO t1 (a) VALUES
('111'),('222'),('222'),('222'),('222'),('444'),('aaa'),('AAA'),('bbb');
explain select * from t1 where a='aaa';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range a a 11 NULL 2 Using index condition; Using MRR
+1 SIMPLE t1 ref a a 11 const 2 Using index condition
explain select * from t1 where a=binary 'aaa';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range a a 11 NULL 2 Using index condition; Using MRR
@@ -708,8 +708,8 @@ WHERE s.oxrootid = 'd8c4177d09f8b11f5.52725521' AND
v.oxrootid ='d8c4177d09f8b11f5.52725521' AND
s.oxleft > v.oxleft AND s.oxleft < v.oxright;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE v range OXLEFT,OXRIGHT,OXROOTID OXROOTID 34 NULL 5 Using index condition; Using MRR
-1 SIMPLE s range OXLEFT,OXROOTID OXROOTID 34 NULL 5 Using index condition; Using where; Using MRR; Using join buffer (Block Nested Loop)
+1 SIMPLE v ref OXLEFT,OXRIGHT,OXROOTID OXROOTID 34 const 5 Using index condition
+1 SIMPLE s ref OXLEFT,OXROOTID OXROOTID 34 const 5 Using index condition; Using where
SELECT s.oxid FROM t1 v, t1 s
WHERE s.oxrootid = 'd8c4177d09f8b11f5.52725521' AND
v.oxrootid ='d8c4177d09f8b11f5.52725521' AND
@@ -1026,10 +1026,10 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range a a 13 NULL # Using index condition; Using MRR
explain select * from t2 where a between 'a' and 'a ';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range a a 13 NULL # Using index condition; Using MRR
+1 SIMPLE t2 ref a a 13 const # Using index condition
explain select * from t2 where a = 'a' or a='a ';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range a a 13 NULL # Using index condition; Using MRR
+1 SIMPLE t2 ref a a 13 const # Using index condition
update t1 set a='b' where a<>'a';
explain select * from t1 where a not between 'b' and 'b';
id select_type table type possible_keys key key_len ref rows Extra
@@ -1115,7 +1115,7 @@ Table Op Msg_type Msg_text
test.t1 analyze status OK
EXPLAIN SELECT * FROM t1 WHERE item='A1' AND started<='2005-12-01 24:00:00';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range PRIMARY PRIMARY 20 NULL 2 Using index condition; Using MRR
+1 SIMPLE t1 ref PRIMARY PRIMARY 20 const 2 Using index condition
Warnings:
Warning 1292 Incorrect datetime value: '2005-12-01 24:00:00' for column 'started' at row 1
Warning 1292 Incorrect datetime value: '2005-12-01 24:00:00' for column 'started' at row 1
@@ -1983,7 +1983,7 @@ INSERT INTO t2 VALUES (1, 1, 2);
# range estimates k is selected.
EXPLAIN SELECT * FROM t2 WHERE a = 1 AND b >= 2 AND c >= 2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range k,l,m,n k 5 NULL 66 Using index condition; Using where; Using MRR
+1 SIMPLE t2 ref k,l,m,n k 5 const 66 Using where
DROP TABLE t1, t2;
#
# BUG#11765831: 'RANGE ACCESS' MAY INCORRECTLY FILTER
diff --git a/mysql-test/r/range_mrr.result b/mysql-test/r/range_mrr.result
index 53bd403c82c..77f202ac6ff 100644
--- a/mysql-test/r/range_mrr.result
+++ b/mysql-test/r/range_mrr.result
@@ -224,27 +224,27 @@ Table Op Msg_type Msg_text
test.t1 analyze status OK
explain select * from t1, t1 t2 where t1.y = 8 and t2.x between 7 and t1.y+0;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range y y 5 NULL 1 Using where; Using MRR
+1 SIMPLE t1 ref y y 5 const 1 NULL
1 SIMPLE t2 range x x 5 NULL 2 Using where; Using MRR; Using join buffer (Block Nested Loop)
explain select * from t1, t1 t2 where t1.y = 8 and t2.x >= 7 and t2.x <= t1.y+0;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range y y 5 NULL 1 Using where; Using MRR
+1 SIMPLE t1 ref y y 5 const 1 NULL
1 SIMPLE t2 range x x 5 NULL 2 Using where; Using MRR; Using join buffer (Block Nested Loop)
explain select * from t1, t1 t2 where t1.y = 2 and t2.x between t1.y-1 and t1.y+1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range y y 5 NULL 1 Using where; Using MRR
+1 SIMPLE t1 ref y y 5 const 1 NULL
1 SIMPLE t2 range x x 5 NULL 3 Using where; Using MRR; Using join buffer (Block Nested Loop)
explain select * from t1, t1 t2 where t1.y = 2 and t2.x >= t1.y-1 and t2.x <= t1.y+1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range y y 5 NULL 1 Using where; Using MRR
+1 SIMPLE t1 ref y y 5 const 1 NULL
1 SIMPLE t2 range x x 5 NULL 3 Using where; Using MRR; Using join buffer (Block Nested Loop)
explain select * from t1, t1 t2 where t1.y = 2 and t2.x between 0 and t1.y;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range y y 5 NULL 1 Using where; Using MRR
+1 SIMPLE t1 ref y y 5 const 1 NULL
1 SIMPLE t2 range x x 5 NULL 2 Using where; Using MRR; Using join buffer (Block Nested Loop)
explain select * from t1, t1 t2 where t1.y = 2 and t2.x >= 0 and t2.x <= t1.y;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range y y 5 NULL 1 Using where; Using MRR
+1 SIMPLE t1 ref y y 5 const 1 NULL
1 SIMPLE t2 range x x 5 NULL 2 Using where; Using MRR; Using join buffer (Block Nested Loop)
explain select count(*) from t1 where x in (1);
id select_type table type possible_keys key key_len ref rows Extra
@@ -326,8 +326,8 @@ KEY recount( owner, line )
INSERT into t1 (owner,id,columnid,line) values (11,15,15,1),(11,13,13,5);
SELECT id, columnid, tableid, content, showid, line, ordinal FROM t1 WHERE owner=11 AND ((columnid IN ( 15, 13, 14 ) AND line IN ( 1, 2, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 31 )) OR (columnid IN ( 13, 14 ) AND line IN ( 15 ))) LIMIT 0 , 30;
id columnid tableid content showid line ordinal
-15 15 1 188 1 1 0
13 13 1 188 1 5 0
+15 15 1 188 1 1 0
drop table t1;
create table t1 (id int(10) primary key);
insert into t1 values (1),(2),(3),(4),(5),(6),(7),(8),(9);
@@ -619,7 +619,7 @@ INSERT INTO t1 (a) VALUES
('111'),('222'),('222'),('222'),('222'),('444'),('aaa'),('AAA'),('bbb');
explain select * from t1 where a='aaa';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range a a 11 NULL 2 Using where; Using MRR
+1 SIMPLE t1 ref a a 11 const 2 Using where
explain select * from t1 where a=binary 'aaa';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range a a 11 NULL 2 Using where; Using MRR
@@ -708,8 +708,8 @@ WHERE s.oxrootid = 'd8c4177d09f8b11f5.52725521' AND
v.oxrootid ='d8c4177d09f8b11f5.52725521' AND
s.oxleft > v.oxleft AND s.oxleft < v.oxright;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE v range OXLEFT,OXRIGHT,OXROOTID OXROOTID 34 NULL 5 Using where; Using MRR
-1 SIMPLE s range OXLEFT,OXROOTID OXROOTID 34 NULL 5 Using where; Using MRR; Using join buffer (Block Nested Loop)
+1 SIMPLE v ref OXLEFT,OXRIGHT,OXROOTID OXROOTID 34 const 5 Using where
+1 SIMPLE s ref OXLEFT,OXROOTID OXROOTID 34 const 5 Using where
SELECT s.oxid FROM t1 v, t1 s
WHERE s.oxrootid = 'd8c4177d09f8b11f5.52725521' AND
v.oxrootid ='d8c4177d09f8b11f5.52725521' AND
@@ -1026,10 +1026,10 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range a a 13 NULL # Using where; Using MRR
explain select * from t2 where a between 'a' and 'a ';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range a a 13 NULL # Using where; Using MRR
+1 SIMPLE t2 ref a a 13 const # Using where
explain select * from t2 where a = 'a' or a='a ';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range a a 13 NULL # Using where; Using MRR
+1 SIMPLE t2 ref a a 13 const # Using where
update t1 set a='b' where a<>'a';
explain select * from t1 where a not between 'b' and 'b';
id select_type table type possible_keys key key_len ref rows Extra
@@ -1115,7 +1115,7 @@ Table Op Msg_type Msg_text
test.t1 analyze status OK
EXPLAIN SELECT * FROM t1 WHERE item='A1' AND started<='2005-12-01 24:00:00';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range PRIMARY PRIMARY 20 NULL 2 Using where; Using MRR
+1 SIMPLE t1 ref PRIMARY PRIMARY 20 const 2 Using where
Warnings:
Warning 1292 Incorrect datetime value: '2005-12-01 24:00:00' for column 'started' at row 1
Warning 1292 Incorrect datetime value: '2005-12-01 24:00:00' for column 'started' at row 1
@@ -1983,7 +1983,7 @@ INSERT INTO t2 VALUES (1, 1, 2);
# range estimates k is selected.
EXPLAIN SELECT * FROM t2 WHERE a = 1 AND b >= 2 AND c >= 2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range k,l,m,n k 5 NULL 66 Using where; Using MRR
+1 SIMPLE t2 ref k,l,m,n k 5 const 66 Using where
DROP TABLE t1, t2;
#
# BUG#11765831: 'RANGE ACCESS' MAY INCORRECTLY FILTER
diff --git a/mysql-test/r/select_all.result b/mysql-test/r/select_all.result
index 0709621b817..4f76c62f66c 100644
--- a/mysql-test/r/select_all.result
+++ b/mysql-test/r/select_all.result
@@ -2363,7 +2363,7 @@ insert into t1 values (1,2), (2,2), (3,2), (4,2);
insert into t2 values (1,3), (2,3), (3,4), (4,4);
explain select * from t1 left join t2 on a=c where d in (4);
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range c,d d 5 NULL 2 Using index condition; Using MRR
+1 SIMPLE t2 ref c,d d 5 const 2 NULL
1 SIMPLE t1 ALL a NULL NULL NULL 4 Using where; Using join buffer (Block Nested Loop)
select * from t1 left join t2 on a=c where d in (4);
a b c d
@@ -2371,7 +2371,7 @@ a b c d
4 2 4 4
explain select * from t1 left join t2 on a=c where d = 4;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range c,d d 5 NULL 2 Using index condition; Using MRR
+1 SIMPLE t2 ref c,d d 5 const 2 NULL
1 SIMPLE t1 ALL a NULL NULL NULL 4 Using where; Using join buffer (Block Nested Loop)
select * from t1 left join t2 on a=c where d = 4;
a b c d
@@ -2718,7 +2718,7 @@ explain select straight_join DISTINCT t2.a,t2.b, t1.c from t1, t3, t2
where (t1.c=t2.a or (t1.c=t3.a and t2.a=t3.b)) and t1.b=556476786 and
t2.b like '%%' order by t2.b limit 0,1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range b,c b 5 NULL 1 Using index condition; Using MRR; Using temporary; Using filesort
+1 SIMPLE t1 ref b,c b 5 const 1 Using temporary; Using filesort
1 SIMPLE t3 index PRIMARY,a,b PRIMARY 8 NULL 2 Using index; Using join buffer (Block Nested Loop)
1 SIMPLE t2 ALL PRIMARY NULL NULL NULL 2 Range checked for each record (index map: 0x1)
DROP TABLE t1,t2,t3;
@@ -3540,7 +3540,7 @@ WHERE t1.id=2;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1 NULL
1 SIMPLE t2 const idx1 NULL NULL NULL 1 NULL
-1 SIMPLE t3 range idx1 idx1 5 NULL 3 Using index condition; Using MRR
+1 SIMPLE t3 ref idx1 idx1 5 const 3 NULL
SELECT * FROM t1 LEFT JOIN t2 ON t2.b=t1.a INNER JOIN t3 ON t3.d=t1.id
WHERE t1.id=2;
id a b c d e
@@ -3677,12 +3677,12 @@ COUNT(*)
2
EXPLAIN SELECT * FROM t1 WHERE ID_better=1 AND ID_with_null IS NULL;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx1,idx2 idx2 4 NULL 1 Using index condition; Using where; Using MRR
+1 SIMPLE t1 ref idx1,idx2 idx2 4 const 1 Using where
DROP INDEX idx1 ON t1;
CREATE UNIQUE INDEX idx1 ON t1(ID_with_null);
EXPLAIN SELECT * FROM t1 WHERE ID_better=1 AND ID_with_null IS NULL;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx1,idx2 idx2 4 NULL 1 Using index condition; Using where; Using MRR
+1 SIMPLE t1 ref idx1,idx2 idx2 4 const 1 Using where
DROP TABLE t1;
CREATE TABLE t1 (
ID1_with_null int NULL,
@@ -3714,34 +3714,34 @@ COUNT(*)
EXPLAIN SELECT * FROM t1
WHERE ID_better=1 AND ID1_with_null IS NULL AND ID2_with_null=3 ;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx1,idx2 idx2 4 NULL 1 Using index condition; Using where; Using MRR
+1 SIMPLE t1 ref idx1,idx2 idx2 4 const 1 Using where
EXPLAIN SELECT * FROM t1
WHERE ID_better=1 AND ID1_with_null=3 AND ID2_with_null=3 IS NULL ;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx1,idx2 idx2 4 NULL 1 Using index condition; Using where; Using MRR
+1 SIMPLE t1 ref idx1,idx2 idx2 4 const 1 Using where
EXPLAIN SELECT * FROM t1
WHERE ID_better=1 AND ID1_with_null IS NULL AND ID2_with_null IS NULL;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx1,idx2 idx2 4 NULL 1 Using index condition; Using where; Using MRR
+1 SIMPLE t1 ref idx1,idx2 idx2 4 const 1 Using where
DROP INDEX idx1 ON t1;
CREATE UNIQUE INDEX idx1 ON t1(ID1_with_null,ID2_with_null);
EXPLAIN SELECT * FROM t1
WHERE ID_better=1 AND ID1_with_null IS NULL AND ID2_with_null=3 ;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx1,idx2 idx2 4 NULL 1 Using index condition; Using where; Using MRR
+1 SIMPLE t1 ref idx1,idx2 idx2 4 const 1 Using where
EXPLAIN SELECT * FROM t1
WHERE ID_better=1 AND ID1_with_null=3 AND ID2_with_null IS NULL ;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx1,idx2 idx2 4 NULL 1 Using index condition; Using where; Using MRR
+1 SIMPLE t1 ref idx1,idx2 idx2 4 const 1 Using where
EXPLAIN SELECT * FROM t1
WHERE ID_better=1 AND ID1_with_null IS NULL AND ID2_with_null IS NULL;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx1,idx2 idx2 4 NULL 1 Using index condition; Using where; Using MRR
+1 SIMPLE t1 ref idx1,idx2 idx2 4 const 1 Using where
EXPLAIN SELECT * FROM t1
WHERE ID_better=1 AND ID1_with_null IS NULL AND
(ID2_with_null=1 OR ID2_with_null=2);
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx1,idx2 idx2 4 NULL 1 Using index condition; Using where; Using MRR
+1 SIMPLE t1 ref idx1,idx2 idx2 4 const 1 Using where
DROP TABLE t1;
CREATE TABLE t1 (a INT, ts TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, KEY ts(ts));
INSERT INTO t1 VALUES (30,"2006-01-03 23:00:00"), (31,"2006-01-03 23:00:00");
diff --git a/mysql-test/r/select_all_bka.result b/mysql-test/r/select_all_bka.result
index 7a2192973a7..0f411eb35ac 100644
--- a/mysql-test/r/select_all_bka.result
+++ b/mysql-test/r/select_all_bka.result
@@ -2364,7 +2364,7 @@ insert into t1 values (1,2), (2,2), (3,2), (4,2);
insert into t2 values (1,3), (2,3), (3,4), (4,4);
explain select * from t1 left join t2 on a=c where d in (4);
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range c,d d 5 NULL 2 Using index condition; Using MRR
+1 SIMPLE t2 ref c,d d 5 const 2 NULL
1 SIMPLE t1 ALL a NULL NULL NULL 4 Using where; Using join buffer (Block Nested Loop)
select * from t1 left join t2 on a=c where d in (4);
a b c d
@@ -2372,7 +2372,7 @@ a b c d
4 2 4 4
explain select * from t1 left join t2 on a=c where d = 4;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range c,d d 5 NULL 2 Using index condition; Using MRR
+1 SIMPLE t2 ref c,d d 5 const 2 NULL
1 SIMPLE t1 ALL a NULL NULL NULL 4 Using where; Using join buffer (Block Nested Loop)
select * from t1 left join t2 on a=c where d = 4;
a b c d
@@ -2719,7 +2719,7 @@ explain select straight_join DISTINCT t2.a,t2.b, t1.c from t1, t3, t2
where (t1.c=t2.a or (t1.c=t3.a and t2.a=t3.b)) and t1.b=556476786 and
t2.b like '%%' order by t2.b limit 0,1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range b,c b 5 NULL 1 Using index condition; Using MRR; Using temporary; Using filesort
+1 SIMPLE t1 ref b,c b 5 const 1 Using temporary; Using filesort
1 SIMPLE t3 index PRIMARY,a,b PRIMARY 8 NULL 2 Using index; Using join buffer (Block Nested Loop)
1 SIMPLE t2 ALL PRIMARY NULL NULL NULL 2 Range checked for each record (index map: 0x1)
DROP TABLE t1,t2,t3;
@@ -3541,7 +3541,7 @@ WHERE t1.id=2;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1 NULL
1 SIMPLE t2 const idx1 NULL NULL NULL 1 NULL
-1 SIMPLE t3 range idx1 idx1 5 NULL 3 Using index condition; Using MRR
+1 SIMPLE t3 ref idx1 idx1 5 const 3 NULL
SELECT * FROM t1 LEFT JOIN t2 ON t2.b=t1.a INNER JOIN t3 ON t3.d=t1.id
WHERE t1.id=2;
id a b c d e
@@ -3678,12 +3678,12 @@ COUNT(*)
2
EXPLAIN SELECT * FROM t1 WHERE ID_better=1 AND ID_with_null IS NULL;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx1,idx2 idx2 4 NULL 1 Using index condition; Using where; Using MRR
+1 SIMPLE t1 ref idx1,idx2 idx2 4 const 1 Using where
DROP INDEX idx1 ON t1;
CREATE UNIQUE INDEX idx1 ON t1(ID_with_null);
EXPLAIN SELECT * FROM t1 WHERE ID_better=1 AND ID_with_null IS NULL;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx1,idx2 idx2 4 NULL 1 Using index condition; Using where; Using MRR
+1 SIMPLE t1 ref idx1,idx2 idx2 4 const 1 Using where
DROP TABLE t1;
CREATE TABLE t1 (
ID1_with_null int NULL,
@@ -3715,34 +3715,34 @@ COUNT(*)
EXPLAIN SELECT * FROM t1
WHERE ID_better=1 AND ID1_with_null IS NULL AND ID2_with_null=3 ;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx1,idx2 idx2 4 NULL 1 Using index condition; Using where; Using MRR
+1 SIMPLE t1 ref idx1,idx2 idx2 4 const 1 Using where
EXPLAIN SELECT * FROM t1
WHERE ID_better=1 AND ID1_with_null=3 AND ID2_with_null=3 IS NULL ;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx1,idx2 idx2 4 NULL 1 Using index condition; Using where; Using MRR
+1 SIMPLE t1 ref idx1,idx2 idx2 4 const 1 Using where
EXPLAIN SELECT * FROM t1
WHERE ID_better=1 AND ID1_with_null IS NULL AND ID2_with_null IS NULL;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx1,idx2 idx2 4 NULL 1 Using index condition; Using where; Using MRR
+1 SIMPLE t1 ref idx1,idx2 idx2 4 const 1 Using where
DROP INDEX idx1 ON t1;
CREATE UNIQUE INDEX idx1 ON t1(ID1_with_null,ID2_with_null);
EXPLAIN SELECT * FROM t1
WHERE ID_better=1 AND ID1_with_null IS NULL AND ID2_with_null=3 ;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx1,idx2 idx2 4 NULL 1 Using index condition; Using where; Using MRR
+1 SIMPLE t1 ref idx1,idx2 idx2 4 const 1 Using where
EXPLAIN SELECT * FROM t1
WHERE ID_better=1 AND ID1_with_null=3 AND ID2_with_null IS NULL ;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx1,idx2 idx2 4 NULL 1 Using index condition; Using where; Using MRR
+1 SIMPLE t1 ref idx1,idx2 idx2 4 const 1 Using where
EXPLAIN SELECT * FROM t1
WHERE ID_better=1 AND ID1_with_null IS NULL AND ID2_with_null IS NULL;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx1,idx2 idx2 4 NULL 1 Using index condition; Using where; Using MRR
+1 SIMPLE t1 ref idx1,idx2 idx2 4 const 1 Using where
EXPLAIN SELECT * FROM t1
WHERE ID_better=1 AND ID1_with_null IS NULL AND
(ID2_with_null=1 OR ID2_with_null=2);
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx1,idx2 idx2 4 NULL 1 Using index condition; Using where; Using MRR
+1 SIMPLE t1 ref idx1,idx2 idx2 4 const 1 Using where
DROP TABLE t1;
CREATE TABLE t1 (a INT, ts TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, KEY ts(ts));
INSERT INTO t1 VALUES (30,"2006-01-03 23:00:00"), (31,"2006-01-03 23:00:00");
diff --git a/mysql-test/r/select_all_bka_nixbnl.result b/mysql-test/r/select_all_bka_nixbnl.result
index 6068f71ca58..c67da491f07 100644
--- a/mysql-test/r/select_all_bka_nixbnl.result
+++ b/mysql-test/r/select_all_bka_nixbnl.result
@@ -2364,7 +2364,7 @@ insert into t1 values (1,2), (2,2), (3,2), (4,2);
insert into t2 values (1,3), (2,3), (3,4), (4,4);
explain select * from t1 left join t2 on a=c where d in (4);
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range c,d d 5 NULL 2 Using index condition; Using where; Using MRR
+1 SIMPLE t2 ref c,d d 5 const 2 Using where
1 SIMPLE t1 ref a a 5 test.t2.c 2 Using join buffer (Batched Key Access)
select * from t1 left join t2 on a=c where d in (4);
a b c d
@@ -2372,7 +2372,7 @@ a b c d
4 2 4 4
explain select * from t1 left join t2 on a=c where d = 4;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range c,d d 5 NULL 2 Using index condition; Using where; Using MRR
+1 SIMPLE t2 ref c,d d 5 const 2 Using where
1 SIMPLE t1 ref a a 5 test.t2.c 2 Using join buffer (Batched Key Access)
select * from t1 left join t2 on a=c where d = 4;
a b c d
@@ -2719,7 +2719,7 @@ explain select straight_join DISTINCT t2.a,t2.b, t1.c from t1, t3, t2
where (t1.c=t2.a or (t1.c=t3.a and t2.a=t3.b)) and t1.b=556476786 and
t2.b like '%%' order by t2.b limit 0,1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range b,c b 5 NULL 1 Using index condition; Using MRR; Using temporary; Using filesort
+1 SIMPLE t1 ref b,c b 5 const 1 Using temporary; Using filesort
1 SIMPLE t3 index PRIMARY,a,b PRIMARY 8 NULL 2 Using index
1 SIMPLE t2 ALL PRIMARY NULL NULL NULL 2 Range checked for each record (index map: 0x1)
DROP TABLE t1,t2,t3;
@@ -3541,7 +3541,7 @@ WHERE t1.id=2;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1 NULL
1 SIMPLE t2 const idx1 NULL NULL NULL 1 NULL
-1 SIMPLE t3 range idx1 idx1 5 NULL 3 Using index condition; Using MRR
+1 SIMPLE t3 ref idx1 idx1 5 const 3 NULL
SELECT * FROM t1 LEFT JOIN t2 ON t2.b=t1.a INNER JOIN t3 ON t3.d=t1.id
WHERE t1.id=2;
id a b c d e
@@ -3678,12 +3678,12 @@ COUNT(*)
2
EXPLAIN SELECT * FROM t1 WHERE ID_better=1 AND ID_with_null IS NULL;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx1,idx2 idx2 4 NULL 1 Using index condition; Using where; Using MRR
+1 SIMPLE t1 ref idx1,idx2 idx2 4 const 1 Using where
DROP INDEX idx1 ON t1;
CREATE UNIQUE INDEX idx1 ON t1(ID_with_null);
EXPLAIN SELECT * FROM t1 WHERE ID_better=1 AND ID_with_null IS NULL;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx1,idx2 idx2 4 NULL 1 Using index condition; Using where; Using MRR
+1 SIMPLE t1 ref idx1,idx2 idx2 4 const 1 Using where
DROP TABLE t1;
CREATE TABLE t1 (
ID1_with_null int NULL,
@@ -3715,34 +3715,34 @@ COUNT(*)
EXPLAIN SELECT * FROM t1
WHERE ID_better=1 AND ID1_with_null IS NULL AND ID2_with_null=3 ;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx1,idx2 idx2 4 NULL 1 Using index condition; Using where; Using MRR
+1 SIMPLE t1 ref idx1,idx2 idx2 4 const 1 Using where
EXPLAIN SELECT * FROM t1
WHERE ID_better=1 AND ID1_with_null=3 AND ID2_with_null=3 IS NULL ;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx1,idx2 idx2 4 NULL 1 Using index condition; Using where; Using MRR
+1 SIMPLE t1 ref idx1,idx2 idx2 4 const 1 Using where
EXPLAIN SELECT * FROM t1
WHERE ID_better=1 AND ID1_with_null IS NULL AND ID2_with_null IS NULL;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx1,idx2 idx2 4 NULL 1 Using index condition; Using where; Using MRR
+1 SIMPLE t1 ref idx1,idx2 idx2 4 const 1 Using where
DROP INDEX idx1 ON t1;
CREATE UNIQUE INDEX idx1 ON t1(ID1_with_null,ID2_with_null);
EXPLAIN SELECT * FROM t1
WHERE ID_better=1 AND ID1_with_null IS NULL AND ID2_with_null=3 ;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx1,idx2 idx2 4 NULL 1 Using index condition; Using where; Using MRR
+1 SIMPLE t1 ref idx1,idx2 idx2 4 const 1 Using where
EXPLAIN SELECT * FROM t1
WHERE ID_better=1 AND ID1_with_null=3 AND ID2_with_null IS NULL ;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx1,idx2 idx2 4 NULL 1 Using index condition; Using where; Using MRR
+1 SIMPLE t1 ref idx1,idx2 idx2 4 const 1 Using where
EXPLAIN SELECT * FROM t1
WHERE ID_better=1 AND ID1_with_null IS NULL AND ID2_with_null IS NULL;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx1,idx2 idx2 4 NULL 1 Using index condition; Using where; Using MRR
+1 SIMPLE t1 ref idx1,idx2 idx2 4 const 1 Using where
EXPLAIN SELECT * FROM t1
WHERE ID_better=1 AND ID1_with_null IS NULL AND
(ID2_with_null=1 OR ID2_with_null=2);
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx1,idx2 idx2 4 NULL 1 Using index condition; Using where; Using MRR
+1 SIMPLE t1 ref idx1,idx2 idx2 4 const 1 Using where
DROP TABLE t1;
CREATE TABLE t1 (a INT, ts TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, KEY ts(ts));
INSERT INTO t1 VALUES (30,"2006-01-03 23:00:00"), (31,"2006-01-03 23:00:00");
diff --git a/mysql-test/r/select_icp_mrr.result b/mysql-test/r/select_icp_mrr.result
index d7cdd279f6c..f78aefbed7b 100644
--- a/mysql-test/r/select_icp_mrr.result
+++ b/mysql-test/r/select_icp_mrr.result
@@ -2363,7 +2363,7 @@ insert into t1 values (1,2), (2,2), (3,2), (4,2);
insert into t2 values (1,3), (2,3), (3,4), (4,4);
explain select * from t1 left join t2 on a=c where d in (4);
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range c,d d 5 NULL 2 Using index condition; Using MRR
+1 SIMPLE t2 ref c,d d 5 const 2 NULL
1 SIMPLE t1 ALL a NULL NULL NULL 4 Using where; Using join buffer (Block Nested Loop)
select * from t1 left join t2 on a=c where d in (4);
a b c d
@@ -2371,7 +2371,7 @@ a b c d
4 2 4 4
explain select * from t1 left join t2 on a=c where d = 4;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range c,d d 5 NULL 2 Using index condition; Using MRR
+1 SIMPLE t2 ref c,d d 5 const 2 NULL
1 SIMPLE t1 ALL a NULL NULL NULL 4 Using where; Using join buffer (Block Nested Loop)
select * from t1 left join t2 on a=c where d = 4;
a b c d
@@ -2718,7 +2718,7 @@ explain select straight_join DISTINCT t2.a,t2.b, t1.c from t1, t3, t2
where (t1.c=t2.a or (t1.c=t3.a and t2.a=t3.b)) and t1.b=556476786 and
t2.b like '%%' order by t2.b limit 0,1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range b,c b 5 NULL 1 Using index condition; Using MRR; Using temporary; Using filesort
+1 SIMPLE t1 ref b,c b 5 const 1 Using temporary; Using filesort
1 SIMPLE t3 index PRIMARY,a,b PRIMARY 8 NULL 2 Using index; Using join buffer (Block Nested Loop)
1 SIMPLE t2 ALL PRIMARY NULL NULL NULL 2 Range checked for each record (index map: 0x1)
DROP TABLE t1,t2,t3;
@@ -3540,7 +3540,7 @@ WHERE t1.id=2;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1 NULL
1 SIMPLE t2 const idx1 NULL NULL NULL 1 NULL
-1 SIMPLE t3 range idx1 idx1 5 NULL 3 Using index condition; Using MRR
+1 SIMPLE t3 ref idx1 idx1 5 const 3 NULL
SELECT * FROM t1 LEFT JOIN t2 ON t2.b=t1.a INNER JOIN t3 ON t3.d=t1.id
WHERE t1.id=2;
id a b c d e
@@ -3677,12 +3677,12 @@ COUNT(*)
2
EXPLAIN SELECT * FROM t1 WHERE ID_better=1 AND ID_with_null IS NULL;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx1,idx2 idx2 4 NULL 1 Using index condition; Using where; Using MRR
+1 SIMPLE t1 ref idx1,idx2 idx2 4 const 1 Using where
DROP INDEX idx1 ON t1;
CREATE UNIQUE INDEX idx1 ON t1(ID_with_null);
EXPLAIN SELECT * FROM t1 WHERE ID_better=1 AND ID_with_null IS NULL;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx1,idx2 idx2 4 NULL 1 Using index condition; Using where; Using MRR
+1 SIMPLE t1 ref idx1,idx2 idx2 4 const 1 Using where
DROP TABLE t1;
CREATE TABLE t1 (
ID1_with_null int NULL,
@@ -3714,34 +3714,34 @@ COUNT(*)
EXPLAIN SELECT * FROM t1
WHERE ID_better=1 AND ID1_with_null IS NULL AND ID2_with_null=3 ;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx1,idx2 idx2 4 NULL 1 Using index condition; Using where; Using MRR
+1 SIMPLE t1 ref idx1,idx2 idx2 4 const 1 Using where
EXPLAIN SELECT * FROM t1
WHERE ID_better=1 AND ID1_with_null=3 AND ID2_with_null=3 IS NULL ;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx1,idx2 idx2 4 NULL 1 Using index condition; Using where; Using MRR
+1 SIMPLE t1 ref idx1,idx2 idx2 4 const 1 Using where
EXPLAIN SELECT * FROM t1
WHERE ID_better=1 AND ID1_with_null IS NULL AND ID2_with_null IS NULL;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx1,idx2 idx2 4 NULL 1 Using index condition; Using where; Using MRR
+1 SIMPLE t1 ref idx1,idx2 idx2 4 const 1 Using where
DROP INDEX idx1 ON t1;
CREATE UNIQUE INDEX idx1 ON t1(ID1_with_null,ID2_with_null);
EXPLAIN SELECT * FROM t1
WHERE ID_better=1 AND ID1_with_null IS NULL AND ID2_with_null=3 ;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx1,idx2 idx2 4 NULL 1 Using index condition; Using where; Using MRR
+1 SIMPLE t1 ref idx1,idx2 idx2 4 const 1 Using where
EXPLAIN SELECT * FROM t1
WHERE ID_better=1 AND ID1_with_null=3 AND ID2_with_null IS NULL ;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx1,idx2 idx2 4 NULL 1 Using index condition; Using where; Using MRR
+1 SIMPLE t1 ref idx1,idx2 idx2 4 const 1 Using where
EXPLAIN SELECT * FROM t1
WHERE ID_better=1 AND ID1_with_null IS NULL AND ID2_with_null IS NULL;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx1,idx2 idx2 4 NULL 1 Using index condition; Using where; Using MRR
+1 SIMPLE t1 ref idx1,idx2 idx2 4 const 1 Using where
EXPLAIN SELECT * FROM t1
WHERE ID_better=1 AND ID1_with_null IS NULL AND
(ID2_with_null=1 OR ID2_with_null=2);
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx1,idx2 idx2 4 NULL 1 Using index condition; Using where; Using MRR
+1 SIMPLE t1 ref idx1,idx2 idx2 4 const 1 Using where
DROP TABLE t1;
CREATE TABLE t1 (a INT, ts TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, KEY ts(ts));
INSERT INTO t1 VALUES (30,"2006-01-03 23:00:00"), (31,"2006-01-03 23:00:00");
diff --git a/mysql-test/r/select_icp_mrr_bka.result b/mysql-test/r/select_icp_mrr_bka.result
index b77df1ca808..eb652487533 100644
--- a/mysql-test/r/select_icp_mrr_bka.result
+++ b/mysql-test/r/select_icp_mrr_bka.result
@@ -2364,7 +2364,7 @@ insert into t1 values (1,2), (2,2), (3,2), (4,2);
insert into t2 values (1,3), (2,3), (3,4), (4,4);
explain select * from t1 left join t2 on a=c where d in (4);
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range c,d d 5 NULL 2 Using index condition; Using MRR
+1 SIMPLE t2 ref c,d d 5 const 2 NULL
1 SIMPLE t1 ALL a NULL NULL NULL 4 Using where; Using join buffer (Block Nested Loop)
select * from t1 left join t2 on a=c where d in (4);
a b c d
@@ -2372,7 +2372,7 @@ a b c d
4 2 4 4
explain select * from t1 left join t2 on a=c where d = 4;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range c,d d 5 NULL 2 Using index condition; Using MRR
+1 SIMPLE t2 ref c,d d 5 const 2 NULL
1 SIMPLE t1 ALL a NULL NULL NULL 4 Using where; Using join buffer (Block Nested Loop)
select * from t1 left join t2 on a=c where d = 4;
a b c d
@@ -2719,7 +2719,7 @@ explain select straight_join DISTINCT t2.a,t2.b, t1.c from t1, t3, t2
where (t1.c=t2.a or (t1.c=t3.a and t2.a=t3.b)) and t1.b=556476786 and
t2.b like '%%' order by t2.b limit 0,1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range b,c b 5 NULL 1 Using index condition; Using MRR; Using temporary; Using filesort
+1 SIMPLE t1 ref b,c b 5 const 1 Using temporary; Using filesort
1 SIMPLE t3 index PRIMARY,a,b PRIMARY 8 NULL 2 Using index; Using join buffer (Block Nested Loop)
1 SIMPLE t2 ALL PRIMARY NULL NULL NULL 2 Range checked for each record (index map: 0x1)
DROP TABLE t1,t2,t3;
@@ -3541,7 +3541,7 @@ WHERE t1.id=2;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1 NULL
1 SIMPLE t2 const idx1 NULL NULL NULL 1 NULL
-1 SIMPLE t3 range idx1 idx1 5 NULL 3 Using index condition; Using MRR
+1 SIMPLE t3 ref idx1 idx1 5 const 3 NULL
SELECT * FROM t1 LEFT JOIN t2 ON t2.b=t1.a INNER JOIN t3 ON t3.d=t1.id
WHERE t1.id=2;
id a b c d e
@@ -3678,12 +3678,12 @@ COUNT(*)
2
EXPLAIN SELECT * FROM t1 WHERE ID_better=1 AND ID_with_null IS NULL;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx1,idx2 idx2 4 NULL 1 Using index condition; Using where; Using MRR
+1 SIMPLE t1 ref idx1,idx2 idx2 4 const 1 Using where
DROP INDEX idx1 ON t1;
CREATE UNIQUE INDEX idx1 ON t1(ID_with_null);
EXPLAIN SELECT * FROM t1 WHERE ID_better=1 AND ID_with_null IS NULL;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx1,idx2 idx2 4 NULL 1 Using index condition; Using where; Using MRR
+1 SIMPLE t1 ref idx1,idx2 idx2 4 const 1 Using where
DROP TABLE t1;
CREATE TABLE t1 (
ID1_with_null int NULL,
@@ -3715,34 +3715,34 @@ COUNT(*)
EXPLAIN SELECT * FROM t1
WHERE ID_better=1 AND ID1_with_null IS NULL AND ID2_with_null=3 ;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx1,idx2 idx2 4 NULL 1 Using index condition; Using where; Using MRR
+1 SIMPLE t1 ref idx1,idx2 idx2 4 const 1 Using where
EXPLAIN SELECT * FROM t1
WHERE ID_better=1 AND ID1_with_null=3 AND ID2_with_null=3 IS NULL ;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx1,idx2 idx2 4 NULL 1 Using index condition; Using where; Using MRR
+1 SIMPLE t1 ref idx1,idx2 idx2 4 const 1 Using where
EXPLAIN SELECT * FROM t1
WHERE ID_better=1 AND ID1_with_null IS NULL AND ID2_with_null IS NULL;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx1,idx2 idx2 4 NULL 1 Using index condition; Using where; Using MRR
+1 SIMPLE t1 ref idx1,idx2 idx2 4 const 1 Using where
DROP INDEX idx1 ON t1;
CREATE UNIQUE INDEX idx1 ON t1(ID1_with_null,ID2_with_null);
EXPLAIN SELECT * FROM t1
WHERE ID_better=1 AND ID1_with_null IS NULL AND ID2_with_null=3 ;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx1,idx2 idx2 4 NULL 1 Using index condition; Using where; Using MRR
+1 SIMPLE t1 ref idx1,idx2 idx2 4 const 1 Using where
EXPLAIN SELECT * FROM t1
WHERE ID_better=1 AND ID1_with_null=3 AND ID2_with_null IS NULL ;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx1,idx2 idx2 4 NULL 1 Using index condition; Using where; Using MRR
+1 SIMPLE t1 ref idx1,idx2 idx2 4 const 1 Using where
EXPLAIN SELECT * FROM t1
WHERE ID_better=1 AND ID1_with_null IS NULL AND ID2_with_null IS NULL;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx1,idx2 idx2 4 NULL 1 Using index condition; Using where; Using MRR
+1 SIMPLE t1 ref idx1,idx2 idx2 4 const 1 Using where
EXPLAIN SELECT * FROM t1
WHERE ID_better=1 AND ID1_with_null IS NULL AND
(ID2_with_null=1 OR ID2_with_null=2);
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx1,idx2 idx2 4 NULL 1 Using index condition; Using where; Using MRR
+1 SIMPLE t1 ref idx1,idx2 idx2 4 const 1 Using where
DROP TABLE t1;
CREATE TABLE t1 (a INT, ts TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, KEY ts(ts));
INSERT INTO t1 VALUES (30,"2006-01-03 23:00:00"), (31,"2006-01-03 23:00:00");
diff --git a/mysql-test/r/select_icp_mrr_bka_nixbnl.result b/mysql-test/r/select_icp_mrr_bka_nixbnl.result
index ff7819edbb7..cd592e0fc56 100644
--- a/mysql-test/r/select_icp_mrr_bka_nixbnl.result
+++ b/mysql-test/r/select_icp_mrr_bka_nixbnl.result
@@ -2364,7 +2364,7 @@ insert into t1 values (1,2), (2,2), (3,2), (4,2);
insert into t2 values (1,3), (2,3), (3,4), (4,4);
explain select * from t1 left join t2 on a=c where d in (4);
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range c,d d 5 NULL 2 Using index condition; Using where; Using MRR
+1 SIMPLE t2 ref c,d d 5 const 2 Using where
1 SIMPLE t1 ref a a 5 test.t2.c 2 Using join buffer (Batched Key Access)
select * from t1 left join t2 on a=c where d in (4);
a b c d
@@ -2372,7 +2372,7 @@ a b c d
4 2 4 4
explain select * from t1 left join t2 on a=c where d = 4;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range c,d d 5 NULL 2 Using index condition; Using where; Using MRR
+1 SIMPLE t2 ref c,d d 5 const 2 Using where
1 SIMPLE t1 ref a a 5 test.t2.c 2 Using join buffer (Batched Key Access)
select * from t1 left join t2 on a=c where d = 4;
a b c d
@@ -2719,7 +2719,7 @@ explain select straight_join DISTINCT t2.a,t2.b, t1.c from t1, t3, t2
where (t1.c=t2.a or (t1.c=t3.a and t2.a=t3.b)) and t1.b=556476786 and
t2.b like '%%' order by t2.b limit 0,1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range b,c b 5 NULL 1 Using index condition; Using MRR; Using temporary; Using filesort
+1 SIMPLE t1 ref b,c b 5 const 1 Using temporary; Using filesort
1 SIMPLE t3 index PRIMARY,a,b PRIMARY 8 NULL 2 Using index
1 SIMPLE t2 ALL PRIMARY NULL NULL NULL 2 Range checked for each record (index map: 0x1)
DROP TABLE t1,t2,t3;
@@ -3541,7 +3541,7 @@ WHERE t1.id=2;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1 NULL
1 SIMPLE t2 const idx1 NULL NULL NULL 1 NULL
-1 SIMPLE t3 range idx1 idx1 5 NULL 3 Using index condition; Using MRR
+1 SIMPLE t3 ref idx1 idx1 5 const 3 NULL
SELECT * FROM t1 LEFT JOIN t2 ON t2.b=t1.a INNER JOIN t3 ON t3.d=t1.id
WHERE t1.id=2;
id a b c d e
@@ -3678,12 +3678,12 @@ COUNT(*)
2
EXPLAIN SELECT * FROM t1 WHERE ID_better=1 AND ID_with_null IS NULL;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx1,idx2 idx2 4 NULL 1 Using index condition; Using where; Using MRR
+1 SIMPLE t1 ref idx1,idx2 idx2 4 const 1 Using where
DROP INDEX idx1 ON t1;
CREATE UNIQUE INDEX idx1 ON t1(ID_with_null);
EXPLAIN SELECT * FROM t1 WHERE ID_better=1 AND ID_with_null IS NULL;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx1,idx2 idx2 4 NULL 1 Using index condition; Using where; Using MRR
+1 SIMPLE t1 ref idx1,idx2 idx2 4 const 1 Using where
DROP TABLE t1;
CREATE TABLE t1 (
ID1_with_null int NULL,
@@ -3715,34 +3715,34 @@ COUNT(*)
EXPLAIN SELECT * FROM t1
WHERE ID_better=1 AND ID1_with_null IS NULL AND ID2_with_null=3 ;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx1,idx2 idx2 4 NULL 1 Using index condition; Using where; Using MRR
+1 SIMPLE t1 ref idx1,idx2 idx2 4 const 1 Using where
EXPLAIN SELECT * FROM t1
WHERE ID_better=1 AND ID1_with_null=3 AND ID2_with_null=3 IS NULL ;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx1,idx2 idx2 4 NULL 1 Using index condition; Using where; Using MRR
+1 SIMPLE t1 ref idx1,idx2 idx2 4 const 1 Using where
EXPLAIN SELECT * FROM t1
WHERE ID_better=1 AND ID1_with_null IS NULL AND ID2_with_null IS NULL;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx1,idx2 idx2 4 NULL 1 Using index condition; Using where; Using MRR
+1 SIMPLE t1 ref idx1,idx2 idx2 4 const 1 Using where
DROP INDEX idx1 ON t1;
CREATE UNIQUE INDEX idx1 ON t1(ID1_with_null,ID2_with_null);
EXPLAIN SELECT * FROM t1
WHERE ID_better=1 AND ID1_with_null IS NULL AND ID2_with_null=3 ;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx1,idx2 idx2 4 NULL 1 Using index condition; Using where; Using MRR
+1 SIMPLE t1 ref idx1,idx2 idx2 4 const 1 Using where
EXPLAIN SELECT * FROM t1
WHERE ID_better=1 AND ID1_with_null=3 AND ID2_with_null IS NULL ;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx1,idx2 idx2 4 NULL 1 Using index condition; Using where; Using MRR
+1 SIMPLE t1 ref idx1,idx2 idx2 4 const 1 Using where
EXPLAIN SELECT * FROM t1
WHERE ID_better=1 AND ID1_with_null IS NULL AND ID2_with_null IS NULL;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx1,idx2 idx2 4 NULL 1 Using index condition; Using where; Using MRR
+1 SIMPLE t1 ref idx1,idx2 idx2 4 const 1 Using where
EXPLAIN SELECT * FROM t1
WHERE ID_better=1 AND ID1_with_null IS NULL AND
(ID2_with_null=1 OR ID2_with_null=2);
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx1,idx2 idx2 4 NULL 1 Using index condition; Using where; Using MRR
+1 SIMPLE t1 ref idx1,idx2 idx2 4 const 1 Using where
DROP TABLE t1;
CREATE TABLE t1 (a INT, ts TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, KEY ts(ts));
INSERT INTO t1 VALUES (30,"2006-01-03 23:00:00"), (31,"2006-01-03 23:00:00");
diff --git a/mysql-test/r/subquery_all.result b/mysql-test/r/subquery_all.result
index bf7bf727917..1916b8ffd6c 100644
--- a/mysql-test/r/subquery_all.result
+++ b/mysql-test/r/subquery_all.result
@@ -1242,7 +1242,7 @@ create table t1 (id int not null auto_increment primary key, salary int, key(sal
insert into t1 (salary) values (100),(1000),(10000),(10),(500),(5000),(50000);
explain extended SELECT id FROM t1 where salary = (SELECT MAX(salary) FROM t1);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t1 range salary salary 5 NULL 1 100.00 Using where; Using MRR
+1 PRIMARY t1 ref salary salary 5 const 1 100.00 Using where
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
Warnings:
Note 1003 /* select#1 */ select `test`.`t1`.`id` AS `id` from `test`.`t1` where (`test`.`t1`.`salary` = (/* select#2 */ select max(`test`.`t1`.`salary`) from `test`.`t1`))
@@ -6274,7 +6274,7 @@ INSERT INTO t1 VALUES (3, 10), (2, 20), (7, 10), (5, 20);
EXPLAIN SELECT * FROM (SELECT * FROM t1 WHERE a=7) t;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2 NULL
-2 DERIVED t1 range a a 5 NULL 1 Using index condition; Using MRR
+2 DERIVED t1 ref a a 5 const 1 NULL
EXPLAIN SELECT * FROM t1 WHERE EXISTS (SELECT * FROM t1 WHERE a=7);
id select_type table type possible_keys key key_len ref rows Extra
@@ -6435,7 +6435,7 @@ INSERT INTO t1 VALUES (3, 10), (2, 20), (7, 10), (5, 20);
EXPLAIN SELECT * FROM (SELECT * FROM t1 WHERE a=7) t;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2 NULL
-2 DERIVED t1 range a a 5 NULL 1 Using index condition; Using MRR
+2 DERIVED t1 ref a a 5 const 1 NULL
EXPLAIN SELECT * FROM t1 WHERE EXISTS (SELECT * FROM t1 WHERE a=7);
id select_type table type possible_keys key key_len ref rows Extra
@@ -6714,7 +6714,7 @@ t1 AS t1f STRAIGHT_JOIN t3 AS t3f;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1f ALL NULL NULL NULL NULL 2 NULL
1 PRIMARY t3f index NULL col_varchar_key 9 NULL 3 Using index; Using join buffer (Block Nested Loop)
-2 DEPENDENT SUBQUERY t1s range col_int_key col_int_key 5 NULL 1 Using index condition; Using where; Using MRR
+2 DEPENDENT SUBQUERY t1s ref col_int_key col_int_key 5 const 1 Using where
2 DEPENDENT SUBQUERY t3s index NULL col_int_key 5 NULL 3 Using index; Using join buffer (Block Nested Loop)
DROP TABLE t1,t3;
#
diff --git a/mysql-test/r/subquery_all_bka.result b/mysql-test/r/subquery_all_bka.result
index 73e4edb14eb..99e3475ea24 100644
--- a/mysql-test/r/subquery_all_bka.result
+++ b/mysql-test/r/subquery_all_bka.result
@@ -1243,7 +1243,7 @@ create table t1 (id int not null auto_increment primary key, salary int, key(sal
insert into t1 (salary) values (100),(1000),(10000),(10),(500),(5000),(50000);
explain extended SELECT id FROM t1 where salary = (SELECT MAX(salary) FROM t1);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t1 range salary salary 5 NULL 1 100.00 Using where; Using MRR
+1 PRIMARY t1 ref salary salary 5 const 1 100.00 Using where
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
Warnings:
Note 1003 /* select#1 */ select `test`.`t1`.`id` AS `id` from `test`.`t1` where (`test`.`t1`.`salary` = (/* select#2 */ select max(`test`.`t1`.`salary`) from `test`.`t1`))
@@ -6275,7 +6275,7 @@ INSERT INTO t1 VALUES (3, 10), (2, 20), (7, 10), (5, 20);
EXPLAIN SELECT * FROM (SELECT * FROM t1 WHERE a=7) t;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2 NULL
-2 DERIVED t1 range a a 5 NULL 1 Using index condition; Using MRR
+2 DERIVED t1 ref a a 5 const 1 NULL
EXPLAIN SELECT * FROM t1 WHERE EXISTS (SELECT * FROM t1 WHERE a=7);
id select_type table type possible_keys key key_len ref rows Extra
@@ -6436,7 +6436,7 @@ INSERT INTO t1 VALUES (3, 10), (2, 20), (7, 10), (5, 20);
EXPLAIN SELECT * FROM (SELECT * FROM t1 WHERE a=7) t;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2 NULL
-2 DERIVED t1 range a a 5 NULL 1 Using index condition; Using MRR
+2 DERIVED t1 ref a a 5 const 1 NULL
EXPLAIN SELECT * FROM t1 WHERE EXISTS (SELECT * FROM t1 WHERE a=7);
id select_type table type possible_keys key key_len ref rows Extra
@@ -6715,7 +6715,7 @@ t1 AS t1f STRAIGHT_JOIN t3 AS t3f;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1f ALL NULL NULL NULL NULL 2 NULL
1 PRIMARY t3f index NULL col_varchar_key 9 NULL 3 Using index; Using join buffer (Block Nested Loop)
-2 DEPENDENT SUBQUERY t1s range col_int_key col_int_key 5 NULL 1 Using index condition; Using where; Using MRR
+2 DEPENDENT SUBQUERY t1s ref col_int_key col_int_key 5 const 1 Using where
2 DEPENDENT SUBQUERY t3s index NULL col_int_key 5 NULL 3 Using index; Using join buffer (Block Nested Loop)
DROP TABLE t1,t3;
#
diff --git a/mysql-test/r/subquery_all_bka_nixbnl.result b/mysql-test/r/subquery_all_bka_nixbnl.result
index fa97394b5e0..6e333e1f0aa 100644
--- a/mysql-test/r/subquery_all_bka_nixbnl.result
+++ b/mysql-test/r/subquery_all_bka_nixbnl.result
@@ -1243,7 +1243,7 @@ create table t1 (id int not null auto_increment primary key, salary int, key(sal
insert into t1 (salary) values (100),(1000),(10000),(10),(500),(5000),(50000);
explain extended SELECT id FROM t1 where salary = (SELECT MAX(salary) FROM t1);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t1 range salary salary 5 NULL 1 100.00 Using where; Using MRR
+1 PRIMARY t1 ref salary salary 5 const 1 100.00 Using where
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
Warnings:
Note 1003 /* select#1 */ select `test`.`t1`.`id` AS `id` from `test`.`t1` where (`test`.`t1`.`salary` = (/* select#2 */ select max(`test`.`t1`.`salary`) from `test`.`t1`))
@@ -6275,7 +6275,7 @@ INSERT INTO t1 VALUES (3, 10), (2, 20), (7, 10), (5, 20);
EXPLAIN SELECT * FROM (SELECT * FROM t1 WHERE a=7) t;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2 NULL
-2 DERIVED t1 range a a 5 NULL 1 Using index condition; Using MRR
+2 DERIVED t1 ref a a 5 const 1 NULL
EXPLAIN SELECT * FROM t1 WHERE EXISTS (SELECT * FROM t1 WHERE a=7);
id select_type table type possible_keys key key_len ref rows Extra
@@ -6436,7 +6436,7 @@ INSERT INTO t1 VALUES (3, 10), (2, 20), (7, 10), (5, 20);
EXPLAIN SELECT * FROM (SELECT * FROM t1 WHERE a=7) t;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2 NULL
-2 DERIVED t1 range a a 5 NULL 1 Using index condition; Using MRR
+2 DERIVED t1 ref a a 5 const 1 NULL
EXPLAIN SELECT * FROM t1 WHERE EXISTS (SELECT * FROM t1 WHERE a=7);
id select_type table type possible_keys key key_len ref rows Extra
@@ -6715,7 +6715,7 @@ t1 AS t1f STRAIGHT_JOIN t3 AS t3f;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1f ALL NULL NULL NULL NULL 2 NULL
1 PRIMARY t3f index NULL col_varchar_key 9 NULL 3 Using index
-2 DEPENDENT SUBQUERY t1s range col_int_key col_int_key 5 NULL 1 Using index condition; Using where; Using MRR
+2 DEPENDENT SUBQUERY t1s ref col_int_key col_int_key 5 const 1 Using where
2 DEPENDENT SUBQUERY t3s index NULL col_int_key 5 NULL 3 Using index
DROP TABLE t1,t3;
#
diff --git a/mysql-test/r/subquery_nomat_nosj.result b/mysql-test/r/subquery_nomat_nosj.result
index d7294392ff0..cfbaf0125b7 100644
--- a/mysql-test/r/subquery_nomat_nosj.result
+++ b/mysql-test/r/subquery_nomat_nosj.result
@@ -1242,7 +1242,7 @@ create table t1 (id int not null auto_increment primary key, salary int, key(sal
insert into t1 (salary) values (100),(1000),(10000),(10),(500),(5000),(50000);
explain extended SELECT id FROM t1 where salary = (SELECT MAX(salary) FROM t1);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t1 range salary salary 5 NULL 1 100.00 Using where; Using MRR
+1 PRIMARY t1 ref salary salary 5 const 1 100.00 Using where
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
Warnings:
Note 1003 /* select#1 */ select `test`.`t1`.`id` AS `id` from `test`.`t1` where (`test`.`t1`.`salary` = (/* select#2 */ select max(`test`.`t1`.`salary`) from `test`.`t1`))
@@ -6274,7 +6274,7 @@ INSERT INTO t1 VALUES (3, 10), (2, 20), (7, 10), (5, 20);
EXPLAIN SELECT * FROM (SELECT * FROM t1 WHERE a=7) t;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2 NULL
-2 DERIVED t1 range a a 5 NULL 1 Using index condition; Using MRR
+2 DERIVED t1 ref a a 5 const 1 NULL
EXPLAIN SELECT * FROM t1 WHERE EXISTS (SELECT * FROM t1 WHERE a=7);
id select_type table type possible_keys key key_len ref rows Extra
@@ -6435,7 +6435,7 @@ INSERT INTO t1 VALUES (3, 10), (2, 20), (7, 10), (5, 20);
EXPLAIN SELECT * FROM (SELECT * FROM t1 WHERE a=7) t;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2 NULL
-2 DERIVED t1 range a a 5 NULL 1 Using index condition; Using MRR
+2 DERIVED t1 ref a a 5 const 1 NULL
EXPLAIN SELECT * FROM t1 WHERE EXISTS (SELECT * FROM t1 WHERE a=7);
id select_type table type possible_keys key key_len ref rows Extra
@@ -6714,7 +6714,7 @@ t1 AS t1f STRAIGHT_JOIN t3 AS t3f;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1f ALL NULL NULL NULL NULL 2 NULL
1 PRIMARY t3f index NULL col_varchar_key 9 NULL 3 Using index; Using join buffer (Block Nested Loop)
-2 DEPENDENT SUBQUERY t1s range col_int_key col_int_key 5 NULL 1 Using index condition; Using where; Using MRR
+2 DEPENDENT SUBQUERY t1s ref col_int_key col_int_key 5 const 1 Using where
2 DEPENDENT SUBQUERY t3s index NULL col_int_key 5 NULL 3 Using index; Using join buffer (Block Nested Loop)
DROP TABLE t1,t3;
#
diff --git a/mysql-test/r/subquery_nomat_nosj_bka.result b/mysql-test/r/subquery_nomat_nosj_bka.result
index 712d01c6731..75bae58be9f 100644
--- a/mysql-test/r/subquery_nomat_nosj_bka.result
+++ b/mysql-test/r/subquery_nomat_nosj_bka.result
@@ -1243,7 +1243,7 @@ create table t1 (id int not null auto_increment primary key, salary int, key(sal
insert into t1 (salary) values (100),(1000),(10000),(10),(500),(5000),(50000);
explain extended SELECT id FROM t1 where salary = (SELECT MAX(salary) FROM t1);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t1 range salary salary 5 NULL 1 100.00 Using where; Using MRR
+1 PRIMARY t1 ref salary salary 5 const 1 100.00 Using where
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
Warnings:
Note 1003 /* select#1 */ select `test`.`t1`.`id` AS `id` from `test`.`t1` where (`test`.`t1`.`salary` = (/* select#2 */ select max(`test`.`t1`.`salary`) from `test`.`t1`))
@@ -6275,7 +6275,7 @@ INSERT INTO t1 VALUES (3, 10), (2, 20), (7, 10), (5, 20);
EXPLAIN SELECT * FROM (SELECT * FROM t1 WHERE a=7) t;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2 NULL
-2 DERIVED t1 range a a 5 NULL 1 Using index condition; Using MRR
+2 DERIVED t1 ref a a 5 const 1 NULL
EXPLAIN SELECT * FROM t1 WHERE EXISTS (SELECT * FROM t1 WHERE a=7);
id select_type table type possible_keys key key_len ref rows Extra
@@ -6436,7 +6436,7 @@ INSERT INTO t1 VALUES (3, 10), (2, 20), (7, 10), (5, 20);
EXPLAIN SELECT * FROM (SELECT * FROM t1 WHERE a=7) t;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2 NULL
-2 DERIVED t1 range a a 5 NULL 1 Using index condition; Using MRR
+2 DERIVED t1 ref a a 5 const 1 NULL
EXPLAIN SELECT * FROM t1 WHERE EXISTS (SELECT * FROM t1 WHERE a=7);
id select_type table type possible_keys key key_len ref rows Extra
@@ -6715,7 +6715,7 @@ t1 AS t1f STRAIGHT_JOIN t3 AS t3f;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1f ALL NULL NULL NULL NULL 2 NULL
1 PRIMARY t3f index NULL col_varchar_key 9 NULL 3 Using index; Using join buffer (Block Nested Loop)
-2 DEPENDENT SUBQUERY t1s range col_int_key col_int_key 5 NULL 1 Using index condition; Using where; Using MRR
+2 DEPENDENT SUBQUERY t1s ref col_int_key col_int_key 5 const 1 Using where
2 DEPENDENT SUBQUERY t3s index NULL col_int_key 5 NULL 3 Using index; Using join buffer (Block Nested Loop)
DROP TABLE t1,t3;
#
diff --git a/mysql-test/r/subquery_nomat_nosj_bka_nixbnl.result b/mysql-test/r/subquery_nomat_nosj_bka_nixbnl.result
index 649378133b0..5dc81ff69e4 100644
--- a/mysql-test/r/subquery_nomat_nosj_bka_nixbnl.result
+++ b/mysql-test/r/subquery_nomat_nosj_bka_nixbnl.result
@@ -1243,7 +1243,7 @@ create table t1 (id int not null auto_increment primary key, salary int, key(sal
insert into t1 (salary) values (100),(1000),(10000),(10),(500),(5000),(50000);
explain extended SELECT id FROM t1 where salary = (SELECT MAX(salary) FROM t1);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t1 range salary salary 5 NULL 1 100.00 Using where; Using MRR
+1 PRIMARY t1 ref salary salary 5 const 1 100.00 Using where
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
Warnings:
Note 1003 /* select#1 */ select `test`.`t1`.`id` AS `id` from `test`.`t1` where (`test`.`t1`.`salary` = (/* select#2 */ select max(`test`.`t1`.`salary`) from `test`.`t1`))
@@ -6275,7 +6275,7 @@ INSERT INTO t1 VALUES (3, 10), (2, 20), (7, 10), (5, 20);
EXPLAIN SELECT * FROM (SELECT * FROM t1 WHERE a=7) t;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2 NULL
-2 DERIVED t1 range a a 5 NULL 1 Using index condition; Using MRR
+2 DERIVED t1 ref a a 5 const 1 NULL
EXPLAIN SELECT * FROM t1 WHERE EXISTS (SELECT * FROM t1 WHERE a=7);
id select_type table type possible_keys key key_len ref rows Extra
@@ -6436,7 +6436,7 @@ INSERT INTO t1 VALUES (3, 10), (2, 20), (7, 10), (5, 20);
EXPLAIN SELECT * FROM (SELECT * FROM t1 WHERE a=7) t;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2 NULL
-2 DERIVED t1 range a a 5 NULL 1 Using index condition; Using MRR
+2 DERIVED t1 ref a a 5 const 1 NULL
EXPLAIN SELECT * FROM t1 WHERE EXISTS (SELECT * FROM t1 WHERE a=7);
id select_type table type possible_keys key key_len ref rows Extra
@@ -6715,7 +6715,7 @@ t1 AS t1f STRAIGHT_JOIN t3 AS t3f;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1f ALL NULL NULL NULL NULL 2 NULL
1 PRIMARY t3f index NULL col_varchar_key 9 NULL 3 Using index
-2 DEPENDENT SUBQUERY t1s range col_int_key col_int_key 5 NULL 1 Using index condition; Using where; Using MRR
+2 DEPENDENT SUBQUERY t1s ref col_int_key col_int_key 5 const 1 Using where
2 DEPENDENT SUBQUERY t3s index NULL col_int_key 5 NULL 3 Using index
DROP TABLE t1,t3;
#
diff --git a/mysql-test/r/subquery_sj_all.result b/mysql-test/r/subquery_sj_all.result
index e1c19cd33d4..15a1b675f3b 100644
--- a/mysql-test/r/subquery_sj_all.result
+++ b/mysql-test/r/subquery_sj_all.result
@@ -6240,7 +6240,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 ALL NULL NULL NULL NULL 2 Using join buffer (Block Nested Loop)
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 Using where; Using join buffer (Block Nested Loop)
2 MATERIALIZED t4 ALL NULL NULL NULL NULL 1 NULL
-2 MATERIALIZED t3 range uid uid 5 NULL 1 Using index condition; Using where; Using MRR; Using join buffer (Block Nested Loop)
+2 MATERIALIZED t3 ref uid uid 5 const 1 Using where
select t2.uid from t2, t1
where t1.uid in (select t4.uid from t4, t3 where t3.uid=1 and t4.uid=t3.fid)
and t2.uid=t1.fid;
@@ -6874,7 +6874,7 @@ explain select name from t2, t1
where t1.uid in (select t4.uid from t4, t3 where t3.uid=1 and t4.uid=t3.fid)
and t2.uid=t1.fid;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t3 range uid uid 5 NULL 4 Using index condition; Using where; Using MRR; Start temporary
+1 SIMPLE t3 ref uid uid 5 const 4 Using where; Start temporary
1 SIMPLE t4 eq_ref PRIMARY PRIMARY 4 test.t3.fid 1 Using index
1 SIMPLE t1 ref uid uid 5 test.t3.fid 2 Using where
1 SIMPLE t2 eq_ref PRIMARY PRIMARY 4 test.t1.fid 1 End temporary
@@ -7952,7 +7952,7 @@ WHERE t2.col_int_key = 1
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t4 ALL NULL NULL NULL NULL 2 Using where
1 SIMPLE <subquery2> eq_ref <auto_key> <auto_key> 9 test.t4.col_int_nokey,test.t4.col_varchar_key 1 NULL
-2 MATERIALIZED t2 range col_int_key col_int_key 5 NULL 3 Using index condition; Using where; Using MRR
+2 MATERIALIZED t2 ref col_int_key col_int_key 5 const 3 Using where
2 MATERIALIZED t1 ref col_varchar_key col_varchar_key 4 test.t2.col_varchar_key 2 Using index
SELECT *
FROM t4
@@ -8113,9 +8113,9 @@ AND grandparent1.col_int_key <> 3
);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
-2 DEPENDENT SUBQUERY grandparent1 range col_int_key col_int_key 4 NULL 12 Using index condition; Using where; Using MRR
+2 DEPENDENT SUBQUERY grandparent1 ref col_int_key col_int_key 4 func 2 Using index condition; Using where
2 DEPENDENT SUBQUERY <subquery3> eq_ref <auto_key> <auto_key> 8 test.grandparent1.col_int_nokey,test.grandparent1.col_int_nokey 1 NULL
-3 MATERIALIZED parent1 range col_int_key col_int_key 4 NULL 12 Using where; Using MRR
+3 MATERIALIZED parent1 ref col_int_key col_int_key 4 func 2 NULL
3 MATERIALIZED parent2 index col_int_key col_int_key 4 NULL 1 Using where; Using index; Using join buffer (Block Nested Loop)
explain format=json SELECT * FROM t3
WHERE g1 NOT IN
@@ -8146,7 +8146,7 @@ EXPLAIN
{
"table": {
"table_name": "grandparent1",
- "access_type": "range",
+ "access_type": "ref",
"possible_keys": [
"col_int_key"
],
@@ -8155,10 +8155,12 @@ EXPLAIN
"col_int_key"
],
"key_length": "4",
- "rows": 12,
+ "ref": [
+ "func"
+ ],
+ "rows": 2,
"filtered": 100,
"index_condition": "(`test`.`grandparent1`.`col_int_key` <> 3)",
- "using_MRR": true,
"attached_condition": "(((`test`.`grandparent1`.`col_int_key` = `test`.`grandparent1`.`col_int_nokey`) and (<cache>('8') = `test`.`grandparent1`.`col_int_nokey`)) and ((`test`.`grandparent1`.`col_int_nokey` is not null) and (`test`.`grandparent1`.`col_int_nokey` is not null)))"
}
},
@@ -8180,7 +8182,7 @@ EXPLAIN
{
"table": {
"table_name": "parent1",
- "access_type": "range",
+ "access_type": "ref",
"possible_keys": [
"col_int_key"
],
@@ -8189,10 +8191,11 @@ EXPLAIN
"col_int_key"
],
"key_length": "4",
- "rows": 12,
- "filtered": 100,
- "using_MRR": true,
- "attached_condition": "1"
+ "ref": [
+ "func"
+ ],
+ "rows": 2,
+ "filtered": 100
}
},
{
@@ -8325,7 +8328,7 @@ FROM t1
);
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 system PRIMARY,col_int_key NULL NULL NULL 1 NULL
-1 SIMPLE t1a range col_int_key col_int_key 4 NULL 1 Using index condition; Using MRR
+1 SIMPLE t1a ref col_int_key col_int_key 4 const 1 NULL
1 SIMPLE t1 ALL NULL NULL NULL NULL 4 Using where; FirstMatch(t1a); Using join buffer (Block Nested Loop)
1 SIMPLE t1b ALL NULL NULL NULL NULL 4 Using where; Using join buffer (Block Nested Loop)
SELECT t1a.*
@@ -10620,7 +10623,7 @@ EXPLAIN SELECT name FROM t2, t1
WHERE t1.uid IN (SELECT t4.uid FROM t4, t3 WHERE t3.uid=1 AND t4.uid=t3.fid)
AND t2.uid=t1.fid;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t3 range uid uid 5 NULL 4 Using index condition; Using where; Using MRR; Start temporary
+1 SIMPLE t3 ref uid uid 5 const 4 Using where; Start temporary
1 SIMPLE t4 eq_ref PRIMARY PRIMARY 4 test.t3.fid 1 Using index
1 SIMPLE t1 ALL uid NULL NULL NULL 11 Using where; End temporary; Using join buffer (Block Nested Loop)
1 SIMPLE t2 eq_ref PRIMARY PRIMARY 4 test.t1.fid 1 NULL
@@ -10647,7 +10650,7 @@ Handler_read_key 16
Handler_read_last 0
Handler_read_next 4
Handler_read_prev 0
-Handler_read_rnd 4
+Handler_read_rnd 0
Handler_read_rnd_next 12
DROP TABLE t1,t2,t3,t4;
# End of test for Bug#18194196
diff --git a/mysql-test/r/subquery_sj_all_bka.result b/mysql-test/r/subquery_sj_all_bka.result
index 0d921663cee..40a4e06a887 100644
--- a/mysql-test/r/subquery_sj_all_bka.result
+++ b/mysql-test/r/subquery_sj_all_bka.result
@@ -6243,7 +6243,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 ALL NULL NULL NULL NULL 2 Using join buffer (Block Nested Loop)
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 Using where; Using join buffer (Block Nested Loop)
2 MATERIALIZED t4 ALL NULL NULL NULL NULL 1 NULL
-2 MATERIALIZED t3 range uid uid 5 NULL 1 Using index condition; Using where; Using MRR; Using join buffer (Block Nested Loop)
+2 MATERIALIZED t3 ref uid uid 5 const 1 Using where; Using join buffer (Batched Key Access)
select t2.uid from t2, t1
where t1.uid in (select t4.uid from t4, t3 where t3.uid=1 and t4.uid=t3.fid)
and t2.uid=t1.fid;
@@ -6879,7 +6879,7 @@ explain select name from t2, t1
where t1.uid in (select t4.uid from t4, t3 where t3.uid=1 and t4.uid=t3.fid)
and t2.uid=t1.fid;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t3 range uid uid 5 NULL 4 Using index condition; Using where; Using MRR; Start temporary
+1 SIMPLE t3 ref uid uid 5 const 4 Using where; Start temporary
1 SIMPLE t4 eq_ref PRIMARY PRIMARY 4 test.t3.fid 1 Using index
1 SIMPLE t1 ref uid uid 5 test.t3.fid 2 Using where; Using join buffer (Batched Key Access)
1 SIMPLE t2 eq_ref PRIMARY PRIMARY 4 test.t1.fid 1 End temporary; Using join buffer (Batched Key Access)
@@ -7957,7 +7957,7 @@ WHERE t2.col_int_key = 1
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t4 ALL NULL NULL NULL NULL 2 Using where
1 SIMPLE <subquery2> eq_ref <auto_key> <auto_key> 9 test.t4.col_int_nokey,test.t4.col_varchar_key 1 NULL
-2 MATERIALIZED t2 range col_int_key col_int_key 5 NULL 3 Using index condition; Using where; Using MRR
+2 MATERIALIZED t2 ref col_int_key col_int_key 5 const 3 Using where
2 MATERIALIZED t1 ref col_varchar_key col_varchar_key 4 test.t2.col_varchar_key 2 Using index
SELECT *
FROM t4
@@ -8118,9 +8118,9 @@ AND grandparent1.col_int_key <> 3
);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
-2 DEPENDENT SUBQUERY grandparent1 range col_int_key col_int_key 4 NULL 12 Using index condition; Using where; Using MRR
+2 DEPENDENT SUBQUERY grandparent1 ref col_int_key col_int_key 4 func 2 Using index condition; Using where
2 DEPENDENT SUBQUERY <subquery3> eq_ref <auto_key> <auto_key> 8 test.grandparent1.col_int_nokey,test.grandparent1.col_int_nokey 1 NULL
-3 MATERIALIZED parent1 range col_int_key col_int_key 4 NULL 12 Using where; Using MRR
+3 MATERIALIZED parent1 ref col_int_key col_int_key 4 func 2 NULL
3 MATERIALIZED parent2 index col_int_key col_int_key 4 NULL 1 Using where; Using index; Using join buffer (Block Nested Loop)
explain format=json SELECT * FROM t3
WHERE g1 NOT IN
@@ -8151,7 +8151,7 @@ EXPLAIN
{
"table": {
"table_name": "grandparent1",
- "access_type": "range",
+ "access_type": "ref",
"possible_keys": [
"col_int_key"
],
@@ -8160,10 +8160,12 @@ EXPLAIN
"col_int_key"
],
"key_length": "4",
- "rows": 12,
+ "ref": [
+ "func"
+ ],
+ "rows": 2,
"filtered": 100,
"index_condition": "(`test`.`grandparent1`.`col_int_key` <> 3)",
- "using_MRR": true,
"attached_condition": "(((`test`.`grandparent1`.`col_int_key` = `test`.`grandparent1`.`col_int_nokey`) and (<cache>('8') = `test`.`grandparent1`.`col_int_nokey`)) and ((`test`.`grandparent1`.`col_int_nokey` is not null) and (`test`.`grandparent1`.`col_int_nokey` is not null)))"
}
},
@@ -8185,7 +8187,7 @@ EXPLAIN
{
"table": {
"table_name": "parent1",
- "access_type": "range",
+ "access_type": "ref",
"possible_keys": [
"col_int_key"
],
@@ -8194,10 +8196,11 @@ EXPLAIN
"col_int_key"
],
"key_length": "4",
- "rows": 12,
- "filtered": 100,
- "using_MRR": true,
- "attached_condition": "1"
+ "ref": [
+ "func"
+ ],
+ "rows": 2,
+ "filtered": 100
}
},
{
@@ -8330,7 +8333,7 @@ FROM t1
);
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 system PRIMARY,col_int_key NULL NULL NULL 1 NULL
-1 SIMPLE t1a range col_int_key col_int_key 4 NULL 1 Using index condition; Using MRR
+1 SIMPLE t1a ref col_int_key col_int_key 4 const 1 NULL
1 SIMPLE t1 ALL NULL NULL NULL NULL 4 Using where; FirstMatch(t1a); Using join buffer (Block Nested Loop)
1 SIMPLE t1b ALL NULL NULL NULL NULL 4 Using where; Using join buffer (Block Nested Loop)
SELECT t1a.*
@@ -10626,7 +10629,7 @@ EXPLAIN SELECT name FROM t2, t1
WHERE t1.uid IN (SELECT t4.uid FROM t4, t3 WHERE t3.uid=1 AND t4.uid=t3.fid)
AND t2.uid=t1.fid;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t3 range uid uid 5 NULL 4 Using index condition; Using where; Using MRR; Start temporary
+1 SIMPLE t3 ref uid uid 5 const 4 Using where; Start temporary
1 SIMPLE t4 eq_ref PRIMARY PRIMARY 4 test.t3.fid 1 Using index
1 SIMPLE t1 ALL uid NULL NULL NULL 11 Using where; End temporary; Using join buffer (Block Nested Loop)
1 SIMPLE t2 eq_ref PRIMARY PRIMARY 4 test.t1.fid 1 Using join buffer (Batched Key Access)
@@ -10653,7 +10656,7 @@ Handler_read_key 16
Handler_read_last 0
Handler_read_next 15
Handler_read_prev 0
-Handler_read_rnd 15
+Handler_read_rnd 11
Handler_read_rnd_next 12
DROP TABLE t1,t2,t3,t4;
# End of test for Bug#18194196
diff --git a/mysql-test/r/subquery_sj_all_bka_nixbnl.result b/mysql-test/r/subquery_sj_all_bka_nixbnl.result
index c54af1095d4..d2c62e5b707 100644
--- a/mysql-test/r/subquery_sj_all_bka_nixbnl.result
+++ b/mysql-test/r/subquery_sj_all_bka_nixbnl.result
@@ -6253,7 +6253,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 ALL NULL NULL NULL NULL 2 NULL
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 Using where
2 MATERIALIZED t4 ALL NULL NULL NULL NULL 1 NULL
-2 MATERIALIZED t3 range uid uid 5 NULL 1 Using index condition; Using where; Using MRR
+2 MATERIALIZED t3 ref uid uid 5 const 1 Using where; Using join buffer (Batched Key Access)
select t2.uid from t2, t1
where t1.uid in (select t4.uid from t4, t3 where t3.uid=1 and t4.uid=t3.fid)
and t2.uid=t1.fid;
@@ -6889,7 +6889,7 @@ explain select name from t2, t1
where t1.uid in (select t4.uid from t4, t3 where t3.uid=1 and t4.uid=t3.fid)
and t2.uid=t1.fid;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t3 range uid uid 5 NULL 4 Using index condition; Using where; Using MRR; Start temporary
+1 SIMPLE t3 ref uid uid 5 const 4 Using where; Start temporary
1 SIMPLE t4 eq_ref PRIMARY PRIMARY 4 test.t3.fid 1 Using index
1 SIMPLE t1 ref uid uid 5 test.t3.fid 2 Using where; Using join buffer (Batched Key Access)
1 SIMPLE t2 eq_ref PRIMARY PRIMARY 4 test.t1.fid 1 End temporary; Using join buffer (Batched Key Access)
@@ -7967,7 +7967,7 @@ WHERE t2.col_int_key = 1
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t4 ALL NULL NULL NULL NULL 2 Using where
1 SIMPLE <subquery2> eq_ref <auto_key> <auto_key> 9 test.t4.col_int_nokey,test.t4.col_varchar_key 1 NULL
-2 MATERIALIZED t2 range col_int_key col_int_key 5 NULL 3 Using index condition; Using where; Using MRR
+2 MATERIALIZED t2 ref col_int_key col_int_key 5 const 3 Using where
2 MATERIALIZED t1 ref col_varchar_key col_varchar_key 4 test.t2.col_varchar_key 2 Using index
SELECT *
FROM t4
@@ -8129,9 +8129,9 @@ AND grandparent1.col_int_key <> 3
);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
-2 DEPENDENT SUBQUERY grandparent1 range col_int_key col_int_key 4 NULL 12 Using index condition; Using where; Using MRR
+2 DEPENDENT SUBQUERY grandparent1 ref col_int_key col_int_key 4 func 2 Using index condition; Using where
2 DEPENDENT SUBQUERY <subquery3> eq_ref <auto_key> <auto_key> 8 test.grandparent1.col_int_nokey,test.grandparent1.col_int_nokey 1 NULL
-3 MATERIALIZED parent1 range col_int_key col_int_key 4 NULL 12 Using where; Using MRR
+3 MATERIALIZED parent1 ref col_int_key col_int_key 4 func 2 NULL
3 MATERIALIZED parent2 ref col_int_key col_int_key 4 test.parent1.col_int_nokey 2 Using index
explain format=json SELECT * FROM t3
WHERE g1 NOT IN
@@ -8162,7 +8162,7 @@ EXPLAIN
{
"table": {
"table_name": "grandparent1",
- "access_type": "range",
+ "access_type": "ref",
"possible_keys": [
"col_int_key"
],
@@ -8171,10 +8171,12 @@ EXPLAIN
"col_int_key"
],
"key_length": "4",
- "rows": 12,
+ "ref": [
+ "func"
+ ],
+ "rows": 2,
"filtered": 100,
"index_condition": "(`test`.`grandparent1`.`col_int_key` <> 3)",
- "using_MRR": true,
"attached_condition": "(((`test`.`grandparent1`.`col_int_key` = `test`.`grandparent1`.`col_int_nokey`) and (<cache>('8') = `test`.`grandparent1`.`col_int_nokey`)) and ((`test`.`grandparent1`.`col_int_nokey` is not null) and (`test`.`grandparent1`.`col_int_nokey` is not null)))"
}
},
@@ -8196,7 +8198,7 @@ EXPLAIN
{
"table": {
"table_name": "parent1",
- "access_type": "range",
+ "access_type": "ref",
"possible_keys": [
"col_int_key"
],
@@ -8205,10 +8207,11 @@ EXPLAIN
"col_int_key"
],
"key_length": "4",
- "rows": 12,
- "filtered": 100,
- "using_MRR": true,
- "attached_condition": "1"
+ "ref": [
+ "func"
+ ],
+ "rows": 2,
+ "filtered": 100
}
},
{
@@ -8342,7 +8345,7 @@ FROM t1
);
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 system PRIMARY,col_int_key NULL NULL NULL 1 NULL
-1 SIMPLE t1a range col_int_key col_int_key 4 NULL 1 Using index condition; Using MRR
+1 SIMPLE t1a ref col_int_key col_int_key 4 const 1 NULL
1 SIMPLE t1 ALL NULL NULL NULL NULL 4 Using where; FirstMatch(t1a)
1 SIMPLE t1b ALL NULL NULL NULL NULL 4 Using where
SELECT t1a.*
@@ -10635,7 +10638,7 @@ EXPLAIN SELECT name FROM t2, t1
WHERE t1.uid IN (SELECT t4.uid FROM t4, t3 WHERE t3.uid=1 AND t4.uid=t3.fid)
AND t2.uid=t1.fid;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t3 range uid uid 5 NULL 4 Using index condition; Using where; Using MRR; Start temporary
+1 SIMPLE t3 ref uid uid 5 const 4 Using where; Start temporary
1 SIMPLE t4 eq_ref PRIMARY PRIMARY 4 test.t3.fid 1 Using index
1 SIMPLE t1 ref uid uid 5 test.t3.fid 4 Using where; End temporary; Using join buffer (Batched Key Access)
1 SIMPLE t2 eq_ref PRIMARY PRIMARY 4 test.t1.fid 1 Using join buffer (Batched Key Access)
@@ -10662,7 +10665,7 @@ Handler_read_key 20
Handler_read_last 0
Handler_read_next 26
Handler_read_prev 0
-Handler_read_rnd 26
+Handler_read_rnd 22
Handler_read_rnd_next 0
DROP TABLE t1,t2,t3,t4;
# End of test for Bug#18194196
1
0
[Commits] 72055d6941d: MDEV-20371: Invalid reads at plan refinement stage: join->positions...
by psergey 16 Sep '19
by psergey 16 Sep '19
16 Sep '19
revision-id: 72055d6941d9e39e2b3672d2423811ce5ffde587 (mariadb-10.2.2-870-g72055d6941d)
parent(s): 2facb2d39b1ad46f3a739be5043e13ef94592dd4
author: Sergei Petrunia
committer: Sergei Petrunia
timestamp: 2019-09-16 14:42:24 +0300
message:
MDEV-20371: Invalid reads at plan refinement stage: join->positions...
(Backported to 10.2-compatiblity, build 22257)
best_access_path() is called from two optimization phases:
1. Plan choice phase, in choose_plan(). Here, the join prefix being
considered is in join->positions[]
2. Plan refinement stage, in fix_semijoin_strategies_for_picked_join_order
Here, the join prefix is in join->best_positions[]
It used to access join->positions[] from stage #2. This didnt cause any
valgrind or asan failures (as join->positions[] has been written-to before)
but the effect was similar to that of reading the random data:
The join prefix we've picked (in join->best_positions) could have
nothing in common with the join prefix that was last to be considered
(in join->positions).
---
sql/opt_subselect.cc | 26 ++++++++++++++++----------
sql/opt_subselect.h | 8 ++++++--
sql/sql_select.cc | 38 +++++++++++++++++++++++---------------
sql/sql_select.h | 8 +++++++-
4 files changed, 52 insertions(+), 28 deletions(-)
diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc
index b4350551461..522aa299658 100644
--- a/sql/opt_subselect.cc
+++ b/sql/opt_subselect.cc
@@ -454,11 +454,6 @@ bool find_eq_ref_candidate(TABLE *table, table_map sj_inner_tables);
static SJ_MATERIALIZATION_INFO *
at_sjmat_pos(const JOIN *join, table_map remaining_tables, const JOIN_TAB *tab,
uint idx, bool *loose_scan);
-void best_access_path(JOIN *join, JOIN_TAB *s,
- table_map remaining_tables, uint idx,
- bool disable_jbuf, double record_count,
- POSITION *pos, POSITION *loose_scan_pos);
-
static Item *create_subq_in_equalities(THD *thd, SJ_MATERIALIZATION_INFO *sjm,
Item_in_subselect *subq_pred);
static void remove_sj_conds(THD *thd, Item **tree);
@@ -2659,6 +2654,13 @@ void advance_sj_state(JOIN *join, table_map remaining_tables, uint idx,
NULL,
};
+#ifdef HAVE_valgrind
+ new (&pos->firstmatch_picker) Firstmatch_picker;
+ new (&pos->loosescan_picker) LooseScan_picker;
+ new (&pos->sjmat_picker) Sj_materialization_picker;
+ new (&pos->dups_weedout_picker) Duplicate_weedout_picker;
+#endif
+
if (join->emb_sjm_nest)
{
/*
@@ -2942,7 +2944,8 @@ bool Sj_materialization_picker::check_qep(JOIN *join,
bool disable_jbuf= (join->thd->variables.join_cache_level == 0);
for (i= first_tab + mat_info->tables; i <= idx; i++)
{
- best_access_path(join, join->positions[i].table, rem_tables, i,
+ best_access_path(join, join->positions[i].table, rem_tables,
+ join->positions, i,
disable_jbuf, prefix_rec_count, &curpos, &dummy);
prefix_rec_count *= curpos.records_read;
prefix_cost += curpos.read_time;
@@ -3555,7 +3558,8 @@ void fix_semijoin_strategies_for_picked_join_order(JOIN *join)
join->cur_sj_inner_tables= 0;
for (i= first + sjm->tables; i <= tablenr; i++)
{
- best_access_path(join, join->best_positions[i].table, rem_tables, i,
+ best_access_path(join, join->best_positions[i].table, rem_tables,
+ join->best_positions, i,
FALSE, prefix_rec_count,
join->best_positions + i, &dummy);
prefix_rec_count *= join->best_positions[i].records_read;
@@ -3587,8 +3591,9 @@ void fix_semijoin_strategies_for_picked_join_order(JOIN *join)
{
if (join->best_positions[idx].use_join_buffer)
{
- best_access_path(join, join->best_positions[idx].table,
- rem_tables, idx, TRUE /* no jbuf */,
+ best_access_path(join, join->best_positions[idx].table,
+ rem_tables, join->best_positions, idx,
+ TRUE /* no jbuf */,
record_count, join->best_positions + idx, &dummy);
}
record_count *= join->best_positions[idx].records_read;
@@ -3618,7 +3623,8 @@ void fix_semijoin_strategies_for_picked_join_order(JOIN *join)
if (join->best_positions[idx].use_join_buffer || (idx == first))
{
best_access_path(join, join->best_positions[idx].table,
- rem_tables, idx, TRUE /* no jbuf */,
+ rem_tables, join->best_positions, idx,
+ TRUE /* no jbuf */,
record_count, join->best_positions + idx,
&loose_scan_pos);
if (idx==first)
diff --git a/sql/opt_subselect.h b/sql/opt_subselect.h
index 7954becfad4..65d08bef2eb 100644
--- a/sql/opt_subselect.h
+++ b/sql/opt_subselect.h
@@ -88,6 +88,7 @@ class Loose_scan_opt
KEYUSE *best_loose_scan_start_key;
uint best_max_loose_keypart;
+ table_map best_ref_depend_map;
public:
Loose_scan_opt():
@@ -250,13 +251,14 @@ class Loose_scan_opt
best_loose_scan_records= records;
best_max_loose_keypart= max_loose_keypart;
best_loose_scan_start_key= start_key;
+ best_ref_depend_map= 0;
}
}
}
}
void check_ref_access_part2(uint key, KEYUSE *start_key, double records,
- double read_time)
+ double read_time, table_map ref_depend_map_arg)
{
if (part1_conds_met && read_time < best_loose_scan_cost)
{
@@ -266,6 +268,7 @@ class Loose_scan_opt
best_loose_scan_records= records;
best_max_loose_keypart= max_loose_keypart;
best_loose_scan_start_key= start_key;
+ best_ref_depend_map= ref_depend_map_arg;
}
}
@@ -281,6 +284,7 @@ class Loose_scan_opt
best_loose_scan_records= rows2double(quick->records);
best_max_loose_keypart= quick_max_loose_keypart;
best_loose_scan_start_key= NULL;
+ best_ref_depend_map= 0;
}
}
@@ -296,7 +300,7 @@ class Loose_scan_opt
pos->loosescan_picker.loosescan_parts= best_max_loose_keypart + 1;
pos->use_join_buffer= FALSE;
pos->table= tab;
- // todo need ref_depend_map ?
+ pos->ref_depend_map= best_ref_depend_map;
DBUG_PRINT("info", ("Produced a LooseScan plan, key %s, %s",
tab->table->key_info[best_loose_scan_key].name,
best_loose_scan_start_key? "(ref access)":
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index be2aeb52618..9bc47569f1a 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -97,10 +97,6 @@ static int sort_keyuse(KEYUSE *a,KEYUSE *b);
static bool are_tables_local(JOIN_TAB *jtab, table_map used_tables);
static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse,
bool allow_full_scan, table_map used_tables);
-void best_access_path(JOIN *join, JOIN_TAB *s,
- table_map remaining_tables, uint idx,
- bool disable_jbuf, double record_count,
- POSITION *pos, POSITION *loose_scan_pos);
static void optimize_straight_join(JOIN *join, table_map join_tables);
static bool greedy_search(JOIN *join, table_map remaining_tables,
uint depth, uint prune_level,
@@ -4573,6 +4569,13 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
{
if (choose_plan(join, all_table_map & ~join->const_table_map))
goto error;
+
+#ifdef HAVE_valgrind
+ // JOIN::positions holds the current query plan. We've already
+ // made the plan choice, so we should only use JOIN::best_positions
+ for (uint k=join->const_tables; k < join->table_count; k++)
+ MEM_UNDEFINED(&join->positions[k], sizeof(join->positions[k]));
+#endif
}
else
{
@@ -6288,6 +6291,7 @@ void
best_access_path(JOIN *join,
JOIN_TAB *s,
table_map remaining_tables,
+ const POSITION *join_positions,
uint idx,
bool disable_jbuf,
double record_count,
@@ -6391,7 +6395,7 @@ best_access_path(JOIN *join,
if (!(keyuse->used_tables & ~join->const_table_map))
const_part|= keyuse->keypart_map;
- double tmp2= prev_record_reads(join->positions, idx,
+ double tmp2= prev_record_reads(join_positions, idx,
(found_ref | keyuse->used_tables));
if (tmp2 < best_prev_record_reads)
{
@@ -6432,7 +6436,7 @@ best_access_path(JOIN *join,
Really, there should be records=0.0 (yes!)
but 1.0 would be probably safer
*/
- tmp= prev_record_reads(join->positions, idx, found_ref);
+ tmp= prev_record_reads(join_positions, idx, found_ref);
records= 1.0;
}
else
@@ -6448,7 +6452,7 @@ best_access_path(JOIN *join,
if ((key_flags & (HA_NOSAME | HA_NULL_PART_KEY)) == HA_NOSAME ||
MY_TEST(key_flags & HA_EXT_NOSAME))
{
- tmp = prev_record_reads(join->positions, idx, found_ref);
+ tmp = prev_record_reads(join_positions, idx, found_ref);
records=1.0;
}
else
@@ -6692,7 +6696,8 @@ best_access_path(JOIN *join,
}
tmp += s->startup_cost;
- loose_scan_opt.check_ref_access_part2(key, start_key, records, tmp);
+ loose_scan_opt.check_ref_access_part2(key, start_key, records, tmp,
+ found_ref);
} /* not ft_key */
if (tmp + 0.0001 < best_time - records/(double) TIME_FOR_COMPARE)
{
@@ -7364,7 +7369,8 @@ optimize_straight_join(JOIN *join, table_map join_tables)
for (JOIN_TAB **pos= join->best_ref + idx ; (s= *pos) ; pos++)
{
/* Find the best access method from 's' to the current partial plan */
- best_access_path(join, s, join_tables, idx, disable_jbuf, record_count,
+ best_access_path(join, s, join_tables, join->positions, idx,
+ disable_jbuf, record_count,
join->positions + idx, &loose_scan_pos);
/* compute the cost of the new plan extended with 's' */
@@ -8270,8 +8276,9 @@ best_extension_by_limited_search(JOIN *join,
/* Find the best access method from 's' to the current partial plan */
POSITION loose_scan_pos;
- best_access_path(join, s, remaining_tables, idx, disable_jbuf,
- record_count, join->positions + idx, &loose_scan_pos);
+ best_access_path(join, s, remaining_tables, join->positions, idx,
+ disable_jbuf, record_count, join->positions + idx,
+ &loose_scan_pos);
/* Compute the cost of extending the plan with 's', avoid overflow */
if (position->records_read < DBL_MAX / record_count)
@@ -8654,11 +8661,11 @@ cache_record_length(JOIN *join,uint idx)
*/
double
-prev_record_reads(POSITION *positions, uint idx, table_map found_ref)
+prev_record_reads(const POSITION *positions, uint idx, table_map found_ref)
{
double found=1.0;
- POSITION *pos_end= positions - 1;
- for (POSITION *pos= positions + idx - 1; pos != pos_end; pos--)
+ const POSITION *pos_end= positions - 1;
+ for (const POSITION *pos= positions + idx - 1; pos != pos_end; pos--)
{
if (pos->table->table->map & found_ref)
{
@@ -15560,7 +15567,8 @@ void optimize_wo_join_buffering(JOIN *join, uint first_tab, uint last_tab,
if ((i == first_tab && first_alt) || join->positions[i].use_join_buffer)
{
/* Find the best access method that would not use join buffering */
- best_access_path(join, rs, reopt_remaining_tables, i,
+ best_access_path(join, rs, reopt_remaining_tables,
+ join->positions, i,
TRUE, rec_count,
&pos, &loose_scan_pos);
}
diff --git a/sql/sql_select.h b/sql/sql_select.h
index eb78f4216f9..98fbb1f4d5b 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -794,6 +794,7 @@ class LooseScan_picker : public Semi_join_strategy_picker
friend void best_access_path(JOIN *join,
JOIN_TAB *s,
table_map remaining_tables,
+ const struct st_position *join_positions,
uint idx,
bool disable_jbuf,
double record_count,
@@ -1970,6 +1971,11 @@ class store_key_const_item :public store_key_item
}
};
+void best_access_path(JOIN *join, JOIN_TAB *s,
+ table_map remaining_tables,
+ const POSITION *join_positions, uint idx,
+ bool disable_jbuf, double record_count,
+ POSITION *pos, POSITION *loose_scan_pos);
bool cp_buffer_from_ref(THD *thd, TABLE *table, TABLE_REF *ref);
bool error_if_full_join(JOIN *join);
int report_error(TABLE *table, int error);
@@ -2334,7 +2340,7 @@ bool instantiate_tmp_table(TABLE *table, KEY *keyinfo,
ulonglong options);
bool open_tmp_table(TABLE *table);
void setup_tmp_table_column_bitmaps(TABLE *table, uchar *bitmaps);
-double prev_record_reads(POSITION *positions, uint idx, table_map found_ref);
+double prev_record_reads(const POSITION *positions, uint idx, table_map found_ref);
void fix_list_after_tbl_changes(SELECT_LEX *new_parent, List<TABLE_LIST> *tlist);
struct st_cond_statistic
1
0
[Commits] 2facb2d39b1: MDEV-20109: Optimizer ignores distinct key created for materialized...
by psergey 16 Sep '19
by psergey 16 Sep '19
16 Sep '19
revision-id: 2facb2d39b1ad46f3a739be5043e13ef94592dd4 (mariadb-10.2.2-869-g2facb2d39b1)
parent(s): 0febf64e75bcc746a00764e681d87e6aa10bd486
author: Sergei Petrunia
committer: Sergei Petrunia
timestamp: 2019-09-16 14:15:00 +0300
message:
MDEV-20109: Optimizer ignores distinct key created for materialized...
(Backported to 10.2-compatiblity, build 22257)
Adjust the testcase according to the review input
---
mysql-test/r/subselect_sj.result | 2 +-
mysql-test/r/subselect_sj_jcl6.result | 2 +-
mysql-test/t/subselect_sj.test | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/mysql-test/r/subselect_sj.result b/mysql-test/r/subselect_sj.result
index ad6af0340ed..bd81d5cfa4a 100644
--- a/mysql-test/r/subselect_sj.result
+++ b/mysql-test/r/subselect_sj.result
@@ -3184,7 +3184,7 @@ insert into t4 select floor(rand()*1000) from t2 limit 500;
# | 1 | PRIMARY | t3 | ALL | NULL | ... | 10000 | Using where; Using join buffer (flat, BNL join) |
#
# Instead, it should use eq_ref on the materialized table.
-explain select * from t3 where a in (select a from t4 group by a);
+explain select * from t3 where a in (select a from t4);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t3 ALL NULL NULL NULL NULL 10000
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
diff --git a/mysql-test/r/subselect_sj_jcl6.result b/mysql-test/r/subselect_sj_jcl6.result
index 785c687402c..ba6f0c5a13e 100644
--- a/mysql-test/r/subselect_sj_jcl6.result
+++ b/mysql-test/r/subselect_sj_jcl6.result
@@ -3197,7 +3197,7 @@ insert into t4 select floor(rand()*1000) from t2 limit 500;
# | 1 | PRIMARY | t3 | ALL | NULL | ... | 10000 | Using where; Using join buffer (flat, BNL join) |
#
# Instead, it should use eq_ref on the materialized table.
-explain select * from t3 where a in (select a from t4 group by a);
+explain select * from t3 where a in (select a from t4);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t3 ALL NULL NULL NULL NULL 10000
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
diff --git a/mysql-test/t/subselect_sj.test b/mysql-test/t/subselect_sj.test
index d29dd998d23..49093190b24 100644
--- a/mysql-test/t/subselect_sj.test
+++ b/mysql-test/t/subselect_sj.test
@@ -2867,7 +2867,7 @@ insert into t4 select floor(rand()*1000) from t2 limit 500;
--echo #
--echo # Instead, it should use eq_ref on the materialized table.
-explain select * from t3 where a in (select a from t4 group by a);
+explain select * from t3 where a in (select a from t4);
drop table t1, t2, t3, t4;
1
0
[Commits] 0febf64e75b: MDEV-20109: Optimizer ignores distinct key created for materialized...
by psergey 16 Sep '19
by psergey 16 Sep '19
16 Sep '19
revision-id: 0febf64e75bcc746a00764e681d87e6aa10bd486 (mariadb-10.2.2-868-g0febf64e75b)
parent(s): 5aeaba11c7dcbda40fd9cd68ab060a446ab6eb77
author: Sergei Petrunia
committer: Sergei Petrunia
timestamp: 2019-09-16 14:09:46 +0300
message:
MDEV-20109: Optimizer ignores distinct key created for materialized...
(Backported to 10.3, addressed review input)
(Backported to 10.2-compatiblity, build 22257)
Sj_materialization_picker::check_qep(): fix error in cost/fanout
calculations:
- for each join prefix, add #prefix_rows / TIME_FOR_COMPARE to the cost,
like best_extension_by_limited_search does
- Remove the fanout produced by the subquery tables.
- Also take into account join condition selectivity
optimize_wo_join_buffering() (used by LooseScan and FirstMatch)
- also add #prefix_rows / TIME_FOR_COMPARE to the cost of each prefix.
- Also take into account join condition selectivity
---
mysql-test/r/analyze_stmt_privileges2.result | 142 +++++++++++-----------
mysql-test/r/cte_nonrecursive.result | 24 ++--
mysql-test/r/group_by.result | 3 +-
mysql-test/r/index_merge_myisam.result | 5 +-
mysql-test/r/innodb_ext_key.result | 8 +-
mysql-test/r/subselect.result | 8 +-
mysql-test/r/subselect3.result | 18 +--
mysql-test/r/subselect3_jcl6.result | 20 +--
mysql-test/r/subselect_mat.result | 4 +-
mysql-test/r/subselect_no_mat.result | 10 +-
mysql-test/r/subselect_no_scache.result | 8 +-
mysql-test/r/subselect_sj.result | 83 ++++++++-----
mysql-test/r/subselect_sj2.result | 18 +--
mysql-test/r/subselect_sj2_jcl6.result | 22 ++--
mysql-test/r/subselect_sj2_mat.result | 30 ++---
mysql-test/r/subselect_sj_jcl6.result | 62 +++++++---
mysql-test/r/subselect_sj_mat.result | 10 +-
mysql-test/suite/gcol/r/gcol_select_innodb.result | 8 +-
mysql-test/suite/gcol/r/gcol_select_myisam.result | 8 +-
mysql-test/t/subselect_sj.test | 26 ++++
sql/opt_subselect.cc | 5 +-
sql/sql_class.h | 5 +-
sql/sql_select.cc | 13 ++
23 files changed, 320 insertions(+), 220 deletions(-)
diff --git a/mysql-test/r/analyze_stmt_privileges2.result b/mysql-test/r/analyze_stmt_privileges2.result
index 892791dd8f8..d95a9b6ce80 100644
--- a/mysql-test/r/analyze_stmt_privileges2.result
+++ b/mysql-test/r/analyze_stmt_privileges2.result
@@ -376,13 +376,13 @@ SELECT * FROM t1 WHERE a IN ( SELECT a FROM t2 );
a b
EXPLAIN SELECT * FROM t1 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3
-1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 4
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3
ANALYZE SELECT * FROM t1 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3 3.00 100.00 100.00
-1 PRIMARY t1 ALL NULL NULL NULL NULL 4 4.00 100.00 0.00 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 4 4.00 100.00 100.00
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 0.00 100.00 100.00
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 3.00 100.00 100.00
#------------------------------------------------------------------------
# I/R/U/D/S on the inner view
@@ -491,14 +491,14 @@ SELECT * FROM v1 WHERE a IN ( SELECT a FROM t2 );
a b
EXPLAIN SELECT * FROM v1 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3
-1 PRIMARY t1 ALL NULL NULL NULL NULL 8 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 8 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3
ANALYZE SELECT * FROM v1 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3 3.00 100.00 100.00
-1 PRIMARY t1 ALL NULL NULL NULL NULL 8 8.00 100.00 0.00 Using where; Using join buffer (flat, BNL join)
-2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 3.00 100.00 100.00
+1 PRIMARY t1 ALL NULL NULL NULL NULL 8 8.00 100.00 0.00 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 NULL 100.00 NULL
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 NULL 100.00 NULL
#------------------------------------------------------------------------
# I/R/U/D/S on the outer view
# Expectation: Can run everything
@@ -598,14 +598,14 @@ SELECT * FROM v2 WHERE a IN ( SELECT a FROM t2 );
a b
EXPLAIN SELECT * FROM v2 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3
-1 PRIMARY t1 ALL NULL NULL NULL NULL 12 Using where; Using join buffer (flat, BNL join)
-2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 12 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3
ANALYZE SELECT * FROM v2 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3 3.00 100.00 100.00
-1 PRIMARY t1 ALL NULL NULL NULL NULL 12 12.00 100.00 0.00 Using where; Using join buffer (flat, BNL join)
-2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 3.00 100.00 100.00 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 12 12.00 100.00 0.00 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 NULL 100.00 NULL
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 NULL 100.00 NULL
#========================================================================
# Test: Grant INSERT on the table
@@ -1591,14 +1591,14 @@ SELECT * FROM v1 WHERE a IN ( SELECT a FROM t2 );
a b
EXPLAIN SELECT * FROM v1 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3
-1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3
ANALYZE SELECT * FROM v1 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3 3.00 100.00 100.00
-1 PRIMARY t1 ALL NULL NULL NULL NULL 4 4.00 100.00 0.00 Using where; Using join buffer (flat, BNL join)
-2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 3.00 100.00 100.00
+1 PRIMARY t1 ALL NULL NULL NULL NULL 4 4.00 100.00 0.00 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 NULL 100.00 NULL
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 NULL 100.00 NULL
#------------------------------------------------------------------------
# I/R/U/D/S on the outer view
# Expectation: Can run everything: SELECT access to the column `a`
@@ -1708,14 +1708,14 @@ SELECT * FROM v2 WHERE a IN ( SELECT a FROM t2 );
a b
EXPLAIN SELECT * FROM v2 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3
-1 PRIMARY t1 ALL NULL NULL NULL NULL 8 Using where; Using join buffer (flat, BNL join)
-2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 8 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3
ANALYZE SELECT * FROM v2 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3 3.00 100.00 100.00
-1 PRIMARY t1 ALL NULL NULL NULL NULL 8 8.00 100.00 0.00 Using where; Using join buffer (flat, BNL join)
-2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 3.00 100.00 100.00 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 8 8.00 100.00 0.00 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 NULL 100.00 NULL
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 NULL 100.00 NULL
#========================================================================
# Test: Grant SELECT, INSERT, UPDATE, DELETE on the table
@@ -1940,14 +1940,14 @@ SELECT * FROM v1 WHERE a IN ( SELECT a FROM t2 );
a b
EXPLAIN SELECT * FROM v1 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3
-1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3
ANALYZE SELECT * FROM v1 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3 3.00 100.00 100.00
-1 PRIMARY t1 ALL NULL NULL NULL NULL 4 4.00 100.00 0.00 Using where; Using join buffer (flat, BNL join)
-2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 3.00 100.00 100.00
+1 PRIMARY t1 ALL NULL NULL NULL NULL 4 4.00 100.00 0.00 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 NULL 100.00 NULL
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 NULL 100.00 NULL
#------------------------------------------------------------------------
# I/R/U/D/S on the outer view
# Expectation: Can run everything
@@ -2048,14 +2048,14 @@ SELECT * FROM v2 WHERE a IN ( SELECT a FROM t2 );
a b
EXPLAIN SELECT * FROM v2 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3
-1 PRIMARY t1 ALL NULL NULL NULL NULL 8 Using where; Using join buffer (flat, BNL join)
-2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 8 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3
ANALYZE SELECT * FROM v2 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3 3.00 100.00 100.00
-1 PRIMARY t1 ALL NULL NULL NULL NULL 8 8.00 100.00 0.00 Using where; Using join buffer (flat, BNL join)
-2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 3.00 100.00 100.00 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 8 8.00 100.00 0.00 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 NULL 100.00 NULL
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 NULL 100.00 NULL
#########################################################################
# Inner view permission tests
@@ -2697,14 +2697,14 @@ SELECT * FROM v1 WHERE a IN ( SELECT a FROM t2 );
a b
EXPLAIN SELECT * FROM v1 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3
-1 PRIMARY t1 ALL NULL NULL NULL NULL 14 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 14 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3
ANALYZE SELECT * FROM v1 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3 3.00 100.00 100.00
-1 PRIMARY t1 ALL NULL NULL NULL NULL 14 14.00 100.00 0.00 Using where; Using join buffer (flat, BNL join)
-2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 3.00 100.00 100.00
+1 PRIMARY t1 ALL NULL NULL NULL NULL 14 14.00 100.00 0.00 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 NULL 100.00 NULL
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 NULL 100.00 NULL
#------------------------------------------------------------------------
# I/R/U/D/S on the outer view
# Expectation: Can run everything
@@ -2804,14 +2804,14 @@ SELECT * FROM v2 WHERE a IN ( SELECT a FROM t2 );
a b
EXPLAIN SELECT * FROM v2 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3
-1 PRIMARY t1 ALL NULL NULL NULL NULL 18 Using where; Using join buffer (flat, BNL join)
-2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 18 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3
ANALYZE SELECT * FROM v2 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3 3.00 100.00 100.00
-1 PRIMARY t1 ALL NULL NULL NULL NULL 18 18.00 100.00 0.00 Using where; Using join buffer (flat, BNL join)
-2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 3.00 100.00 100.00 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 18 18.00 100.00 0.00 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 NULL 100.00 NULL
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 NULL 100.00 NULL
#========================================================================
# Test: Grant INSERT on the inner view
@@ -3987,14 +3987,14 @@ SELECT * FROM v1 WHERE a IN ( SELECT a FROM t2 );
a b
EXPLAIN SELECT * FROM v1 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3
-1 PRIMARY t1 ALL NULL NULL NULL NULL 35 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 35 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3
ANALYZE SELECT * FROM v1 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3 3.00 100.00 100.00
-1 PRIMARY t1 ALL NULL NULL NULL NULL 35 35.00 100.00 0.00 Using where; Using join buffer (flat, BNL join)
-2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 3.00 100.00 100.00
+1 PRIMARY t1 ALL NULL NULL NULL NULL 35 35.00 100.00 0.00 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 NULL 100.00 NULL
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 NULL 100.00 NULL
#------------------------------------------------------------------------
# I/R/U/D/S on the outer view
# Expectation: Can run everything
@@ -4094,14 +4094,14 @@ SELECT * FROM v2 WHERE a IN ( SELECT a FROM t2 );
a b
EXPLAIN SELECT * FROM v2 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3
-1 PRIMARY t1 ALL NULL NULL NULL NULL 39 Using where; Using join buffer (flat, BNL join)
-2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 39 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3
ANALYZE SELECT * FROM v2 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3 3.00 100.00 100.00
-1 PRIMARY t1 ALL NULL NULL NULL NULL 39 39.00 100.00 0.00 Using where; Using join buffer (flat, BNL join)
-2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 3.00 100.00 100.00 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 39 39.00 100.00 0.00 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 NULL 100.00 NULL
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 NULL 100.00 NULL
#########################################################################
# Outer view permission tests
@@ -4614,14 +4614,14 @@ SELECT * FROM v2 WHERE a IN ( SELECT a FROM t2 );
a b
EXPLAIN SELECT * FROM v2 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3
-1 PRIMARY t1 ALL NULL NULL NULL NULL 39 Using where; Using join buffer (flat, BNL join)
-2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 39 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3
ANALYZE SELECT * FROM v2 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3 3.00 100.00 100.00
-1 PRIMARY t1 ALL NULL NULL NULL NULL 39 39.00 100.00 0.00 Using where; Using join buffer (flat, BNL join)
-2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 3.00 100.00 100.00 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 39 39.00 100.00 0.00 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 NULL 100.00 NULL
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 NULL 100.00 NULL
#========================================================================
# Test: Grant INSERT on the outer view
@@ -5221,14 +5221,14 @@ SELECT * FROM v2 WHERE a IN ( SELECT a FROM t2 );
a b
EXPLAIN SELECT * FROM v2 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3
-1 PRIMARY t1 ALL NULL NULL NULL NULL 44 Using where; Using join buffer (flat, BNL join)
-2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 44 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3
ANALYZE SELECT * FROM v2 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3 3.00 100.00 100.00
-1 PRIMARY t1 ALL NULL NULL NULL NULL 44 44.00 100.00 0.00 Using where; Using join buffer (flat, BNL join)
-2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 3.00 100.00 100.00 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 44 44.00 100.00 0.00 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 NULL 100.00 NULL
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 NULL 100.00 NULL
disconnect con1;
connection default;
DROP USER 'privtest'@localhost;
diff --git a/mysql-test/r/cte_nonrecursive.result b/mysql-test/r/cte_nonrecursive.result
index 53334512b20..42e4fc67813 100644
--- a/mysql-test/r/cte_nonrecursive.result
+++ b/mysql-test/r/cte_nonrecursive.result
@@ -1159,9 +1159,9 @@ with cte as
union
(select a from t1 where a < 2);
a
-7
-5
4
+5
+7
1
prepare stmt from "with cte as
(select a from t1 where a between 4 and 7 group by a)
@@ -1170,15 +1170,15 @@ union
(select a from t1 where a < 2)";
execute stmt;
a
-7
-5
4
+5
+7
1
execute stmt;
a
-7
-5
4
+5
+7
1
deallocate prepare stmt;
with cte as
@@ -1188,9 +1188,9 @@ union
(select a from cte where exists( select a from t1 where cte.a=t1.a ));
a
1
-7
-5
4
+5
+7
prepare stmt from "with cte as
(select a from t1 where a between 4 and 7 group by a)
(select a from t1 where a < 2)
@@ -1199,15 +1199,15 @@ union
execute stmt;
a
1
-7
-5
4
+5
+7
execute stmt;
a
1
-7
-5
4
+5
+7
deallocate prepare stmt;
with cte as
(select a from t1 where a between 4 and 7)
diff --git a/mysql-test/r/group_by.result b/mysql-test/r/group_by.result
index 62c659dd933..09dac2171a6 100644
--- a/mysql-test/r/group_by.result
+++ b/mysql-test/r/group_by.result
@@ -1607,7 +1607,8 @@ EXPLAIN SELECT 1 FROM t2 WHERE a IN
(SELECT a FROM t1 USE INDEX (i2) IGNORE INDEX (i2));
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 index a a 5 NULL 4 Using index
-1 PRIMARY t1 ALL NULL NULL NULL NULL 144 Using where; FirstMatch(t2)
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED t1 ALL NULL NULL NULL NULL 144
SET optimizer_switch=@save_optimizer_switch;
DROP TABLE t1, t2;
CREATE TABLE t1(
diff --git a/mysql-test/r/index_merge_myisam.result b/mysql-test/r/index_merge_myisam.result
index 992e1d831b5..a201ad3d6d5 100644
--- a/mysql-test/r/index_merge_myisam.result
+++ b/mysql-test/r/index_merge_myisam.result
@@ -556,8 +556,9 @@ where exists (select 1 from t2, t3
where t2.a=t1.a and (t3.a=t2.b or t3.b=t2.b or t3.b=t2.b+1));
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2
-1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Using where
-1 PRIMARY t3 ALL a,b NULL NULL NULL 1002 Range checked for each record (index map: 0x3); FirstMatch(t1)
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 2
+2 MATERIALIZED t3 ALL a,b NULL NULL NULL 1002 Range checked for each record (index map: 0x3)
select * from t1
where exists (select 1 from t2, t3
where t2.a=t1.a and (t3.a=t2.b or t3.b=t2.b or t3.b=t2.b+1));
diff --git a/mysql-test/r/innodb_ext_key.result b/mysql-test/r/innodb_ext_key.result
index c55e8d138f8..a48f889f4df 100644
--- a/mysql-test/r/innodb_ext_key.result
+++ b/mysql-test/r/innodb_ext_key.result
@@ -727,8 +727,8 @@ SELECT a FROM t1 AS t, t2
WHERE c = a AND b IN (SELECT b FROM t1, t2 WHERE b = t.b);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t index a,b b 7 NULL 10 Using index
-1 PRIMARY t1 ref b b 3 test.t.b 2 Using index
-1 PRIMARY t2 index NULL PRIMARY 4 NULL 11 Using index; FirstMatch(t)
+1 PRIMARY t1 ref b b 3 test.t.b 2 Using index; Start temporary
+1 PRIMARY t2 index NULL PRIMARY 4 NULL 11 Using index; End temporary; Using join buffer (flat, BNL join)
1 PRIMARY t2 eq_ref PRIMARY PRIMARY 4 test.t.a 1 Using index
SELECT a FROM t1 AS t, t2
WHERE c = a AND b IN (SELECT b FROM t1, t2 WHERE b = t.b);
@@ -740,8 +740,8 @@ SELECT a FROM t1 AS t, t2
WHERE c = a AND b IN (SELECT b FROM t1, t2 WHERE b = t.b);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t index a,b b 7 NULL 10 Using index
-1 PRIMARY t1 ref b b 3 test.t.b 2 Using index
-1 PRIMARY t2 index NULL PRIMARY 4 NULL 11 Using index; FirstMatch(t)
+1 PRIMARY t1 ref b b 3 test.t.b 2 Using index; Start temporary
+1 PRIMARY t2 index NULL PRIMARY 4 NULL 11 Using index; End temporary; Using join buffer (flat, BNL join)
1 PRIMARY t2 eq_ref PRIMARY PRIMARY 4 test.t.a 1 Using index
SELECT a FROM t1 AS t, t2
WHERE c = a AND b IN (SELECT b FROM t1, t2 WHERE b = t.b);
diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result
index 38d0336772e..25e95159864 100644
--- a/mysql-test/r/subselect.result
+++ b/mysql-test/r/subselect.result
@@ -5688,8 +5688,8 @@ EXPLAIN
SELECT * FROM t1
WHERE EXISTS (SELECT a FROM t2 USE INDEX() WHERE t2.a = t1.a);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3
-1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 4
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3
SELECT * FROM t1
WHERE EXISTS (SELECT a FROM t2 WHERE t2.a = t1.a);
@@ -5699,8 +5699,8 @@ EXPLAIN
SELECT * FROM t1
WHERE EXISTS (SELECT a FROM t2 WHERE t2.a = t1.a);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3
-1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 4
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
2 MATERIALIZED t2 index idx idx 5 NULL 3 Using index
DROP TABLE t1,t2;
#
diff --git a/mysql-test/r/subselect3.result b/mysql-test/r/subselect3.result
index ca151daf146..3c33182b3ef 100644
--- a/mysql-test/r/subselect3.result
+++ b/mysql-test/r/subselect3.result
@@ -1139,8 +1139,8 @@ create table t3 (a int);
insert into t3 select A.a + 10*B.a from t0 A, t0 B;
explain select * from t3 where a in (select kp1 from t1 where kp1<20);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 range kp1 kp1 5 NULL 48 Using where; Using index; LooseScan
-1 PRIMARY t3 ALL NULL NULL NULL NULL 100 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t3 ALL NULL NULL NULL NULL 100 Using where
+1 PRIMARY t1 ref kp1 kp1 5 test.t3.a 1 Using index; FirstMatch(t3)
create table t4 (pk int primary key);
insert into t4 select a from t3;
explain select * from t3 where a in (select t1.kp1 from t1,t4 where kp1<20
@@ -1276,12 +1276,12 @@ insert into t1 select A.a, B.a, 'filler' from t0 A, t0 B;
create table t2 as select * from t1;
explain select * from t2 where a in (select b from t1 where a=3);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 ref a a 5 const 8 Using index; LooseScan
-1 PRIMARY t2 ALL NULL NULL NULL NULL 100 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t2 ALL NULL NULL NULL NULL 100 Using where
+1 PRIMARY t1 ref a a 10 const,test.t2.a 1 Using index; FirstMatch(t2)
explain select * from t2 where (b,a) in (select a,b from t1 where a=3);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 ref a a 5 const 8 Using index; LooseScan
-1 PRIMARY t2 ALL NULL NULL NULL NULL 100 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t2 ALL NULL NULL NULL NULL 100 Using where
+1 PRIMARY t1 ref a a 10 const,test.t2.a 1 Using index; FirstMatch(t2)
drop table t1,t2;
set @@optimizer_switch=@save_optimizer_switch;
create table t1 (a int, b int);
@@ -1339,9 +1339,9 @@ insert into t2 select * from t2;
explain select * from t1 where (a,b,c) in (select X.a, Y.a, Z.a from t2 X, t2 Y, t2 Z where X.b=33);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3
-1 PRIMARY X ALL NULL NULL NULL NULL 6 Using where
-1 PRIMARY Y ALL NULL NULL NULL NULL 6 Using where
-1 PRIMARY Z ALL NULL NULL NULL NULL 6 Using where; FirstMatch(t1)
+1 PRIMARY X ALL NULL NULL NULL NULL 6 Using where; Start temporary; Using join buffer (flat, BNL join)
+1 PRIMARY Y ALL NULL NULL NULL NULL 6 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY Z ALL NULL NULL NULL NULL 6 Using where; End temporary; Using join buffer (flat, BNL join)
drop table t0,t1,t2;
set @@optimizer_switch=@save_optimizer_switch;
diff --git a/mysql-test/r/subselect3_jcl6.result b/mysql-test/r/subselect3_jcl6.result
index adb3ec80394..69f720a95b7 100644
--- a/mysql-test/r/subselect3_jcl6.result
+++ b/mysql-test/r/subselect3_jcl6.result
@@ -1149,8 +1149,8 @@ create table t3 (a int);
insert into t3 select A.a + 10*B.a from t0 A, t0 B;
explain select * from t3 where a in (select kp1 from t1 where kp1<20);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 range kp1 kp1 5 NULL 48 Using where; Using index; LooseScan
-1 PRIMARY t3 ALL NULL NULL NULL NULL 100 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t3 ALL NULL NULL NULL NULL 100 Using where
+1 PRIMARY t1 ref kp1 kp1 5 test.t3.a 1 Using index; FirstMatch(t3)
create table t4 (pk int primary key);
insert into t4 select a from t3;
explain select * from t3 where a in (select t1.kp1 from t1,t4 where kp1<20
@@ -1286,12 +1286,12 @@ insert into t1 select A.a, B.a, 'filler' from t0 A, t0 B;
create table t2 as select * from t1;
explain select * from t2 where a in (select b from t1 where a=3);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 ref a a 5 const 8 Using index; LooseScan
-1 PRIMARY t2 ALL NULL NULL NULL NULL 100 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t2 ALL NULL NULL NULL NULL 100 Using where
+1 PRIMARY t1 ref a a 10 const,test.t2.a 1 Using index; FirstMatch(t2)
explain select * from t2 where (b,a) in (select a,b from t1 where a=3);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 ref a a 5 const 8 Using index; LooseScan
-1 PRIMARY t2 ALL NULL NULL NULL NULL 100 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t2 ALL NULL NULL NULL NULL 100 Using where
+1 PRIMARY t1 ref a a 10 const,test.t2.a 1 Using index; FirstMatch(t2)
drop table t1,t2;
set @@optimizer_switch=@save_optimizer_switch;
create table t1 (a int, b int);
@@ -1348,10 +1348,10 @@ create table t2 as select a as a, a as b from t0 where a < 3;
insert into t2 select * from t2;
explain select * from t1 where (a,b,c) in (select X.a, Y.a, Z.a from t2 X, t2 Y, t2 Z where X.b=33);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 3
-1 PRIMARY X ALL NULL NULL NULL NULL 6 Using where; Using join buffer (flat, BNL join)
-1 PRIMARY Y ALL NULL NULL NULL NULL 6 Using where; Using join buffer (incremental, BNL join)
-1 PRIMARY Z ALL NULL NULL NULL NULL 6 Using where; FirstMatch(t1); Using join buffer (incremental, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where
+1 PRIMARY X hash_ALL NULL #hash#$hj 5 test.t1.a 6 Using where; Start temporary; Using join buffer (flat, BNLH join)
+1 PRIMARY Y hash_ALL NULL #hash#$hj 5 test.t1.b 6 Using where; Using join buffer (incremental, BNLH join)
+1 PRIMARY Z hash_ALL NULL #hash#$hj 5 test.t1.c 6 Using where; End temporary; Using join buffer (incremental, BNLH join)
drop table t0,t1,t2;
set @@optimizer_switch=@save_optimizer_switch;
diff --git a/mysql-test/r/subselect_mat.result b/mysql-test/r/subselect_mat.result
index 350275d2463..f2f194ed67b 100644
--- a/mysql-test/r/subselect_mat.result
+++ b/mysql-test/r/subselect_mat.result
@@ -1477,8 +1477,8 @@ set @@optimizer_switch=@optimizer_switch_local_default;
SET @@optimizer_switch='semijoin=on,materialization=on';
EXPLAIN SELECT COUNT(*) FROM t1 WHERE (f1,f2) IN (SELECT f1,f2 FROM t2);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 2
-1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 7 func,func 1
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 2
SELECT COUNT(*) FROM t1 WHERE (f1,f2) IN (SELECT f1,f2 FROM t2);
COUNT(*)
diff --git a/mysql-test/r/subselect_no_mat.result b/mysql-test/r/subselect_no_mat.result
index d365a0932e6..ce13ee562e9 100644
--- a/mysql-test/r/subselect_no_mat.result
+++ b/mysql-test/r/subselect_no_mat.result
@@ -5668,9 +5668,9 @@ WHERE (ot1.a,ot4.a) IN (SELECT it2.a,it3.a
FROM it2,it3);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY ot1 ALL NULL NULL NULL NULL 2
-1 PRIMARY ot4 ALL NULL NULL NULL NULL 8 Using join buffer (flat, BNL join)
-1 PRIMARY it2 ALL NULL NULL NULL NULL 4 Using where
-1 PRIMARY it3 ALL NULL NULL NULL NULL 6 Using where; FirstMatch(ot4)
+1 PRIMARY it2 ALL NULL NULL NULL NULL 4 Using where; Start temporary; Using join buffer (flat, BNL join)
+1 PRIMARY it3 ALL NULL NULL NULL NULL 6 Using join buffer (flat, BNL join)
+1 PRIMARY ot4 ALL NULL NULL NULL NULL 8 Using where; End temporary; Using join buffer (flat, BNL join)
DROP TABLE IF EXISTS ot1, ot4, it2, it3;
#
# Bug#729039: NULL keys used to evaluate subquery
@@ -5697,8 +5697,8 @@ EXPLAIN
SELECT * FROM t1
WHERE EXISTS (SELECT a FROM t2 WHERE t2.a = t1.a);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t2 index idx idx 5 NULL 3 Using index; LooseScan
-1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where
+1 PRIMARY t2 ref idx idx 5 test.t1.a 2 Using index; FirstMatch(t1)
DROP TABLE t1,t2;
#
# BUG#752992: Wrong results for a subquery with 'semijoin=on'
diff --git a/mysql-test/r/subselect_no_scache.result b/mysql-test/r/subselect_no_scache.result
index 61f2154e984..8c0bdd8b321 100644
--- a/mysql-test/r/subselect_no_scache.result
+++ b/mysql-test/r/subselect_no_scache.result
@@ -5694,8 +5694,8 @@ EXPLAIN
SELECT * FROM t1
WHERE EXISTS (SELECT a FROM t2 USE INDEX() WHERE t2.a = t1.a);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3
-1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 4
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3
SELECT * FROM t1
WHERE EXISTS (SELECT a FROM t2 WHERE t2.a = t1.a);
@@ -5705,8 +5705,8 @@ EXPLAIN
SELECT * FROM t1
WHERE EXISTS (SELECT a FROM t2 WHERE t2.a = t1.a);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3
-1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 4
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
2 MATERIALIZED t2 index idx idx 5 NULL 3 Using index
DROP TABLE t1,t2;
#
diff --git a/mysql-test/r/subselect_sj.result b/mysql-test/r/subselect_sj.result
index a601dac5337..ad6af0340ed 100644
--- a/mysql-test/r/subselect_sj.result
+++ b/mysql-test/r/subselect_sj.result
@@ -729,8 +729,8 @@ SELECT int_key FROM ot1
WHERE int_nokey IN (SELECT it2.int_key
FROM it1 LEFT JOIN it2 ON it2.datetime_key);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 11
-1 PRIMARY ot1 ALL NULL NULL NULL NULL 20 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY ot1 ALL NULL NULL NULL NULL 20
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
2 MATERIALIZED it1 index NULL int_key 4 NULL 2 Using index
2 MATERIALIZED it2 ALL int_key,datetime_key NULL NULL NULL 20 Using where
DROP TABLE ot1, it1, it2;
@@ -972,11 +972,11 @@ SELECT `varchar_key` , `varchar_nokey`
FROM t1
WHERE `varchar_nokey` < 'n' XOR `pk` ) ;
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 15 100.00
-1 PRIMARY t2 ALL NULL NULL NULL NULL 18 100.00 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t2 ALL NULL NULL NULL NULL 18 100.00
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1 100.00
2 MATERIALIZED t1 ALL varchar_key NULL NULL NULL 15 100.00 Using where
Warnings:
-Note 1003 select `test`.`t2`.`varchar_nokey` AS `varchar_nokey` from `test`.`t2` semi join (`test`.`t1`) where `test`.`t1`.`varchar_nokey` = `test`.`t1`.`varchar_key` and `test`.`t2`.`varchar_nokey` = `test`.`t1`.`varchar_key` and (`test`.`t1`.`varchar_key` < 'n' xor `test`.`t1`.`pk`)
+Note 1003 select `test`.`t2`.`varchar_nokey` AS `varchar_nokey` from `test`.`t2` semi join (`test`.`t1`) where `test`.`t1`.`varchar_nokey` = `test`.`t1`.`varchar_key` and (`test`.`t1`.`varchar_key` < 'n' xor `test`.`t1`.`pk`)
SELECT varchar_nokey
FROM t2
WHERE ( `varchar_nokey` , `varchar_nokey` ) IN (
@@ -1246,8 +1246,8 @@ INSERT INTO t2 VALUES (1, 0), (1, 1), (2, 0), (2, 1);
EXPLAIN
SELECT * FROM t1 WHERE (i) IN (SELECT i FROM t2 where j > 0);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t2 index k k 10 NULL 4 Using where; Using index; LooseScan
-1 PRIMARY t1 ALL NULL NULL NULL NULL 5 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 5
+1 PRIMARY t2 index k k 10 NULL 4 Using where; Using index; Start temporary; End temporary
SELECT * FROM t1 WHERE (i) IN (SELECT i FROM t2 where j > 0);
i
1
@@ -1757,8 +1757,8 @@ insert into t3 values('three'),( 'four');
insert into t3 values('three'),( 'four');
explain select * from t3 where t3.b in (select t2.b from t1 left join t2 on t1.a=t2.a);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 2
-1 PRIMARY t3 ALL NULL NULL NULL NULL 8 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t3 ALL NULL NULL NULL NULL 8
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 10 func 1
2 MATERIALIZED t1 ALL NULL NULL NULL NULL 2
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 2 Using where
select * from t3 where t3.b in (select t2.b from t1 left join t2 on t1.a=t2.a);
@@ -1991,12 +1991,13 @@ CREATE VIEW v4 AS SELECT DISTINCT f2 FROM t4 ;
explain extended
SELECT * FROM t1 NATURAL LEFT JOIN (t2, t3) WHERE t2.f3 IN (SELECT * FROM t4);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t2 ALL NULL NULL NULL NULL 2 100.00 Using where
-1 PRIMARY t4 ref f2 f2 5 test.t2.f3 2 100.00 Using index; FirstMatch(t2)
+1 PRIMARY t2 ALL NULL NULL NULL NULL 2 100.00
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 100.00
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (flat, BNL join)
1 PRIMARY t3 ALL NULL NULL NULL NULL 5 100.00 Using where; Using join buffer (flat, BNL join)
+2 MATERIALIZED t4 index f2 f2 5 NULL 2 100.00 Using index
Warnings:
-Note 1003 select `test`.`t1`.`f1` AS `f1`,`test`.`t1`.`f2` AS `f2`,`test`.`t2`.`f3` AS `f3`,`test`.`t3`.`f3` AS `f3` from `test`.`t1` semi join (`test`.`t4`) join `test`.`t2` join `test`.`t3` where `test`.`t4`.`f2` = `test`.`t2`.`f3` and `test`.`t3`.`f1` = `test`.`t1`.`f1` and `test`.`t1`.`f2` = `test`.`t2`.`f2`
+Note 1003 select `test`.`t1`.`f1` AS `f1`,`test`.`t1`.`f2` AS `f2`,`test`.`t2`.`f3` AS `f3`,`test`.`t3`.`f3` AS `f3` from `test`.`t1` semi join (`test`.`t4`) join `test`.`t2` join `test`.`t3` where `test`.`t3`.`f1` = `test`.`t1`.`f1` and `test`.`t1`.`f2` = `test`.`t2`.`f2`
SELECT * FROM t1 NATURAL LEFT JOIN (t2, t3) WHERE t2.f3 IN (SELECT * FROM t4);
f1 f2 f3 f3
2 0 0 0
@@ -2495,8 +2496,8 @@ WHERE t1.a = t2.a AND t2.a IN (SELECT b FROM t3 STRAIGHT_JOIN t4);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t3 system NULL NULL NULL NULL 1
1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 1
-1 PRIMARY t1 ref a a 5 const 1 Using index
-1 PRIMARY t2 ref a a 5 func 1 Using index
+1 PRIMARY t2 ref a a 5 const 1 Using index
+1 PRIMARY t1 ref a a 5 func 1 Using index
2 MATERIALIZED t4 ALL NULL NULL NULL NULL 0
SELECT * FROM t1, t2
WHERE t1.a = t2.a AND t2.a IN (SELECT b FROM t3 STRAIGHT_JOIN t4);
@@ -2562,25 +2563,25 @@ SELECT a, b, d FROM t1, t2
WHERE ( b, d ) IN
( SELECT b, d FROM t1, t2 WHERE b = c );
a b d
+1 2 1
+1 2 1
2 1 2
-7 1 2
2 1 2
-7 1 2
-1 2 1
+3 3 3
+3 3 3
4 2 1
-10 2 1
-1 2 1
4 2 1
-10 2 1
-3 3 3
+5 5 5
6 3 3
-9 3 3
-3 3 3
6 3 3
-9 3 3
+7 1 2
+7 1 2
8 4 2
8 4 2
-5 5 5
+9 3 3
+9 3 3
+10 2 1
+10 2 1
DROP TABLE t1, t2;
#
# BUG#920713: Wrong result (missing rows) with firstmatch+BNL, IN subquery, ...
@@ -2645,8 +2646,8 @@ a
19
explain select * from t3 where a in (select kp1 from t1 where kp1<20);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 range kp1 kp1 5 NULL 48 Using where; Using index; LooseScan
-1 PRIMARY t3 ALL NULL NULL NULL NULL 100 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t3 ALL NULL NULL NULL NULL 100 Using where
+1 PRIMARY t1 ref kp1 kp1 5 test.t3.a 1 Using index; FirstMatch(t3)
drop table t0,t1,t3;
set optimizer_switch= @tmp_923246;
#
@@ -2862,8 +2863,8 @@ WHERE alias1.pk = 58 OR alias1.col_varchar_key = 'o'
);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 2
-1 PRIMARY alias1 index_merge PRIMARY,col_int_key,col_varchar_key PRIMARY,col_varchar_key 4,4 NULL 2 Using sort_union(PRIMARY,col_varchar_key); Using where
-1 PRIMARY alias2 ALL col_int_key NULL NULL NULL 12 Range checked for each record (index map: 0x2); FirstMatch(t2)
+1 PRIMARY alias1 index_merge PRIMARY,col_int_key,col_varchar_key PRIMARY,col_varchar_key 4,4 NULL 2 Using sort_union(PRIMARY,col_varchar_key); Using where; Start temporary
+1 PRIMARY alias2 ALL col_int_key NULL NULL NULL 12 Range checked for each record (index map: 0x2); End temporary
SELECT *
FROM t2
WHERE (field1) IN (SELECT alias1.col_varchar_nokey AS field1
@@ -3165,4 +3166,28 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
Warnings:
Note 1003 /* select#1 */ select `test`.`t1`.`c1` AS `c1`,`test`.`t2`.`c2` AS `c2`,`test`.`t4`.`c4` AS `c4` from `test`.`t1` left join (`test`.`t2` join `test`.`t4`) on(`test`.`t2`.`c2` = `test`.`t1`.`c1` and <in_optimizer>(`test`.`t1`.`c1`,<exists>(/* select#3 */ select `test`.`t3`.`c3` from `test`.`t3` where <cache>(`test`.`t2`.`c2`) = `test`.`t3`.`c3`))) where 1
DROP TABLE t1,t2,t3,t4;
+set optimizer_switch = 'materialization=on';
+#
+# MDEV-20109: Optimizer ignores distinct key created for materialized
+# semi-join subquery when searching for best execution plan
+#
+create table t1(a int);
+insert into t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+create table t2(a int);
+insert into t2 select A.a + B.a* 10 + C.a * 100 from t1 A, t1 B, t1 C;
+create table t3 (a int);
+create table t4 (a int);
+insert into t3 select A.a +1000*B.a from t2 A, t1 B;
+insert into t4 select floor(rand()*1000) from t2 limit 500;
+# The following must not use this query plan that does a cross join:
+# | 1 | PRIMARY | <subquery2> | ALL | distinct_key | ... | 500 | |
+# | 1 | PRIMARY | t3 | ALL | NULL | ... | 10000 | Using where; Using join buffer (flat, BNL join) |
+#
+# Instead, it should use eq_ref on the materialized table.
+explain select * from t3 where a in (select a from t4 group by a);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t3 ALL NULL NULL NULL NULL 10000
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED t4 ALL NULL NULL NULL NULL 500
+drop table t1, t2, t3, t4;
set optimizer_switch=@subselect_sj_tmp;
diff --git a/mysql-test/r/subselect_sj2.result b/mysql-test/r/subselect_sj2.result
index 948be5766a2..b5070d55b69 100644
--- a/mysql-test/r/subselect_sj2.result
+++ b/mysql-test/r/subselect_sj2.result
@@ -118,8 +118,9 @@ set join_buffer_size= @save_join_buffer_size;
set max_heap_table_size= @save_max_heap_table_size;
explain select * from t1 where a in (select b from t2);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where
-1 PRIMARY t2 ref b b 5 test.t1.a 2 Using index; FirstMatch(t1)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED t2 index b b 5 NULL 20 Using index
select * from t1;
a b
1 1
@@ -146,8 +147,8 @@ explain select
a, mid(filler1, 1,10), length(filler1)=length(filler2) as Z
from t1 ot where a in (select a from t2 it);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 22
-1 PRIMARY ot ALL NULL NULL NULL NULL 32 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY ot ALL NULL NULL NULL NULL 32
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
2 MATERIALIZED it ALL NULL NULL NULL NULL 22
select
a, mid(filler1, 1,10), length(filler1)=length(filler2) as Z
@@ -214,8 +215,8 @@ explain select
a, mid(filler1, 1,10), length(filler1)=length(filler2) as Z
from t1 ot where a in (select a from t2 it);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 22
-1 PRIMARY ot ALL NULL NULL NULL NULL 52 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY ot ALL NULL NULL NULL NULL 52
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
2 MATERIALIZED it ALL NULL NULL NULL NULL 22
select
a, mid(filler1, 1,10), length(filler1)=length(filler2) as Z
@@ -745,9 +746,10 @@ c2 in (select 1 from t3, t2) and
c1 in (select convert(c6,char(1)) from t2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 1 Using where
-1 PRIMARY t2 ALL NULL NULL NULL NULL 1 Using where; FirstMatch(t2)
+1 PRIMARY <subquery3> eq_ref distinct_key distinct_key 4 func 1 Using where
1 PRIMARY t2 ALL NULL NULL NULL NULL 1
-1 PRIMARY t3 ALL NULL NULL NULL NULL 2 FirstMatch(t2)
+1 PRIMARY t3 ALL NULL NULL NULL NULL 2 FirstMatch((sj-nest))
+3 MATERIALIZED t2 ALL NULL NULL NULL NULL 1
drop table t2, t3;
#
# BUG#761598: InnoDB: Error: row_search_for_mysql() is called without ha_innobase::external_lock() in maria-5.3
diff --git a/mysql-test/r/subselect_sj2_jcl6.result b/mysql-test/r/subselect_sj2_jcl6.result
index 2955307eb86..23c54ab7734 100644
--- a/mysql-test/r/subselect_sj2_jcl6.result
+++ b/mysql-test/r/subselect_sj2_jcl6.result
@@ -158,9 +158,9 @@ explain select
a, mid(filler1, 1,10), length(filler1)=length(filler2) as Z
from t1 ot where a in (select a from t2 it);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 22
-1 PRIMARY ot hash_ALL NULL #hash#$hj 5 test.it.a 32 Using where; Using join buffer (flat, BNLH join)
-2 MATERIALIZED it ALL NULL NULL NULL NULL 22 Using where
+1 PRIMARY ot ALL NULL NULL NULL NULL 32
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED it ALL NULL NULL NULL NULL 22
select
a, mid(filler1, 1,10), length(filler1)=length(filler2) as Z
from t1 ot where a in (select a from t2 it);
@@ -226,9 +226,9 @@ explain select
a, mid(filler1, 1,10), length(filler1)=length(filler2) as Z
from t1 ot where a in (select a from t2 it);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 22
-1 PRIMARY ot hash_ALL NULL #hash#$hj 5 test.it.a 52 Using where; Using join buffer (flat, BNLH join)
-2 MATERIALIZED it ALL NULL NULL NULL NULL 22 Using where
+1 PRIMARY ot ALL NULL NULL NULL NULL 52
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED it ALL NULL NULL NULL NULL 22
select
a, mid(filler1, 1,10), length(filler1)=length(filler2) as Z
from t1 ot where a in (select a from t2 it);
@@ -1367,9 +1367,10 @@ SELECT t3.* FROM t1 JOIN t3 ON t3.b = t1.b
WHERE c IN (SELECT t4.b FROM t4 JOIN t2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t3 ALL NULL NULL NULL NULL 1 Using where
-1 PRIMARY t2 ALL NULL NULL NULL NULL 1 Using join buffer (flat, BNL join)
-1 PRIMARY t4 ALL NULL NULL NULL NULL 2 Using where; FirstMatch(t3); Using join buffer (incremental, BNL join)
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
1 PRIMARY t1 ref b b 4 test.t3.b 1 Using index
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 1
+2 MATERIALIZED t4 ALL NULL NULL NULL NULL 2 Using join buffer (flat, BNL join)
SELECT t3.* FROM t1 JOIN t3 ON t3.b = t1.b
WHERE c IN (SELECT t4.b FROM t4 JOIN t2);
b c
@@ -1395,9 +1396,10 @@ EXPLAIN
SELECT * FROM t1, t2 WHERE b IN (SELECT a FROM t3, t4 WHERE b = pk);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 1
-1 PRIMARY t4 ALL NULL NULL NULL NULL 1 Using where
-1 PRIMARY t3 eq_ref PRIMARY PRIMARY 4 test.t4.b 1 Using where; FirstMatch(t2)
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using join buffer (flat, BNL join)
+2 MATERIALIZED t4 ALL NULL NULL NULL NULL 1 Using where
+2 MATERIALIZED t3 eq_ref PRIMARY PRIMARY 4 test.t4.b 1
SELECT * FROM t1, t2 WHERE b IN (SELECT a FROM t3, t4 WHERE b = pk);
pk a b
1 6 8
diff --git a/mysql-test/r/subselect_sj2_mat.result b/mysql-test/r/subselect_sj2_mat.result
index 6a1f310511f..51f919beeab 100644
--- a/mysql-test/r/subselect_sj2_mat.result
+++ b/mysql-test/r/subselect_sj2_mat.result
@@ -120,8 +120,9 @@ set join_buffer_size= @save_join_buffer_size;
set max_heap_table_size= @save_max_heap_table_size;
explain select * from t1 where a in (select b from t2);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where
-1 PRIMARY t2 ref b b 5 test.t1.a 2 Using index; FirstMatch(t1)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED t2 index b b 5 NULL 20 Using index
select * from t1;
a b
1 1
@@ -148,8 +149,8 @@ explain select
a, mid(filler1, 1,10), length(filler1)=length(filler2) as Z
from t1 ot where a in (select a from t2 it);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 22
-1 PRIMARY ot ALL NULL NULL NULL NULL 32 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY ot ALL NULL NULL NULL NULL 32
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
2 MATERIALIZED it ALL NULL NULL NULL NULL 22
select
a, mid(filler1, 1,10), length(filler1)=length(filler2) as Z
@@ -216,8 +217,8 @@ explain select
a, mid(filler1, 1,10), length(filler1)=length(filler2) as Z
from t1 ot where a in (select a from t2 it);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 22
-1 PRIMARY ot ALL NULL NULL NULL NULL 52 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY ot ALL NULL NULL NULL NULL 52
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
2 MATERIALIZED it ALL NULL NULL NULL NULL 22
select
a, mid(filler1, 1,10), length(filler1)=length(filler2) as Z
@@ -747,9 +748,10 @@ c2 in (select 1 from t3, t2) and
c1 in (select convert(c6,char(1)) from t2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 1 Using where
-1 PRIMARY t2 ALL NULL NULL NULL NULL 1 Using where; FirstMatch(t2)
+1 PRIMARY <subquery3> eq_ref distinct_key distinct_key 4 func 1 Using where
1 PRIMARY t2 ALL NULL NULL NULL NULL 1
-1 PRIMARY t3 ALL NULL NULL NULL NULL 2 FirstMatch(t2)
+1 PRIMARY t3 ALL NULL NULL NULL NULL 2 FirstMatch((sj-nest))
+3 MATERIALIZED t2 ALL NULL NULL NULL NULL 1
drop table t2, t3;
#
# BUG#761598: InnoDB: Error: row_search_for_mysql() is called without ha_innobase::external_lock() in maria-5.3
@@ -1596,12 +1598,12 @@ set optimizer_switch='materialization=on,semijoin=on';
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE i1 IN (SELECT i3 FROM t2, t3 WHERE i3 = i2 OR 1=2);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3 100.00
-1 PRIMARY t1 hash_ALL NULL #hash#$hj 5 test.t2.i2 5 100.00 Using where; Using join buffer (flat, BNLH join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 5 100.00
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 100.00
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 2 100.00 Using where
2 MATERIALIZED t3 hash_ALL NULL #hash#$hj 5 test.t2.i2 3 100.00 Using where; Using join buffer (flat, BNLH join)
Warnings:
-Note 1003 select `test`.`t1`.`i1` AS `i1` from `test`.`t1` semi join (`test`.`t2` join `test`.`t3`) where `test`.`t3`.`i3` = `test`.`t2`.`i2` and `test`.`t1`.`i1` = `test`.`t2`.`i2`
+Note 1003 select `test`.`t1`.`i1` AS `i1` from `test`.`t1` semi join (`test`.`t2` join `test`.`t3`) where `test`.`t3`.`i3` = `test`.`t2`.`i2`
SELECT * FROM t1 WHERE i1 IN (SELECT i3 FROM t2, t3 WHERE i3 = i2 OR 1=2);
i1
7
@@ -1609,12 +1611,12 @@ EXPLAIN EXTENDED
SELECT * FROM t1
WHERE i1 IN (SELECT i3 FROM t2, t3 WHERE i3 > 0 AND i3 = i2 OR 1=2);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3 100.00
-1 PRIMARY t1 hash_ALL NULL #hash#$hj 5 test.t2.i2 5 100.00 Using where; Using join buffer (flat, BNLH join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 5 100.00
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 100.00
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 2 100.00 Using where
2 MATERIALIZED t3 hash_ALL NULL #hash#$hj 5 test.t2.i2 3 100.00 Using where; Using join buffer (flat, BNLH join)
Warnings:
-Note 1003 select `test`.`t1`.`i1` AS `i1` from `test`.`t1` semi join (`test`.`t2` join `test`.`t3`) where `test`.`t3`.`i3` = `test`.`t2`.`i2` and `test`.`t1`.`i1` = `test`.`t2`.`i2` and `test`.`t3`.`i3` > 0
+Note 1003 select `test`.`t1`.`i1` AS `i1` from `test`.`t1` semi join (`test`.`t2` join `test`.`t3`) where `test`.`t3`.`i3` = `test`.`t2`.`i2` and `test`.`t3`.`i3` > 0
SELECT * FROM t1
WHERE i1 IN (SELECT i3 FROM t2, t3 WHERE i3 > 0 AND i3 = i2 OR 1=2);
i1
diff --git a/mysql-test/r/subselect_sj_jcl6.result b/mysql-test/r/subselect_sj_jcl6.result
index 77a073ea2d3..785c687402c 100644
--- a/mysql-test/r/subselect_sj_jcl6.result
+++ b/mysql-test/r/subselect_sj_jcl6.result
@@ -742,8 +742,8 @@ SELECT int_key FROM ot1
WHERE int_nokey IN (SELECT it2.int_key
FROM it1 LEFT JOIN it2 ON it2.datetime_key);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 11
-1 PRIMARY ot1 ALL NULL NULL NULL NULL 20 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY ot1 ALL NULL NULL NULL NULL 20
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
2 MATERIALIZED it1 index NULL int_key 4 NULL 2 Using index
2 MATERIALIZED it2 ALL int_key,datetime_key NULL NULL NULL 20 Using where; Using join buffer (flat, BNL join)
DROP TABLE ot1, it1, it2;
@@ -985,11 +985,11 @@ SELECT `varchar_key` , `varchar_nokey`
FROM t1
WHERE `varchar_nokey` < 'n' XOR `pk` ) ;
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 15 100.00
-1 PRIMARY t2 ALL NULL NULL NULL NULL 18 100.00 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t2 ALL NULL NULL NULL NULL 18 100.00
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1 100.00
2 MATERIALIZED t1 ALL varchar_key NULL NULL NULL 15 100.00 Using where
Warnings:
-Note 1003 select `test`.`t2`.`varchar_nokey` AS `varchar_nokey` from `test`.`t2` semi join (`test`.`t1`) where `test`.`t1`.`varchar_nokey` = `test`.`t1`.`varchar_key` and `test`.`t2`.`varchar_nokey` = `test`.`t1`.`varchar_key` and (`test`.`t1`.`varchar_key` < 'n' xor `test`.`t1`.`pk`)
+Note 1003 select `test`.`t2`.`varchar_nokey` AS `varchar_nokey` from `test`.`t2` semi join (`test`.`t1`) where `test`.`t1`.`varchar_nokey` = `test`.`t1`.`varchar_key` and (`test`.`t1`.`varchar_key` < 'n' xor `test`.`t1`.`pk`)
SELECT varchar_nokey
FROM t2
WHERE ( `varchar_nokey` , `varchar_nokey` ) IN (
@@ -1259,8 +1259,8 @@ INSERT INTO t2 VALUES (1, 0), (1, 1), (2, 0), (2, 1);
EXPLAIN
SELECT * FROM t1 WHERE (i) IN (SELECT i FROM t2 where j > 0);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t2 index k k 10 NULL 4 Using where; Using index; LooseScan
-1 PRIMARY t1 ALL NULL NULL NULL NULL 5 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 5
+1 PRIMARY t2 index k k 10 NULL 4 Using where; Using index; Start temporary; End temporary; Using join buffer (flat, BNL join)
SELECT * FROM t1 WHERE (i) IN (SELECT i FROM t2 where j > 0);
i
1
@@ -1770,8 +1770,8 @@ insert into t3 values('three'),( 'four');
insert into t3 values('three'),( 'four');
explain select * from t3 where t3.b in (select t2.b from t1 left join t2 on t1.a=t2.a);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 2
-1 PRIMARY t3 ALL NULL NULL NULL NULL 8 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t3 ALL NULL NULL NULL NULL 8
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 10 func 1
2 MATERIALIZED t1 ALL NULL NULL NULL NULL 2
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 2 Using where; Using join buffer (flat, BNL join)
select * from t3 where t3.b in (select t2.b from t1 left join t2 on t1.a=t2.a);
@@ -2509,8 +2509,8 @@ WHERE t1.a = t2.a AND t2.a IN (SELECT b FROM t3 STRAIGHT_JOIN t4);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t3 system NULL NULL NULL NULL 1
1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 1
-1 PRIMARY t1 ref a a 5 const 1 Using index
-1 PRIMARY t2 ref a a 5 func 1 Using index
+1 PRIMARY t2 ref a a 5 const 1 Using index
+1 PRIMARY t1 ref a a 5 func 1 Using index
2 MATERIALIZED t4 ALL NULL NULL NULL NULL 0
SELECT * FROM t1, t2
WHERE t1.a = t2.a AND t2.a IN (SELECT b FROM t3 STRAIGHT_JOIN t4);
@@ -2659,8 +2659,8 @@ a
19
explain select * from t3 where a in (select kp1 from t1 where kp1<20);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 range kp1 kp1 5 NULL 48 Using where; Using index; LooseScan
-1 PRIMARY t3 ALL NULL NULL NULL NULL 100 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t3 ALL NULL NULL NULL NULL 100 Using where
+1 PRIMARY t1 ref kp1 kp1 5 test.t3.a 1 Using index; FirstMatch(t3)
drop table t0,t1,t3;
set optimizer_switch= @tmp_923246;
#
@@ -2876,8 +2876,8 @@ WHERE alias1.pk = 58 OR alias1.col_varchar_key = 'o'
);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 2
-1 PRIMARY alias1 index_merge PRIMARY,col_int_key,col_varchar_key PRIMARY,col_varchar_key 4,4 NULL 2 Using sort_union(PRIMARY,col_varchar_key); Using where
-1 PRIMARY alias2 ALL col_int_key NULL NULL NULL 12 Range checked for each record (index map: 0x2); FirstMatch(t2)
+1 PRIMARY alias1 index_merge PRIMARY,col_int_key,col_varchar_key PRIMARY,col_varchar_key 4,4 NULL 2 Using sort_union(PRIMARY,col_varchar_key); Using where; Start temporary; Using join buffer (flat, BNL join)
+1 PRIMARY alias2 ALL col_int_key NULL NULL NULL 12 Range checked for each record (index map: 0x2); End temporary
SELECT *
FROM t2
WHERE (field1) IN (SELECT alias1.col_varchar_nokey AS field1
@@ -3179,6 +3179,30 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
Warnings:
Note 1003 /* select#1 */ select `test`.`t1`.`c1` AS `c1`,`test`.`t2`.`c2` AS `c2`,`test`.`t4`.`c4` AS `c4` from `test`.`t1` left join (`test`.`t2` join `test`.`t4`) on(`test`.`t2`.`c2` = `test`.`t1`.`c1` and <in_optimizer>(`test`.`t1`.`c1`,<exists>(/* select#3 */ select `test`.`t3`.`c3` from `test`.`t3` where <cache>(`test`.`t2`.`c2`) = `test`.`t3`.`c3`))) where 1
DROP TABLE t1,t2,t3,t4;
+set optimizer_switch = 'materialization=on';
+#
+# MDEV-20109: Optimizer ignores distinct key created for materialized
+# semi-join subquery when searching for best execution plan
+#
+create table t1(a int);
+insert into t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+create table t2(a int);
+insert into t2 select A.a + B.a* 10 + C.a * 100 from t1 A, t1 B, t1 C;
+create table t3 (a int);
+create table t4 (a int);
+insert into t3 select A.a +1000*B.a from t2 A, t1 B;
+insert into t4 select floor(rand()*1000) from t2 limit 500;
+# The following must not use this query plan that does a cross join:
+# | 1 | PRIMARY | <subquery2> | ALL | distinct_key | ... | 500 | |
+# | 1 | PRIMARY | t3 | ALL | NULL | ... | 10000 | Using where; Using join buffer (flat, BNL join) |
+#
+# Instead, it should use eq_ref on the materialized table.
+explain select * from t3 where a in (select a from t4 group by a);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t3 ALL NULL NULL NULL NULL 10000
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED t4 ALL NULL NULL NULL NULL 500
+drop table t1, t2, t3, t4;
set optimizer_switch=@subselect_sj_tmp;
#
# BUG#49129: Wrong result with IN-subquery with join_cache_level=6 and firstmatch=off
@@ -3386,8 +3410,8 @@ EXPLAIN
SELECT a FROM t1 t WHERE a IN (SELECT b FROM t1, t2 WHERE b = a)
GROUP BY a HAVING a != 'z';
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t index idx_a idx_a 4 NULL 3 Using index
-1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 2 Using temporary; Using filesort
+1 PRIMARY t index idx_a idx_a 4 NULL 3 Using where; Using index
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 2 Using where
2 MATERIALIZED t1 ref idx_a idx_a 4 test.t2.b 2 Using index
SELECT a FROM t1 t WHERE a IN (SELECT b FROM t1, t2 WHERE b = a)
@@ -3400,8 +3424,8 @@ EXPLAIN
SELECT a FROM t1 t WHERE a IN (SELECT b FROM t1, t2 WHERE b = a)
GROUP BY a HAVING a != 'z';
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t index idx_a idx_a 4 NULL 3 Using index
-1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 2 Using temporary; Using filesort
+1 PRIMARY t index idx_a idx_a 4 NULL 3 Using where; Using index; Using join buffer (flat, BNL join)
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 2 Using where
2 MATERIALIZED t1 ref idx_a idx_a 4 test.t2.b 2 Using index
SELECT a FROM t1 t WHERE a IN (SELECT b FROM t1, t2 WHERE b = a)
diff --git a/mysql-test/r/subselect_sj_mat.result b/mysql-test/r/subselect_sj_mat.result
index 9e1870875ce..7ef29b4a42f 100644
--- a/mysql-test/r/subselect_sj_mat.result
+++ b/mysql-test/r/subselect_sj_mat.result
@@ -1100,11 +1100,11 @@ insert into t3 values (30);
explain extended
select a from t1 where a in (select c from t2 where d >= 20);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 6 100.00
-1 PRIMARY t1 ALL NULL NULL NULL NULL 7 100.00 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 7 100.00
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 100.00
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 6 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` semi join (`test`.`t2`) where `test`.`t1`.`a` = `test`.`t2`.`c` and `test`.`t2`.`d` >= 20
+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` semi join (`test`.`t2`) where `test`.`t2`.`d` >= 20
select a from t1 where a in (select c from t2 where d >= 20);
a
2
@@ -1514,8 +1514,8 @@ set @@optimizer_switch=@optimizer_switch_local_default;
SET @@optimizer_switch='semijoin=on,materialization=on';
EXPLAIN SELECT COUNT(*) FROM t1 WHERE (f1,f2) IN (SELECT f1,f2 FROM t2);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 2
-1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 7 func,func 1
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 2
SELECT COUNT(*) FROM t1 WHERE (f1,f2) IN (SELECT f1,f2 FROM t2);
COUNT(*)
diff --git a/mysql-test/suite/gcol/r/gcol_select_innodb.result b/mysql-test/suite/gcol/r/gcol_select_innodb.result
index bc9bddad690..81194cf7e13 100644
--- a/mysql-test/suite/gcol/r/gcol_select_innodb.result
+++ b/mysql-test/suite/gcol/r/gcol_select_innodb.result
@@ -691,8 +691,8 @@ WHERE t4.c1 < 'o'
)
AND t1.i1 <= t3.i2_key;
id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 4
1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3
-1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using join buffer (flat, BNL join)
1 PRIMARY t3 eq_ref PRIMARY PRIMARY 4 test.t4.i1 1 Using where
1 PRIMARY t2 ALL NULL NULL NULL NULL 5 Using join buffer (flat, BNL join)
2 MATERIALIZED t4 ALL NULL NULL NULL NULL 3 Using where
@@ -746,8 +746,8 @@ WHERE t4.c1 < 'o'
)
AND t1.i1 <= t3.i2_key;
id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 4
1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3
-1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using join buffer (flat, BNL join)
1 PRIMARY t3 eq_ref PRIMARY PRIMARY 4 test.t4.i1 1 Using where
1 PRIMARY t2 ALL NULL NULL NULL NULL 5 Using join buffer (flat, BNL join)
2 MATERIALIZED t4 ALL NULL NULL NULL NULL 3 Using where
@@ -802,8 +802,8 @@ WHERE t4.c1 < 'o'
)
AND t1.i1 <= t3.i2_key;
id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 4
1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3
-1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using join buffer (flat, BNL join)
1 PRIMARY t3 eq_ref PRIMARY PRIMARY 4 test.t4.i1 1 Using where
1 PRIMARY t2 ALL NULL NULL NULL NULL 5 Using join buffer (flat, BNL join)
2 MATERIALIZED t4 ALL NULL NULL NULL NULL 3 Using where
@@ -866,8 +866,8 @@ WHERE t4.c1 < 'o'
)
AND t1.i1 <= t3.i2_key;
id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 4
1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3
-1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using join buffer (flat, BNL join)
1 PRIMARY t3 eq_ref PRIMARY PRIMARY 4 test.t4.i1 1 Using where
1 PRIMARY t2 ALL NULL NULL NULL NULL 5 Using join buffer (flat, BNL join)
2 MATERIALIZED t4 ALL NULL NULL NULL NULL 3 Using where
diff --git a/mysql-test/suite/gcol/r/gcol_select_myisam.result b/mysql-test/suite/gcol/r/gcol_select_myisam.result
index d0fe7fbd0d4..934443d3e3d 100644
--- a/mysql-test/suite/gcol/r/gcol_select_myisam.result
+++ b/mysql-test/suite/gcol/r/gcol_select_myisam.result
@@ -1313,8 +1313,8 @@ WHERE t4.c1 < 'o'
)
AND t1.i1 <= t3.i2_key;
id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 4
1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3
-1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using join buffer (flat, BNL join)
1 PRIMARY t3 eq_ref PRIMARY,v_idx PRIMARY 4 test.t4.i1 1 Using where
1 PRIMARY t2 ALL NULL NULL NULL NULL 5 Using join buffer (flat, BNL join)
2 MATERIALIZED t4 ALL NULL NULL NULL NULL 3 Using where
@@ -1369,8 +1369,8 @@ WHERE t4.c1 < 'o'
)
AND t1.i1 <= t3.i2_key;
id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 4
1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3
-1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using join buffer (flat, BNL join)
1 PRIMARY t3 eq_ref PRIMARY,v_idx,v_idx2 PRIMARY 4 test.t4.i1 1 Using where
1 PRIMARY t2 ALL NULL NULL NULL NULL 5 Using join buffer (flat, BNL join)
2 MATERIALIZED t4 ALL NULL NULL NULL NULL 3 Using where
@@ -1427,8 +1427,8 @@ WHERE t4.c1 < 'o'
)
AND t1.i1 <= t3.i2_key;
id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 4
1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3
-1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using join buffer (flat, BNL join)
1 PRIMARY t3 eq_ref PRIMARY,v_idx2 PRIMARY 4 test.t4.i1 1 Using where
1 PRIMARY t2 ALL NULL NULL NULL NULL 5 Using join buffer (flat, BNL join)
2 MATERIALIZED t4 ALL NULL NULL NULL NULL 3 Using where
@@ -1494,8 +1494,8 @@ WHERE t4.c1 < 'o'
)
AND t1.i1 <= t3.i2_key;
id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 4
1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3
-1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using join buffer (flat, BNL join)
1 PRIMARY t3 eq_ref PRIMARY,v_idx PRIMARY 4 test.t4.i1 1 Using where
1 PRIMARY t2 ALL NULL NULL NULL NULL 5 Using join buffer (flat, BNL join)
2 MATERIALIZED t4 ALL NULL NULL NULL NULL 3 Using where
diff --git a/mysql-test/t/subselect_sj.test b/mysql-test/t/subselect_sj.test
index f90f1e2e927..d29dd998d23 100644
--- a/mysql-test/t/subselect_sj.test
+++ b/mysql-test/t/subselect_sj.test
@@ -2845,5 +2845,31 @@ eval EXPLAIN EXTENDED $q2;
DROP TABLE t1,t2,t3,t4;
+set optimizer_switch = 'materialization=on';
+--echo #
+--echo # MDEV-20109: Optimizer ignores distinct key created for materialized
+--echo # semi-join subquery when searching for best execution plan
+--echo #
+create table t1(a int);
+insert into t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+
+create table t2(a int);
+insert into t2 select A.a + B.a* 10 + C.a * 100 from t1 A, t1 B, t1 C;
+
+create table t3 (a int);
+create table t4 (a int);
+insert into t3 select A.a +1000*B.a from t2 A, t1 B;
+insert into t4 select floor(rand()*1000) from t2 limit 500;
+
+--echo # The following must not use this query plan that does a cross join:
+--echo # | 1 | PRIMARY | <subquery2> | ALL | distinct_key | ... | 500 | |
+--echo # | 1 | PRIMARY | t3 | ALL | NULL | ... | 10000 | Using where; Using join buffer (flat, BNL join) |
+--echo #
+--echo # Instead, it should use eq_ref on the materialized table.
+
+explain select * from t3 where a in (select a from t4 group by a);
+
+drop table t1, t2, t3, t4;
+
# The following command must be the last one the file
set optimizer_switch=@subselect_sj_tmp;
diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc
index 3b98b650f8f..b4350551461 100644
--- a/sql/opt_subselect.cc
+++ b/sql/opt_subselect.cc
@@ -2329,7 +2329,7 @@ bool optimize_semijoin_nests(JOIN *join, table_map all_table_map)
&subjoin_out_rows);
sjm->materialization_cost.convert_from_cost(subjoin_read_time);
- sjm->rows= subjoin_out_rows;
+ sjm->rows_with_duplicates= sjm->rows= subjoin_out_rows;
// Don't use the following list because it has "stale" items. use
// ref_pointer_array instead:
@@ -2946,11 +2946,12 @@ bool Sj_materialization_picker::check_qep(JOIN *join,
disable_jbuf, prefix_rec_count, &curpos, &dummy);
prefix_rec_count *= curpos.records_read;
prefix_cost += curpos.read_time;
+ prefix_cost += prefix_rec_count / (double) TIME_FOR_COMPARE;
}
*strategy= SJ_OPT_MATERIALIZE_SCAN;
*read_time= prefix_cost;
- *record_count= prefix_rec_count;
+ *record_count= prefix_rec_count / mat_info->rows_with_duplicates;
*handled_fanout= mat_nest->sj_inner_tables;
return TRUE;
}
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 37a111ade5e..e69a8475a88 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -5498,7 +5498,10 @@ class SJ_MATERIALIZATION_INFO : public Sql_alloc
uint tables; /* Number of tables in the sj-nest */
- /* Expected #rows in the materialized table */
+ /* Number of rows in the materialized table, before the de-duplication */
+ double rows_with_duplicates;
+
+ /* Expected #rows in the materialized table, after de-duplication */
double rows;
/*
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 2e123df75f0..be2aeb52618 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -8383,6 +8383,7 @@ best_extension_by_limited_search(JOIN *join,
restore_prev_nj_state(s);
restore_prev_sj_state(remaining_tables, s, idx);
}
+ /* TODO: Take into account condition selectivities here */
}
DBUG_RETURN(FALSE);
}
@@ -15573,6 +15574,18 @@ void optimize_wo_join_buffering(JOIN *join, uint first_tab, uint last_tab,
rec_count *= pos.records_read;
cost += pos.read_time;
+ cost += rec_count / (double) TIME_FOR_COMPARE;
+ //TODO: take into account join condition selectivity here
+ double pushdown_cond_selectivity= 1.0;
+ table_map real_table_bit= rs->table->map;
+ if (join->thd->variables.optimizer_use_condition_selectivity > 1)
+ {
+ pushdown_cond_selectivity= table_cond_selectivity(join, i, rs,
+ reopt_remaining_tables &
+ ~real_table_bit);
+ }
+ (*outer_rec_count) *= pushdown_cond_selectivity;
+
if (!rs->emb_sj_nest)
*outer_rec_count *= pos.records_read;
}
1
0
[Commits] e4c5536: MDEV-19956 Queries with subqueries containing UNION are not parsed
by IgorBabaev 15 Sep '19
by IgorBabaev 15 Sep '19
15 Sep '19
revision-id: e4c5536a237093249f589d4946494dad41c60486 (mariadb-10.4.5-120-ge4c5536)
parent(s): e8392e58b2a5a69f9c0bd5b5aed90348b4a0ccb3
author: Igor Babaev
committer: Igor Babaev
timestamp: 2019-09-14 17:23:20 -0700
message:
MDEV-19956 Queries with subqueries containing UNION are not parsed
Shift-Reduce conflicts prevented parsing some queries with subqueries that
used set operations when the subqueries occurred in expressions or in IN
predicands.
The grammar rules for query expression were transformed in order to avoid
these conflicts. New grammar rules employ an idea taken from MySQL 8.0.
---
mysql-test/main/brackets.result | 4022 +++++++++++++++++++-
mysql-test/main/brackets.test | 2318 +++++++++++
mysql-test/main/cte_nonrecursive.result | 4 +-
mysql-test/main/cte_recursive.result | 6 +-
mysql-test/main/except.result | 4 +-
mysql-test/main/intersect.result | 6 +-
mysql-test/main/parser.result | 2 +-
mysql-test/main/parser.test | 1 -
mysql-test/main/ps.result | 8 +-
mysql-test/main/statement-expr.result | 16 +-
mysql-test/main/subselect.result | 19 +-
mysql-test/main/subselect.test | 4 -
mysql-test/main/subselect_no_exists_to_in.result | 19 +-
mysql-test/main/subselect_no_mat.result | 19 +-
mysql-test/main/subselect_no_opts.result | 19 +-
mysql-test/main/subselect_no_scache.result | 19 +-
mysql-test/main/subselect_no_semijoin.result | 19 +-
mysql-test/main/subselect_notembedded.result | 2 +-
mysql-test/suite/compat/oracle/r/ps.result | 8 +-
.../suite/compat/oracle/r/statement-expr.result | 16 +-
sql/item_subselect.cc | 3 +-
sql/sql_cte.cc | 16 +
sql/sql_lex.cc | 295 +-
sql/sql_lex.h | 48 +-
sql/sql_table.cc | 2 +-
sql/sql_tvc.cc | 4 +-
sql/sql_union.cc | 49 +-
sql/sql_yacc.yy | 442 ++-
sql/sql_yacc_ora.yy | 428 ++-
29 files changed, 7226 insertions(+), 592 deletions(-)
diff --git a/mysql-test/main/brackets.result b/mysql-test/main/brackets.result
index e14bef9..dedd9a2 100644
--- a/mysql-test/main/brackets.result
+++ b/mysql-test/main/brackets.result
@@ -355,7 +355,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 UNION t1 ALL NULL NULL NULL NULL 3 100.00
NULL UNION RESULT <union1,2> ALL NULL NULL NULL NULL NULL NULL Using filesort
Warnings:
-Note 1003 (/* select#1 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = 20) union /* select#2 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` order by `a` desc limit 1
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = 20 union /* select#2 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` order by `a` desc limit 1
explain format=json ((select a from t1 where a=20 union select a from t1) order by a desc) limit 1;
EXPLAIN
{
@@ -494,4 +494,4024 @@ a
3
8
drop table t1;
+#
+# MDEV-19956: query expressions in different contexts
+#
+create table t1 (a int);
+insert into t1 values (3), (7), (1), (2), (4);
+create table t2 (a int, b int);
+insert into t2 values (3,30), (7,70), (1,10), (2,20), (4,40);
+# 1. select
+# 1.1. simple select
+select * from t1;
+a
+3
+7
+1
+2
+4
+(select * from t1);
+a
+3
+7
+1
+2
+4
+((select * from t1));
+a
+3
+7
+1
+2
+4
+# 1.2. select with tail
+select * from t1 order by a;
+a
+1
+2
+3
+4
+7
+select a from t1 order by a;
+a
+1
+2
+3
+4
+7
+select a from t1 order by 1;
+a
+1
+2
+3
+4
+7
+select * from t1 order by t1.a;
+a
+1
+2
+3
+4
+7
+(select * from t1 order by t1.a);
+a
+1
+2
+3
+4
+7
+((select * from t1 order by t1.a));
+a
+1
+2
+3
+4
+7
+(select * from t1 order by t1.a limit 2);
+a
+1
+2
+(select a from t1 where a=1) order by 1 desc;
+a
+1
+# 1.2. select with several tails
+(select * from t2 order by a limit 2) order by b desc;
+a b
+2 20
+1 10
+(select * from t2 order by t2.a limit 2) order by b desc;
+a b
+2 20
+1 10
+((select * from t2 order by t2.a limit 2) order by b desc);
+a b
+2 20
+1 10
+(((select * from t2 order by t2.a) limit 2) order by b desc);
+a b
+2 20
+1 10
+# 2. union
+# 2.1 simple union
+select a from t1 union select a from t1;
+a
+3
+7
+1
+2
+4
+select a from t1 union all select a from t1;
+a
+3
+7
+1
+2
+4
+3
+7
+1
+2
+4
+select a from t1 union select b from t2;
+a
+3
+7
+1
+2
+4
+30
+70
+10
+20
+40
+(select a from t1) union (select a from t1);
+a
+3
+7
+1
+2
+4
+(select a from t1) union (select b from t2);
+a
+3
+7
+1
+2
+4
+30
+70
+10
+20
+40
+select a from t1 where a=1 union select a from t1 where a=3;
+a
+1
+3
+(select a from t1 where a=1) union select a from t1 where a=3;
+a
+1
+3
+((select a from t1 where a=1) union select a from t1 where a=3);
+a
+1
+3
+((select a from t1 where a<=3) union (select a from t1 where a=3));
+a
+3
+1
+2
+select a from t1 where a=1 union (select a from t1 where a=3);
+a
+1
+3
+(select a from t1 where a=1 union (select a from t1 where a=3));
+a
+1
+3
+((select a from t1 where a=1 union (select a from t1 where a=3)));
+a
+1
+3
+select a from t1 where a=1
+union
+select a from t1 where a=3
+union
+select a from t1 where a=7;
+a
+1
+3
+7
+( select a from t1 where a=1
+union
+select a from t1 where a=3
+union
+select a from t1 where a=7 );
+a
+1
+3
+7
+(select a from t1 where a=1 order by a) union select a from t1 where a=3;
+a
+1
+3
+(select a from t1 where a!=3 order by a desc) union select a from t1 where a=3;
+a
+7
+1
+2
+4
+3
+((select a from t1 where a=1 order by a) union select a from t1 where a=3);
+a
+1
+3
+(select a from t1 where a!=3 order by a desc) union select a from t1 where a=3;
+a
+7
+1
+2
+4
+3
+( ( select a from t1 where a!=3 order by a desc limit 3)
+union
+select a from t1 where a=3 );
+a
+7
+4
+2
+3
+( select a from t1 where a <=3 except select a from t1 where a >=3 )
+union
+select a from t1 where a=7;
+a
+1
+2
+7
+( ( select a from t1 where a <=3
+except
+select a from t1 where a >=3 )
+union
+select a from t1 where a=7 );
+a
+1
+2
+7
+( select a from t1 where a <=3
+except
+( select a from t1 where a >=3
+union
+select a from t1 where a=7 ) );
+a
+1
+2
+( ( select a from t1 where a <=3 )
+except
+( select a from t1 where a >=3
+union
+select a from t1 where a=7 ) );
+a
+1
+2
+# 2.2. union with tail
+select a from t1 where a=1 union select a from t1 where a=3 order by a desc;
+a
+3
+1
+(select a from t1 limit 2) union select a from t1 where a=3 order by a desc;
+a
+7
+3
+select a from t1 where a=4 union (select a from t1 where a <=4 limit 2)
+order by a desc;
+a
+4
+3
+1
+select a from t1 where a=4
+union
+(select a from t1 where a <=4 order by a limit 2)
+order by a desc;
+a
+4
+2
+1
+( select a from t1 where a=4
+union
+( select a from t1 where a <=4 order by a limit 2 ) )
+order by a desc;
+a
+4
+2
+1
+( select a from t1 where a <=3 except select a from t1 where a >=3 )
+union
+select a from t1 where a=7 order by a desc;
+a
+7
+2
+1
+( select a from t1 where a!=3 order by a desc )
+union
+select a from t1 where a=3
+order by a desc;
+a
+7
+4
+3
+2
+1
+(select a from t1 where a=1)
+union
+(select a from t1 where a=3)
+order by a desc;
+a
+3
+1
+( select a from t1 where a=1
+union
+select a from t1 where a=3 )
+order by a desc;
+a
+3
+1
+( ( select a from t1 where a=1 )
+union
+( select a from t1 where a=3 ) )
+order by a desc;
+a
+3
+1
+( select a from t1 where a=1
+union
+select a from t1 where a=3 )
+order by 1 desc;
+a
+3
+1
+((select a from t1 where a=1 union select a from t1 where a=3)) order by 1 desc;
+a
+3
+1
+(((select a from t1 where a=1) union (select a from t1 where a=3)))
+order by 1 desc;
+a
+3
+1
+( (select a from t1 where a=1 )
+union
+(select a from t1 where a=3) )
+order by 1 desc;
+a
+3
+1
+# 2.3. complex union
+select a from t1 where a=1
+union
+select a from t1 where a=3
+union
+select a from t1 where a=2
+union
+select a from t1 where a=4;
+a
+1
+3
+2
+4
+( select a from t1 where a=1
+union
+select a from t1 where a=3
+union
+select a from t1 where a=2 )
+union
+select a from t1 where a=4;
+a
+1
+3
+2
+4
+(select a from t1 where a=1 union select a from t1 where a=3)
+union
+(select a from t1 where a=2 union select a from t1 where a=4);
+a
+1
+3
+2
+4
+(select a from t1 where a=1 union (select a from t1 where a=3))
+union
+((select a from t1 where a=2) union select a from t1 where a=4);
+a
+1
+3
+2
+4
+( ( select a from t1 where a=1)
+union
+select a from t1 where a=3 )
+union
+select a from t1 where a=2
+union
+select a from t1 where a=4;
+a
+1
+3
+2
+4
+( ( ( select a from t1 where a=1)
+union
+select a from t1 where a=3 )
+union
+select a from t1 where a=2 )
+union
+select a from t1 where a=4;
+a
+1
+3
+2
+4
+select a from t1 where a=1
+union
+select a from t1 where a=3
+union
+select a from t1 where a=2
+union
+(select a from t1 where a=4);
+a
+1
+3
+2
+4
+select a from t1 where a=1
+union
+select a from t1 where a=3
+union
+( select a from t1 where a=2
+union
+( select a from t1 where a=4 ) );
+a
+1
+3
+2
+4
+select a from t1 where a=1
+union
+( select a from t1 where a=3
+union
+( select a from t1 where a=2
+union
+( select a from t1 where a=4 ) ) );
+a
+1
+3
+2
+4
+# 2.4. complex union with tail
+( ( select a from t1 where a=1 union select a from t1 where a=3 )
+order by a desc )
+union
+( ( select a from t1 where a=2 union select a from t1 where a=4 )
+order by a desc );
+a
+3
+1
+4
+2
+( ( select a from t1 where a=1 union select a from t1 where a=3 )
+order by a desc )
+union
+( ( select a from t1 where a=2 union select a from t1 where a=4 )
+order by a desc )
+order by a;
+a
+1
+2
+3
+4
+( select a from t1 where a=1
+union
+select a from t1 where a=3
+union
+select a from t1 where a=2 order by a desc limit 2 )
+union
+select a from t1 where a=4
+order by a;
+a
+2
+3
+4
+( select a from t1 where a=1
+union
+select a from t1 where a=3 order by a desc )
+union
+select a from t1 where a=2 order by a desc limit 2;
+a
+3
+2
+( ( select a from t1 where a >= 2
+union
+select a from t1 where a=1 order by a desc limit 2 )
+union
+select a from t1 where a=3 order by a limit 2 )
+union
+select a from t1 where a=1;
+a
+3
+4
+1
+# 3. TVC
+# 3.1. simple TVC
+values (3), (7), (1);
+3
+3
+7
+1
+(values (3), (7), (1));
+3
+3
+7
+1
+((values (3), (7), (1)));
+3
+3
+7
+1
+# 3.2. simple TVC with tail(s)
+values (3), (7), (1) order by 1;
+3
+1
+3
+7
+(values (3), (7), (1)) order by 1;
+3
+1
+3
+7
+((values (3), (7), (1))) order by 1;
+3
+1
+3
+7
+(((values (3), (7), (1))) order by 1);
+3
+1
+3
+7
+(values (3), (7), (1) limit 2) order by 1 desc;
+3
+7
+3
+((values (3), (7), (1)) order by 1 desc) limit 2;
+3
+7
+3
+(((values (3), (7), (1)) order by 1 desc) limit 2);
+3
+7
+3
+# 3.3. union of TVCs
+values (3), (7), (1) union values (3), (4), (2);
+3
+3
+7
+1
+4
+2
+values (3), (7), (1) union all values (3), (4), (2);
+3
+3
+7
+1
+3
+4
+2
+values (3), (7), (1) union values (3), (4), (2);
+3
+3
+7
+1
+4
+2
+values (3), (7), (1) except values (3), (4), (2);
+3
+7
+1
+(values (3), (7), (1)) union (values (3), (4), (2));
+3
+3
+7
+1
+4
+2
+(values (3), (7), (1)) union (values (3), (4), (2)) union values (5), (7);
+3
+3
+7
+1
+4
+2
+5
+(values (3), (7), (1)) union (values (3), (4), (2)) union (values (5), (7));
+3
+3
+7
+1
+4
+2
+5
+(values (3), (7), (1) union values (3), (4), (2)) union values (5), (7);
+3
+3
+7
+1
+4
+2
+5
+values (3), (7), (1) union (values (3), (4), (2) union values (5), (7));
+3
+3
+7
+1
+4
+2
+5
+(values (3), (7), (1) union ((values (3), (4), (2) union values (5), (7))));
+3
+3
+7
+1
+4
+2
+5
+# 3.4. tailed union of TVCs
+values (3), (7), (1) union values (3), (4), (2) order by 1;
+3
+1
+2
+3
+4
+7
+(values (3), (7), (1) union values (3), (4), (2)) order by 1;
+3
+1
+2
+3
+4
+7
+(values (3), (7), (1) union values (3), (4), (2)) order by 1;
+3
+1
+2
+3
+4
+7
+values (3), (7), (1) union (values (3), (4), (2)) order by 1;
+3
+1
+2
+3
+4
+7
+(values (3), (7), (1) union values (3), (4), (2)) order by 1;
+3
+1
+2
+3
+4
+7
+((values (3), (7), (1)) union values (3), (4), (2)) order by 1;
+3
+1
+2
+3
+4
+7
+# 3.5. union of tailed TVCs
+(values (3), (7), (1) order by 1 limit 2)
+union
+(values (3), (4), (2) order by 1 desc limit 2);
+3
+1
+3
+4
+((values (3), (7), (1) order by 1) limit 2)
+union
+((values (3), (4), (2) order by 1 desc) limit 2);
+3
+1
+3
+4
+(((values (3), (7), (1)) order by 1) limit 2)
+union
+(((values (3), (4), (2)) order by 1 desc) limit 2);
+3
+1
+3
+4
+# 3.6. tailed union of tailed TVCs
+(values (3), (7), (1) order by 1 limit 2)
+union
+values (3), (4), (2)
+order by 1;
+3
+1
+2
+3
+4
+((values (3), (7), (1)) order by 1 limit 2)
+union
+((values (3), (4), (2) order by 1 desc) limit 2)
+order by 1;
+3
+1
+3
+4
+# 3.7 [tailed] union of [tailed] select and [tailed] TVC
+(select a from t1 where a <=3 order by 1 limit 2)
+union
+(values (3), (4), (2) order by 1 desc limit 2);
+a
+1
+2
+4
+3
+((select a from t1 where a <=3) order by 1 limit 2)
+union
+(values (3), (4), (2) order by 1 desc limit 2);
+a
+1
+2
+4
+3
+(((select a from t1 where a <=3) order by a) limit 2)
+union
+(((values (3), (4), (2)) order by 1 desc) limit 2);
+a
+1
+2
+4
+3
+( (((select a from t1 where a <=3) order by a) limit 2)
+union
+(((values (3), (4), (2)) order by 1 desc) limit 2) );
+a
+1
+2
+4
+3
+(select a from t1 where a <=3 order by 1 limit 2)
+union
+(values (3), (4), (2) order by 1 desc limit 2)
+order by a;
+a
+1
+2
+3
+4
+((select a from t1 where a <=3) order by 1 limit 2)
+union
+(values (3), (4), (2) order by 1 desc limit 2)
+order by a;
+a
+1
+2
+3
+4
+(((select a from t1 where a <=3) order by a) limit 2)
+union
+(((values (3), (4), (2)) order by 1 desc) limit 2)
+order by a;
+a
+1
+2
+3
+4
+(((values (3), (4), (2)) order by 1 desc) limit 2);
+3
+4
+3
+( (((select a from t1 where a <=3) order by a) limit 2)
+union
+(((values (3), (4), (2)) order by 1 desc) limit 2) )
+order by a;
+a
+1
+2
+3
+4
+(values (3), (4), (2) order by 1 desc limit 2)
+union
+(select a from t1 where a <=3 order by 1 limit 2);
+3
+4
+3
+1
+2
+(values (3), (4), (2) order by 1 desc limit 2)
+union
+((select a from t1 where a <=3) order by 1 limit 2);
+3
+4
+3
+1
+2
+(((values (3), (4), (2)) order by 1 desc) limit 2)
+union
+(((select a from t1 where a <=3) order by 1) limit 2);
+3
+4
+3
+1
+2
+(((values (3), (4), (2)) order by 1 desc) limit 2)
+union
+(((select a from t1 where a <=3) order by a) limit 2)
+order by 1;
+3
+1
+2
+3
+4
+( select a from t1 where a=1
+union
+values (3), (4), (2) order by 1 desc )
+union
+select a from t1 where a=2 order by a desc limit 3;
+a
+4
+3
+2
+4. CTE
+4.1. simple select with simple CTE
+with t as (select * from t1 where a <=3)
+select * from t;
+a
+3
+1
+2
+with t as (select * from t1 where a <=3)
+(select * from t);
+a
+3
+1
+2
+with t as (select * from t1 where a <=3)
+((select * from t));
+a
+3
+1
+2
+with t as ((select * from t1 where a <=3))
+select * from t;
+a
+3
+1
+2
+with t as (((select * from t1 where a <=3)))
+select * from t;
+a
+3
+1
+2
+4.2. tailed select with simple CTE
+with t as (select * from t1 where a <=3)
+select * from t order by a;
+a
+1
+2
+3
+with t as (select * from t1 where a <=3)
+(select * from t) order by a;
+a
+1
+2
+3
+with t as (select * from t1 where a <=3)
+(select * from t) order by a desc limit 2;
+a
+3
+2
+4.3. [tailed] select with tailed CTE
+with t as (select * from t1 where a >=2 order by a limit 2)
+select * from t;
+a
+2
+3
+with t as (((select * from t1 where a >=2) order by a desc) limit 2)
+select * from t;
+a
+7
+4
+with t as (select * from t1 where a >=2 order by a desc limit 2)
+select * from t order by a;
+a
+4
+7
+4.4. [tailed] union with CTE
+with t as (select * from t1 where a <=3)
+select a from t1 where a=1 union select a from t where a=3;
+a
+1
+3
+with t as (select * from t1 where a <=3)
+(select a from t) union (select b from t2);
+a
+3
+1
+2
+30
+70
+10
+20
+40
+with t as (select * from t1 where a <=3)
+(select a from t) union (select b as a from t2) order by a desc;
+a
+70
+40
+30
+20
+10
+3
+2
+1
+4.5. [tailed] union with [tailed] union in CTE
+with t as (select * from t1 where a < 3 union select * from t1 where a > 3)
+select a from t1 where a=1 union select a from t where a=7;
+a
+1
+7
+with t as
+( select * from t1 where a < 3
+union
+select * from t1 where a > 3
+order by a desc limit 3 )
+select a from t1 where a=4 union select a from t where a=7;
+a
+4
+7
+with t as
+( select * from t1 where a < 3
+union
+select * from t1 where a > 3
+order by a desc limit 3 )
+select a from t1 where a=4 union select a from t where a=7 order by a desc;
+a
+7
+4
+with t as
+( (select * from t1 where a < 3)
+union
+(select * from t1 where a > 3)
+order by a desc limit 3 )
+select a from t1 where a=4 union select a from t where a=7 order by a desc;
+a
+7
+4
+with t as
+( (select * from t1 where a < 3)
+union
+(select * from t1 where a > 3)
+order by a desc limit 3 )
+(select a from t1 where a=4 union select a from t where a=7 order by a desc);
+a
+7
+4
+with t as
+( (select * from t1 where a < 3)
+union
+(select * from t1 where a > 3)
+order by a desc limit 3 )
+((select a from t1 where a=4 union select a from t where a=7) order by a desc);
+a
+7
+4
+with t as
+( select * from t1 where a < 3
+union
+values (4), (7)
+order by a desc limit 3 )
+select a from t1 where a=4 union select a from t where a=7 order by a desc;
+a
+7
+4
+4.6. [tailed] union with [tailed] union of TVC in CTE
+with t(a) as
+( values (2), (1)
+union
+(values (4), (7))
+order by 1 desc limit 3 )
+select a from t1 where a=4 union select a from t where a=7 order by a desc;
+a
+7
+4
+with t(a) as
+( (values (2), (1))
+union
+(values (4), (7) order by 1 desc)
+order by 1 desc limit 3 )
+select a from t1 where a=1 union select a from t where a=7 order by a desc;
+a
+7
+1
+with t(a) as
+( (values (2), (1))
+union
+(values (4), (7) order by 1 desc)
+order by 1 limit 3 )
+select a from t where a=1 union values (7) order by a desc;
+a
+7
+1
+with t(a) as
+( (values (2), (1))
+union
+(values (4), (7) order by 1 desc ) )
+select a from t where a=1 union select 7 order by a desc;
+a
+7
+1
+4.5. [tailed] union with two CTEs
+with t as (select * from t1 where a < 3),
+s as (select * from t1 where a > 3)
+select a from t where a=1 union select a from s where a=7 order by a desc;
+a
+7
+1
+with t as (select * from t1 where a < 3),
+s as (select * from t1 where a > 3)
+(select a from t where a=1 union select a from s where a=7 order by a desc);
+a
+7
+1
+with t as (select * from t1 where a < 3),
+s as (select * from t1 where a > 3)
+(select a from t where a=1 union select a from s where a=7) order by a desc;
+a
+7
+1
+with t as (select * from t1 where a < 3),
+s as (select * from t where a > 3)
+select a from t where a=1 union select a from s where a=7 order by a desc;
+a
+1
+# 5. single-row subquery in expression
+# 5.1. [tailed] simple select in expression
+select (a+1) + b as r from t2;
+r
+34
+78
+12
+23
+45
+select ((a+1) + b) as r from t2;
+r
+34
+78
+12
+23
+45
+select (b + (select 1)) as r from t2;
+r
+31
+71
+11
+21
+41
+select (select a from t1 where a <=3 order by a desc limit 1) as r from t2;
+r
+3
+3
+3
+3
+3
+select
+(select a from t1 where a <=3 order by a desc limit 1) as r from t2;
+r
+3
+3
+3
+3
+3
+select (select 100) as r from t2;
+r
+100
+100
+100
+100
+100
+select ((select 100)) as r from t2;
+r
+100
+100
+100
+100
+100
+select (select 100) + t2.b as r from t2;
+r
+130
+170
+110
+120
+140
+select ((select 100) + t2.b) as r from t2;
+r
+130
+170
+110
+120
+140
+# 5.2. [tailed] TVC in expression
+select (values (200)) as r from t2;
+r
+200
+200
+200
+200
+200
+select ((values (200))) as r from t2;
+r
+200
+200
+200
+200
+200
+select (values (200)) + t2.b as r from t2;
+r
+230
+270
+210
+220
+240
+select ((values (200)) + t2.b) as r from t2;
+r
+230
+270
+210
+220
+240
+select (values (200), (300) order by 1 desc limit 1) as r from t2;
+r
+300
+300
+300
+300
+300
+select ((values (200), (300)) order by 1 desc limit 1) as r from t2;
+r
+300
+300
+300
+300
+300
+select (select * from t1 limit 1) as r from t2;
+r
+3
+3
+3
+3
+3
+select (select * from t1 order by a limit 1) as r from t2;
+r
+1
+1
+1
+1
+1
+select ((select * from t1 order by a limit 1)) as r from t2;
+r
+1
+1
+1
+1
+1
+((select ((select * from t1 order by a limit 1)) as r from t2));
+r
+1
+1
+1
+1
+1
+select (select * from t1 order by a limit 1) + t2.b as r from t2;
+r
+31
+71
+11
+21
+41
+# 5.3. [tailed] union in expression
+select
+( select a from t1 where a<3 union select a from t1 where a>4
+order by a desc limit 1 ) as r
+from t1;
+r
+7
+7
+7
+7
+7
+select
+( (select a from t1 where a<3) union (select a from t1 where a>4)
+order by a desc limit 1 ) as r
+from t1;
+r
+7
+7
+7
+7
+7
+select
+( select a from t1 where a<3 union select a from t1 where a>4
+order by a desc limit 1 ) + t1.a as r
+from t1;
+r
+10
+14
+8
+9
+11
+select
+t1.a +
+( select a from t1 where a<3 union select a from t1 where a>4
+order by a desc limit 1 ) as r
+from t1;
+r
+10
+14
+8
+9
+11
+select
+( (select a from t1 where a<3 union select a from t1 where a>4
+order by a desc limit 1 ) + t1.a) as r
+from t1;
+r
+10
+14
+8
+9
+11
+select
+( ( (select a from t1 where a<3) union (select a from t1 where a>4)
+order by a desc limit 1 ) + t1.a ) as r
+from t1;
+r
+10
+14
+8
+9
+11
+# 5.4. [tailed] select with simple CTE in expression
+select
+( with t as (select * from t1 where a <=3)
+select a from t limit 1) as r
+from t2;
+r
+3
+3
+3
+3
+3
+select
+( with t as (select * from t1 where a <=3)
+select a from t limit 1) + t2.b as r
+from t2;
+r
+33
+73
+13
+23
+43
+select
+t2.b +( with t as (select * from t1 where a <=3)
+select a from t limit 1) as r
+from t2;
+r
+33
+73
+13
+23
+43
+select
+((( with t as (select * from t1 where a <=3)
+select a from t limit 1) + t2.b)) as r
+from t2;
+r
+33
+73
+13
+23
+43
+select
+( with t as (select * from t1 where a <=3)
+select a from t limit 1) + 100 as r
+from t2;
+r
+103
+103
+103
+103
+103
+select
+( with t as (select * from t1 where a <=3)
+select a from t limit 1) + (select 100) as r
+from t2;
+r
+103
+103
+103
+103
+103
+select
+( with t as (select * from t1 where a <=3)
+select a from t limit 1) + t2.b + (select 100) as r
+from t2;
+r
+133
+173
+113
+123
+143
+select
+( with t as (select * from t1 where a <=3)
+select a from t limit 1 ) + (t2.b + (select 100)) as r
+from t2;
+r
+133
+173
+113
+123
+143
+select
+( with t as (select * from t1 where a <=3)
+select a from t limit 1 ) + t2.b + (values (100)) as r
+from t2;
+r
+133
+173
+113
+123
+143
+# 5.5. [tailed] union with simple CTE in expression
+select
+( with t as (select * from t1 where a <=3)
+select a from t union select b from t2 order by a desc limit 1) as r
+from t2;
+r
+70
+70
+70
+70
+70
+select
+( with t as (select * from t1 where a <=3)
+(select a from t) union (select b from t2) order by a desc limit 1) as r
+from t2;
+r
+70
+70
+70
+70
+70
+select
+( with t as (select * from t1 where a <=3)
+(select a from t) union (select b from t2) order by a desc limit 1) as r
+from t2;
+r
+70
+70
+70
+70
+70
+select
+( ( with t as (select * from t1 where a <=3)
+(select a from t) union (select b from t2) order by a desc limit 1) +
+t2.a ) as r
+from t2;
+r
+73
+77
+71
+72
+74
+# 5.6. [tailed] union with CTE with union in expression
+select
+( with t as
+( select * from t1 where a < 3
+union
+select * from t1 where a > 3
+order by a desc limit 3 )
+select a from t1 where a=4 union select a from t where a=7 limit 1) as r
+from t2;
+r
+4
+4
+4
+4
+4
+select
+( with t as
+( select * from t1 where a < 3
+union
+select * from t1 where a > 3
+order by a desc limit 3 )
+select a from t1 where a=4 union select a from t where a=7 limit 1) +
+t2. b as r
+from t2;
+r
+34
+74
+14
+24
+44
+# 5.7. [tailed] union of TVCs with CTE with union in expression
+select
+( with t(a) as
+( (values (2), (1))
+union
+(values (4), (7) order by 1 limit 1)
+order by 1 desc limit 3 ) select * from t limit 1 ) + t2.b as r
+from t2;
+r
+34
+74
+14
+24
+44
+select
+( with t(a) as
+( select 2 union select 1
+union
+(values (4), (7) order by 1 limit 1)
+order by 1 limit 3 ) select * from t limit 1 ) + t2.b as r
+from t2;
+r
+31
+71
+11
+21
+41
+# 6. subquery
+# 6.1. TVC in IN subquery
+select a from t1 where a in (1,8,7);
+a
+7
+1
+select a from t1 where a in (values (1), (8), (7));
+a
+7
+1
+# 6.2. simple select in IN subquery
+select a from t1 where a in (select a from t2 where a <= 3);
+a
+3
+1
+2
+select a from t1 where a in ((select a from t2 where a <= 3));
+a
+3
+1
+2
+# 6.3. union in IN subquery
+select a from t1
+where a in (select a from t1 where a<=2 union select a from t2 where b>40);
+a
+7
+1
+2
+select a from t1
+where a in (select a from t1 where a<=2 union (select a from t2 where b>40));
+a
+7
+1
+2
+select a from t1
+where a in ((select a from t1 where a<=2) union select a from t2 where b>40);
+a
+7
+1
+2
+select a from t1
+where a in ((select a from t1 where a<=2) union (select a from t2 where b>40));
+a
+7
+1
+2
+# 6.4. select with CTE and union in IN subquery
+with t as (select a from t1 where a<=2)
+select a from t1
+where a in ((select a from t) union (select a from t2 where b>40));
+a
+7
+1
+2
+with t as ((select a from t1 where a<=2))
+select a from t1
+where a in ((select a from t) union (select a from t2 where b>40));
+a
+7
+1
+2
+with t as ((select a from t1 where a<=2) order by a desc limit 1)
+select a from t1
+where a in ((select a from t) union (select a from t2 where b>40));
+a
+7
+2
+# 6.5. NOT IN subquery
+select a from t1 where a not in (1,8,7);
+a
+3
+2
+4
+select a from t1 where a not in (values (1), (8), (7));
+a
+3
+2
+4
+select a from t1 where a not in (select a from t2 where a <= 3);
+a
+7
+4
+select a from t1 where a not in ((select a from t2 where a <= 3));
+a
+7
+4
+select a from t1
+where a not in (select a from t1 where a<=2
+union
+select a from t2 where b>40);
+a
+3
+4
+select a from t1
+where a not in (select a from t1 where a<=2
+union
+(select a from t2 where b>40));
+a
+3
+4
+select a from t1
+where a not in ((select a from t1 where a<=2)
+union
+select a from t2 where b>40);
+a
+3
+4
+select a from t1
+where a not in ((select a from t1 where a<=2)
+union
+(select a from t2 where b>40));
+a
+3
+4
+with t as ((select a from t1 where a<=2) order by a desc limit 1)
+select a from t1
+where a not in ((select a from t) union (select a from t2 where b>40));
+a
+3
+1
+4
+# 6.6. IN subquery in expression
+select 1 in (select a from t1) as r, b from t2 where b > 30;
+r b
+1 70
+1 40
+select (1 in (select a from t1)) as r, b from t2 where b > 30;
+r b
+1 70
+1 40
+select 1 in ((select a from t1)) as r, b from t2 where b > 30;
+r b
+1 70
+1 40
+select ((1 in ((select a from t1)))) as r, b from t2 where b > 30;
+r b
+1 70
+1 40
+select ((1 in ((select a from t1)))) as r, b from t2 where b > 30;
+r b
+1 70
+1 40
+select b, if (a in (select a from t1 where a > 3),10,20) as r from t2;
+b r
+30 20
+70 10
+10 20
+20 20
+40 10
+select b, if (a in ((select a from t1 where a > 3)),10,20) as r from t2;
+b r
+30 20
+70 10
+10 20
+20 20
+40 10
+# 6.7. IN subquery in SF and SP
+create function f1(x int) returns int
+return (x in ((select a from t1 where a <= 4)));
+select b, f1(a) from t2 where b > 20;
+b f1(a)
+30 1
+70 0
+40 1
+drop function f1;
+create function f2(x int) returns int
+if x in ((select a from t1 where a <= 4))
+then return 100;
+else return 200;
+end if |
+select b, f2(a) from t2 where b > 20;
+b f2(a)
+30 100
+70 200
+40 100
+drop function f2;
+# 6.8. EXISTS subquery
+select exists (select a from t1 where t1.a=t2.a) as r, b from t2 where b > 30;
+r b
+1 70
+1 40
+select exists ((select a from t1 where t1.a=t2.a)) as r, b from t2 where b > 30;
+r b
+1 70
+1 40
+with s as
+( (select * from t1 where a <=4 order by 1 desc limit 2)
+union
+values (3), (8), (7) )
+select * from t2 where exists ((select * from s where s.a=t2.a));
+a b
+3 30
+7 70
+4 40
+with t as ((select a from t1 where a<=2) order by a desc limit 1)
+select a from t2
+where not exists ((select a from t where t.a=t2.a)
+except
+(select a from t where a>40));
+a
+3
+7
+1
+4
+# 6.9. EXISTS subquery with SF and SP
+create function f1(x int) returns int
+return exists (((select * from t1 where x=a and a <= 4)));
+select b, f1(a) from t2 where b > 20;
+b f1(a)
+30 1
+70 0
+40 1
+drop function f1;
+create function f2(x int) returns int
+if not exists (((select * from t1 where x=a and a <= 4)))
+then return 100;
+else return 200;
+end if |
+select b, f2(a) from t2 where b > 20;
+b f2(a)
+30 200
+70 100
+40 200
+drop function f2;
+# 6.10. subquery with ANY
+select a from t1 where a = any(select a from t2 where a <= 3);
+a
+3
+1
+2
+select a from t1 where a = any((select a from t2 where a <= 3));
+a
+3
+1
+2
+select a from t1
+where a = any (select a from t1 where a<=2
+union
+select a from t2 where b>40);
+a
+7
+1
+2
+select a from t1
+where a = any(select a from t1 where a<=2
+union
+(select a from t2 where b>40));
+a
+7
+1
+2
+select a from t1
+where a = any((select a from t1 where a<=2)
+union
+select a from t2 where b>40);
+a
+7
+1
+2
+select a from t1
+where a = any((select a from t1 where a<=2)
+union
+(select a from t2 where b>40));
+a
+7
+1
+2
+# 7. create table as
+# 7.1. create table as simple select
+create table t as select * from t1 where a <=3;
+select * from t;
+a
+3
+1
+2
+drop table t;
+create table t select * from t1 where a <=3;
+select * from t;
+a
+3
+1
+2
+drop table t;
+create table t as (select * from t1 where a <=3);
+select * from t;
+a
+3
+1
+2
+drop table t;
+create table t (select * from t1 where a <=3);
+select * from t;
+a
+3
+1
+2
+drop table t;
+create table t as ((select * from t1 where a <=3));
+select * from t;
+a
+3
+1
+2
+drop table t;
+create table t ((select * from t1 where a <=3));
+select * from t;
+a
+3
+1
+2
+drop table t;
+create table t(a decimal(10,2)) as select * from t1 where a <=3;
+select * from t;
+a
+3.00
+1.00
+2.00
+drop table t;
+create table t(a decimal(10,2)) select * from t1 where a <=3;
+select * from t;
+a
+3.00
+1.00
+2.00
+drop table t;
+create table t(a decimal(10,2)) as (select * from t1 where a <=3);
+select * from t;
+a
+3.00
+1.00
+2.00
+drop table t;
+create table t(a decimal(10,2)) (select * from t1 where a <=3);
+select * from t;
+a
+3.00
+1.00
+2.00
+drop table t;
+create table t(a decimal(10,2)) as ((select * from t1 where a <=3));
+select * from t;
+a
+3.00
+1.00
+2.00
+drop table t;
+create table t(a decimal(10,2)) ((select * from t1 where a <=3));
+select * from t;
+a
+3.00
+1.00
+2.00
+drop table t;
+create table t(a decimal(10,2), b int) as
+((select a, a as b from t1 where a <=3));
+select * from t;
+a b
+3.00 3
+1.00 1
+2.00 2
+drop table t;
+create table t(a decimal(10,2), b int)
+((select a, a as b from t1 where a <=3));
+select * from t;
+a b
+3.00 3
+1.00 1
+2.00 2
+drop table t;
+# 7.2. create table as tailed select
+create table t as select * from t1 where a <=3 order by 1;
+select * from t;
+a
+1
+2
+3
+drop table t;
+create table t select * from t1 where a <=3 order by 1;
+select * from t;
+a
+1
+2
+3
+drop table t;
+create table t as select * from t1 where a <=3 order by 1 desc limit 2;
+select * from t;
+a
+3
+2
+drop table t;
+create table t select * from t1 where a <=3 order by 1 desc limit 2;
+select * from t;
+a
+3
+2
+drop table t;
+create table t as ((select * from t1 where a <=3) order by 1 desc) limit 2;
+select * from t;
+a
+3
+2
+drop table t;
+create table t ((select * from t1 where a <=3) order by 1 desc) limit 2;
+select * from t;
+a
+3
+2
+drop table t;
+# 7.3. create table as select wihout from clause
+create table t as select 10;
+select * from t;
+10
+10
+drop table t;
+create table t select 10;
+select * from t;
+10
+10
+drop table t;
+# 7.4. create table as union of selects wihout from clause
+create table t as select 10 union select 70;
+select * from t;
+10
+10
+70
+drop table t;
+create table t select 10 union select 70;
+select * from t;
+10
+10
+70
+drop table t;
+# 7.5. create table as TVC
+create table t as values (7), (3), (8);
+select * from t;
+7
+7
+3
+8
+drop table t;
+create table t values (7), (3), (8);
+select * from t;
+7
+7
+3
+8
+drop table t;
+create table t as (values (7), (3), (8));
+select * from t;
+7
+7
+3
+8
+drop table t;
+create table t (values (7), (3), (8));
+select * from t;
+7
+7
+3
+8
+drop table t;
+create table t as ((values (7), (3), (8)));
+select * from t;
+7
+7
+3
+8
+drop table t;
+create table t ((values (7), (3), (8)));
+select * from t;
+7
+7
+3
+8
+drop table t;
+# 7.6. create table as select with CTE
+create table t as
+with s(a) as (select * from t1 where a <=3 order by 1 desc limit 2)
+select * from s;
+select * from t;
+a
+3
+2
+drop table t;
+create table t
+with s(a) as (select * from t1 where a <=3 order by 1 desc limit 2)
+select * from s;
+select * from t;
+a
+3
+2
+drop table t;
+create table t as
+with s as
+( (select * from t1 where a <=4 order by 1 desc limit 2)
+union
+values (3), (8), (7) )
+select * from s;
+select * from t;
+a
+4
+3
+8
+7
+drop table t;
+create table t
+with s as
+( (select * from t1 where a <=4 order by 1 desc limit 2)
+union
+values (3), (8), (7) )
+select * from s;
+select * from t;
+a
+4
+3
+8
+7
+drop table t;
+create table t as
+with s(a) as (select * from t1 where a <=3 order by 1 desc limit 2)
+select * from s;
+select * from t;
+a
+3
+2
+drop table t;
+# 7.7. create table as union with CTE
+create table t as
+with s as
+( (select * from t1 where a <=4 order by 1 desc limit 2)
+union
+values (3), (8), (7) )
+select * from s where a>=7 union select a from t2 where b<40;
+select * from t;
+a
+8
+7
+3
+1
+2
+drop table t;
+create table t
+with s as
+( (select * from t1 where a <=4 order by 1 desc limit 2)
+union
+values (3), (8), (7) )
+select * from s where a>=7 union select a from t2 where b<40;
+select * from t;
+a
+8
+7
+3
+1
+2
+drop table t;
+create table t
+with s as
+( (select * from t1 where a <=4 order by 1 desc limit 2)
+union
+values (3), (8), (7) )
+select * from s where a>=7 union select a from t2 where b<40;
+select * from t;
+a
+8
+7
+3
+1
+2
+drop table t;
+create table t as
+with s as
+( ( (select * from t1 where a <=4 order by 1 desc limit 2)
+union
+values (3), (8), (7) ) )
+select * from s where a>=7 union select a from t2 where b<40;
+select * from t;
+a
+8
+7
+3
+1
+2
+drop table t;
+create table t
+with s as
+( ( (select * from t1 where a <=4 order by 1 desc limit 2)
+union
+values (3), (8), (7) ) )
+select * from s where a>=7 union select a from t2 where b<40;
+select * from t;
+a
+8
+7
+3
+1
+2
+drop table t;
+create table t as
+with s as
+( (select * from t1 where a <=4 order by 1 desc limit 2)
+union
+values (3), (8), (7) )
+select * from s where a>=7 union select a from s where a<4;
+select * from t;
+a
+8
+7
+3
+drop table t;
+create table t
+with s as
+( (select * from t1 where a <=4 order by 1 desc limit 2)
+union
+values (3), (8), (7) )
+select * from s where a>=7 union select a from s where a<4;
+select * from t;
+a
+8
+7
+3
+drop table t;
+create table t as
+with s as
+( select * from t1 where a <=4 or a=7 )
+select * from s where a>=7 union select a from s where a<3;
+select * from t;
+a
+7
+1
+2
+drop table t;
+create table t
+with s as
+(select * from t1 where a <=4 or a=7)
+select * from s where a>=7 union select a from s where a<3;
+select * from t;
+a
+7
+1
+2
+drop table t;
+create table t (a int)
+with s as
+( select * from t1 where a <=4 or a=7 )
+select * from s where a>=7 union select a from s where a<3;
+select * from t;
+a
+7
+1
+2
+drop table t;
+create table t (a int)
+with s as
+(select * from t1 where a <=4 or a=7)
+select * from s where a>=7 union select a from s where a<3;
+select * from t;
+a
+7
+1
+2
+drop table t;
+create table t
+with s as
+( select * from t1 where a <=4 or a=7 )
+select * from s where a>=7 union select a from s where a<3
+order by a desc limit 2;
+select * from t;
+a
+7
+2
+drop table t;
+create table t
+( with s as
+( select * from t1 where a <=4 or a=7 )
+select * from s where a>=7 union select a from s where a<3
+order by a desc limit 2 );
+select * from t;
+a
+7
+2
+drop table t;
+# 8. insert
+create table t (c int, d int);
+# 8.1. insert simple select
+insert into t select * from t2 where a <=3;
+select * from t;
+c d
+3 30
+1 10
+2 20
+delete from t;
+insert into t(c) select t2.a from t2 where a <=3;
+select * from t;
+c d
+3 NULL
+1 NULL
+2 NULL
+delete from t;
+insert into t (select * from t2 where a <=3);
+select * from t;
+c d
+3 30
+1 10
+2 20
+delete from t;
+insert into t(c) (select t2.a from t2 where a <=3);
+select * from t;
+c d
+3 NULL
+1 NULL
+2 NULL
+delete from t;
+insert into t ((select * from t2 where a <=3));
+select * from t;
+c d
+3 30
+1 10
+2 20
+delete from t;
+insert into t(c) ((select t2.a from t2 where a <=3));
+select * from t;
+c d
+3 NULL
+1 NULL
+2 NULL
+delete from t;
+drop table t;
+create table t(c decimal(10,2));
+insert into t select * from t1 where a <=3;
+select * from t;
+c
+3.00
+1.00
+2.00
+delete from t;
+insert into t(c) select * from t1 where a <=3;
+select * from t;
+c
+3.00
+1.00
+2.00
+delete from t;
+insert into t (select * from t1 where a <=3);
+select * from t;
+c
+3.00
+1.00
+2.00
+delete from t;
+insert into t(c) (select * from t1 where a <=3);
+select * from t;
+c
+3.00
+1.00
+2.00
+delete from t;
+insert into t ((select * from t1 where a <=3));
+select * from t;
+c
+3.00
+1.00
+2.00
+delete from t;
+insert into t(c) ((select * from t1 where a <=3));
+select * from t;
+c
+3.00
+1.00
+2.00
+delete from t;
+drop table t;
+create table t(a decimal(10,2), b int);
+insert into t ((select * from t2 where a <=3));
+select * from t;
+a b
+3.00 30
+1.00 10
+2.00 20
+delete from t;
+insert into t(a) ((select a from t2 where a <=3));
+select * from t;
+a b
+3.00 NULL
+1.00 NULL
+2.00 NULL
+delete from t;
+drop table t;
+create table t(c int, d int);
+# 8.2. insert tailed select
+insert into t select * from t2 where a <=3 order by 1;
+select * from t;
+c d
+1 10
+2 20
+3 30
+delete from t;
+insert into t(c) select a from t2 where a <=3 order by 1;
+select * from t;
+c d
+1 NULL
+2 NULL
+3 NULL
+delete from t;
+insert into t select * from t2 where a <=3 order by 1 desc limit 2;
+select * from t;
+c d
+3 30
+2 20
+delete from t;
+insert into t(c) select a from t2 where a <=3 order by 1 desc limit 2;
+select * from t;
+c d
+3 NULL
+2 NULL
+delete from t;
+insert into t ((select * from t2 where a <=3) order by 1 desc) limit 2;
+select * from t;
+c d
+3 30
+2 20
+delete from t;
+insert into t(c) ((select a from t2 where a <=3) order by 1 desc) limit 2;
+select * from t;
+c d
+3 NULL
+2 NULL
+delete from t;
+# 8.3. insert select without from clause
+insert into t select 10, 20;
+select * from t;
+c d
+10 20
+delete from t;
+insert into t(c) select 10;
+select * from t;
+c d
+10 NULL
+delete from t;
+# 8.4. insert union of selects without from clause
+insert into t select 10,20 union select 70,80;
+select * from t;
+c d
+10 20
+70 80
+delete from t;
+insert into t(c) select 10 union select 70;
+select * from t;
+c d
+10 NULL
+70 NULL
+delete from t;
+# 8.5. insert TVC
+insert into t values (7,70), (3,30), (8,80);
+select * from t;
+c d
+7 70
+3 30
+8 80
+delete from t;
+insert into t(c) values (7), (3), (8);
+select * from t;
+c d
+7 NULL
+3 NULL
+8 NULL
+delete from t;
+insert into t (values (7,70), (3,30), (8,80));
+select * from t;
+c d
+7 70
+3 30
+8 80
+delete from t;
+insert into t(c) (values (7), (3), (8));
+select * from t;
+c d
+7 NULL
+3 NULL
+8 NULL
+delete from t;
+insert into t ((values (7,70), (3,30), (8,80)));
+select * from t;
+c d
+7 70
+3 30
+8 80
+delete from t;
+insert into t(c) ((values (7), (3), (8)));
+select * from t;
+c d
+7 NULL
+3 NULL
+8 NULL
+delete from t;
+# 8.7. insert simple select with CTE
+insert into t
+with s(a,b) as (select * from t2 where a <=3 order by 1 desc limit 2)
+select * from s;
+select * from t;
+c d
+3 30
+2 20
+delete from t;
+insert into t(c)
+with s(a) as (select a from t2 where a <=3 order by 1 desc limit 2)
+select * from s;
+select * from t;
+c d
+3 NULL
+2 NULL
+delete from t;
+insert into t
+with s as
+( (select * from t2 where a <=4 order by 1 desc limit 2)
+union
+values (3,30), (8,80), (7,70) )
+select * from s;
+select * from t;
+c d
+4 40
+3 30
+8 80
+7 70
+delete from t;
+insert into t(c)
+with s as
+( (select a from t2 where a <=4 order by 1 desc limit 2)
+union
+values (3), (8), (7) )
+select * from s;
+select * from t;
+c d
+4 NULL
+3 NULL
+8 NULL
+7 NULL
+delete from t;
+# 8.8. insert into union with CTE
+insert into t(c)
+with s as
+( (select a from t2 where a <=4 order by 1 desc limit 2)
+union
+values (3), (8), (7) )
+select * from s where a>=7 union select a from t2 where b<40;
+select * from t;
+c d
+8 NULL
+7 NULL
+3 NULL
+1 NULL
+2 NULL
+delete from t;
+insert into t
+with s as
+( (select * from t2 where a <=4 order by 1 desc limit 2)
+union
+values (3,30), (8,80), (7,70) )
+select * from s where a>=7 union select * from s where a<4;
+select * from t;
+c d
+8 80
+7 70
+3 30
+delete from t;
+insert into t(c)
+with s as
+( (select a from t2 where a <=4 order by 1 desc limit 2)
+union
+values (3), (8), (7) )
+select * from s where a>=7 union select * from s where a<4;
+select * from t;
+c d
+8 NULL
+7 NULL
+3 NULL
+delete from t;
+insert into t
+with s as
+( select * from t2 where a <=4 or a=7 )
+select * from s where a>=7 union select * from s where a<3;
+select * from t;
+c d
+7 70
+1 10
+2 20
+delete from t;
+insert into t(c)
+with s as
+( select a from t2 where a <=4 or a=7 )
+select * from s where a>=7 union select * from s where a<3;
+select * from t;
+c d
+7 NULL
+1 NULL
+2 NULL
+delete from t;
+drop table t;
+# 9. derived table
+# 9.1. derived table as [tailed] simple select
+select * from (select * from t1) as dt;
+a
+3
+7
+1
+2
+4
+select * from ((select * from t1)) as dt;
+a
+3
+7
+1
+2
+4
+select * from (((select * from t1))) as dt;
+a
+3
+7
+1
+2
+4
+select * from (select * from t1 order by a) as dt;
+a
+3
+7
+1
+2
+4
+select * from (select a from t1 order by a) as dt;
+a
+3
+7
+1
+2
+4
+select * from (select a from t1 order by 1) as dt;
+a
+3
+7
+1
+2
+4
+select * from (select a from t1 order by t1.a) as dt;
+a
+3
+7
+1
+2
+4
+select * from ((select * from t1 order by t1.a limit 2)) as dt;
+a
+1
+2
+select * from ((select * from t2 order by a limit 2) order by b desc) dt;
+a b
+1 10
+2 20
+select * from ((select a from t1 where a=1) order by 1 desc) dt;
+a
+1
+# 9.2. derived table as select with two tails
+select * from
+((select * from t2 order by t2.a limit 2) order by b desc) dt;
+a b
+1 10
+2 20
+select * from
+((select * from t2 order by t2.a limit 2) order by b desc) as dt;
+a b
+1 10
+2 20
+select * from
+(((select * from t2 order by t2.a limit 2) order by b desc )) as dt;
+a b
+1 10
+2 20
+select * from
+(((select * from t2 order by t2.a) limit 2) order by b desc) dt;
+a b
+1 10
+2 20
+select * from
+((select * from t2 order by a limit 2) order by b desc) dt;
+a b
+1 10
+2 20
+select * from
+((select a from t1 where a=1) order by 1 desc) as dt;
+a
+1
+select * from
+((select * from t2 order by t2.a limit 2) order by b desc) as dt;
+a b
+1 10
+2 20
+# 9.3. derived table as union
+select * from (select a from t1 union select a from t1) as dt;
+a
+3
+7
+1
+2
+4
+select * from (select a from t1 union all select a from t1) as dt;
+a
+3
+7
+1
+2
+4
+3
+7
+1
+2
+4
+select * from (select a from t1 union select b from t2) as dt;
+a
+3
+7
+1
+2
+4
+30
+70
+10
+20
+40
+select * from
+((select a from t1) union (select a from t1)) as dt;
+a
+3
+7
+1
+2
+4
+select * from
+((select a from t1) union (select b from t2)) as dt;
+a
+3
+7
+1
+2
+4
+30
+70
+10
+20
+40
+select * from
+(select a from t1 where a=1 union select a from t1 where a=3) dt;
+a
+1
+3
+select * from
+((select a from t1 where a=1) union select a from t1 where a=3) dt;
+a
+1
+3
+select * from
+(((select a from t1 where a=1) union select a from t1 where a=3)) dt;
+a
+1
+3
+select * from
+(((select a from t1 where a<=3) union (select a from t1 where a=3))) as dt;
+a
+3
+1
+2
+select * from
+(select a from t1 where a=1 union (select a from t1 where a=3)) as dt;
+a
+1
+3
+select * from
+((select a from t1 where a=1 union (select a from t1 where a=3))) as dt;
+a
+1
+3
+select * from
+(((select a from t1 where a=1 union (select a from t1 where a=3)))) as dt;
+a
+1
+3
+select * from
+( select a from t1 where a=1
+union
+select a from t1 where a=3
+union
+select a from t1 where a=7 ) as dt;
+a
+1
+3
+7
+select * from
+( (select a from t1 where a=1 order by a)
+union
+select a from t1 where a=3 ) as dt;
+a
+1
+3
+select * from
+( (select a from t1 where a!=3 order by a desc)
+union
+select a from t1 where a=3 ) as dt;
+a
+7
+1
+2
+4
+3
+select * from
+( ( select a from t1 where a <=3 except select a from t1 where a >=3 )
+union
+select a from t1 where a=7 ) as dt;
+a
+1
+2
+7
+select * from
+( ( ( select a from t1 where a <=3
+except
+select a from t1 where a >=3 )
+union
+select a from t1 where a=7 ) ) as dt;
+a
+1
+2
+7
+select * from
+( select a from t1 where a=1
+union
+select a from t1 where a=3
+order by a desc) as dt;
+a
+3
+1
+select *from
+( (select a from t1 limit 2)
+union
+select a from t1 where a=3
+order by a desc) as dt;
+a
+7
+3
+select * from
+( select a from t1 where a=4
+union
+(select a from t1 where a <=4 limit 2)
+order by a desc ) as dt;
+a
+4
+3
+1
+select * from
+( ( select a from t1 where a=4
+union
+( select a from t1 where a <=4 order by a ) )
+order by a desc limit 2 ) as dt;
+a
+4
+3
+select * from
+( ( select a from t1 where a <=3 except select a from t1 where a >=3 )
+union
+select a from t1 where a=7 order by a desc ) as dt;
+a
+7
+2
+1
+select * from
+( ( select a from t1 where a!=3 order by a desc )
+union
+select a from t1 where a=3
+order by a desc ) as dt;
+a
+7
+4
+3
+2
+1
+select * from
+( (select a from t1 where a=1)
+union
+(select a from t1 where a=3)
+order by a desc ) as dt;
+a
+3
+1
+select * from
+( ( select a from t1 where a=1
+union
+select a from t1 where a=3 )
+order by a desc ) as dt;
+a
+3
+1
+select * from
+( ( ( select a from t1 where a=1 )
+union
+( select a from t1 where a=3 ) )
+order by a desc ) as dt;
+a
+3
+1
+select * from
+( ( select a from t1 where a=1
+union
+select a from t1 where a=3 )
+order by 1 desc ) as dt;
+a
+3
+1
+select * from
+( ( (select a from t1 where a=1
+union
+select a from t1 where a=3) ) order by 1 desc ) as dt;
+a
+3
+1
+select * from
+((((select a from t1 where a=1) union (select a from t1 where a=3)))
+order by 1 desc ) as dt;
+a
+3
+1
+select * from
+( ( (select a from t1 where a=1 )
+union
+(select a from t1 where a=3) )
+order by 1 desc ) as dt;
+a
+3
+1
+select * from
+( select a from t1 where a=1
+union
+select a from t1 where a=3
+union
+select a from t1 where a=2
+union
+select a from t1 where a=4 ) as dt;
+a
+1
+3
+2
+4
+select * from
+( ( select a from t1 where a=1
+union
+select a from t1 where a=3
+union
+select a from t1 where a=2 )
+union
+select a from t1 where a=4 ) as dt;
+a
+1
+3
+2
+4
+select * from
+( (select a from t1 where a=1 union select a from t1 where a=3)
+union
+(select a from t1 where a=2 union select a from t1 where a=4) ) as dt;
+a
+1
+3
+2
+4
+select * from
+( (select a from t1 where a=1 union (select a from t1 where a=3))
+union
+((select a from t1 where a=2) union select a from t1 where a=4) ) as dt;
+a
+1
+3
+2
+4
+select * from
+( ( ( select a from t1 where a=1)
+union
+select a from t1 where a=3 )
+union
+select a from t1 where a=2
+union
+select a from t1 where a=4 ) as dt;
+a
+1
+3
+2
+4
+select * from
+( ( ( ( select a from t1 where a=1)
+union
+select a from t1 where a=3 )
+union
+select a from t1 where a=2 )
+union
+select a from t1 where a=4 ) as dt;
+a
+1
+3
+2
+4
+select * from
+( select a from t1 where a=1
+union
+select a from t1 where a=3
+union
+select a from t1 where a=2
+union
+(select a from t1 where a=4) ) as dt;
+a
+1
+3
+2
+4
+select * from
+( select a from t1 where a=1
+union
+select a from t1 where a=3
+union
+( select a from t1 where a=2
+union
+( select a from t1 where a=4 ) ) ) as dt;
+a
+1
+3
+2
+4
+select * from
+( select a from t1 where a=1
+union
+( select a from t1 where a=3
+union
+( select a from t1 where a=2
+union
+( select a from t1 where a=4 ) ) ) ) as dt;
+a
+1
+3
+2
+4
+select * from
+( ( ( select a from t1 where a=1 union select a from t1 where a=3 )
+order by a desc limit 2 )
+union
+( ( select a from t1 where a=2 union select a from t1 where a=4 )
+order by a desc limit 1 ) ) as dt;
+a
+3
+1
+4
+select * from
+( ( ( select a from t1 where a=1 union select a from t1 where a=3 )
+order by a desc limit 2 )
+union
+( ( select a from t1 where a=2 union select a from t1 where a=4 )
+order by a desc limit 2 )
+order by a) as dt;
+a
+1
+2
+3
+4
+select * from
+( ( select a from t1 where a=1
+union
+select a from t1 where a=3
+union
+select a from t1 where a=2 order by a desc limit 2 )
+union
+select a from t1 where a=4
+order by a limit 3 ) as dt;
+a
+2
+3
+4
+select * from
+( ( select a from t1 where a=1
+union
+select a from t1 where a=3 order by a desc limit 2)
+union
+select a from t1 where a=2 order by a desc limit 2 ) as dt;
+a
+3
+2
+select * from
+( ( ( select a from t1 where a >= 2
+union
+select a from t1 where a=1 order by a desc limit 2 )
+union
+select a from t1 where a=3 order by a limit 2 )
+union
+select a from t1 where a=1 ) as dt;
+a
+3
+4
+1
+# 9.3. derived table as [tailed] TVC
+select * from
+( values (3), (7), (1) ) as dt;
+3
+3
+7
+1
+select * from
+( (values (3), (7), (1)) ) as dt;
+3
+3
+7
+1
+select * from
+(((values (3), (7), (1)))) as dt;
+3
+3
+7
+1
+select * from
+( values (3), (7), (1) order by 1 limit 2 ) as dt;
+3
+1
+3
+select * from
+( (values (3), (7), (1)) order by 1 limit 2 ) as dt;
+3
+1
+3
+select * from
+( ((values (3), (7), (1))) order by 1 limit 2 ) as dt;
+3
+1
+3
+select * from
+( (((values (3), (7), (1))) order by 1 limit 2) ) as dt;
+3
+1
+3
+select * from
+( ( (values (3), (7), (1) limit 2) order by 1 desc) ) as dt;
+3
+3
+7
+select * from
+( ((values (3), (7), (1)) order by 1 desc) limit 2 ) as dt;
+3
+7
+3
+select * from
+( (((values (3), (7), (1)) order by 1 desc) limit 2) ) as dt;
+3
+7
+3
+# 9.3. derived table as union of TVCs
+select * from
+( values (3), (7), (1) union values (3), (4), (2) ) dt;
+3
+3
+7
+1
+4
+2
+select * from
+( values (3), (7), (1) union all values (3), (4), (2) ) as dt;
+3
+3
+7
+1
+3
+4
+2
+select * from
+( values (3), (7), (1) union values (3), (4), (2) ) as dt;
+3
+3
+7
+1
+4
+2
+select * from
+( values (3), (7), (1) except values (3), (4), (2) ) as dt;
+3
+7
+1
+select * from
+( (values (3), (7), (1)) union (values (3), (4), (2)) ) as dt;
+3
+3
+7
+1
+4
+2
+select * from
+( (values (3), (7), (1))
+union
+(values (3), (4), (2))
+union values (5), (7) ) dt;
+3
+3
+7
+1
+4
+2
+5
+select * from
+( (values (3), (7), (1))
+union
+(values (3), (4), (2))
+union
+(values (5), (7)) ) as dt;
+3
+3
+7
+1
+4
+2
+5
+select * from
+( (values (3), (7), (1)
+union
+values (3), (4), (2))
+union
+values (5), (7) ) as dt;
+3
+3
+7
+1
+4
+2
+5
+select * from
+( values (3), (7), (1)
+union (values (3), (4), (2)
+union
+values (5), (7)) ) as dt;
+3
+3
+7
+1
+4
+2
+5
+select * from
+( (values (3), (7), (1)
+union
+((values (3), (4), (2)
+union values (5), (7)))) ) dt;
+3
+3
+7
+1
+4
+2
+5
+select * from
+( values (3), (7), (1)
+union
+values (3), (4), (2)
+order by 1 ) as dt;
+3
+1
+2
+3
+4
+7
+select * from
+( (values (3), (7), (1) union values (3), (4), (2)) order by 1 ) as dt;
+3
+1
+2
+3
+4
+7
+select * from
+( (values (3), (7), (1) union values (3), (4), (2)) order by 1 ) as dt;
+3
+1
+2
+3
+4
+7
+select * from
+( values (3), (7), (1) union (values (3), (4), (2)) order by 1 ) as dt;
+3
+1
+2
+3
+4
+7
+select * from
+( (values (3), (7), (1) union values (3), (4), (2)) order by 1 ) as dt;
+3
+1
+2
+3
+4
+7
+select * from
+( ((values (3), (7), (1)) union values (3), (4), (2)) order by 1 ) as dt;
+3
+1
+2
+3
+4
+7
+select * from
+( (values (3), (7), (1) order by 1 limit 2)
+union
+(values (3), (4), (2) order by 1 desc limit 2) ) as dt;
+3
+1
+3
+4
+select * from
+( ((values (3), (7), (1) order by 1) limit 2)
+union
+((values (3), (4), (2) order by 1 desc) limit 2) ) as dt;
+3
+1
+3
+4
+select * from
+( (((values (3), (7), (1)) order by 1) limit 2)
+union
+(((values (3), (4), (2)) order by 1 desc) limit 2) ) as dt;
+3
+1
+3
+4
+select * from
+( (values (3), (7), (1) order by 1 limit 2)
+union
+values (3), (4), (2)
+order by 1 limit 3 ) as dt;
+3
+1
+2
+3
+select * from
+( ((values (3), (7), (1)) order by 1 limit 2)
+union
+((values (3), (4), (2) order by 1 desc) limit 2)
+order by 1 limit 3 ) as dt;
+3
+1
+3
+4
+select * from
+( (select a from t1 where a <=3 order by 1 limit 2)
+union
+(values (3), (4), (2) order by 1 desc limit 2) ) dt;
+a
+1
+2
+4
+3
+select * from
+( ((select a from t1 where a <=3) order by 1 limit 2)
+union
+(values (3), (4), (2) order by 1 desc limit 2) ) as dt;
+a
+1
+2
+4
+3
+select * from
+( (((select a from t1 where a <=3) order by a) limit 2)
+union
+(((values (3), (4), (2)) order by 1 desc) limit 2) ) as dt;
+a
+1
+2
+4
+3
+select * from
+( ( (((select a from t1 where a <=3) order by a) limit 2)
+union
+(((values (3), (4), (2)) order by 1 desc) limit 2) ) ) dt;
+a
+1
+2
+4
+3
+select * from
+( (select a from t1 where a <=3 order by 1 limit 2)
+union
+(values (3), (4), (2) order by 1 desc limit 2)
+order by a ) as dt;
+a
+1
+2
+3
+4
+select * from
+( ((select a from t1 where a <=3) order by 1 limit 2)
+union
+(values (3), (4), (2) order by 1 desc limit 2)
+order by a ) as dt;
+a
+1
+2
+3
+4
+select * from
+( (((select a from t1 where a <=3) order by a) limit 2)
+union
+(((values (3), (4), (2)) order by 1 desc) limit 2)
+order by a ) as dt;
+a
+1
+2
+3
+4
+select * from
+( (((values (3), (4), (2)) order by 1 desc) limit 2) ) as dt;
+3
+4
+3
+select * from
+( ( (((select a from t1 where a <=3) order by a) limit 2)
+union
+(((values (3), (4), (2)) order by 1 desc) limit 2) )
+order by a ) as dt;
+a
+1
+2
+3
+4
+select * from
+( (values (3), (4), (2) order by 1 desc limit 2)
+union
+(select a from t1 where a <=3 order by 1 limit 2) ) as dt;
+3
+4
+3
+1
+2
+select * from
+( (values (3), (4), (2) order by 1 desc limit 2)
+union
+((select a from t1 where a <=3) order by 1 limit 2) ) as dt;
+3
+4
+3
+1
+2
+select * from
+( (((values (3), (4), (2)) order by 1 desc) limit 2)
+union
+(((select a from t1 where a <=3) order by 1) limit 2) ) as dt;
+3
+4
+3
+1
+2
+select * from
+( (((values (3), (4), (2)) order by 1 desc) limit 2)
+union
+(((select a from t1 where a <=3) order by a) limit 2)
+order by 1 ) as dt;
+3
+1
+2
+3
+4
+select * from
+( ( select a from t1 where a=1
+union
+values (3), (4), (2) order by 1 desc )
+union
+select a from t1 where a=2 order by a desc limit 3 ) as dt;
+a
+4
+3
+2
+# 9.4. derived table as [tailed] simple select with CTE
+select * from
+( with t as (select * from t1 where a <=3)
+select * from t ) as dt;
+a
+3
+1
+2
+select * from
+( with t as (select * from t1 where a <=3)
+(select * from t) ) as dt;
+a
+3
+1
+2
+select * from
+( with t as (select * from t1 where a <=3)
+((select * from t)) ) as dt;
+a
+3
+1
+2
+select * from
+( with t as ((select * from t1 where a <=3))
+select * from t ) as dt;
+a
+3
+1
+2
+select * from
+( with t as (((select * from t1 where a <=3)))
+select * from t ) as dt;
+a
+3
+1
+2
+select * from
+( with t as (select * from t1 where a <=3)
+select * from t order by a ) as dt;
+a
+3
+1
+2
+select * from
+( with t as (select * from t1 where a <=3)
+(select * from t) order by a ) as dt;
+a
+3
+1
+2
+select * from
+( with t as (select * from t1 where a <=3)
+(select * from t) order by a desc limit 2 ) as dt;
+a
+3
+2
+select * from
+( with t as (select * from t1 where a >=2 order by a limit 2)
+select * from t ) as dt;
+a
+2
+3
+select * from
+( with t as (((select * from t1 where a >=2) order by a desc) limit 2)
+select * from t ) as dt;
+a
+7
+4
+select * from
+( with t as (select * from t1 where a >=2 order by a desc limit 2)
+select * from t order by a ) as dt;
+a
+7
+4
+# 9.5. derived table as tailed union with CTE
+select * from
+( with t as (select * from t1 where a <=3)
+select a from t1 where a=1 union select a from t where a=3 ) as dt;
+a
+1
+3
+select * from
+( with t as (select * from t1 where a <=3)
+(select a from t) union (select b from t2) ) as dt;
+a
+3
+1
+2
+30
+70
+10
+20
+40
+select * from
+( with t as (select * from t1 where a <=3)
+(select a from t) union (select b as a from t2) order by a desc ) as dt;
+a
+70
+40
+30
+20
+10
+3
+2
+1
+select * from
+( with t as (select * from t1 where a < 3 union select * from t1 where a > 3)
+select a from t1 where a=1 union select a from t where a=7 ) as dt;
+a
+1
+7
+select * from
+( with t as
+( select * from t1 where a < 3
+union
+select * from t1 where a > 3
+order by a desc limit 3 )
+select a from t1 where a=4 union select a from t where a=7 ) as dt;
+a
+4
+7
+select * from
+( with t as
+( select * from t1 where a < 3
+union
+select * from t1 where a > 3
+order by a desc limit 3 )
+select a from t1 where a=4
+union
+select a from t where a=7
+order by a desc ) as dt;
+a
+7
+4
+select * from
+( with t as
+( (select * from t1 where a < 3)
+union
+(select * from t1 where a > 3)
+order by a desc limit 3 )
+select a from t1 where a=4
+union select a from t where a=7
+order by a desc ) dt;
+a
+7
+4
+select * from
+( with t as
+( (select * from t1 where a < 3)
+union
+(select * from t1 where a > 3)
+order by a desc limit 3 )
+(select a from t1 where a=4
+union
+select a from t where a=7
+order by a desc) ) as dt;
+a
+7
+4
+select * from
+( with t as
+( (select * from t1 where a < 3)
+union
+(select * from t1 where a > 3)
+order by a desc limit 3 )
+((select a from t1 where a=4
+union
+select a from t where a=7) order by a desc) ) as dt;
+a
+7
+4
+select * from
+( with t as
+( select * from t1 where a < 3
+union
+values (4), (7)
+order by a desc limit 3 )
+select a from t1 where a=4
+union
+select a from t where a=7
+order by a desc ) dt;
+a
+7
+4
+select * from
+( with t(a) as
+( values (2), (1)
+union
+(values (4), (7))
+order by 1 desc limit 3 )
+select a from t1 where a=4
+union select a from t where a=7
+order by a desc ) as dt;
+a
+7
+4
+select * from
+( with t(a) as
+( (values (2), (1))
+union
+(values (4), (7) order by 1 desc)
+order by 1 desc limit 3 )
+select a from t1 where a=1
+union
+select a from t where a=7 order by a desc ) as dt;
+a
+7
+1
+select * from
+( with t(a) as
+( (values (2), (1))
+union
+(values (4), (7) order by 1 desc)
+order by 1 limit 3 )
+select a from t where a=1 union values (7) order by a desc ) as dt;
+a
+7
+1
+select * from
+( with t(a) as
+( (values (2), (1))
+union
+(values (4), (7) order by 1 desc ) )
+select a from t where a=1 union select 7 order by a desc ) as dt;
+a
+7
+1
+select * from
+( with t as (select * from t1 where a < 3),
+s as (select * from t1 where a > 3)
+select a from t where a=1
+union select a from s where a=7
+order by a desc ) dt;
+a
+7
+1
+select * from
+( with t as (select * from t1 where a < 3),
+s as (select * from t1 where a > 3)
+(select a from t where a=1
+union
+select a from s where a=7 order by a desc) ) dt;
+a
+7
+1
+select * from
+( with t as (select * from t1 where a < 3),
+s as (select * from t1 where a > 3)
+(select a from t where a=1
+union
+select a from s where a=7)
+order by a desc ) dt;
+a
+7
+1
+10. view
+10.1. view as simple select
+create view v1 as
+select * from t1;
+show create view v1;
+View Create View character_set_client collation_connection
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`a` AS `a` from `t1` latin1 latin1_swedish_ci
+select * from v1;
+a
+3
+7
+1
+2
+4
+drop view v1;
+create view v1 as
+select 2*a as c from t1;
+show create view v1;
+View Create View character_set_client collation_connection
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select 2 * `t1`.`a` AS `c` from `t1` latin1 latin1_swedish_ci
+select * from v1;
+c
+6
+14
+2
+4
+8
+drop view v1;
+create view v1(c) as
+select 2*a from t1;
+show create view v1;
+View Create View character_set_client collation_connection
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select 2 * `t1`.`a` AS `c` from `t1` latin1 latin1_swedish_ci
+select * from v1;
+c
+6
+14
+2
+4
+8
+drop view v1;
+create view v1 as
+((select * from t1));
+show create view v1;
+View Create View character_set_client collation_connection
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS (select `t1`.`a` AS `a` from `t1`) latin1 latin1_swedish_ci
+select * from v1;
+a
+3
+7
+1
+2
+4
+drop view v1;
+10.2. view as tailed simple select
+create view v1 as
+select * from t1 order by a;
+show create view v1;
+View Create View character_set_client collation_connection
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`a` AS `a` from `t1` order by `t1`.`a` latin1 latin1_swedish_ci
+select * from v1;
+a
+1
+2
+3
+4
+7
+drop view v1;
+create view v1 as
+(select * from t2 order by a limit 2) order by b desc;
+show create view v1;
+View Create View character_set_client collation_connection
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `__3`.`a` AS `a`,`__3`.`b` AS `b` from (select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t2` order by `test`.`t2`.`a` limit 2) `__3` order by `__3`.`b` desc latin1 latin1_swedish_ci
+select * from v1;
+a b
+2 20
+1 10
+drop view v1;
+10.3. view as union
+create view v1 as
+select a from t1 union select b from t2;
+show create view v1;
+View Create View character_set_client collation_connection
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`a` AS `a` from `t1` union select `t2`.`b` AS `b` from `t2` latin1 latin1_swedish_ci
+select * from v1;
+a
+3
+7
+1
+2
+4
+30
+70
+10
+20
+40
+drop view v1;
+create view v1 as
+(select a from t1) union (select b from t2);
+show create view v1;
+View Create View character_set_client collation_connection
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS (select `t1`.`a` AS `a` from `t1`) union (select `t2`.`b` AS `b` from `t2`) latin1 latin1_swedish_ci
+select * from v1;
+a
+3
+7
+1
+2
+4
+30
+70
+10
+20
+40
+drop view v1;
+create view v1 as
+(select a from t1 where a=1) union select a from t1 where a=3;
+show create view v1;
+View Create View character_set_client collation_connection
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS (select `t1`.`a` AS `a` from `t1` where `t1`.`a` = 1) union select `t1`.`a` AS `a` from `t1` where `t1`.`a` = 3 latin1 latin1_swedish_ci
+select * from v1;
+a
+1
+3
+drop view v1;
+create view v1 as
+((select a from t1 where a<=3) union (select a from t1 where a=3));
+show create view v1;
+View Create View character_set_client collation_connection
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS (select `t1`.`a` AS `a` from `t1` where `t1`.`a` <= 3) union (select `t1`.`a` AS `a` from `t1` where `t1`.`a` = 3) latin1 latin1_swedish_ci
+select * from v1;
+a
+3
+1
+2
+drop view v1;
+create view v1 as
+select a from t1 where a=1
+union
+select a from t1 where a=3
+union
+select a from t1 where a=7;
+show create view v1;
+View Create View character_set_client collation_connection
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`a` AS `a` from `t1` where `t1`.`a` = 1 union select `t1`.`a` AS `a` from `t1` where `t1`.`a` = 3 union select `t1`.`a` AS `a` from `t1` where `t1`.`a` = 7 latin1 latin1_swedish_ci
+select * from v1;
+a
+1
+3
+7
+drop view v1;
+create view v1 as
+( ( select a from t1 where a!=3 order by a desc limit 3)
+union
+select a from t1 where a=3 );
+show create view v1;
+View Create View character_set_client collation_connection
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS (select `t1`.`a` AS `a` from `t1` where `t1`.`a` <> 3 order by `t1`.`a` desc limit 3) union select `t1`.`a` AS `a` from `t1` where `t1`.`a` = 3 latin1 latin1_swedish_ci
+select * from v1;
+a
+7
+4
+2
+3
+drop view v1;
+create view v1 as
+( select a from t1 where a <=3 except select a from t1 where a >=3 )
+union
+select a from t1 where a=7;
+show create view v1;
+View Create View character_set_client collation_connection
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `__5`.`a` AS `a` from (select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` <= 3 except select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` >= 3) `__5` union select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = 7 latin1 latin1_swedish_ci
+select * from v1;
+a
+1
+2
+7
+drop view v1;
+create view v1 as
+(select a from t1 limit 2) union select a from t1 where a=3 order by a desc;
+show create view v1;
+View Create View character_set_client collation_connection
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS (select `t1`.`a` AS `a` from `t1` limit 2) union select `t1`.`a` AS `a` from `t1` where `t1`.`a` = 3 order by `a` desc latin1 latin1_swedish_ci
+select * from v1;
+a
+7
+3
+drop view v1;
+create view v1 as
+select a from t1 where a=1
+union
+( select a from t1 where a=3
+union
+( select a from t1 where a=2
+union
+( select a from t1 where a=4 ) ) );
+show create view v1;
+View Create View character_set_client collation_connection
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = 1 union select `__7`.`a` AS `a` from (select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = 3 union select `__6`.`a` AS `a` from (select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = 2 union (select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = 4)) `__6`) `__7` latin1 latin1_swedish_ci
+select * from v1;
+a
+1
+3
+2
+4
+drop view v1;
+create view v1 as
+( ( select a from t1 where a >= 2
+union
+select a from t1 where a=1 order by a desc limit 2 )
+union
+select a from t1 where a=3 order by a limit 2 )
+union
+select a from t1 where a=1;
+show create view v1;
+View Create View character_set_client collation_connection
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `__7`.`a` AS `a` from (select `__5`.`a` AS `a` from (select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` >= 2 union select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = 1 order by `a` desc limit 2) `__5` union select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = 3 order by `a` limit 2) `__7` union select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = 1 latin1 latin1_swedish_ci
+select * from v1;
+a
+3
+4
+1
+drop view v1;
+10.4. view as [tailed] TVC
+create view v1 as
+values (3), (7), (1);
+show create view v1;
+View Create View character_set_client collation_connection
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS values (3),(7),(1) latin1 latin1_swedish_ci
+select * from v1;
+3
+3
+7
+1
+drop view v1;
+create view v1 as
+(((values (3), (7), (1))) order by 1);
+show create view v1;
+View Create View character_set_client collation_connection
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS (values (3),(7),(1) order by 1) latin1 latin1_swedish_ci
+select * from v1;
+3
+1
+3
+7
+drop view v1;
+10.5. view as [tailed] union of TVCs
+create view v1 as
+values (3), (7), (1) union values (3), (4), (2);
+show create view v1;
+View Create View character_set_client collation_connection
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS values (3),(7),(1) union values (3),(4),(2) latin1 latin1_swedish_ci
+select * from v1;
+3
+3
+7
+1
+4
+2
+drop view v1;
+create view v1 as
+(values (3), (7), (1) union values (3), (4), (2)) order by 1;
+show create view v1;
+View Create View character_set_client collation_connection
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS values (3),(7),(1) union values (3),(4),(2) order by 1 latin1 latin1_swedish_ci
+select * from v1;
+3
+1
+2
+3
+4
+7
+drop view v1;
+create view v1 as
+(values (3), (7), (1) order by 1 limit 2)
+union
+(values (3), (4), (2) order by 1 desc limit 2);
+show create view v1;
+View Create View character_set_client collation_connection
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS (values (3),(7),(1) order by 1 limit 2) union (values (3),(4),(2) order by 1 desc limit 2) latin1 latin1_swedish_ci
+select * from v1;
+3
+1
+3
+4
+drop view v1;
+create view v1 as
+(values (3), (7), (1) order by 1 limit 2)
+union
+values (3), (4), (2)
+order by 1;
+show create view v1;
+View Create View character_set_client collation_connection
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS (values (3),(7),(1) order by 1 limit 2) union values (3),(4),(2) order by 1 latin1 latin1_swedish_ci
+select * from v1;
+3
+1
+2
+3
+4
+drop view v1;
+10.6. view as [tailed] union of [tailed] select and tailed TVC
+create view v1 as
+( (((select a from t1 where a <=3) order by a) limit 2)
+union
+(((values (3), (4), (2)) order by 1 desc) limit 2) )
+order by a;
+show create view v1;
+View Create View character_set_client collation_connection
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS (select `t1`.`a` AS `a` from `t1` where `t1`.`a` <= 3 order by `t1`.`a` limit 2) union (values (3),(4),(2) order by 1 desc limit 2) order by `a` latin1 latin1_swedish_ci
+select * from v1;
+a
+1
+2
+3
+4
+drop view v1;
+create view v1 as
+( select a from t1 where a=1
+union
+values (3), (4), (2) order by 1 desc )
+union
+select a from t1 where a=2 order by a desc limit 3;
+show create view v1;
+View Create View character_set_client collation_connection
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `__5`.`a` AS `a` from (select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = 1 union values (3),(4),(2) order by 1 desc) `__5` union select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = 2 order by `a` desc limit 3 latin1 latin1_swedish_ci
+select * from v1;
+a
+4
+3
+2
+drop view v1;
+10.7. view as select with CTE
+create view v1 as
+with t as (select * from t1 where a <=3)
+select * from t;
+show create view v1;
+View Create View character_set_client collation_connection
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS with t as (select `t1`.`a` AS `a` from `t1` where `t1`.`a` <= 3)select `t`.`a` AS `a` from `t` latin1 latin1_swedish_ci
+select * from v1;
+a
+3
+1
+2
+drop view v1;
+create view v1 as
+with t as
+( select * from t1 where a < 3
+union
+select * from t1 where a > 3
+order by a desc limit 3 )
+select a from t1 where a=4 union select a from t where a=7;
+show create view v1;
+View Create View character_set_client collation_connection
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS with t as (select `t1`.`a` AS `a` from `t1` where `t1`.`a` < 3 union select `t1`.`a` AS `a` from `t1` where `t1`.`a` > 3 order by `a` desc limit 3)select `t1`.`a` AS `a` from `t1` where `t1`.`a` = 4 union select `t`.`a` AS `a` from `t` where `t`.`a` = 7 latin1 latin1_swedish_ci
+select * from v1;
+a
+4
+7
+drop view v1;
+10.8. view as union with CTE
+create view v1 as
+with t as
+( (select * from t1 where a < 3)
+union
+(select * from t1 where a > 3)
+order by a desc limit 3 )
+(select a from t1 where a=4 union select a from t where a=7 order by a desc);
+show create view v1;
+View Create View character_set_client collation_connection
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS with t as ((select `t1`.`a` AS `a` from `t1` where `t1`.`a` < 3) union (select `t1`.`a` AS `a` from `t1` where `t1`.`a` > 3) order by `a` desc limit 3)select `t1`.`a` AS `a` from `t1` where `t1`.`a` = 4 union select `t`.`a` AS `a` from `t` where `t`.`a` = 7 order by `a` desc latin1 latin1_swedish_ci
+select * from v1;
+a
+7
+4
+drop view v1;
+create view v1 as
+with t as
+( (select * from t1 where a < 3)
+union
+(select * from t1 where a > 3)
+order by a desc limit 3 )
+(select a from t where a=4 union select a from t where a=7 order by a desc);
+show create view v1;
+View Create View character_set_client collation_connection
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS with t as ((select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` < 3) union (select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` > 3) order by `a` desc limit 3)select `t`.`a` AS `a` from `t` where `t`.`a` = 4 union select `t`.`a` AS `a` from ((select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` < 3) union (select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` > 3) order by `a` desc limit 3) `t` where `t`.`a` = 7 order by `a` desc latin1 latin1_swedish_ci
+select * from v1;
+a
+7
+4
+drop view v1;
+create view v1 as
+with t(a) as (values (2), (1)) select a from t;
+show create view v1;
+View Create View character_set_client collation_connection
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS with t(a) as (values (2),(1))select `t`.`a` AS `a` from `t` latin1 latin1_swedish_ci
+select * from v1;
+a
+2
+1
+drop view v1;
+create view v1 as
+with t(a) as
+( values (2), (1)
+union
+(values (4), (7))
+order by 1 desc limit 3 )
+select a from t1 where a=4 union select a from t where a=7 order by a desc;
+show create view v1;
+View Create View character_set_client collation_connection
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS with t(a) as (values (2),(1) union (values (4),(7)) order by 1 desc limit 3)select `t1`.`a` AS `a` from `t1` where `t1`.`a` = 4 union select `t`.`a` AS `a` from `t` where `t`.`a` = 7 order by `a` desc latin1 latin1_swedish_ci
+select * from v1;
+a
+7
+4
+drop view v1;
+create view v1 as
+with t(a) as
+( (values (2), (1))
+union
+(values (4), (7) order by 1 desc)
+order by 1 desc limit 3 )
+select a from t1 where a=1 union select a from t where a=7 order by a desc;
+show create view v1;
+View Create View character_set_client collation_connection
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS with t(a) as ((values (2),(1)) union (values (4),(7) order by 1 desc) order by 1 desc limit 3)select `t1`.`a` AS `a` from `t1` where `t1`.`a` = 1 union select `t`.`a` AS `a` from `t` where `t`.`a` = 7 order by `a` desc latin1 latin1_swedish_ci
+select * from v1;
+a
+7
+1
+drop view v1;
+create view v1 as
+with t as (select * from t1 where a < 3),
+s as (select * from t1 where a > 3)
+select a from t where a=1 union select a from s where a=7 order by a desc;
+show create view v1;
+View Create View character_set_client collation_connection
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS with t as (select `t1`.`a` AS `a` from `t1` where `t1`.`a` < 3), s as (select `t1`.`a` AS `a` from `t1` where `t1`.`a` > 3)select `t`.`a` AS `a` from `t` where `t`.`a` = 1 union select `s`.`a` AS `a` from `s` where `s`.`a` = 7 order by `a` desc latin1 latin1_swedish_ci
+select * from v1;
+a
+7
+1
+drop view v1;
+create view v1 as
+with t as (select * from t1 where a < 3),
+s as (select * from t where a > 3)
+select a from t where a=1 union select a from s where a=7 order by a desc;
+show create view v1;
+View Create View character_set_client collation_connection
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS with t as (select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` < 3), s as (select `t`.`a` AS `a` from (select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` < 3) `t` where `t`.`a` > 3)select `t`.`a` AS `a` from `t` where `t`.`a` = 1 union select `s`.`a` AS `a` from `s` where `s`.`a` = 7 order by `a` desc latin1 latin1_swedish_ci
+select * from v1;
+a
+1
+drop view v1;
+drop table t1,t2;
# End of 10.4 tests
diff --git a/mysql-test/main/brackets.test b/mysql-test/main/brackets.test
index 9ca86b8..b7bb616 100644
--- a/mysql-test/main/brackets.test
+++ b/mysql-test/main/brackets.test
@@ -176,5 +176,2323 @@ select * from t1;
drop table t1;
+--echo #
+--echo # MDEV-19956: query expressions in different contexts
+--echo #
+
+create table t1 (a int);
+insert into t1 values (3), (7), (1), (2), (4);
+create table t2 (a int, b int);
+insert into t2 values (3,30), (7,70), (1,10), (2,20), (4,40);
+
+
+--echo # 1. select
+
+--echo # 1.1. simple select
+
+select * from t1;
+(select * from t1);
+((select * from t1));
+--echo # 1.2. select with tail
+select * from t1 order by a;
+select a from t1 order by a;
+select a from t1 order by 1;
+select * from t1 order by t1.a;
+(select * from t1 order by t1.a);
+((select * from t1 order by t1.a));
+(select * from t1 order by t1.a limit 2);
+(select a from t1 where a=1) order by 1 desc;
+
+--echo # 1.2. select with several tails
+
+(select * from t2 order by a limit 2) order by b desc;
+(select * from t2 order by t2.a limit 2) order by b desc;
+((select * from t2 order by t2.a limit 2) order by b desc);
+(((select * from t2 order by t2.a) limit 2) order by b desc);
+
+
+--echo # 2. union
+
+--echo # 2.1 simple union
+
+select a from t1 union select a from t1;
+select a from t1 union all select a from t1;
+select a from t1 union select b from t2;
+(select a from t1) union (select a from t1);
+(select a from t1) union (select b from t2);
+select a from t1 where a=1 union select a from t1 where a=3;
+(select a from t1 where a=1) union select a from t1 where a=3;
+((select a from t1 where a=1) union select a from t1 where a=3);
+((select a from t1 where a<=3) union (select a from t1 where a=3));
+select a from t1 where a=1 union (select a from t1 where a=3);
+(select a from t1 where a=1 union (select a from t1 where a=3));
+((select a from t1 where a=1 union (select a from t1 where a=3)));
+
+select a from t1 where a=1
+union
+select a from t1 where a=3
+union
+select a from t1 where a=7;
+
+( select a from t1 where a=1
+ union
+ select a from t1 where a=3
+ union
+ select a from t1 where a=7 );
+
+(select a from t1 where a=1 order by a) union select a from t1 where a=3;
+(select a from t1 where a!=3 order by a desc) union select a from t1 where a=3;
+((select a from t1 where a=1 order by a) union select a from t1 where a=3);
+(select a from t1 where a!=3 order by a desc) union select a from t1 where a=3;
+
+( ( select a from t1 where a!=3 order by a desc limit 3)
+ union
+ select a from t1 where a=3 );
+
+( select a from t1 where a <=3 except select a from t1 where a >=3 )
+ union
+ select a from t1 where a=7;
+
+( ( select a from t1 where a <=3
+ except
+ select a from t1 where a >=3 )
+ union
+ select a from t1 where a=7 );
+
+( select a from t1 where a <=3
+ except
+ ( select a from t1 where a >=3
+ union
+ select a from t1 where a=7 ) );
+
+( ( select a from t1 where a <=3 )
+ except
+ ( select a from t1 where a >=3
+ union
+ select a from t1 where a=7 ) );
+
+--echo # 2.2. union with tail
+
+select a from t1 where a=1 union select a from t1 where a=3 order by a desc;
+(select a from t1 limit 2) union select a from t1 where a=3 order by a desc;
+
+select a from t1 where a=4 union (select a from t1 where a <=4 limit 2)
+order by a desc;
+
+select a from t1 where a=4
+union
+(select a from t1 where a <=4 order by a limit 2)
+order by a desc;
+
+( select a from t1 where a=4
+ union
+ ( select a from t1 where a <=4 order by a limit 2 ) )
+order by a desc;
+
+( select a from t1 where a <=3 except select a from t1 where a >=3 )
+ union
+ select a from t1 where a=7 order by a desc;
+
+( select a from t1 where a!=3 order by a desc )
+ union
+ select a from t1 where a=3
+ order by a desc;
+
+(select a from t1 where a=1)
+union
+(select a from t1 where a=3)
+order by a desc;
+
+( select a from t1 where a=1
+ union
+ select a from t1 where a=3 )
+order by a desc;
+
+( ( select a from t1 where a=1 )
+ union
+ ( select a from t1 where a=3 ) )
+order by a desc;
+
+( select a from t1 where a=1
+ union
+ select a from t1 where a=3 )
+order by 1 desc;
+
+((select a from t1 where a=1 union select a from t1 where a=3)) order by 1 desc;
+(((select a from t1 where a=1) union (select a from t1 where a=3)))
+order by 1 desc;
+
+( (select a from t1 where a=1 )
+ union
+ (select a from t1 where a=3) )
+order by 1 desc;
+
+--echo # 2.3. complex union
+
+select a from t1 where a=1
+union
+select a from t1 where a=3
+union
+select a from t1 where a=2
+union
+select a from t1 where a=4;
+
+( select a from t1 where a=1
+ union
+ select a from t1 where a=3
+ union
+ select a from t1 where a=2 )
+union
+select a from t1 where a=4;
+
+(select a from t1 where a=1 union select a from t1 where a=3)
+union
+(select a from t1 where a=2 union select a from t1 where a=4);
+(select a from t1 where a=1 union (select a from t1 where a=3))
+union
+((select a from t1 where a=2) union select a from t1 where a=4);
+
+( ( select a from t1 where a=1)
+ union
+ select a from t1 where a=3 )
+union
+select a from t1 where a=2
+union
+select a from t1 where a=4;
+( ( ( select a from t1 where a=1)
+ union
+ select a from t1 where a=3 )
+ union
+ select a from t1 where a=2 )
+union
+select a from t1 where a=4;
+
+select a from t1 where a=1
+union
+select a from t1 where a=3
+union
+select a from t1 where a=2
+union
+(select a from t1 where a=4);
+
+select a from t1 where a=1
+union
+select a from t1 where a=3
+union
+( select a from t1 where a=2
+ union
+ ( select a from t1 where a=4 ) );
+
+select a from t1 where a=1
+union
+( select a from t1 where a=3
+ union
+ ( select a from t1 where a=2
+ union
+ ( select a from t1 where a=4 ) ) );
+
+--echo # 2.4. complex union with tail
+
+( ( select a from t1 where a=1 union select a from t1 where a=3 )
+ order by a desc )
+union
+( ( select a from t1 where a=2 union select a from t1 where a=4 )
+ order by a desc );
+
+( ( select a from t1 where a=1 union select a from t1 where a=3 )
+ order by a desc )
+union
+( ( select a from t1 where a=2 union select a from t1 where a=4 )
+ order by a desc )
+order by a;
+
+( select a from t1 where a=1
+ union
+ select a from t1 where a=3
+ union
+ select a from t1 where a=2 order by a desc limit 2 )
+union
+select a from t1 where a=4
+order by a;
+
+( select a from t1 where a=1
+ union
+ select a from t1 where a=3 order by a desc )
+union
+select a from t1 where a=2 order by a desc limit 2;
+
+( ( select a from t1 where a >= 2
+ union
+ select a from t1 where a=1 order by a desc limit 2 )
+ union
+ select a from t1 where a=3 order by a limit 2 )
+union
+select a from t1 where a=1;
+
+
+--echo # 3. TVC
+
+--echo # 3.1. simple TVC
+
+values (3), (7), (1);
+(values (3), (7), (1));
+((values (3), (7), (1)));
+
+--echo # 3.2. simple TVC with tail(s)
+
+values (3), (7), (1) order by 1;
+(values (3), (7), (1)) order by 1;
+((values (3), (7), (1))) order by 1;
+(((values (3), (7), (1))) order by 1);
+(values (3), (7), (1) limit 2) order by 1 desc;
+((values (3), (7), (1)) order by 1 desc) limit 2;
+(((values (3), (7), (1)) order by 1 desc) limit 2);
+
+--echo # 3.3. union of TVCs
+
+values (3), (7), (1) union values (3), (4), (2);
+values (3), (7), (1) union all values (3), (4), (2);
+values (3), (7), (1) union values (3), (4), (2);
+values (3), (7), (1) except values (3), (4), (2);
+(values (3), (7), (1)) union (values (3), (4), (2));
+(values (3), (7), (1)) union (values (3), (4), (2)) union values (5), (7);
+(values (3), (7), (1)) union (values (3), (4), (2)) union (values (5), (7));
+(values (3), (7), (1) union values (3), (4), (2)) union values (5), (7);
+values (3), (7), (1) union (values (3), (4), (2) union values (5), (7));
+(values (3), (7), (1) union ((values (3), (4), (2) union values (5), (7))));
+
+--echo # 3.4. tailed union of TVCs
+
+values (3), (7), (1) union values (3), (4), (2) order by 1;
+(values (3), (7), (1) union values (3), (4), (2)) order by 1;
+(values (3), (7), (1) union values (3), (4), (2)) order by 1;
+values (3), (7), (1) union (values (3), (4), (2)) order by 1;
+(values (3), (7), (1) union values (3), (4), (2)) order by 1;
+((values (3), (7), (1)) union values (3), (4), (2)) order by 1;
+
+--echo # 3.5. union of tailed TVCs
+
+(values (3), (7), (1) order by 1 limit 2)
+union
+(values (3), (4), (2) order by 1 desc limit 2);
+
+((values (3), (7), (1) order by 1) limit 2)
+union
+((values (3), (4), (2) order by 1 desc) limit 2);
+
+(((values (3), (7), (1)) order by 1) limit 2)
+union
+(((values (3), (4), (2)) order by 1 desc) limit 2);
+
+--echo # 3.6. tailed union of tailed TVCs
+
+(values (3), (7), (1) order by 1 limit 2)
+union
+values (3), (4), (2)
+order by 1;
+
+((values (3), (7), (1)) order by 1 limit 2)
+union
+((values (3), (4), (2) order by 1 desc) limit 2)
+order by 1;
+
+--echo # 3.7 [tailed] union of [tailed] select and [tailed] TVC
+
+(select a from t1 where a <=3 order by 1 limit 2)
+union
+(values (3), (4), (2) order by 1 desc limit 2);
+
+((select a from t1 where a <=3) order by 1 limit 2)
+union
+(values (3), (4), (2) order by 1 desc limit 2);
+
+(((select a from t1 where a <=3) order by a) limit 2)
+union
+(((values (3), (4), (2)) order by 1 desc) limit 2);
+
+( (((select a from t1 where a <=3) order by a) limit 2)
+ union
+ (((values (3), (4), (2)) order by 1 desc) limit 2) );
+
+(select a from t1 where a <=3 order by 1 limit 2)
+union
+(values (3), (4), (2) order by 1 desc limit 2)
+order by a;
+
+((select a from t1 where a <=3) order by 1 limit 2)
+union
+(values (3), (4), (2) order by 1 desc limit 2)
+order by a;
+
+(((select a from t1 where a <=3) order by a) limit 2)
+union
+(((values (3), (4), (2)) order by 1 desc) limit 2)
+order by a;
+
+(((values (3), (4), (2)) order by 1 desc) limit 2);
+( (((select a from t1 where a <=3) order by a) limit 2)
+ union
+ (((values (3), (4), (2)) order by 1 desc) limit 2) )
+order by a;
+
+(values (3), (4), (2) order by 1 desc limit 2)
+union
+(select a from t1 where a <=3 order by 1 limit 2);
+
+(values (3), (4), (2) order by 1 desc limit 2)
+union
+((select a from t1 where a <=3) order by 1 limit 2);
+
+(((values (3), (4), (2)) order by 1 desc) limit 2)
+union
+(((select a from t1 where a <=3) order by 1) limit 2);
+
+(((values (3), (4), (2)) order by 1 desc) limit 2)
+union
+(((select a from t1 where a <=3) order by a) limit 2)
+order by 1;
+
+( select a from t1 where a=1
+ union
+ values (3), (4), (2) order by 1 desc )
+union
+select a from t1 where a=2 order by a desc limit 3;
+
+
+--echo 4. CTE
+
+--echo 4.1. simple select with simple CTE
+
+with t as (select * from t1 where a <=3)
+select * from t;
+
+with t as (select * from t1 where a <=3)
+(select * from t);
+
+with t as (select * from t1 where a <=3)
+((select * from t));
+
+with t as ((select * from t1 where a <=3))
+select * from t;
+with t as (((select * from t1 where a <=3)))
+select * from t;
+
+--echo 4.2. tailed select with simple CTE
+
+with t as (select * from t1 where a <=3)
+select * from t order by a;
+
+with t as (select * from t1 where a <=3)
+(select * from t) order by a;
+
+with t as (select * from t1 where a <=3)
+(select * from t) order by a desc limit 2;
+
+--echo 4.3. [tailed] select with tailed CTE
+
+with t as (select * from t1 where a >=2 order by a limit 2)
+select * from t;
+
+with t as (((select * from t1 where a >=2) order by a desc) limit 2)
+select * from t;
+
+with t as (select * from t1 where a >=2 order by a desc limit 2)
+select * from t order by a;
+
+--echo 4.4. [tailed] union with CTE
+
+with t as (select * from t1 where a <=3)
+select a from t1 where a=1 union select a from t where a=3;
+
+with t as (select * from t1 where a <=3)
+(select a from t) union (select b from t2);
+
+with t as (select * from t1 where a <=3)
+(select a from t) union (select b as a from t2) order by a desc;
+
+--echo 4.5. [tailed] union with [tailed] union in CTE
+
+with t as (select * from t1 where a < 3 union select * from t1 where a > 3)
+select a from t1 where a=1 union select a from t where a=7;
+
+with t as
+( select * from t1 where a < 3
+ union
+ select * from t1 where a > 3
+ order by a desc limit 3 )
+select a from t1 where a=4 union select a from t where a=7;
+
+with t as
+( select * from t1 where a < 3
+ union
+ select * from t1 where a > 3
+ order by a desc limit 3 )
+select a from t1 where a=4 union select a from t where a=7 order by a desc;
+
+with t as
+( (select * from t1 where a < 3)
+ union
+ (select * from t1 where a > 3)
+ order by a desc limit 3 )
+select a from t1 where a=4 union select a from t where a=7 order by a desc;
+
+with t as
+( (select * from t1 where a < 3)
+ union
+ (select * from t1 where a > 3)
+ order by a desc limit 3 )
+(select a from t1 where a=4 union select a from t where a=7 order by a desc);
+
+with t as
+( (select * from t1 where a < 3)
+ union
+ (select * from t1 where a > 3)
+ order by a desc limit 3 )
+((select a from t1 where a=4 union select a from t where a=7) order by a desc);
+
+with t as
+( select * from t1 where a < 3
+ union
+ values (4), (7)
+ order by a desc limit 3 )
+select a from t1 where a=4 union select a from t where a=7 order by a desc;
+
+
+--echo 4.6. [tailed] union with [tailed] union of TVC in CTE
+
+with t(a) as
+( values (2), (1)
+ union
+ (values (4), (7))
+ order by 1 desc limit 3 )
+select a from t1 where a=4 union select a from t where a=7 order by a desc;
+
+with t(a) as
+( (values (2), (1))
+ union
+ (values (4), (7) order by 1 desc)
+ order by 1 desc limit 3 )
+select a from t1 where a=1 union select a from t where a=7 order by a desc;
+
+with t(a) as
+( (values (2), (1))
+ union
+ (values (4), (7) order by 1 desc)
+ order by 1 limit 3 )
+select a from t where a=1 union values (7) order by a desc;
+
+with t(a) as
+( (values (2), (1))
+ union
+ (values (4), (7) order by 1 desc ) )
+select a from t where a=1 union select 7 order by a desc;
+
+--echo 4.5. [tailed] union with two CTEs
+
+with t as (select * from t1 where a < 3),
+ s as (select * from t1 where a > 3)
+select a from t where a=1 union select a from s where a=7 order by a desc;
+
+with t as (select * from t1 where a < 3),
+ s as (select * from t1 where a > 3)
+(select a from t where a=1 union select a from s where a=7 order by a desc);
+
+with t as (select * from t1 where a < 3),
+ s as (select * from t1 where a > 3)
+(select a from t where a=1 union select a from s where a=7) order by a desc;
+
+with t as (select * from t1 where a < 3),
+ s as (select * from t where a > 3)
+select a from t where a=1 union select a from s where a=7 order by a desc;
+
+
+--echo # 5. single-row subquery in expression
+
+--echo # 5.1. [tailed] simple select in expression
+
+select (a+1) + b as r from t2;
+select ((a+1) + b) as r from t2;
+select (b + (select 1)) as r from t2;
+select (select a from t1 where a <=3 order by a desc limit 1) as r from t2;
+
+select
+(select a from t1 where a <=3 order by a desc limit 1) as r from t2;
+
+select (select 100) as r from t2;
+select ((select 100)) as r from t2;
+select (select 100) + t2.b as r from t2;
+select ((select 100) + t2.b) as r from t2;
+
+--echo # 5.2. [tailed] TVC in expression
+
+select (values (200)) as r from t2;
+select ((values (200))) as r from t2;
+select (values (200)) + t2.b as r from t2;
+select ((values (200)) + t2.b) as r from t2;
+select (values (200), (300) order by 1 desc limit 1) as r from t2;
+select ((values (200), (300)) order by 1 desc limit 1) as r from t2;
+select (select * from t1 limit 1) as r from t2;
+select (select * from t1 order by a limit 1) as r from t2;
+select ((select * from t1 order by a limit 1)) as r from t2;
+((select ((select * from t1 order by a limit 1)) as r from t2));
+select (select * from t1 order by a limit 1) + t2.b as r from t2;
+
+--echo # 5.3. [tailed] union in expression
+
+select
+( select a from t1 where a<3 union select a from t1 where a>4
+ order by a desc limit 1 ) as r
+from t1;
+
+select
+( (select a from t1 where a<3) union (select a from t1 where a>4)
+ order by a desc limit 1 ) as r
+from t1;
+
+select
+( select a from t1 where a<3 union select a from t1 where a>4
+ order by a desc limit 1 ) + t1.a as r
+from t1;
+
+select
+t1.a +
+( select a from t1 where a<3 union select a from t1 where a>4
+ order by a desc limit 1 ) as r
+from t1;
+
+select
+( (select a from t1 where a<3 union select a from t1 where a>4
+ order by a desc limit 1 ) + t1.a) as r
+from t1;
+
+select
+( ( (select a from t1 where a<3) union (select a from t1 where a>4)
+ order by a desc limit 1 ) + t1.a ) as r
+from t1;
+
+--echo # 5.4. [tailed] select with simple CTE in expression
+
+select
+( with t as (select * from t1 where a <=3)
+ select a from t limit 1) as r
+from t2;
+
+select
+( with t as (select * from t1 where a <=3)
+ select a from t limit 1) + t2.b as r
+from t2;
+
+select
+t2.b +( with t as (select * from t1 where a <=3)
+ select a from t limit 1) as r
+from t2;
+
+select
+((( with t as (select * from t1 where a <=3)
+ select a from t limit 1) + t2.b)) as r
+from t2;
+
+select
+( with t as (select * from t1 where a <=3)
+ select a from t limit 1) + 100 as r
+from t2;
+
+select
+( with t as (select * from t1 where a <=3)
+ select a from t limit 1) + (select 100) as r
+from t2;
+
+select
+( with t as (select * from t1 where a <=3)
+ select a from t limit 1) + t2.b + (select 100) as r
+from t2;
+
+select
+( with t as (select * from t1 where a <=3)
+ select a from t limit 1 ) + (t2.b + (select 100)) as r
+from t2;
+
+select
+( with t as (select * from t1 where a <=3)
+ select a from t limit 1 ) + t2.b + (values (100)) as r
+from t2;
+
+--echo # 5.5. [tailed] union with simple CTE in expression
+
+select
+( with t as (select * from t1 where a <=3)
+ select a from t union select b from t2 order by a desc limit 1) as r
+from t2;
+
+select
+( with t as (select * from t1 where a <=3)
+ (select a from t) union (select b from t2) order by a desc limit 1) as r
+from t2;
+
+select
+( with t as (select * from t1 where a <=3)
+ (select a from t) union (select b from t2) order by a desc limit 1) as r
+from t2;
+
+select
+( ( with t as (select * from t1 where a <=3)
+ (select a from t) union (select b from t2) order by a desc limit 1) +
+ t2.a ) as r
+from t2;
+
+--echo # 5.6. [tailed] union with CTE with union in expression
+
+select
+( with t as
+ ( select * from t1 where a < 3
+ union
+ select * from t1 where a > 3
+ order by a desc limit 3 )
+ select a from t1 where a=4 union select a from t where a=7 limit 1) as r
+from t2;
+
+select
+( with t as
+ ( select * from t1 where a < 3
+ union
+ select * from t1 where a > 3
+ order by a desc limit 3 )
+ select a from t1 where a=4 union select a from t where a=7 limit 1) +
+t2. b as r
+from t2;
+
+--echo # 5.7. [tailed] union of TVCs with CTE with union in expression
+
+select
+( with t(a) as
+ ( (values (2), (1))
+ union
+ (values (4), (7) order by 1 limit 1)
+ order by 1 desc limit 3 ) select * from t limit 1 ) + t2.b as r
+from t2;
+
+select
+( with t(a) as
+ ( select 2 union select 1
+ union
+ (values (4), (7) order by 1 limit 1)
+ order by 1 limit 3 ) select * from t limit 1 ) + t2.b as r
+from t2;
+
+
+--echo # 6. subquery
+
+--echo # 6.1. TVC in IN subquery
+
+select a from t1 where a in (1,8,7);
+select a from t1 where a in (values (1), (8), (7));
+
+--echo # 6.2. simple select in IN subquery
+
+select a from t1 where a in (select a from t2 where a <= 3);
+select a from t1 where a in ((select a from t2 where a <= 3));
+
+--echo # 6.3. union in IN subquery
+
+select a from t1
+where a in (select a from t1 where a<=2 union select a from t2 where b>40);
+
+select a from t1
+where a in (select a from t1 where a<=2 union (select a from t2 where b>40));
+
+select a from t1
+where a in ((select a from t1 where a<=2) union select a from t2 where b>40);
+
+select a from t1
+where a in ((select a from t1 where a<=2) union (select a from t2 where b>40));
+
+--echo # 6.4. select with CTE and union in IN subquery
+
+with t as (select a from t1 where a<=2)
+select a from t1
+where a in ((select a from t) union (select a from t2 where b>40));
+
+with t as ((select a from t1 where a<=2))
+select a from t1
+where a in ((select a from t) union (select a from t2 where b>40));
+
+with t as ((select a from t1 where a<=2) order by a desc limit 1)
+select a from t1
+where a in ((select a from t) union (select a from t2 where b>40));
+
+
+--echo # 6.5. NOT IN subquery
+
+select a from t1 where a not in (1,8,7);
+select a from t1 where a not in (values (1), (8), (7));
+select a from t1 where a not in (select a from t2 where a <= 3);
+select a from t1 where a not in ((select a from t2 where a <= 3));
+
+select a from t1
+where a not in (select a from t1 where a<=2
+ union
+ select a from t2 where b>40);
+
+select a from t1
+where a not in (select a from t1 where a<=2
+ union
+ (select a from t2 where b>40));
+
+select a from t1
+where a not in ((select a from t1 where a<=2)
+ union
+ select a from t2 where b>40);
+
+select a from t1
+where a not in ((select a from t1 where a<=2)
+ union
+ (select a from t2 where b>40));
+
+with t as ((select a from t1 where a<=2) order by a desc limit 1)
+select a from t1
+where a not in ((select a from t) union (select a from t2 where b>40));
+
+--echo # 6.6. IN subquery in expression
+
+select 1 in (select a from t1) as r, b from t2 where b > 30;
+select (1 in (select a from t1)) as r, b from t2 where b > 30;
+select 1 in ((select a from t1)) as r, b from t2 where b > 30;
+select ((1 in ((select a from t1)))) as r, b from t2 where b > 30;
+select ((1 in ((select a from t1)))) as r, b from t2 where b > 30;
+select b, if (a in (select a from t1 where a > 3),10,20) as r from t2;
+select b, if (a in ((select a from t1 where a > 3)),10,20) as r from t2;
+
+--echo # 6.7. IN subquery in SF and SP
+
+create function f1(x int) returns int
+return (x in ((select a from t1 where a <= 4)));
+select b, f1(a) from t2 where b > 20;
+drop function f1;
+delimiter |;
+create function f2(x int) returns int
+if x in ((select a from t1 where a <= 4))
+ then return 100;
+ else return 200;
+end if |
+delimiter ;|
+select b, f2(a) from t2 where b > 20;
+drop function f2;
+
+--echo # 6.8. EXISTS subquery
+
+select exists (select a from t1 where t1.a=t2.a) as r, b from t2 where b > 30;
+select exists ((select a from t1 where t1.a=t2.a)) as r, b from t2 where b > 30;
+with s as
+( (select * from t1 where a <=4 order by 1 desc limit 2)
+ union
+ values (3), (8), (7) )
+select * from t2 where exists ((select * from s where s.a=t2.a));
+with t as ((select a from t1 where a<=2) order by a desc limit 1)
+select a from t2
+where not exists ((select a from t where t.a=t2.a)
+ except
+ (select a from t where a>40));
+
+--echo # 6.9. EXISTS subquery with SF and SP
+
+create function f1(x int) returns int
+return exists (((select * from t1 where x=a and a <= 4)));
+select b, f1(a) from t2 where b > 20;
+drop function f1;
+
+delimiter |;
+create function f2(x int) returns int
+if not exists (((select * from t1 where x=a and a <= 4)))
+ then return 100;
+ else return 200;
+end if |
+delimiter ;|
+select b, f2(a) from t2 where b > 20;
+drop function f2;
+
+--echo # 6.10. subquery with ANY
+
+select a from t1 where a = any(select a from t2 where a <= 3);
+select a from t1 where a = any((select a from t2 where a <= 3));
+
+select a from t1
+where a = any (select a from t1 where a<=2
+ union
+ select a from t2 where b>40);
+
+select a from t1
+where a = any(select a from t1 where a<=2
+ union
+ (select a from t2 where b>40));
+
+select a from t1
+where a = any((select a from t1 where a<=2)
+ union
+ select a from t2 where b>40);
+
+select a from t1
+where a = any((select a from t1 where a<=2)
+ union
+ (select a from t2 where b>40));
+
+
+--echo # 7. create table as
+
+--echo # 7.1. create table as simple select
+
+create table t as select * from t1 where a <=3;
+select * from t;
+drop table t;
+
+create table t select * from t1 where a <=3;
+select * from t;
+drop table t;
+
+create table t as (select * from t1 where a <=3);
+select * from t;
+drop table t;
+
+create table t (select * from t1 where a <=3);
+select * from t;
+drop table t;
+
+create table t as ((select * from t1 where a <=3));
+select * from t;
+drop table t;
+
+create table t ((select * from t1 where a <=3));
+select * from t;
+drop table t;
+
+create table t(a decimal(10,2)) as select * from t1 where a <=3;
+select * from t;
+drop table t;
+
+create table t(a decimal(10,2)) select * from t1 where a <=3;
+select * from t;
+drop table t;
+
+create table t(a decimal(10,2)) as (select * from t1 where a <=3);
+select * from t;
+drop table t;
+
+create table t(a decimal(10,2)) (select * from t1 where a <=3);
+select * from t;
+drop table t;
+
+create table t(a decimal(10,2)) as ((select * from t1 where a <=3));
+select * from t;
+drop table t;
+
+create table t(a decimal(10,2)) ((select * from t1 where a <=3));
+select * from t;
+drop table t;
+
+create table t(a decimal(10,2), b int) as
+ ((select a, a as b from t1 where a <=3));
+select * from t;
+drop table t;
+
+create table t(a decimal(10,2), b int)
+ ((select a, a as b from t1 where a <=3));
+select * from t;
+drop table t;
+
+--echo # 7.2. create table as tailed select
+
+create table t as select * from t1 where a <=3 order by 1;
+select * from t;
+drop table t;
+
+create table t select * from t1 where a <=3 order by 1;
+select * from t;
+drop table t;
+
+create table t as select * from t1 where a <=3 order by 1 desc limit 2;
+select * from t;
+drop table t;
+
+create table t select * from t1 where a <=3 order by 1 desc limit 2;
+select * from t;
+drop table t;
+
+create table t as ((select * from t1 where a <=3) order by 1 desc) limit 2;
+select * from t;
+drop table t;
+
+create table t ((select * from t1 where a <=3) order by 1 desc) limit 2;
+select * from t;
+drop table t;
+
+--echo # 7.3. create table as select wihout from clause
+
+create table t as select 10;
+select * from t;
+drop table t;
+
+create table t select 10;
+select * from t;
+drop table t;
+
+--echo # 7.4. create table as union of selects wihout from clause
+
+create table t as select 10 union select 70;
+select * from t;
+drop table t;
+
+create table t select 10 union select 70;
+select * from t;
+drop table t;
+
+--echo # 7.5. create table as TVC
+
+create table t as values (7), (3), (8);
+select * from t;
+drop table t;
+
+create table t values (7), (3), (8);
+select * from t;
+drop table t;
+
+create table t as (values (7), (3), (8));
+select * from t;
+drop table t;
+
+create table t (values (7), (3), (8));
+select * from t;
+drop table t;
+
+create table t as ((values (7), (3), (8)));
+select * from t;
+drop table t;
+
+create table t ((values (7), (3), (8)));
+select * from t;
+drop table t;
+
+--echo # 7.6. create table as select with CTE
+
+create table t as
+with s(a) as (select * from t1 where a <=3 order by 1 desc limit 2)
+select * from s;
+select * from t;
+drop table t;
+
+create table t
+with s(a) as (select * from t1 where a <=3 order by 1 desc limit 2)
+select * from s;
+select * from t;
+drop table t;
+
+create table t as
+with s as
+( (select * from t1 where a <=4 order by 1 desc limit 2)
+ union
+ values (3), (8), (7) )
+select * from s;
+select * from t;
+drop table t;
+
+create table t
+with s as
+( (select * from t1 where a <=4 order by 1 desc limit 2)
+ union
+ values (3), (8), (7) )
+select * from s;
+select * from t;
+drop table t;
+
+create table t as
+with s(a) as (select * from t1 where a <=3 order by 1 desc limit 2)
+select * from s;
+select * from t;
+drop table t;
+
+--echo # 7.7. create table as union with CTE
+
+create table t as
+with s as
+( (select * from t1 where a <=4 order by 1 desc limit 2)
+ union
+ values (3), (8), (7) )
+select * from s where a>=7 union select a from t2 where b<40;
+select * from t;
+drop table t;
+
+create table t
+with s as
+( (select * from t1 where a <=4 order by 1 desc limit 2)
+ union
+ values (3), (8), (7) )
+select * from s where a>=7 union select a from t2 where b<40;
+select * from t;
+drop table t;
+
+create table t
+with s as
+( (select * from t1 where a <=4 order by 1 desc limit 2)
+ union
+ values (3), (8), (7) )
+select * from s where a>=7 union select a from t2 where b<40;
+select * from t;
+drop table t;
+
+create table t as
+with s as
+( ( (select * from t1 where a <=4 order by 1 desc limit 2)
+ union
+ values (3), (8), (7) ) )
+select * from s where a>=7 union select a from t2 where b<40;
+select * from t;
+drop table t;
+
+create table t
+with s as
+( ( (select * from t1 where a <=4 order by 1 desc limit 2)
+ union
+ values (3), (8), (7) ) )
+select * from s where a>=7 union select a from t2 where b<40;
+select * from t;
+drop table t;
+
+create table t as
+with s as
+( (select * from t1 where a <=4 order by 1 desc limit 2)
+ union
+ values (3), (8), (7) )
+select * from s where a>=7 union select a from s where a<4;
+select * from t;
+drop table t;
+
+create table t
+with s as
+( (select * from t1 where a <=4 order by 1 desc limit 2)
+ union
+ values (3), (8), (7) )
+select * from s where a>=7 union select a from s where a<4;
+select * from t;
+drop table t;
+
+create table t as
+with s as
+( select * from t1 where a <=4 or a=7 )
+select * from s where a>=7 union select a from s where a<3;
+select * from t;
+drop table t;
+
+create table t
+with s as
+(select * from t1 where a <=4 or a=7)
+select * from s where a>=7 union select a from s where a<3;
+select * from t;
+drop table t;
+
+create table t (a int)
+with s as
+( select * from t1 where a <=4 or a=7 )
+select * from s where a>=7 union select a from s where a<3;
+select * from t;
+drop table t;
+
+create table t (a int)
+with s as
+(select * from t1 where a <=4 or a=7)
+select * from s where a>=7 union select a from s where a<3;
+select * from t;
+drop table t;
+
+create table t
+with s as
+( select * from t1 where a <=4 or a=7 )
+select * from s where a>=7 union select a from s where a<3
+order by a desc limit 2;
+select * from t;
+drop table t;
+
+create table t
+( with s as
+ ( select * from t1 where a <=4 or a=7 )
+ select * from s where a>=7 union select a from s where a<3
+ order by a desc limit 2 );
+select * from t;
+drop table t;
+
+
+--echo # 8. insert
+
+create table t (c int, d int);
+
+--echo # 8.1. insert simple select
+
+insert into t select * from t2 where a <=3;
+select * from t;
+delete from t;
+
+insert into t(c) select t2.a from t2 where a <=3;
+select * from t;
+delete from t;
+
+insert into t (select * from t2 where a <=3);
+select * from t;
+delete from t;
+
+insert into t(c) (select t2.a from t2 where a <=3);
+select * from t;
+delete from t;
+
+insert into t ((select * from t2 where a <=3));
+select * from t;
+delete from t;
+
+insert into t(c) ((select t2.a from t2 where a <=3));
+select * from t;
+delete from t;
+
+drop table t;
+create table t(c decimal(10,2));
+
+insert into t select * from t1 where a <=3;
+select * from t;
+delete from t;
+
+insert into t(c) select * from t1 where a <=3;
+select * from t;
+delete from t;
+
+insert into t (select * from t1 where a <=3);
+select * from t;
+delete from t;
+
+insert into t(c) (select * from t1 where a <=3);
+select * from t;
+delete from t;
+
+insert into t ((select * from t1 where a <=3));
+select * from t;
+delete from t;
+
+insert into t(c) ((select * from t1 where a <=3));
+select * from t;
+delete from t;
+
+drop table t;
+create table t(a decimal(10,2), b int);
+
+insert into t ((select * from t2 where a <=3));
+select * from t;
+delete from t;
+
+insert into t(a) ((select a from t2 where a <=3));
+select * from t;
+delete from t;
+
+drop table t;
+create table t(c int, d int);
+
+--echo # 8.2. insert tailed select
+
+insert into t select * from t2 where a <=3 order by 1;
+select * from t;
+delete from t;
+
+insert into t(c) select a from t2 where a <=3 order by 1;
+select * from t;
+delete from t;
+
+insert into t select * from t2 where a <=3 order by 1 desc limit 2;
+select * from t;
+delete from t;
+
+insert into t(c) select a from t2 where a <=3 order by 1 desc limit 2;
+select * from t;
+delete from t;
+
+insert into t ((select * from t2 where a <=3) order by 1 desc) limit 2;
+select * from t;
+delete from t;
+
+insert into t(c) ((select a from t2 where a <=3) order by 1 desc) limit 2;
+select * from t;
+delete from t;
+
+--echo # 8.3. insert select without from clause
+
+insert into t select 10, 20;
+select * from t;
+delete from t;
+
+insert into t(c) select 10;
+select * from t;
+delete from t;
+
+--echo # 8.4. insert union of selects without from clause
+
+insert into t select 10,20 union select 70,80;
+select * from t;
+delete from t;
+
+insert into t(c) select 10 union select 70;
+select * from t;
+delete from t;
+
+--echo # 8.5. insert TVC
+
+insert into t values (7,70), (3,30), (8,80);
+select * from t;
+delete from t;
+
+insert into t(c) values (7), (3), (8);
+select * from t;
+delete from t;
+
+insert into t (values (7,70), (3,30), (8,80));
+select * from t;
+delete from t;
+
+insert into t(c) (values (7), (3), (8));
+select * from t;
+delete from t;
+
+insert into t ((values (7,70), (3,30), (8,80)));
+select * from t;
+delete from t;
+
+insert into t(c) ((values (7), (3), (8)));
+select * from t;
+delete from t;
+
+--echo # 8.7. insert simple select with CTE
+
+insert into t
+with s(a,b) as (select * from t2 where a <=3 order by 1 desc limit 2)
+select * from s;
+select * from t;
+delete from t;
+
+insert into t(c)
+with s(a) as (select a from t2 where a <=3 order by 1 desc limit 2)
+select * from s;
+select * from t;
+delete from t;
+
+insert into t
+with s as
+( (select * from t2 where a <=4 order by 1 desc limit 2)
+ union
+ values (3,30), (8,80), (7,70) )
+select * from s;
+select * from t;
+delete from t;
+
+insert into t(c)
+with s as
+( (select a from t2 where a <=4 order by 1 desc limit 2)
+ union
+ values (3), (8), (7) )
+select * from s;
+select * from t;
+delete from t;
+
+--echo # 8.8. insert into union with CTE
+insert into t(c)
+with s as
+( (select a from t2 where a <=4 order by 1 desc limit 2)
+ union
+ values (3), (8), (7) )
+select * from s where a>=7 union select a from t2 where b<40;
+select * from t;
+delete from t;
+
+insert into t
+with s as
+( (select * from t2 where a <=4 order by 1 desc limit 2)
+ union
+ values (3,30), (8,80), (7,70) )
+select * from s where a>=7 union select * from s where a<4;
+select * from t;
+delete from t;
+
+insert into t(c)
+with s as
+( (select a from t2 where a <=4 order by 1 desc limit 2)
+ union
+ values (3), (8), (7) )
+select * from s where a>=7 union select * from s where a<4;
+select * from t;
+delete from t;
+
+insert into t
+with s as
+( select * from t2 where a <=4 or a=7 )
+select * from s where a>=7 union select * from s where a<3;
+select * from t;
+delete from t;
+
+insert into t(c)
+with s as
+( select a from t2 where a <=4 or a=7 )
+select * from s where a>=7 union select * from s where a<3;
+select * from t;
+delete from t;
+
+drop table t;
+
+
+--echo # 9. derived table
+
+--echo # 9.1. derived table as [tailed] simple select
+
+select * from (select * from t1) as dt;
+select * from ((select * from t1)) as dt;
+select * from (((select * from t1))) as dt;
+select * from (select * from t1 order by a) as dt;
+select * from (select a from t1 order by a) as dt;
+select * from (select a from t1 order by 1) as dt;
+select * from (select a from t1 order by t1.a) as dt;
+select * from ((select * from t1 order by t1.a limit 2)) as dt;
+select * from ((select * from t2 order by a limit 2) order by b desc) dt;
+select * from ((select a from t1 where a=1) order by 1 desc) dt;
+
+--echo # 9.2. derived table as select with two tails
+
+select * from
+((select * from t2 order by t2.a limit 2) order by b desc) dt;
+
+select * from
+((select * from t2 order by t2.a limit 2) order by b desc) as dt;
+
+select * from
+(((select * from t2 order by t2.a limit 2) order by b desc )) as dt;
+
+select * from
+(((select * from t2 order by t2.a) limit 2) order by b desc) dt;
+
+select * from
+((select * from t2 order by a limit 2) order by b desc) dt;
+
+select * from
+((select a from t1 where a=1) order by 1 desc) as dt;
+
+select * from
+((select * from t2 order by t2.a limit 2) order by b desc) as dt;
+
+
+--echo # 9.3. derived table as union
+
+select * from (select a from t1 union select a from t1) as dt;
+select * from (select a from t1 union all select a from t1) as dt;
+select * from (select a from t1 union select b from t2) as dt;
+
+select * from
+((select a from t1) union (select a from t1)) as dt;
+
+select * from
+((select a from t1) union (select b from t2)) as dt;
+
+select * from
+(select a from t1 where a=1 union select a from t1 where a=3) dt;
+
+select * from
+((select a from t1 where a=1) union select a from t1 where a=3) dt;
+
+select * from
+(((select a from t1 where a=1) union select a from t1 where a=3)) dt;
+
+select * from
+(((select a from t1 where a<=3) union (select a from t1 where a=3))) as dt;
+
+select * from
+(select a from t1 where a=1 union (select a from t1 where a=3)) as dt;
+
+select * from
+((select a from t1 where a=1 union (select a from t1 where a=3))) as dt;
+
+select * from
+(((select a from t1 where a=1 union (select a from t1 where a=3)))) as dt;
+
+select * from
+( select a from t1 where a=1
+ union
+ select a from t1 where a=3
+ union
+ select a from t1 where a=7 ) as dt;
+
+select * from
+( (select a from t1 where a=1 order by a)
+ union
+ select a from t1 where a=3 ) as dt;
+
+select * from
+( (select a from t1 where a!=3 order by a desc)
+ union
+ select a from t1 where a=3 ) as dt;
+
+select * from
+( ( select a from t1 where a <=3 except select a from t1 where a >=3 )
+ union
+ select a from t1 where a=7 ) as dt;
+
+select * from
+( ( ( select a from t1 where a <=3
+ except
+ select a from t1 where a >=3 )
+ union
+ select a from t1 where a=7 ) ) as dt;
+
+select * from
+( select a from t1 where a=1
+ union
+ select a from t1 where a=3
+ order by a desc) as dt;
+
+select *from
+( (select a from t1 limit 2)
+ union
+ select a from t1 where a=3
+ order by a desc) as dt;
+
+select * from
+( select a from t1 where a=4
+ union
+ (select a from t1 where a <=4 limit 2)
+ order by a desc ) as dt;
+
+select * from
+( ( select a from t1 where a=4
+ union
+ ( select a from t1 where a <=4 order by a ) )
+ order by a desc limit 2 ) as dt;
+
+select * from
+( ( select a from t1 where a <=3 except select a from t1 where a >=3 )
+ union
+ select a from t1 where a=7 order by a desc ) as dt;
+
+select * from
+( ( select a from t1 where a!=3 order by a desc )
+ union
+ select a from t1 where a=3
+ order by a desc ) as dt;
+
+select * from
+( (select a from t1 where a=1)
+ union
+ (select a from t1 where a=3)
+ order by a desc ) as dt;
+
+select * from
+( ( select a from t1 where a=1
+ union
+ select a from t1 where a=3 )
+ order by a desc ) as dt;
+
+select * from
+( ( ( select a from t1 where a=1 )
+ union
+ ( select a from t1 where a=3 ) )
+ order by a desc ) as dt;
+
+select * from
+( ( select a from t1 where a=1
+ union
+ select a from t1 where a=3 )
+ order by 1 desc ) as dt;
+
+select * from
+( ( (select a from t1 where a=1
+ union
+ select a from t1 where a=3) ) order by 1 desc ) as dt;
+
+select * from
+((((select a from t1 where a=1) union (select a from t1 where a=3)))
+ order by 1 desc ) as dt;
+
+select * from
+( ( (select a from t1 where a=1 )
+ union
+ (select a from t1 where a=3) )
+ order by 1 desc ) as dt;
+
+select * from
+( select a from t1 where a=1
+ union
+ select a from t1 where a=3
+ union
+ select a from t1 where a=2
+ union
+ select a from t1 where a=4 ) as dt;
+
+select * from
+( ( select a from t1 where a=1
+ union
+ select a from t1 where a=3
+ union
+ select a from t1 where a=2 )
+ union
+ select a from t1 where a=4 ) as dt;
+
+select * from
+( (select a from t1 where a=1 union select a from t1 where a=3)
+ union
+ (select a from t1 where a=2 union select a from t1 where a=4) ) as dt;
+
+select * from
+( (select a from t1 where a=1 union (select a from t1 where a=3))
+ union
+ ((select a from t1 where a=2) union select a from t1 where a=4) ) as dt;
+
+select * from
+( ( ( select a from t1 where a=1)
+ union
+ select a from t1 where a=3 )
+ union
+ select a from t1 where a=2
+ union
+ select a from t1 where a=4 ) as dt;
+
+select * from
+( ( ( ( select a from t1 where a=1)
+ union
+ select a from t1 where a=3 )
+ union
+ select a from t1 where a=2 )
+ union
+ select a from t1 where a=4 ) as dt;
+
+select * from
+( select a from t1 where a=1
+ union
+ select a from t1 where a=3
+ union
+ select a from t1 where a=2
+ union
+ (select a from t1 where a=4) ) as dt;
+
+select * from
+( select a from t1 where a=1
+ union
+ select a from t1 where a=3
+ union
+ ( select a from t1 where a=2
+ union
+ ( select a from t1 where a=4 ) ) ) as dt;
+
+select * from
+( select a from t1 where a=1
+ union
+ ( select a from t1 where a=3
+ union
+ ( select a from t1 where a=2
+ union
+ ( select a from t1 where a=4 ) ) ) ) as dt;
+
+select * from
+( ( ( select a from t1 where a=1 union select a from t1 where a=3 )
+ order by a desc limit 2 )
+ union
+ ( ( select a from t1 where a=2 union select a from t1 where a=4 )
+ order by a desc limit 1 ) ) as dt;
+
+select * from
+( ( ( select a from t1 where a=1 union select a from t1 where a=3 )
+ order by a desc limit 2 )
+ union
+ ( ( select a from t1 where a=2 union select a from t1 where a=4 )
+ order by a desc limit 2 )
+ order by a) as dt;
+
+select * from
+( ( select a from t1 where a=1
+ union
+ select a from t1 where a=3
+ union
+ select a from t1 where a=2 order by a desc limit 2 )
+ union
+ select a from t1 where a=4
+ order by a limit 3 ) as dt;
+
+select * from
+( ( select a from t1 where a=1
+ union
+ select a from t1 where a=3 order by a desc limit 2)
+ union
+ select a from t1 where a=2 order by a desc limit 2 ) as dt;
+
+select * from
+( ( ( select a from t1 where a >= 2
+ union
+ select a from t1 where a=1 order by a desc limit 2 )
+ union
+ select a from t1 where a=3 order by a limit 2 )
+ union
+ select a from t1 where a=1 ) as dt;
+
+--echo # 9.3. derived table as [tailed] TVC
+
+select * from
+( values (3), (7), (1) ) as dt;
+
+select * from
+( (values (3), (7), (1)) ) as dt;
+
+select * from
+(((values (3), (7), (1)))) as dt;
+
+select * from
+( values (3), (7), (1) order by 1 limit 2 ) as dt;
+
+select * from
+( (values (3), (7), (1)) order by 1 limit 2 ) as dt;
+
+select * from
+( ((values (3), (7), (1))) order by 1 limit 2 ) as dt;
+
+select * from
+( (((values (3), (7), (1))) order by 1 limit 2) ) as dt;
+
+select * from
+( ( (values (3), (7), (1) limit 2) order by 1 desc) ) as dt;
+
+select * from
+( ((values (3), (7), (1)) order by 1 desc) limit 2 ) as dt;
+
+select * from
+( (((values (3), (7), (1)) order by 1 desc) limit 2) ) as dt;
+
+--echo # 9.3. derived table as union of TVCs
+
+select * from
+( values (3), (7), (1) union values (3), (4), (2) ) dt;
+
+select * from
+( values (3), (7), (1) union all values (3), (4), (2) ) as dt;
+
+select * from
+( values (3), (7), (1) union values (3), (4), (2) ) as dt;
+
+select * from
+( values (3), (7), (1) except values (3), (4), (2) ) as dt;
+
+select * from
+( (values (3), (7), (1)) union (values (3), (4), (2)) ) as dt;
+
+select * from
+( (values (3), (7), (1))
+ union
+ (values (3), (4), (2))
+ union values (5), (7) ) dt;
+
+select * from
+( (values (3), (7), (1))
+ union
+ (values (3), (4), (2))
+ union
+ (values (5), (7)) ) as dt;
+
+select * from
+( (values (3), (7), (1)
+ union
+ values (3), (4), (2))
+ union
+ values (5), (7) ) as dt;
+
+select * from
+( values (3), (7), (1)
+ union (values (3), (4), (2)
+ union
+ values (5), (7)) ) as dt;
+
+select * from
+( (values (3), (7), (1)
+ union
+ ((values (3), (4), (2)
+ union values (5), (7)))) ) dt;
+
+select * from
+( values (3), (7), (1)
+ union
+ values (3), (4), (2)
+ order by 1 ) as dt;
+
+select * from
+( (values (3), (7), (1) union values (3), (4), (2)) order by 1 ) as dt;
+
+select * from
+( (values (3), (7), (1) union values (3), (4), (2)) order by 1 ) as dt;
+
+select * from
+( values (3), (7), (1) union (values (3), (4), (2)) order by 1 ) as dt;
+
+select * from
+( (values (3), (7), (1) union values (3), (4), (2)) order by 1 ) as dt;
+
+select * from
+( ((values (3), (7), (1)) union values (3), (4), (2)) order by 1 ) as dt;
+
+select * from
+( (values (3), (7), (1) order by 1 limit 2)
+ union
+ (values (3), (4), (2) order by 1 desc limit 2) ) as dt;
+
+select * from
+( ((values (3), (7), (1) order by 1) limit 2)
+ union
+ ((values (3), (4), (2) order by 1 desc) limit 2) ) as dt;
+
+select * from
+( (((values (3), (7), (1)) order by 1) limit 2)
+ union
+ (((values (3), (4), (2)) order by 1 desc) limit 2) ) as dt;
+
+select * from
+( (values (3), (7), (1) order by 1 limit 2)
+ union
+ values (3), (4), (2)
+ order by 1 limit 3 ) as dt;
+
+select * from
+( ((values (3), (7), (1)) order by 1 limit 2)
+ union
+ ((values (3), (4), (2) order by 1 desc) limit 2)
+ order by 1 limit 3 ) as dt;
+
+select * from
+( (select a from t1 where a <=3 order by 1 limit 2)
+ union
+ (values (3), (4), (2) order by 1 desc limit 2) ) dt;
+
+select * from
+( ((select a from t1 where a <=3) order by 1 limit 2)
+ union
+ (values (3), (4), (2) order by 1 desc limit 2) ) as dt;
+
+select * from
+( (((select a from t1 where a <=3) order by a) limit 2)
+ union
+ (((values (3), (4), (2)) order by 1 desc) limit 2) ) as dt;
+
+select * from
+ ( ( (((select a from t1 where a <=3) order by a) limit 2)
+ union
+ (((values (3), (4), (2)) order by 1 desc) limit 2) ) ) dt;
+
+select * from
+( (select a from t1 where a <=3 order by 1 limit 2)
+ union
+ (values (3), (4), (2) order by 1 desc limit 2)
+ order by a ) as dt;
+
+select * from
+( ((select a from t1 where a <=3) order by 1 limit 2)
+ union
+ (values (3), (4), (2) order by 1 desc limit 2)
+ order by a ) as dt;
+
+select * from
+( (((select a from t1 where a <=3) order by a) limit 2)
+ union
+ (((values (3), (4), (2)) order by 1 desc) limit 2)
+ order by a ) as dt;
+
+select * from
+( (((values (3), (4), (2)) order by 1 desc) limit 2) ) as dt;
+
+select * from
+( ( (((select a from t1 where a <=3) order by a) limit 2)
+ union
+ (((values (3), (4), (2)) order by 1 desc) limit 2) )
+ order by a ) as dt;
+
+select * from
+( (values (3), (4), (2) order by 1 desc limit 2)
+ union
+ (select a from t1 where a <=3 order by 1 limit 2) ) as dt;
+
+select * from
+( (values (3), (4), (2) order by 1 desc limit 2)
+ union
+ ((select a from t1 where a <=3) order by 1 limit 2) ) as dt;
+
+select * from
+( (((values (3), (4), (2)) order by 1 desc) limit 2)
+ union
+ (((select a from t1 where a <=3) order by 1) limit 2) ) as dt;
+
+select * from
+( (((values (3), (4), (2)) order by 1 desc) limit 2)
+ union
+ (((select a from t1 where a <=3) order by a) limit 2)
+ order by 1 ) as dt;
+
+select * from
+( ( select a from t1 where a=1
+ union
+ values (3), (4), (2) order by 1 desc )
+ union
+ select a from t1 where a=2 order by a desc limit 3 ) as dt;
+
+
+--echo # 9.4. derived table as [tailed] simple select with CTE
+
+
+select * from
+( with t as (select * from t1 where a <=3)
+ select * from t ) as dt;
+
+select * from
+( with t as (select * from t1 where a <=3)
+ (select * from t) ) as dt;
+
+select * from
+( with t as (select * from t1 where a <=3)
+ ((select * from t)) ) as dt;
+
+select * from
+( with t as ((select * from t1 where a <=3))
+ select * from t ) as dt;
+
+select * from
+( with t as (((select * from t1 where a <=3)))
+ select * from t ) as dt;
+
+select * from
+( with t as (select * from t1 where a <=3)
+ select * from t order by a ) as dt;
+
+select * from
+( with t as (select * from t1 where a <=3)
+ (select * from t) order by a ) as dt;
+
+select * from
+( with t as (select * from t1 where a <=3)
+ (select * from t) order by a desc limit 2 ) as dt;
+
+select * from
+( with t as (select * from t1 where a >=2 order by a limit 2)
+ select * from t ) as dt;
+
+select * from
+( with t as (((select * from t1 where a >=2) order by a desc) limit 2)
+ select * from t ) as dt;
+
+select * from
+( with t as (select * from t1 where a >=2 order by a desc limit 2)
+ select * from t order by a ) as dt;
+
+--echo # 9.5. derived table as tailed union with CTE
+
+select * from
+( with t as (select * from t1 where a <=3)
+ select a from t1 where a=1 union select a from t where a=3 ) as dt;
+
+select * from
+( with t as (select * from t1 where a <=3)
+ (select a from t) union (select b from t2) ) as dt;
+
+select * from
+( with t as (select * from t1 where a <=3)
+ (select a from t) union (select b as a from t2) order by a desc ) as dt;
+
+select * from
+( with t as (select * from t1 where a < 3 union select * from t1 where a > 3)
+ select a from t1 where a=1 union select a from t where a=7 ) as dt;
+
+select * from
+( with t as
+ ( select * from t1 where a < 3
+ union
+ select * from t1 where a > 3
+ order by a desc limit 3 )
+ select a from t1 where a=4 union select a from t where a=7 ) as dt;
+
+select * from
+( with t as
+ ( select * from t1 where a < 3
+ union
+ select * from t1 where a > 3
+ order by a desc limit 3 )
+ select a from t1 where a=4
+ union
+ select a from t where a=7
+ order by a desc ) as dt;
+
+select * from
+( with t as
+ ( (select * from t1 where a < 3)
+ union
+ (select * from t1 where a > 3)
+ order by a desc limit 3 )
+ select a from t1 where a=4
+ union select a from t where a=7
+ order by a desc ) dt;
+
+select * from
+( with t as
+ ( (select * from t1 where a < 3)
+ union
+ (select * from t1 where a > 3)
+ order by a desc limit 3 )
+ (select a from t1 where a=4
+ union
+ select a from t where a=7
+ order by a desc) ) as dt;
+
+select * from
+( with t as
+ ( (select * from t1 where a < 3)
+ union
+ (select * from t1 where a > 3)
+ order by a desc limit 3 )
+ ((select a from t1 where a=4
+ union
+ select a from t where a=7) order by a desc) ) as dt;
+
+select * from
+( with t as
+ ( select * from t1 where a < 3
+ union
+ values (4), (7)
+ order by a desc limit 3 )
+ select a from t1 where a=4
+ union
+ select a from t where a=7
+ order by a desc ) dt;
+
+select * from
+( with t(a) as
+ ( values (2), (1)
+ union
+ (values (4), (7))
+ order by 1 desc limit 3 )
+ select a from t1 where a=4
+ union select a from t where a=7
+ order by a desc ) as dt;
+
+select * from
+( with t(a) as
+ ( (values (2), (1))
+ union
+ (values (4), (7) order by 1 desc)
+ order by 1 desc limit 3 )
+ select a from t1 where a=1
+ union
+ select a from t where a=7 order by a desc ) as dt;
+
+select * from
+( with t(a) as
+ ( (values (2), (1))
+ union
+ (values (4), (7) order by 1 desc)
+ order by 1 limit 3 )
+ select a from t where a=1 union values (7) order by a desc ) as dt;
+
+select * from
+( with t(a) as
+ ( (values (2), (1))
+ union
+ (values (4), (7) order by 1 desc ) )
+ select a from t where a=1 union select 7 order by a desc ) as dt;
+
+select * from
+( with t as (select * from t1 where a < 3),
+ s as (select * from t1 where a > 3)
+ select a from t where a=1
+ union select a from s where a=7
+ order by a desc ) dt;
+
+select * from
+( with t as (select * from t1 where a < 3),
+ s as (select * from t1 where a > 3)
+ (select a from t where a=1
+ union
+ select a from s where a=7 order by a desc) ) dt;
+
+select * from
+( with t as (select * from t1 where a < 3),
+ s as (select * from t1 where a > 3)
+ (select a from t where a=1
+ union
+ select a from s where a=7)
+ order by a desc ) dt;
+
+
+--echo 10. view
+
+--echo 10.1. view as simple select
+
+create view v1 as
+select * from t1;
+show create view v1;
+select * from v1;
+drop view v1;
+
+create view v1 as
+select 2*a as c from t1;
+show create view v1;
+select * from v1;
+drop view v1;
+
+create view v1(c) as
+select 2*a from t1;
+show create view v1;
+select * from v1;
+drop view v1;
+
+create view v1 as
+((select * from t1));
+show create view v1;
+select * from v1;
+drop view v1;
+
+--echo 10.2. view as tailed simple select
+
+create view v1 as
+select * from t1 order by a;
+show create view v1;
+select * from v1;
+drop view v1;
+
+create view v1 as
+(select * from t2 order by a limit 2) order by b desc;
+show create view v1;
+select * from v1;
+drop view v1;
+
+--echo 10.3. view as union
+
+create view v1 as
+select a from t1 union select b from t2;
+show create view v1;
+select * from v1;
+drop view v1;
+
+create view v1 as
+(select a from t1) union (select b from t2);
+show create view v1;
+select * from v1;
+drop view v1;
+
+create view v1 as
+(select a from t1 where a=1) union select a from t1 where a=3;
+show create view v1;
+select * from v1;
+drop view v1;
+
+create view v1 as
+((select a from t1 where a<=3) union (select a from t1 where a=3));
+show create view v1;
+select * from v1;
+drop view v1;
+
+create view v1 as
+select a from t1 where a=1
+union
+select a from t1 where a=3
+union
+select a from t1 where a=7;
+show create view v1;
+select * from v1;
+drop view v1;
+
+create view v1 as
+( ( select a from t1 where a!=3 order by a desc limit 3)
+ union
+ select a from t1 where a=3 );
+show create view v1;
+select * from v1;
+drop view v1;
+
+create view v1 as
+( select a from t1 where a <=3 except select a from t1 where a >=3 )
+ union
+ select a from t1 where a=7;
+show create view v1;
+select * from v1;
+drop view v1;
+
+create view v1 as
+(select a from t1 limit 2) union select a from t1 where a=3 order by a desc;
+show create view v1;
+select * from v1;
+drop view v1;
+
+create view v1 as
+select a from t1 where a=1
+union
+( select a from t1 where a=3
+ union
+ ( select a from t1 where a=2
+ union
+ ( select a from t1 where a=4 ) ) );
+show create view v1;
+select * from v1;
+drop view v1;
+
+create view v1 as
+( ( select a from t1 where a >= 2
+ union
+ select a from t1 where a=1 order by a desc limit 2 )
+ union
+ select a from t1 where a=3 order by a limit 2 )
+union
+select a from t1 where a=1;
+show create view v1;
+select * from v1;
+drop view v1;
+
+--echo 10.4. view as [tailed] TVC
+
+create view v1 as
+values (3), (7), (1);
+show create view v1;
+select * from v1;
+drop view v1;
+create view v1 as
+(((values (3), (7), (1))) order by 1);
+show create view v1;
+select * from v1;
+drop view v1;
+
+--echo 10.5. view as [tailed] union of TVCs
+
+create view v1 as
+values (3), (7), (1) union values (3), (4), (2);
+show create view v1;
+select * from v1;
+drop view v1;
+create view v1 as
+(values (3), (7), (1) union values (3), (4), (2)) order by 1;
+show create view v1;
+select * from v1;
+drop view v1;
+
+create view v1 as
+(values (3), (7), (1) order by 1 limit 2)
+union
+(values (3), (4), (2) order by 1 desc limit 2);
+show create view v1;
+select * from v1;
+drop view v1;
+
+create view v1 as
+(values (3), (7), (1) order by 1 limit 2)
+union
+values (3), (4), (2)
+order by 1;
+show create view v1;
+select * from v1;
+drop view v1;
+
+--echo 10.6. view as [tailed] union of [tailed] select and tailed TVC
+
+create view v1 as
+( (((select a from t1 where a <=3) order by a) limit 2)
+ union
+ (((values (3), (4), (2)) order by 1 desc) limit 2) )
+order by a;
+show create view v1;
+select * from v1;
+drop view v1;
+
+create view v1 as
+( select a from t1 where a=1
+ union
+ values (3), (4), (2) order by 1 desc )
+union
+select a from t1 where a=2 order by a desc limit 3;
+show create view v1;
+select * from v1;
+drop view v1;
+
+--echo 10.7. view as select with CTE
+
+create view v1 as
+with t as (select * from t1 where a <=3)
+select * from t;
+show create view v1;
+select * from v1;
+drop view v1;
+
+create view v1 as
+with t as
+( select * from t1 where a < 3
+ union
+ select * from t1 where a > 3
+ order by a desc limit 3 )
+select a from t1 where a=4 union select a from t where a=7;
+show create view v1;
+select * from v1;
+drop view v1;
+
+--echo 10.8. view as union with CTE
+
+create view v1 as
+with t as
+( (select * from t1 where a < 3)
+ union
+ (select * from t1 where a > 3)
+ order by a desc limit 3 )
+(select a from t1 where a=4 union select a from t where a=7 order by a desc);
+show create view v1;
+select * from v1;
+drop view v1;
+
+create view v1 as
+with t as
+( (select * from t1 where a < 3)
+ union
+ (select * from t1 where a > 3)
+ order by a desc limit 3 )
+(select a from t where a=4 union select a from t where a=7 order by a desc);
+show create view v1;
+select * from v1;
+drop view v1;
+
+create view v1 as
+with t(a) as (values (2), (1)) select a from t;
+show create view v1;
+select * from v1;
+drop view v1;
+
+create view v1 as
+with t(a) as
+( values (2), (1)
+ union
+ (values (4), (7))
+ order by 1 desc limit 3 )
+select a from t1 where a=4 union select a from t where a=7 order by a desc;
+show create view v1;
+select * from v1;
+drop view v1;
+
+create view v1 as
+with t(a) as
+( (values (2), (1))
+ union
+ (values (4), (7) order by 1 desc)
+ order by 1 desc limit 3 )
+select a from t1 where a=1 union select a from t where a=7 order by a desc;
+show create view v1;
+select * from v1;
+drop view v1;
+
+create view v1 as
+with t as (select * from t1 where a < 3),
+ s as (select * from t1 where a > 3)
+select a from t where a=1 union select a from s where a=7 order by a desc;
+show create view v1;
+select * from v1;
+drop view v1;
+
+create view v1 as
+with t as (select * from t1 where a < 3),
+ s as (select * from t where a > 3)
+select a from t where a=1 union select a from s where a=7 order by a desc;
+show create view v1;
+select * from v1;
+drop view v1;
+
+drop table t1,t2;
+
--echo # End of 10.4 tests
diff --git a/mysql-test/main/cte_nonrecursive.result b/mysql-test/main/cte_nonrecursive.result
index 2556fd4..f0f69a7 100644
--- a/mysql-test/main/cte_nonrecursive.result
+++ b/mysql-test/main/cte_nonrecursive.result
@@ -606,7 +606,7 @@ with t(c) as (select a from t1 where b >= 'c')
select * from t r1 where r1.c=4;
show create view v3;
View Create View character_set_client collation_connection
-v3 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v3` AS with t as (select `t1`.`a` AS `c` from `t1` where `t1`.`b` >= 'c')select `r1`.`c` AS `c` from `t` `r1` where `r1`.`c` = 4 latin1 latin1_swedish_ci
+v3 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v3` AS with t(c) as (select `t1`.`a` AS `c` from `t1` where `t1`.`b` >= 'c')select `r1`.`c` AS `c` from `t` `r1` where `r1`.`c` = 4 latin1 latin1_swedish_ci
select * from v3;
c
4
@@ -618,7 +618,7 @@ with t(c) as (select a from t1 where b >= 'c')
select * from t r1, t r2 where r1.c=r2.c and r2.c=4;
show create view v4;
View Create View character_set_client collation_connection
-v4 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v4` AS with t as (select `test`.`t1`.`a` AS `c` from `test`.`t1` where `test`.`t1`.`b` >= 'c')select `r1`.`c` AS `c`,`r2`.`c` AS `d` from (`t` `r1` join (select `test`.`t1`.`a` AS `c` from `test`.`t1` where `test`.`t1`.`b` >= 'c') `r2`) where `r1`.`c` = `r2`.`c` and `r2`.`c` = 4 latin1 latin1_swedish_ci
+v4 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v4` AS with t(c) as (select `test`.`t1`.`a` AS `c` from `test`.`t1` where `test`.`t1`.`b` >= 'c')select `r1`.`c` AS `c`,`r2`.`c` AS `d` from (`t` `r1` join (select `test`.`t1`.`a` AS `c` from `test`.`t1` where `test`.`t1`.`b` >= 'c') `r2`) where `r1`.`c` = `r2`.`c` and `r2`.`c` = 4 latin1 latin1_swedish_ci
select * from v4;
c d
4 4
diff --git a/mysql-test/main/cte_recursive.result b/mysql-test/main/cte_recursive.result
index 0b22da8..b88f0ff 100644
--- a/mysql-test/main/cte_recursive.result
+++ b/mysql-test/main/cte_recursive.result
@@ -699,7 +699,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
5 RECURSIVE UNION p ALL NULL NULL NULL NULL 12 100.00 Using where; Using join buffer (flat, BNL join)
NULL UNION RESULT <union3,4,5> ALL NULL NULL NULL NULL NULL NULL
Warnings:
-Note 1003 with recursive ancestor_couple_ids as (/* select#2 */ select `a`.`father` AS `h_id`,`a`.`mother` AS `w_id` from `coupled_ancestors` `a` where `a`.`father` is not null and `a`.`mother` is not null), coupled_ancestors as (/* select#3 */ select `test`.`folks`.`id` AS `id`,`test`.`folks`.`name` AS `name`,`test`.`folks`.`dob` AS `dob`,`test`.`folks`.`father` AS `father`,`test`.`folks`.`mother` AS `mother` from `test`.`folks` where `test`.`folks`.`name` = 'Me' union all /* select#4 */ select `test`.`p`.`id` AS `id`,`test`.`p`.`name` AS `name`,`test`.`p`.`dob` AS `dob`,`test`.`p`.`father` AS `father`,`test`.`p`.`mother` AS `mother` from `test`.`folks` `p` join `ancestor_couple_ids` `fa` where `test`.`p`.`id` = `fa`.`h_id` union all /* select#5 */ select `test`.`p`.`id` AS `id`,`test`.`p`.`name` AS `name`,`test`.`p`.`dob` AS `dob`,`test`.`p`.`father` AS `father`,`test`.`p`.`mother` AS `mother` from `test`.`folks` `p` join `ancestor_couple_ids` `ma` where `test`.`p`.`id` =
`ma`.`w_
id`)/* select#1 */ select `h`.`name` AS `name`,`h`.`dob` AS `dob`,`w`.`name` AS `name`,`w`.`dob` AS `dob` from `ancestor_couple_ids` `c` join `coupled_ancestors` `h` join `coupled_ancestors` `w` where `h`.`id` = `c`.`h_id` and `w`.`id` = `c`.`w_id`
+Note 1003 with recursive ancestor_couple_ids(h_id,w_id) as (/* select#2 */ select `a`.`father` AS `h_id`,`a`.`mother` AS `w_id` from `coupled_ancestors` `a` where `a`.`father` is not null and `a`.`mother` is not null), coupled_ancestors(id,name,dob,father,mother) as (/* select#3 */ select `test`.`folks`.`id` AS `id`,`test`.`folks`.`name` AS `name`,`test`.`folks`.`dob` AS `dob`,`test`.`folks`.`father` AS `father`,`test`.`folks`.`mother` AS `mother` from `test`.`folks` where `test`.`folks`.`name` = 'Me' union all /* select#4 */ select `test`.`p`.`id` AS `id`,`test`.`p`.`name` AS `name`,`test`.`p`.`dob` AS `dob`,`test`.`p`.`father` AS `father`,`test`.`p`.`mother` AS `mother` from `test`.`folks` `p` join `ancestor_couple_ids` `fa` where `test`.`p`.`id` = `fa`.`h_id` union all /* select#5 */ select `test`.`p`.`id` AS `id`,`test`.`p`.`name` AS `name`,`test`.`p`.`dob` AS `dob`,`test`.`p`.`father` AS `father`,`test`.`p`.`mother` AS `mother` from `test`.`folks` `p` join `ancestor_cou
ple_ids`
`ma` where `test`.`p`.`id` = `ma`.`w_id`)/* select#1 */ select `h`.`name` AS `name`,`h`.`dob` AS `dob`,`w`.`name` AS `name`,`w`.`dob` AS `dob` from `ancestor_couple_ids` `c` join `coupled_ancestors` `h` join `coupled_ancestors` `w` where `h`.`id` = `c`.`h_id` and `w`.`id` = `c`.`w_id`
# simple mutual recursion
with recursive
ancestor_couple_ids(h_id, w_id)
@@ -3091,7 +3091,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
4 DEPENDENT SUBQUERY <derived2> ALL NULL NULL NULL NULL 16 100.00 Using where
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL
Warnings:
-Note 1003 with recursive destinations as (/* select#2 */ select `test`.`a`.`arrival` AS `city`,1 AS `legs` from `test`.`flights` `a` where `test`.`a`.`departure` = 'Cairo' union /* select#3 */ select `test`.`b`.`arrival` AS `arrival`,`r`.`legs` + 1 AS `r.legs + 1` from `destinations` `r` join `test`.`flights` `b` where `r`.`city` = `test`.`b`.`departure` and !<in_optimizer>(`test`.`b`.`arrival`,<exists>(/* select#4 */ select `destinations`.`city` from `destinations` where trigcond(`test`.`b`.`arrival` = `destinations`.`city` or `destinations`.`city` is null) having trigcond(`destinations`.`city` is null))))/* select#1 */ select `destinations`.`city` AS `city`,`destinations`.`legs` AS `legs` from `destinations`
+Note 1003 with recursive destinations(city,legs) as (/* select#2 */ select `test`.`a`.`arrival` AS `city`,1 AS `legs` from `test`.`flights` `a` where `test`.`a`.`departure` = 'Cairo' union /* select#3 */ select `test`.`b`.`arrival` AS `arrival`,`r`.`legs` + 1 AS `r.legs + 1` from `destinations` `r` join `test`.`flights` `b` where `r`.`city` = `test`.`b`.`departure` and !<in_optimizer>(`test`.`b`.`arrival`,<exists>(/* select#4 */ select `destinations`.`city` from `destinations` where trigcond(`test`.`b`.`arrival` = `destinations`.`city` or `destinations`.`city` is null) having trigcond(`destinations`.`city` is null))))/* select#1 */ select `destinations`.`city` AS `city`,`destinations`.`legs` AS `legs` from `destinations`
set standard_compliant_cte=default;
drop table flights;
#
@@ -3378,7 +3378,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 RECURSIVE UNION <derived2> ALL NULL NULL NULL NULL 2 100.00 Using where
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL
Warnings:
-Note 1003 with recursive rcte as (/* select#2 */ select 1 AS `a` union /* select#3 */ select cast(`rcte`.`a` + 1 as unsigned) AS `cast(a+1 as unsigned)` from `rcte` where `rcte`.`a` < 10), cte1 as (/* select#4 */ select count(0) AS `c1` from `rcte` join `test`.`t1` where `rcte`.`a` between 3 and 5 and `test`.`t1`.`id` = `rcte`.`a` - 3), cte2 as (/* select#5 */ select count(0) AS `c2` from `rcte` join `test`.`t1` where `rcte`.`a` between 7 and 8 and `test`.`t1`.`id` = `rcte`.`a` - 7)/* select#1 */ select `cte1`.`c1` AS `c1`,`cte2`.`c2` AS `c2` from `cte1` join `cte2`
+Note 1003 with recursive rcte(a) as (/* select#2 */ select 1 AS `a` union /* select#3 */ select cast(`rcte`.`a` + 1 as unsigned) AS `cast(a+1 as unsigned)` from `rcte` where `rcte`.`a` < 10), cte1 as (/* select#4 */ select count(0) AS `c1` from `rcte` join `test`.`t1` where `rcte`.`a` between 3 and 5 and `test`.`t1`.`id` = `rcte`.`a` - 3), cte2 as (/* select#5 */ select count(0) AS `c2` from `rcte` join `test`.`t1` where `rcte`.`a` between 7 and 8 and `test`.`t1`.`id` = `rcte`.`a` - 7)/* select#1 */ select `cte1`.`c1` AS `c1`,`cte2`.`c2` AS `c2` from `cte1` join `cte2`
prepare stmt from "with recursive
rcte(a) as
(select 1 union select cast(a+1 as unsigned) from rcte where a < 10),
diff --git a/mysql-test/main/except.result b/mysql-test/main/except.result
index 9c5a3ea..4c6a094 100644
--- a/mysql-test/main/except.result
+++ b/mysql-test/main/except.result
@@ -24,7 +24,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 EXCEPT t2 ALL NULL NULL NULL NULL 2 100.00
NULL EXCEPT RESULT <except2,3> ALL NULL NULL NULL NULL NULL NULL
Warnings:
-Note 1003 /* select#1 */ select `a`.`a` AS `a`,`a`.`b` AS `b` from (/* select#2 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` except (/* select#3 */ select `test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d` from `test`.`t2`)) `a`
+Note 1003 /* select#1 */ select `a`.`a` AS `a`,`a`.`b` AS `b` from ((/* select#2 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1`) except (/* select#3 */ select `test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d` from `test`.`t2`)) `a`
EXPLAIN format=json (select a,b from t1) except (select c,d from t2);
EXPLAIN
{
@@ -229,7 +229,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 EXCEPT t4 ALL NULL NULL NULL NULL 2 100.00 Using join buffer (flat, BNL join)
NULL EXCEPT RESULT <except2,3> ALL NULL NULL NULL NULL NULL NULL
Warnings:
-Note 1003 /* select#1 */ select `a`.`a` AS `a`,`a`.`b` AS `b`,`a`.`e` AS `e`,`a`.`f` AS `f` from (/* select#2 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t3`.`e` AS `e`,`test`.`t3`.`f` AS `f` from `test`.`t1` join `test`.`t3` except (/* select#3 */ select `test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d`,`test`.`t4`.`g` AS `g`,`test`.`t4`.`h` AS `h` from `test`.`t2` join `test`.`t4`)) `a`
+Note 1003 /* select#1 */ select `a`.`a` AS `a`,`a`.`b` AS `b`,`a`.`e` AS `e`,`a`.`f` AS `f` from ((/* select#2 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t3`.`e` AS `e`,`test`.`t3`.`f` AS `f` from `test`.`t1` join `test`.`t3`) except (/* select#3 */ select `test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d`,`test`.`t4`.`g` AS `g`,`test`.`t4`.`h` AS `h` from `test`.`t2` join `test`.`t4`)) `a`
EXPLAIN format=json (select a,b,e,f from t1,t3) except (select c,d,g,h from t2,t4);
EXPLAIN
{
diff --git a/mysql-test/main/intersect.result b/mysql-test/main/intersect.result
index bd88243..4b66580 100644
--- a/mysql-test/main/intersect.result
+++ b/mysql-test/main/intersect.result
@@ -37,7 +37,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
4 INTERSECT t3 ALL NULL NULL NULL NULL 3 100.00
NULL INTERSECT RESULT <intersect2,3,4> ALL NULL NULL NULL NULL NULL NULL
Warnings:
-Note 1003 /* select#1 */ select `a`.`a` AS `a`,`a`.`b` AS `b` from (/* select#2 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` intersect (/* select#3 */ select `test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d` from `test`.`t2`) intersect (/* select#4 */ select `test`.`t3`.`e` AS `e`,`test`.`t3`.`f` AS `f` from `test`.`t3`)) `a`
+Note 1003 /* select#1 */ select `a`.`a` AS `a`,`a`.`b` AS `b` from ((/* select#2 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1`) intersect (/* select#3 */ select `test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d` from `test`.`t2`) intersect (/* select#4 */ select `test`.`t3`.`e` AS `e`,`test`.`t3`.`f` AS `f` from `test`.`t3`)) `a`
EXPLAIN format=json (select a,b from t1) intersect (select c,d from t2) intersect (select e,f from t3);
EXPLAIN
{
@@ -278,7 +278,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 INTERSECT t3 ALL NULL NULL NULL NULL 3 100.00 Using join buffer (flat, BNL join)
NULL INTERSECT RESULT <intersect2,3> ALL NULL NULL NULL NULL NULL NULL
Warnings:
-Note 1003 /* select#1 */ select `a`.`a` AS `a`,`a`.`b` AS `b` from (/* select#2 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` intersect (/* select#3 */ select `test`.`t2`.`c` AS `c`,`test`.`t3`.`e` AS `e` from `test`.`t2` join `test`.`t3`)) `a`
+Note 1003 /* select#1 */ select `a`.`a` AS `a`,`a`.`b` AS `b` from ((/* select#2 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1`) intersect (/* select#3 */ select `test`.`t2`.`c` AS `c`,`test`.`t3`.`e` AS `e` from `test`.`t2` join `test`.`t3`)) `a`
EXPLAIN format=json (select a,b from t1) intersect (select c,e from t2,t3);
EXPLAIN
{
@@ -720,7 +720,7 @@ a b
drop procedure p1;
show create view v1;
View Create View character_set_client collation_connection
-v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS (select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1`) union select `__6`.`c` AS `c`,`__6`.`d` AS `d` from (select `test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d` from `test`.`t2` intersect (select `test`.`t3`.`e` AS `e`,`test`.`t3`.`f` AS `f` from `test`.`t3`)) `__6` union (select 4 AS `4`,4 AS `4`) latin1 latin1_swedish_ci
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS (select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1`) union select `__6`.`c` AS `c`,`__6`.`d` AS `d` from ((select `test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d` from `test`.`t2`) intersect (select `test`.`t3`.`e` AS `e`,`test`.`t3`.`f` AS `f` from `test`.`t3`)) `__6` union (select 4 AS `4`,4 AS `4`) latin1 latin1_swedish_ci
drop view v1;
drop tables t1,t2,t3;
#
diff --git a/mysql-test/main/parser.result b/mysql-test/main/parser.result
index 2e234216..46ec3ea 100644
--- a/mysql-test/main/parser.result
+++ b/mysql-test/main/parser.result
@@ -1776,7 +1776,7 @@ End of 10.3 tests
#
create table t1 (a int);
(select * from t1) for update;
-ERROR HY000: Incorrect usage of lock options and SELECT in brackets
+a
(select * from t1) union (select * from t1) for update;
ERROR HY000: Incorrect usage of lock options and SELECT in brackets
(select * from t1 for update);
diff --git a/mysql-test/main/parser.test b/mysql-test/main/parser.test
index 35a2334..d024f06 100644
--- a/mysql-test/main/parser.test
+++ b/mysql-test/main/parser.test
@@ -1544,7 +1544,6 @@ SELECT @@GLOBAL.role;
--echo #
create table t1 (a int);
---error ER_WRONG_USAGE
(select * from t1) for update;
--error ER_WRONG_USAGE
(select * from t1) union (select * from t1) for update;
diff --git a/mysql-test/main/ps.result b/mysql-test/main/ps.result
index 1e84618..766abc3 100644
--- a/mysql-test/main/ps.result
+++ b/mysql-test/main/ps.result
@@ -4484,7 +4484,7 @@ DEALLOCATE PREPARE stmt;
#
PREPARE stmt FROM 'SELECT ? FROM DUAL';
EXECUTE stmt USING (SELECT 1);
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'SELECT 1)' at line 1
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ')' at line 1
DEALLOCATE PREPARE stmt;
CREATE FUNCTION f1() RETURNS VARCHAR(10) RETURN 'test';
PREPARE stmt FROM 'SELECT ? FROM DUAL';
@@ -4683,7 +4683,7 @@ ERROR 21000: Operand should contain 1 column(s)
# Testing disallowed expressions in USING
#
EXECUTE IMMEDIATE 'SELECT ? FROM DUAL' USING (SELECT 1);
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'SELECT 1)' at line 1
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ')' at line 1
CREATE FUNCTION f1() RETURNS VARCHAR(10) RETURN 'test';
EXECUTE IMMEDIATE 'SELECT ? FROM DUAL' USING f1();
ERROR 42000: EXECUTE IMMEDIATE does not support subqueries or stored functions
@@ -4869,9 +4869,9 @@ ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (latin2
PREPARE stmt FROM CONCAT(_latin1'SELECT 1 AS c FROM ', _latin2 'DUAL');
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (latin2_general_ci,COERCIBLE) for operation 'concat'
EXECUTE IMMEDIATE (SELECT 'SELECT 1');
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'SELECT 'SELECT 1')' at line 1
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ')' at line 1
PREPARE stmt FROM (SELECT 'SELECT 1');
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'SELECT 'SELECT 1')' at line 1
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ')' at line 1
EXECUTE IMMEDIATE a;
ERROR 42S22: Unknown column 'a' in 'field list'
PREPARE stmt FROM a;
diff --git a/mysql-test/main/statement-expr.result b/mysql-test/main/statement-expr.result
index c73ed28..d19a1ce 100644
--- a/mysql-test/main/statement-expr.result
+++ b/mysql-test/main/statement-expr.result
@@ -12,9 +12,9 @@ ROW(1, 7) IN (SELECT id, id1 FROM t1 WHERE id1= 8)
0
DROP TABLE t1;
EXECUTE IMMEDIATE 'SELECT ?' USING (1 IN (SELECT * FROM t1));
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'SELECT * FROM t1))' at line 1
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '))' at line 1
EXECUTE IMMEDIATE 'SELECT ?' USING (SELECT * FROM t1);
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'SELECT * FROM t1)' at line 1
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ')' at line 1
CREATE TABLE t1 (id INT);
INSERT INTO t1 VALUES (10);
CREATE PROCEDURE p1(a INT) BEGIN END;
@@ -45,21 +45,21 @@ ERROR 42000: You have an error in your SQL syntax; check the manual that corresp
SIGNAL SQLSTATE '01000';
END' at line 3
PREPARE stmt FROM (1 IN (SELECT * FROM t1));
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'SELECT * FROM t1))' at line 1
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '))' at line 1
PREPARE stmt FROM EXISTS (SELECT * FROM t1);
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '(SELECT * FROM t1)' at line 1
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ')' at line 1
EXECUTE IMMEDIATE (1 IN (SELECT * FROM t1));
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'SELECT * FROM t1))' at line 1
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '))' at line 1
EXECUTE IMMEDIATE EXISTS (SELECT * FROM t1);
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '(SELECT * FROM t1)' at line 1
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ')' at line 1
GET DIAGNOSTICS CONDITION (1 IN (SELECT * FROM t1)) @errno=MYSQL_ERRNO;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '(1 IN (SELECT * FROM t1)) @errno=MYSQL_ERRNO' at line 1
GET DIAGNOSTICS CONDITION EXISTS (SELECT * FROM t1) @errno=MYSQL_ERRNO;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'EXISTS (SELECT * FROM t1) @errno=MYSQL_ERRNO' at line 1
PURGE BINARY LOGS BEFORE (1 IN (SELECT * FROM t1));
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'SELECT * FROM t1))' at line 1
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '))' at line 1
PURGE BINARY LOGS BEFORE EXISTS (SELECT * FROM t1);
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '(SELECT * FROM t1)' at line 1
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ')' at line 1
CREATE TABLE t1 (a INT);
INSERT INTO t1 VALUES (1),(2),(3);
DO 1 IN (SELECT * FROM t1);
diff --git a/mysql-test/main/subselect.result b/mysql-test/main/subselect.result
index 1fdf8d1..28909ae 100644
--- a/mysql-test/main/subselect.result
+++ b/mysql-test/main/subselect.result
@@ -82,7 +82,7 @@ SELECT 1 FROM (SELECT 1 as a) b WHERE 1 IN (SELECT (SELECT a));
select (SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE(1));
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'PROCEDURE ANALYSE(1))' at line 1
SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE((SELECT 1));
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'SELECT 1))' at line 1
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '))' at line 1
SELECT (SELECT 1) as a FROM (SELECT 1) b WHERE (SELECT a) IS NULL;
ERROR 42S22: Unknown column 'a' in 'field list'
SELECT (SELECT 1) as a FROM (SELECT 1) b WHERE (SELECT a) IS NOT NULL;
@@ -1132,7 +1132,7 @@ ERROR 42S02: Table 'test.t1' doesn't exist
CREATE TABLE t1 (a int, KEY(a));
HANDLER t1 OPEN;
HANDLER t1 READ a=((SELECT 1));
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'SELECT 1))' at line 1
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '))' at line 1
HANDLER t1 CLOSE;
drop table t1;
create table t1 (a int);
@@ -3735,8 +3735,11 @@ WHERE NOT EXISTS (((SELECT i FROM t1) UNION (SELECT i FROM t1)));
i
explain select ((select t11.i from t1 t11) union (select t12.i from t1 t12))
from t1;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'union (select t12.i from t1 t12))
-from t1' at line 1
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 system NULL NULL NULL NULL 0 Const row not found
+2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL no matching row in const table
+3 UNION NULL NULL NULL NULL NULL NULL NULL no matching row in const table
+NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL
explain select * from t1 where not exists
((select t11.i from t1 t11) union (select t12.i from t1 t12));
id select_type table type possible_keys key key_len ref rows Extra
@@ -5304,7 +5307,7 @@ SELECT ( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) );
( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) )
1
SELECT ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1' at line 1
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '' at line 1
SELECT ( SELECT 1 UNION SELECT 1 UNION SELECT 1 );
( SELECT 1 UNION SELECT 1 UNION SELECT 1 )
1
@@ -5334,7 +5337,8 @@ SELECT * FROM t1 WHERE a IN ( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) );
a
1
SELECT * FROM t1 WHERE a = ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 );
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 )' at line 1
+a
+1
SELECT * FROM t1 WHERE a = ALL ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 );
a
1
@@ -5342,7 +5346,8 @@ SELECT * FROM t1 WHERE a = ANY ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 );
a
1
SELECT * FROM t1 WHERE a IN ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 );
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 )' at line 1
+a
+1
SELECT * FROM t1 WHERE a = ( SELECT 1 UNION SELECT 1 UNION SELECT 1 );
a
1
diff --git a/mysql-test/main/subselect.test b/mysql-test/main/subselect.test
index 82823b4..994a2c1 100644
--- a/mysql-test/main/subselect.test
+++ b/mysql-test/main/subselect.test
@@ -2610,8 +2610,6 @@ SELECT sql_no_cache * FROM t1 WHERE NOT EXISTS
SELECT * FROM t1
WHERE NOT EXISTS (((SELECT i FROM t1) UNION (SELECT i FROM t1)));
-#TODO:not supported
---error ER_PARSE_ERROR
explain select ((select t11.i from t1 t11) union (select t12.i from t1 t12))
from t1;
@@ -4413,11 +4411,9 @@ SELECT * FROM t1 WHERE a = ALL ( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) );
SELECT * FROM t1 WHERE a = ANY ( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) );
SELECT * FROM t1 WHERE a IN ( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) );
---error ER_PARSE_ERROR
SELECT * FROM t1 WHERE a = ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 );
SELECT * FROM t1 WHERE a = ALL ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 );
SELECT * FROM t1 WHERE a = ANY ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 );
---error ER_PARSE_ERROR
SELECT * FROM t1 WHERE a IN ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 );
SELECT * FROM t1 WHERE a = ( SELECT 1 UNION SELECT 1 UNION SELECT 1 );
diff --git a/mysql-test/main/subselect_no_exists_to_in.result b/mysql-test/main/subselect_no_exists_to_in.result
index 613a0d8..1849210 100644
--- a/mysql-test/main/subselect_no_exists_to_in.result
+++ b/mysql-test/main/subselect_no_exists_to_in.result
@@ -86,7 +86,7 @@ SELECT 1 FROM (SELECT 1 as a) b WHERE 1 IN (SELECT (SELECT a));
select (SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE(1));
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'PROCEDURE ANALYSE(1))' at line 1
SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE((SELECT 1));
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'SELECT 1))' at line 1
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '))' at line 1
SELECT (SELECT 1) as a FROM (SELECT 1) b WHERE (SELECT a) IS NULL;
ERROR 42S22: Unknown column 'a' in 'field list'
SELECT (SELECT 1) as a FROM (SELECT 1) b WHERE (SELECT a) IS NOT NULL;
@@ -1136,7 +1136,7 @@ ERROR 42S02: Table 'test.t1' doesn't exist
CREATE TABLE t1 (a int, KEY(a));
HANDLER t1 OPEN;
HANDLER t1 READ a=((SELECT 1));
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'SELECT 1))' at line 1
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '))' at line 1
HANDLER t1 CLOSE;
drop table t1;
create table t1 (a int);
@@ -3738,8 +3738,11 @@ WHERE NOT EXISTS (((SELECT i FROM t1) UNION (SELECT i FROM t1)));
i
explain select ((select t11.i from t1 t11) union (select t12.i from t1 t12))
from t1;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'union (select t12.i from t1 t12))
-from t1' at line 1
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 system NULL NULL NULL NULL 0 Const row not found
+2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL no matching row in const table
+3 UNION NULL NULL NULL NULL NULL NULL NULL no matching row in const table
+NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL
explain select * from t1 where not exists
((select t11.i from t1 t11) union (select t12.i from t1 t12));
id select_type table type possible_keys key key_len ref rows Extra
@@ -5306,7 +5309,7 @@ SELECT ( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) );
( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) )
1
SELECT ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1' at line 1
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '' at line 1
SELECT ( SELECT 1 UNION SELECT 1 UNION SELECT 1 );
( SELECT 1 UNION SELECT 1 UNION SELECT 1 )
1
@@ -5336,7 +5339,8 @@ SELECT * FROM t1 WHERE a IN ( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) );
a
1
SELECT * FROM t1 WHERE a = ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 );
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 )' at line 1
+a
+1
SELECT * FROM t1 WHERE a = ALL ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 );
a
1
@@ -5344,7 +5348,8 @@ SELECT * FROM t1 WHERE a = ANY ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 );
a
1
SELECT * FROM t1 WHERE a IN ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 );
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 )' at line 1
+a
+1
SELECT * FROM t1 WHERE a = ( SELECT 1 UNION SELECT 1 UNION SELECT 1 );
a
1
diff --git a/mysql-test/main/subselect_no_mat.result b/mysql-test/main/subselect_no_mat.result
index 982e701..63784c1 100644
--- a/mysql-test/main/subselect_no_mat.result
+++ b/mysql-test/main/subselect_no_mat.result
@@ -89,7 +89,7 @@ SELECT 1 FROM (SELECT 1 as a) b WHERE 1 IN (SELECT (SELECT a));
select (SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE(1));
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'PROCEDURE ANALYSE(1))' at line 1
SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE((SELECT 1));
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'SELECT 1))' at line 1
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '))' at line 1
SELECT (SELECT 1) as a FROM (SELECT 1) b WHERE (SELECT a) IS NULL;
ERROR 42S22: Unknown column 'a' in 'field list'
SELECT (SELECT 1) as a FROM (SELECT 1) b WHERE (SELECT a) IS NOT NULL;
@@ -1139,7 +1139,7 @@ ERROR 42S02: Table 'test.t1' doesn't exist
CREATE TABLE t1 (a int, KEY(a));
HANDLER t1 OPEN;
HANDLER t1 READ a=((SELECT 1));
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'SELECT 1))' at line 1
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '))' at line 1
HANDLER t1 CLOSE;
drop table t1;
create table t1 (a int);
@@ -3738,8 +3738,11 @@ WHERE NOT EXISTS (((SELECT i FROM t1) UNION (SELECT i FROM t1)));
i
explain select ((select t11.i from t1 t11) union (select t12.i from t1 t12))
from t1;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'union (select t12.i from t1 t12))
-from t1' at line 1
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 system NULL NULL NULL NULL 0 Const row not found
+2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL no matching row in const table
+3 UNION NULL NULL NULL NULL NULL NULL NULL no matching row in const table
+NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL
explain select * from t1 where not exists
((select t11.i from t1 t11) union (select t12.i from t1 t12));
id select_type table type possible_keys key key_len ref rows Extra
@@ -5304,7 +5307,7 @@ SELECT ( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) );
( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) )
1
SELECT ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1' at line 1
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '' at line 1
SELECT ( SELECT 1 UNION SELECT 1 UNION SELECT 1 );
( SELECT 1 UNION SELECT 1 UNION SELECT 1 )
1
@@ -5334,7 +5337,8 @@ SELECT * FROM t1 WHERE a IN ( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) );
a
1
SELECT * FROM t1 WHERE a = ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 );
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 )' at line 1
+a
+1
SELECT * FROM t1 WHERE a = ALL ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 );
a
1
@@ -5342,7 +5346,8 @@ SELECT * FROM t1 WHERE a = ANY ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 );
a
1
SELECT * FROM t1 WHERE a IN ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 );
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 )' at line 1
+a
+1
SELECT * FROM t1 WHERE a = ( SELECT 1 UNION SELECT 1 UNION SELECT 1 );
a
1
diff --git a/mysql-test/main/subselect_no_opts.result b/mysql-test/main/subselect_no_opts.result
index 1937f2a..0923d3c 100644
--- a/mysql-test/main/subselect_no_opts.result
+++ b/mysql-test/main/subselect_no_opts.result
@@ -85,7 +85,7 @@ SELECT 1 FROM (SELECT 1 as a) b WHERE 1 IN (SELECT (SELECT a));
select (SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE(1));
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'PROCEDURE ANALYSE(1))' at line 1
SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE((SELECT 1));
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'SELECT 1))' at line 1
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '))' at line 1
SELECT (SELECT 1) as a FROM (SELECT 1) b WHERE (SELECT a) IS NULL;
ERROR 42S22: Unknown column 'a' in 'field list'
SELECT (SELECT 1) as a FROM (SELECT 1) b WHERE (SELECT a) IS NOT NULL;
@@ -1135,7 +1135,7 @@ ERROR 42S02: Table 'test.t1' doesn't exist
CREATE TABLE t1 (a int, KEY(a));
HANDLER t1 OPEN;
HANDLER t1 READ a=((SELECT 1));
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'SELECT 1))' at line 1
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '))' at line 1
HANDLER t1 CLOSE;
drop table t1;
create table t1 (a int);
@@ -3734,8 +3734,11 @@ WHERE NOT EXISTS (((SELECT i FROM t1) UNION (SELECT i FROM t1)));
i
explain select ((select t11.i from t1 t11) union (select t12.i from t1 t12))
from t1;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'union (select t12.i from t1 t12))
-from t1' at line 1
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 system NULL NULL NULL NULL 0 Const row not found
+2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL no matching row in const table
+3 UNION NULL NULL NULL NULL NULL NULL NULL no matching row in const table
+NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL
explain select * from t1 where not exists
((select t11.i from t1 t11) union (select t12.i from t1 t12));
id select_type table type possible_keys key key_len ref rows Extra
@@ -5300,7 +5303,7 @@ SELECT ( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) );
( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) )
1
SELECT ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1' at line 1
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '' at line 1
SELECT ( SELECT 1 UNION SELECT 1 UNION SELECT 1 );
( SELECT 1 UNION SELECT 1 UNION SELECT 1 )
1
@@ -5330,7 +5333,8 @@ SELECT * FROM t1 WHERE a IN ( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) );
a
1
SELECT * FROM t1 WHERE a = ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 );
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 )' at line 1
+a
+1
SELECT * FROM t1 WHERE a = ALL ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 );
a
1
@@ -5338,7 +5342,8 @@ SELECT * FROM t1 WHERE a = ANY ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 );
a
1
SELECT * FROM t1 WHERE a IN ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 );
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 )' at line 1
+a
+1
SELECT * FROM t1 WHERE a = ( SELECT 1 UNION SELECT 1 UNION SELECT 1 );
a
1
diff --git a/mysql-test/main/subselect_no_scache.result b/mysql-test/main/subselect_no_scache.result
index 929af9b..5184405 100644
--- a/mysql-test/main/subselect_no_scache.result
+++ b/mysql-test/main/subselect_no_scache.result
@@ -88,7 +88,7 @@ SELECT 1 FROM (SELECT 1 as a) b WHERE 1 IN (SELECT (SELECT a));
select (SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE(1));
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'PROCEDURE ANALYSE(1))' at line 1
SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE((SELECT 1));
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'SELECT 1))' at line 1
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '))' at line 1
SELECT (SELECT 1) as a FROM (SELECT 1) b WHERE (SELECT a) IS NULL;
ERROR 42S22: Unknown column 'a' in 'field list'
SELECT (SELECT 1) as a FROM (SELECT 1) b WHERE (SELECT a) IS NOT NULL;
@@ -1138,7 +1138,7 @@ ERROR 42S02: Table 'test.t1' doesn't exist
CREATE TABLE t1 (a int, KEY(a));
HANDLER t1 OPEN;
HANDLER t1 READ a=((SELECT 1));
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'SELECT 1))' at line 1
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '))' at line 1
HANDLER t1 CLOSE;
drop table t1;
create table t1 (a int);
@@ -3741,8 +3741,11 @@ WHERE NOT EXISTS (((SELECT i FROM t1) UNION (SELECT i FROM t1)));
i
explain select ((select t11.i from t1 t11) union (select t12.i from t1 t12))
from t1;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'union (select t12.i from t1 t12))
-from t1' at line 1
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 system NULL NULL NULL NULL 0 Const row not found
+2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL no matching row in const table
+3 UNION NULL NULL NULL NULL NULL NULL NULL no matching row in const table
+NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL
explain select * from t1 where not exists
((select t11.i from t1 t11) union (select t12.i from t1 t12));
id select_type table type possible_keys key key_len ref rows Extra
@@ -5310,7 +5313,7 @@ SELECT ( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) );
( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) )
1
SELECT ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1' at line 1
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '' at line 1
SELECT ( SELECT 1 UNION SELECT 1 UNION SELECT 1 );
( SELECT 1 UNION SELECT 1 UNION SELECT 1 )
1
@@ -5340,7 +5343,8 @@ SELECT * FROM t1 WHERE a IN ( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) );
a
1
SELECT * FROM t1 WHERE a = ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 );
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 )' at line 1
+a
+1
SELECT * FROM t1 WHERE a = ALL ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 );
a
1
@@ -5348,7 +5352,8 @@ SELECT * FROM t1 WHERE a = ANY ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 );
a
1
SELECT * FROM t1 WHERE a IN ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 );
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 )' at line 1
+a
+1
SELECT * FROM t1 WHERE a = ( SELECT 1 UNION SELECT 1 UNION SELECT 1 );
a
1
diff --git a/mysql-test/main/subselect_no_semijoin.result b/mysql-test/main/subselect_no_semijoin.result
index 52c81e5..a7ead73 100644
--- a/mysql-test/main/subselect_no_semijoin.result
+++ b/mysql-test/main/subselect_no_semijoin.result
@@ -85,7 +85,7 @@ SELECT 1 FROM (SELECT 1 as a) b WHERE 1 IN (SELECT (SELECT a));
select (SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE(1));
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'PROCEDURE ANALYSE(1))' at line 1
SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE((SELECT 1));
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'SELECT 1))' at line 1
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '))' at line 1
SELECT (SELECT 1) as a FROM (SELECT 1) b WHERE (SELECT a) IS NULL;
ERROR 42S22: Unknown column 'a' in 'field list'
SELECT (SELECT 1) as a FROM (SELECT 1) b WHERE (SELECT a) IS NOT NULL;
@@ -1135,7 +1135,7 @@ ERROR 42S02: Table 'test.t1' doesn't exist
CREATE TABLE t1 (a int, KEY(a));
HANDLER t1 OPEN;
HANDLER t1 READ a=((SELECT 1));
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'SELECT 1))' at line 1
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '))' at line 1
HANDLER t1 CLOSE;
drop table t1;
create table t1 (a int);
@@ -3734,8 +3734,11 @@ WHERE NOT EXISTS (((SELECT i FROM t1) UNION (SELECT i FROM t1)));
i
explain select ((select t11.i from t1 t11) union (select t12.i from t1 t12))
from t1;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'union (select t12.i from t1 t12))
-from t1' at line 1
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 system NULL NULL NULL NULL 0 Const row not found
+2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL no matching row in const table
+3 UNION NULL NULL NULL NULL NULL NULL NULL no matching row in const table
+NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL
explain select * from t1 where not exists
((select t11.i from t1 t11) union (select t12.i from t1 t12));
id select_type table type possible_keys key key_len ref rows Extra
@@ -5300,7 +5303,7 @@ SELECT ( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) );
( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) )
1
SELECT ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1' at line 1
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '' at line 1
SELECT ( SELECT 1 UNION SELECT 1 UNION SELECT 1 );
( SELECT 1 UNION SELECT 1 UNION SELECT 1 )
1
@@ -5330,7 +5333,8 @@ SELECT * FROM t1 WHERE a IN ( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) );
a
1
SELECT * FROM t1 WHERE a = ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 );
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 )' at line 1
+a
+1
SELECT * FROM t1 WHERE a = ALL ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 );
a
1
@@ -5338,7 +5342,8 @@ SELECT * FROM t1 WHERE a = ANY ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 );
a
1
SELECT * FROM t1 WHERE a IN ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 );
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 )' at line 1
+a
+1
SELECT * FROM t1 WHERE a = ( SELECT 1 UNION SELECT 1 UNION SELECT 1 );
a
1
diff --git a/mysql-test/main/subselect_notembedded.result b/mysql-test/main/subselect_notembedded.result
index 9153706..5822115 100644
--- a/mysql-test/main/subselect_notembedded.result
+++ b/mysql-test/main/subselect_notembedded.result
@@ -1,5 +1,5 @@
purge master logs before (select adddate(current_timestamp(), interval -4 day));
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'select adddate(current_timestamp(), interval -4 day))' at line 1
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ')' at line 1
purge master logs before adddate(current_timestamp(), interval -4 day);
drop table if exists t1;
create table t1(a int,b int,key(a),key(b));
diff --git a/mysql-test/suite/compat/oracle/r/ps.result b/mysql-test/suite/compat/oracle/r/ps.result
index 73aa04b..4410438 100644
--- a/mysql-test/suite/compat/oracle/r/ps.result
+++ b/mysql-test/suite/compat/oracle/r/ps.result
@@ -47,7 +47,7 @@ EXECUTE stmt USING @a, @b;
#
PREPARE stmt FROM 'SELECT :1 FROM DUAL';
EXECUTE stmt USING (SELECT 1);
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'SELECT 1)' at line 1
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ')' at line 1
DEALLOCATE PREPARE stmt;
CREATE FUNCTION f1() RETURN VARCHAR
AS
@@ -155,7 +155,7 @@ DROP TABLE t1;
# Testing disallowed expressions in USING
#
EXECUTE IMMEDIATE 'SELECT :1 FROM DUAL' USING (SELECT 1);
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'SELECT 1)' at line 1
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ')' at line 1
CREATE FUNCTION f1() RETURN VARCHAR
AS
BEGIN
@@ -182,9 +182,9 @@ ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (latin2
PREPARE stmt FROM _latin1'SELECT 1 AS c FROM ' || _latin2 'DUAL';
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (latin2_general_ci,COERCIBLE) for operation 'concat_operator_oracle'
EXECUTE IMMEDIATE (SELECT 'SELECT 1');
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'SELECT 'SELECT 1')' at line 1
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ')' at line 1
PREPARE stmt FROM (SELECT 'SELECT 1');
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'SELECT 'SELECT 1')' at line 1
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ')' at line 1
EXECUTE IMMEDIATE a;
ERROR 42S22: Unknown column 'a' in 'field list'
PREPARE stmt FROM a;
diff --git a/mysql-test/suite/compat/oracle/r/statement-expr.result b/mysql-test/suite/compat/oracle/r/statement-expr.result
index ea3bd52..6208c58 100644
--- a/mysql-test/suite/compat/oracle/r/statement-expr.result
+++ b/mysql-test/suite/compat/oracle/r/statement-expr.result
@@ -13,9 +13,9 @@ ROW(1, 7) IN (SELECT id, id1 FROM t1 WHERE id1= 8)
0
DROP TABLE t1;
EXECUTE IMMEDIATE 'SELECT ?' USING (1 IN (SELECT * FROM t1));
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'SELECT * FROM t1))' at line 1
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '))' at line 1
EXECUTE IMMEDIATE 'SELECT ?' USING (SELECT * FROM t1);
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'SELECT * FROM t1)' at line 1
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ')' at line 1
CREATE TABLE t1 (id INT);
INSERT INTO t1 VALUES (10);
CREATE PROCEDURE p1(a INT) AS BEGIN NULL; END;
@@ -47,21 +47,21 @@ ERROR 42000: You have an error in your SQL syntax; check the manual that corresp
SIGNAL SQLSTATE '01000';
END' at line 3
PREPARE stmt FROM (1 IN (SELECT * FROM t1));
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'SELECT * FROM t1))' at line 1
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '))' at line 1
PREPARE stmt FROM EXISTS (SELECT * FROM t1);
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '(SELECT * FROM t1)' at line 1
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ')' at line 1
EXECUTE IMMEDIATE (1 IN (SELECT * FROM t1));
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'SELECT * FROM t1))' at line 1
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '))' at line 1
EXECUTE IMMEDIATE EXISTS (SELECT * FROM t1);
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '(SELECT * FROM t1)' at line 1
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ')' at line 1
GET DIAGNOSTICS CONDITION (1 IN (SELECT * FROM t1)) @errno=MYSQL_ERRNO;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '(1 IN (SELECT * FROM t1)) @errno=MYSQL_ERRNO' at line 1
GET DIAGNOSTICS CONDITION EXISTS (SELECT * FROM t1) @errno=MYSQL_ERRNO;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'EXISTS (SELECT * FROM t1) @errno=MYSQL_ERRNO' at line 1
PURGE BINARY LOGS BEFORE (1 IN (SELECT * FROM t1));
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'SELECT * FROM t1))' at line 1
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '))' at line 1
PURGE BINARY LOGS BEFORE EXISTS (SELECT * FROM t1);
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '(SELECT * FROM t1)' at line 1
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ')' at line 1
CREATE TABLE t1 (a INT);
INSERT INTO t1 VALUES (1),(2),(3);
DO 1 IN (SELECT * FROM t1);
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index 1d950a7..54c63ea 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -122,7 +122,8 @@ void Item_subselect::init(st_select_lex *select_lex,
parsing_place= (outer_select->in_sum_expr ?
NO_MATTER :
outer_select->parsing_place);
- if (unit->is_unit_op() && unit->first_select()->next_select())
+ if (unit->is_unit_op() &&
+ (unit->first_select()->next_select() or unit->fake_select_lex))
engine= new subselect_union_engine(unit, result, this);
else
engine= new subselect_single_select_engine(select_lex, result, this);
diff --git a/sql/sql_cte.cc b/sql/sql_cte.cc
index 6f5162b..a391adb 100644
--- a/sql/sql_cte.cc
+++ b/sql/sql_cte.cc
@@ -1438,6 +1438,22 @@ void With_clause::print(String *str, enum_query_type query_type)
void With_element::print(String *str, enum_query_type query_type)
{
str->append(query_name);
+ if (column_list.elements)
+ {
+ List_iterator_fast<LEX_CSTRING> li(column_list);
+ str->append('(');
+ for (LEX_CSTRING *col_name= li++; ; )
+ {
+ str->append(col_name);
+ col_name= li++;
+ if (!col_name)
+ {
+ str->append(')');
+ break;
+ }
+ str->append(',');
+ }
+ }
str->append(STRING_WITH_LEN(" as "));
str->append('(');
spec->print(str, query_type);
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 777391d..a7c20e3 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -1444,7 +1444,7 @@ int Lex_input_stream::lex_token(YYSTYPE *yylval, THD *thd)
return LEFT_PAREN_LIKE;
if (token == WITH)
return LEFT_PAREN_WITH;
- if (token != left_paren && token != SELECT_SYM)
+ if (token != left_paren && token != SELECT_SYM && token != VALUES)
return LEFT_PAREN_ALT;
else
return left_paren;
@@ -5338,10 +5338,9 @@ LEX::create_unit(SELECT_LEX *first_sel)
SELECT_LEX_UNIT *unit;
DBUG_ENTER("LEX::create_unit");
- if (first_sel->master_unit())
- DBUG_RETURN(first_sel->master_unit());
+ unit = first_sel->master_unit();
- if (!(unit= alloc_unit()))
+ if (!unit && !(unit= alloc_unit()))
DBUG_RETURN(NULL);
unit->register_select_chain(first_sel);
@@ -8990,7 +8989,8 @@ bool LEX::insert_select_hack(SELECT_LEX *sel)
builtin_select.link_prev= NULL; // indicator of removal
}
- set_main_unit(sel->master_unit());
+ if (set_main_unit(sel->master_unit()))
+ return true;
DBUG_ASSERT(builtin_select.table_list.elements == 1);
TABLE_LIST *insert_table= builtin_select.table_list.first;
@@ -9034,9 +9034,10 @@ bool LEX::insert_select_hack(SELECT_LEX *sel)
}
-/*
+/**
Create an Item_singlerow_subselect for a query expression.
*/
+
Item *LEX::create_item_query_expression(THD *thd,
const char *tok_start,
st_select_lex_unit *unit)
@@ -9051,118 +9052,17 @@ Item *LEX::create_item_query_expression(THD *thd,
SELECT_LEX *curr_sel= select_stack_head();
DBUG_ASSERT(current_select == curr_sel);
if (!curr_sel)
+ {
curr_sel= &builtin_select;
- curr_sel->register_unit(unit, &curr_sel->context);
- curr_sel->add_statistics(unit);
+ curr_sel->register_unit(unit, &curr_sel->context);
+ curr_sel->add_statistics(unit);
+ }
return new (thd->mem_root)
Item_singlerow_subselect(thd, unit->first_select());
}
-/**
- Process unit parsed in brackets
-*/
-
-bool LEX::parsed_unit_in_brackets(SELECT_LEX_UNIT *unit)
-{
- SELECT_LEX *first_in_nest= unit->pre_last_parse->next_select()->first_nested;
- if (first_in_nest->first_nested != first_in_nest)
- {
- /* There is a priority jump starting from first_in_nest */
- if (create_priority_nest(first_in_nest) == NULL)
- return true;
- unit->fix_distinct();
- }
- push_select(unit->fake_select_lex);
- return false;
-}
-
-
-
-/**
- Process tail of unit parsed in brackets
-*/
-SELECT_LEX *LEX::parsed_unit_in_brackets_tail(SELECT_LEX_UNIT *unit,
- Lex_order_limit_lock * l)
-{
- pop_select();
- if (l)
- {
- (l)->set_to(unit->fake_select_lex);
- }
- return unit->first_select();
-}
-
-
-/**
- Process select parsed in brackets
-*/
-
-SELECT_LEX *LEX::parsed_select(SELECT_LEX *sel, Lex_order_limit_lock * l)
-{
- pop_select();
- if (l)
- {
- if (sel->next_select())
- {
- SELECT_LEX_UNIT *unit= sel->master_unit();
- if (!unit)
- unit= create_unit(sel);
- if (!unit)
- return NULL;
- if (!unit->fake_select_lex->is_set_query_expr_tail)
- l->set_to(unit->fake_select_lex);
- else
- {
- if (!l->order_list && !unit->fake_select_lex->explicit_limit)
- {
- sel= unit->fake_select_lex;
- l->order_list= &sel->order_list;
- }
- else
- sel= wrap_unit_into_derived(unit);
- if (!sel)
- return NULL;
- l->set_to(sel);
- }
- }
- else if (!sel->is_set_query_expr_tail)
- {
- l->set_to(sel);
- }
- else
- {
- if (!l->order_list && !sel->explicit_limit)
- l->order_list= &sel->order_list;
- else
- {
- SELECT_LEX_UNIT *unit= create_unit(sel);
- if (!unit)
- return NULL;
- sel= wrap_unit_into_derived(unit);
- }
- if (!sel)
- return NULL;
- l->set_to(sel);
- }
- }
- return sel;
-}
-
-
-/**
- Process select parsed in brackets
-*/
-
-SELECT_LEX *LEX::parsed_select_in_brackets(SELECT_LEX *sel,
- Lex_order_limit_lock * l)
-{
- sel->braces= TRUE;
- return parsed_select(sel, l);
-}
-
-
SELECT_LEX_UNIT *LEX::parsed_select_expr_start(SELECT_LEX *s1, SELECT_LEX *s2,
enum sub_select_type unit_type,
bool distinct)
@@ -9193,6 +9093,7 @@ SELECT_LEX_UNIT *LEX::parsed_select_expr_start(SELECT_LEX *s1, SELECT_LEX *s2,
if (res == NULL)
return NULL;
res->pre_last_parse= sel1;
+ push_select(res->fake_select_lex);
return res;
}
@@ -9205,12 +9106,6 @@ SELECT_LEX_UNIT *LEX::parsed_select_expr_cont(SELECT_LEX_UNIT *unit,
SELECT_LEX *sel1;
if (!s2->next_select())
sel1= s2;
- else
- {
- sel1= wrap_unit_into_derived(s2->master_unit());
- if (!sel1)
- return NULL;
- }
SELECT_LEX *last= unit->pre_last_parse->next_select();
int cmp= oracle? 0 : cmp_unit_op(unit_type, last->get_linkage());
@@ -9242,41 +9137,73 @@ SELECT_LEX_UNIT *LEX::parsed_select_expr_cont(SELECT_LEX_UNIT *unit,
return unit;
}
+
/**
- Process parsed select in body
+ Add primary expression as the next term in a given query expression body
+ pruducing a new query expression body
*/
-SELECT_LEX_UNIT *LEX::parsed_body_select(SELECT_LEX *sel,
- Lex_order_limit_lock * l)
+SELECT_LEX_UNIT *
+LEX::add_primary_to_query_expression_body(SELECT_LEX_UNIT *unit,
+ SELECT_LEX *sel,
+ enum sub_select_type unit_type,
+ bool distinct,
+ bool oracle)
{
- if (sel->braces && l && l->lock.defined_lock)
+ SELECT_LEX *sel2= sel;
+ if (sel->master_unit() && sel->master_unit()->first_select()->next_select())
{
- my_error(ER_WRONG_USAGE, MYF(0), "lock options",
- "SELECT in brackets");
- return NULL;
+ sel2= wrap_unit_into_derived(sel->master_unit());
+ if (!sel2)
+ return NULL;
}
- if (!(sel= parsed_select(sel, l)))
- return NULL;
+ SELECT_LEX *sel1= unit->first_select();
+ if (!sel1->next_select())
+ unit= parsed_select_expr_start(sel1, sel2, unit_type, distinct);
+ else
+ unit= parsed_select_expr_cont(unit, sel2, unit_type, distinct, oracle);
+ return unit;
+}
- SELECT_LEX_UNIT *res= create_unit(sel);
- if (res && sel->tvc && sel->order_list.elements)
+
+/**
+ Add query primary to a parenthesized query primary
+ pruducing a new query expression body
+*/
+
+SELECT_LEX_UNIT *
+LEX::add_primary_to_query_expression_body_ext_parens(
+ SELECT_LEX_UNIT *unit,
+ SELECT_LEX *sel,
+ enum sub_select_type unit_type,
+ bool distinct)
+{
+ SELECT_LEX *sel1= unit->first_select();
+ if (unit->first_select()->next_select())
{
- if (res->add_fake_select_lex(thd))
+ sel1= wrap_unit_into_derived(unit);
+ if (!sel1)
+ return NULL;
+ if (!create_unit(sel1))
return NULL;
- SELECT_LEX *fake= res->fake_select_lex;
- fake->order_list= sel->order_list;
- fake->explicit_limit= sel->explicit_limit;
- fake->select_limit= sel->select_limit;
- fake->offset_limit= sel->offset_limit;
}
- return res;
+ SELECT_LEX *sel2= sel;
+ if (sel->master_unit() && sel->master_unit()->first_select()->next_select())
+ {
+ sel2= wrap_unit_into_derived(sel->master_unit());
+ if (!sel2)
+ return NULL;
+ }
+ unit= parsed_select_expr_start(sel1, sel2, unit_type, distinct);
+ return unit;
}
+
/**
- Process parsed unit in body
+ Process multi-operand query expression body
*/
-bool LEX::parsed_body_unit(SELECT_LEX_UNIT *unit)
+bool LEX::parsed_multi_operand_query_expression_body(SELECT_LEX_UNIT *unit)
{
SELECT_LEX *first_in_nest=
unit->pre_last_parse->next_select()->first_nested;
@@ -9287,27 +9214,60 @@ bool LEX::parsed_body_unit(SELECT_LEX_UNIT *unit)
return true;
unit->fix_distinct();
}
- push_select(unit->fake_select_lex);
return false;
}
+
/**
- Process parsed tail of unit in body
+ Add non-empty tail to a query expression body
+*/
- TODO: make processing for double tail case
+SELECT_LEX_UNIT *LEX::add_tail_to_query_expression_body(SELECT_LEX_UNIT *unit,
+ Lex_order_limit_lock *l)
+{
+ DBUG_ASSERT(l != NULL);
+ pop_select();
+ SELECT_LEX *sel= unit->first_select()->next_select() ? unit->fake_select_lex :
+ unit->first_select();
+ l->set_to(sel);
+ return unit;
+}
+
+
+/**
+ Add non-empty tail to a parenthesized query primary
*/
-SELECT_LEX_UNIT *LEX::parsed_body_unit_tail(SELECT_LEX_UNIT *unit,
- Lex_order_limit_lock * l)
+SELECT_LEX_UNIT *
+LEX::add_tail_to_query_expression_body_ext_parens(SELECT_LEX_UNIT *unit,
+ Lex_order_limit_lock *l)
{
+ SELECT_LEX *sel= unit->first_select()->next_select() ? unit->fake_select_lex :
+ unit->first_select();
+
+ DBUG_ASSERT(l != NULL);
+
pop_select();
- if (l)
+ if (sel->is_set_query_expr_tail)
{
- (l)->set_to(unit->fake_select_lex);
+ if (!l->order_list && !sel->explicit_limit)
+ l->order_list= &sel->order_list;
+ else
+ {
+ if (!unit)
+ return NULL;
+ sel= wrap_unit_into_derived(unit);
+ if (!sel)
+ return NULL;
+ if (!create_unit(sel))
+ return NULL;
+ }
}
- return unit;
+ l->set_to(sel);
+ return sel->master_unit();
}
+
/**
Process subselect parsing
*/
@@ -9333,7 +9293,6 @@ SELECT_LEX *LEX::parsed_subselect(SELECT_LEX_UNIT *unit, char *place)
}
-
/**
Process INSERT-like select
*/
@@ -9388,40 +9347,8 @@ SELECT_LEX *LEX::parsed_TVC_end()
}
-TABLE_LIST *LEX::parsed_derived_select(SELECT_LEX *sel, int for_system_time,
- LEX_CSTRING *alias)
-{
- TABLE_LIST *res;
- derived_tables|= DERIVED_SUBQUERY;
- sel->set_linkage(DERIVED_TABLE_TYPE);
- sel->braces= FALSE;
- // Add the subtree of subquery to the current SELECT_LEX
- SELECT_LEX *curr_sel= select_stack_head();
- DBUG_ASSERT(current_select == curr_sel);
- SELECT_LEX_UNIT *unit= sel->master_unit();
- if (!unit)
- {
- unit= create_unit(sel);
- if (!unit)
- return NULL;
- }
- curr_sel->register_unit(unit, &curr_sel->context);
- curr_sel->add_statistics(unit);
-
- Table_ident *ti= new (thd->mem_root) Table_ident(unit);
- if (ti == NULL)
- return NULL;
- if (!(res= curr_sel->add_table_to_list(thd, ti, alias, 0,
- TL_READ, MDL_SHARED_READ)))
- return NULL;
- if (for_system_time)
- {
- res->vers_conditions= vers_conditions;
- }
- return res;
-}
-TABLE_LIST *LEX::parsed_derived_unit(SELECT_LEX_UNIT *unit,
+TABLE_LIST *LEX::parsed_derived_table(SELECT_LEX_UNIT *unit,
int for_system_time,
LEX_CSTRING *alias)
{
@@ -9432,8 +9359,6 @@ TABLE_LIST *LEX::parsed_derived_unit(SELECT_LEX_UNIT *unit,
// Add the subtree of subquery to the current SELECT_LEX
SELECT_LEX *curr_sel= select_stack_head();
DBUG_ASSERT(current_select == curr_sel);
- curr_sel->register_unit(unit, &curr_sel->context);
- curr_sel->add_statistics(unit);
Table_ident *ti= new (thd->mem_root) Table_ident(unit);
if (ti == NULL)
@@ -9451,7 +9376,8 @@ TABLE_LIST *LEX::parsed_derived_unit(SELECT_LEX_UNIT *unit,
bool LEX::parsed_create_view(SELECT_LEX_UNIT *unit, int check)
{
SQL_I_List<TABLE_LIST> *save= &first_select_lex()->table_list;
- set_main_unit(unit);
+ if (set_main_unit(unit))
+ return true;
if (check_main_unit_semantics())
return true;
first_select_lex()->table_list.push_front(save);
@@ -9474,7 +9400,8 @@ bool LEX::select_finalize(st_select_lex_unit *expr)
sql_command= SQLCOM_SELECT;
selects_allow_into= TRUE;
selects_allow_procedure= TRUE;
- set_main_unit(expr);
+ if (set_main_unit(expr))
+ return true;
return check_main_unit_semantics();
}
@@ -9485,6 +9412,7 @@ bool LEX::select_finalize(st_select_lex_unit *expr, Lex_select_lock l)
select_finalize(expr);
}
+
/*
"IN" and "EXISTS" subselect can appear in two statement types:
@@ -9517,7 +9445,6 @@ void LEX::relink_hack(st_select_lex *select_lex)
}
-
bool SELECT_LEX_UNIT::set_lock_to_the_last_select(Lex_select_lock l)
{
if (l.defined_lock)
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 0e1d17d..6ead29b 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -4429,9 +4429,6 @@ struct LEX: public Query_tables_list
insert_list= 0;
}
- bool make_select_in_brackets(SELECT_LEX* dummy_select,
- SELECT_LEX *nselect, bool automatic);
-
SELECT_LEX_UNIT *alloc_unit();
SELECT_LEX *alloc_select(bool is_select);
SELECT_LEX_UNIT *create_unit(SELECT_LEX*);
@@ -4441,7 +4438,7 @@ struct LEX: public Query_tables_list
bool insert_select_hack(SELECT_LEX *sel);
SELECT_LEX *create_priority_nest(SELECT_LEX *first_in_nest);
- void set_main_unit(st_select_lex_unit *u)
+ bool set_main_unit(st_select_lex_unit *u)
{
unit.options= u->options;
unit.uncacheable= u->uncacheable;
@@ -4451,16 +4448,10 @@ struct LEX: public Query_tables_list
unit.union_distinct= u->union_distinct;
unit.set_with_clause(u->with_clause);
builtin_select.exclude_from_global();
+ return false;
}
bool check_main_unit_semantics();
- // reaction on different parsed parts (bodies are in sql_yacc.yy)
- bool parsed_unit_in_brackets(SELECT_LEX_UNIT *unit);
- SELECT_LEX *parsed_select(SELECT_LEX *sel, Lex_order_limit_lock * l);
- SELECT_LEX *parsed_unit_in_brackets_tail(SELECT_LEX_UNIT *unit,
- Lex_order_limit_lock * l);
- SELECT_LEX *parsed_select_in_brackets(SELECT_LEX *sel,
- Lex_order_limit_lock * l);
SELECT_LEX_UNIT *parsed_select_expr_start(SELECT_LEX *s1, SELECT_LEX *s2,
enum sub_select_type unit_type,
bool distinct);
@@ -4468,20 +4459,35 @@ struct LEX: public Query_tables_list
SELECT_LEX *s2,
enum sub_select_type unit_type,
bool distinct, bool oracle);
- SELECT_LEX_UNIT *parsed_body_select(SELECT_LEX *sel,
- Lex_order_limit_lock * l);
- bool parsed_body_unit(SELECT_LEX_UNIT *unit);
- SELECT_LEX_UNIT *parsed_body_unit_tail(SELECT_LEX_UNIT *unit,
- Lex_order_limit_lock * l);
+ bool parsed_multi_operand_query_expression_body(SELECT_LEX_UNIT *unit);
+ SELECT_LEX_UNIT *add_tail_to_query_expression_body(SELECT_LEX_UNIT *unit,
+ Lex_order_limit_lock *l);
+ SELECT_LEX_UNIT *
+ add_tail_to_query_expression_body_ext_parens(SELECT_LEX_UNIT *unit,
+ Lex_order_limit_lock *l);
+ SELECT_LEX_UNIT *parsed_body_ext_parens_primary(SELECT_LEX_UNIT *unit,
+ SELECT_LEX *primary,
+ enum sub_select_type unit_type,
+ bool distinct);
+ SELECT_LEX_UNIT *
+ add_primary_to_query_expression_body(SELECT_LEX_UNIT *unit,
+ SELECT_LEX *sel,
+ enum sub_select_type unit_type,
+ bool distinct,
+ bool oracle);
+ SELECT_LEX_UNIT *
+ add_primary_to_query_expression_body_ext_parens(
+ SELECT_LEX_UNIT *unit,
+ SELECT_LEX *sel,
+ enum sub_select_type unit_type,
+ bool distinct);
SELECT_LEX *parsed_subselect(SELECT_LEX_UNIT *unit, char *place);
bool parsed_insert_select(SELECT_LEX *firs_select);
bool parsed_TVC_start();
SELECT_LEX *parsed_TVC_end();
- TABLE_LIST *parsed_derived_select(SELECT_LEX *sel, int for_system_time,
- LEX_CSTRING *alias);
- TABLE_LIST *parsed_derived_unit(SELECT_LEX_UNIT *unit,
- int for_system_time,
- LEX_CSTRING *alias);
+ TABLE_LIST *parsed_derived_table(SELECT_LEX_UNIT *unit,
+ int for_system_time,
+ LEX_CSTRING *alias);
bool parsed_create_view(SELECT_LEX_UNIT *unit, int check);
bool select_finalize(st_select_lex_unit *expr);
bool select_finalize(st_select_lex_unit *expr, Lex_select_lock l);
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index cf96bfa..ec9ec17 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -11190,7 +11190,7 @@ bool Sql_cmd_create_table_like::execute(THD *thd)
}
#endif
- if (select_lex->item_list.elements) // With select
+ if (select_lex->item_list.elements || select_lex->tvc) // With select or TVC
{
select_result *result;
diff --git a/sql/sql_tvc.cc b/sql/sql_tvc.cc
index ef8e15d..4022cb8 100644
--- a/sql/sql_tvc.cc
+++ b/sql/sql_tvc.cc
@@ -599,8 +599,8 @@ static bool create_tvc_name(THD *thd, st_select_lex *parent_select,
bool table_value_constr::to_be_wrapped_as_with_tail()
{
- return select_lex->master_unit()->first_select()->next_select() &&
- select_lex->order_list.elements && select_lex->explicit_limit;
+ return select_lex->master_unit()->first_select()->next_select() &&
+ select_lex->order_list.elements && select_lex->explicit_limit;
}
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index 41f4234..da25fa7 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -831,8 +831,8 @@ bool st_select_lex_unit::prepare(TABLE_LIST *derived_arg,
bool is_union_select;
bool have_except= FALSE, have_intersect= FALSE;
bool instantiate_tmp_table= false;
- bool single_tvc= !first_sl->next_select() && first_sl->tvc &&
- !fake_select_lex;
+ bool single_tvc= !first_sl->next_select() && first_sl->tvc;
+ bool single_tvc_wo_order= single_tvc && !first_sl->order_list.elements;
DBUG_ENTER("st_select_lex_unit::prepare");
DBUG_ASSERT(thd == current_thd);
@@ -924,8 +924,9 @@ bool st_select_lex_unit::prepare(TABLE_LIST *derived_arg,
if (is_union_select || is_recursive)
{
- if ((is_unit_op() && !union_needs_tmp_table() &&
- !have_except && !have_intersect) || single_tvc)
+ if ((single_tvc_wo_order && !fake_select_lex) ||
+ (is_unit_op() && !union_needs_tmp_table() &&
+ !have_except && !have_intersect && !single_tvc))
{
SELECT_LEX *last= first_select();
while (last->next_select())
@@ -940,7 +941,7 @@ bool st_select_lex_unit::prepare(TABLE_LIST *derived_arg,
else
{
if (!is_recursive)
- union_result= new (thd->mem_root) select_unit(thd);
+ union_result= new (thd->mem_root) select_unit(thd);
else
{
with_element->rec_result=
@@ -986,17 +987,40 @@ bool st_select_lex_unit::prepare(TABLE_LIST *derived_arg,
if (sl->tvc && sl->order_list.elements &&
!sl->tvc->to_be_wrapped_as_with_tail())
{
+ SELECT_LEX_UNIT *unit= sl->master_unit();
if (thd->lex->context_analysis_only & CONTEXT_ANALYSIS_ONLY_VIEW)
{
- sl->master_unit()->fake_select_lex= 0;
- sl->master_unit()->saved_fake_select_lex= 0;
+ unit->fake_select_lex= 0;
+ unit->saved_fake_select_lex= 0;
}
else
{
- sl->order_list.empty();
- sl->explicit_limit= 0;
- sl->select_limit= 0;
- sl->offset_limit= 0;
+ if (!unit->first_select()->next_select())
+ {
+ if (!unit->fake_select_lex)
+ {
+ Query_arena *arena, backup_arena;
+ arena= thd->activate_stmt_arena_if_needed(&backup_arena);
+ bool rc= unit->add_fake_select_lex(thd);
+ if (arena)
+ thd->restore_active_arena(arena, &backup_arena);
+ if (rc)
+ goto err;
+ }
+ SELECT_LEX *fake= unit->fake_select_lex;
+ fake->order_list= sl->order_list;
+ fake->explicit_limit= sl->explicit_limit;
+ fake->select_limit= sl->select_limit;
+ fake->offset_limit= sl->offset_limit;
+ sl->order_list.empty();
+ sl->explicit_limit= 0;
+ sl->select_limit= 0;
+ sl->offset_limit= 0;
+ if (describe)
+ fake->options|= SELECT_DESCRIBE;
+ }
+ else if (!sl->explicit_limit)
+ sl->order_list.empty();
}
}
@@ -1021,7 +1045,7 @@ bool st_select_lex_unit::prepare(TABLE_LIST *derived_arg,
goto err;
}
else if (sl->tvc->prepare(thd, sl, tmp_result, this))
- goto err;
+ goto err;
}
else if (prepare_join(thd, sl, tmp_result, additional_options,
is_union_select))
@@ -1875,6 +1899,7 @@ bool st_select_lex_unit::cleanup()
DBUG_RETURN(FALSE);
}
}
+ columns_are_renamed= false;
cleaned= 1;
for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select())
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 183a250..6f53937 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -817,10 +817,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
%parse-param { THD *thd }
%lex-param { THD *thd }
/*
- Currently there are 48 shift/reduce conflicts.
+ Currently there are 39 shift/reduce conflicts.
We should not introduce new conflicts any more.
*/
-%expect 48
+%expect 39
/*
Comments for TOKENS.
@@ -1638,6 +1638,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
%left MYSQL_CONCAT_SYM
%left NEG '~' NOT2_SYM BINARY
%left COLLATE_SYM
+%left SUBQUERY_AS_EXPR
/*
Tokens that can change their meaning from identifier to something else
@@ -1728,7 +1729,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
ALTER TABLE t1 ADD SYSTEM VERSIONING;
*/
%left PREC_BELOW_CONTRACTION_TOKEN2
-%left TEXT_STRING '(' VALUE_SYM VERSIONING_SYM
+%left TEXT_STRING '(' ')' VALUE_SYM VERSIONING_SYM
+%left EMPTY_FROM_CLAUSE
+%right INTO
%type <lex_str>
DECIMAL_NUM FLOAT_NUM NUM LONG_NUM
@@ -1991,16 +1994,18 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
query_specification
table_value_constructor
simple_table
+ query_simple
query_primary
- query_primary_parens
+ subquery
select_into_query_specification
-
%type <select_lex_unit>
- query_specification_start
- query_expression_body
query_expression
- query_expression_unit
+ query_expression_no_with_clause
+ query_expression_body_ext
+ query_expression_body_ext_parens
+ query_expression_body
+ query_specification_start
%type <boolfunc2creator> comp_op
@@ -2025,7 +2030,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
%type <order_limit_lock>
query_expression_tail
+ opt_query_expression_tail
order_or_limit
+ order_limit_lock
opt_order_limit_lock
%type <select_order> opt_order_clause order_clause order_list
@@ -2175,7 +2182,7 @@ END_OF_INPUT
THEN_SYM WHEN_SYM DIV_SYM MOD_SYM OR2_SYM AND_AND_SYM DELETE_SYM
MYSQL_CONCAT_SYM ORACLE_CONCAT_SYM
-%type <with_clause> opt_with_clause with_clause
+%type <with_clause> with_clause
%type <lex_str_ptr> query_name
@@ -5265,7 +5272,7 @@ create_select_query_expression:
if (Lex->parsed_insert_select($1->first_select()))
MYSQL_YYABORT;
}
- | LEFT_PAREN_WITH with_clause query_expression_body ')'
+ | LEFT_PAREN_WITH with_clause query_expression_no_with_clause ')'
{
SELECT_LEX *first_select= $3->first_select();
$3->set_with_clause($2);
@@ -6773,13 +6780,7 @@ parse_vcol_expr:
;
parenthesized_expr:
- remember_tok_start
- query_expression
- {
- if (!($$= Lex->create_item_query_expression(thd, $1, $2)))
- MYSQL_YYABORT;
- }
- | expr
+ expr
| expr ',' expr_list
{
$3->push_front($1, thd->mem_root);
@@ -6798,6 +6799,16 @@ virtual_column_func:
MYSQL_YYABORT;
$$= v;
}
+ | subquery
+ {
+ Item *item;
+ if (!(item= new (thd->mem_root) Item_singlerow_subselect(thd, $1)))
+ MYSQL_YYABORT;
+ Virtual_column_info *v= add_virtual_expression(thd, item);
+ if (unlikely(!v))
+ MYSQL_YYABORT;
+ $$= v;
+ }
;
expr_or_literal: column_default_non_parenthesized_expr | signed_literal ;
@@ -9138,8 +9149,9 @@ opt_ignore_leaves:
Select : retrieve data from table
*/
+
select:
- query_expression_body
+ query_expression_no_with_clause
{
if (Lex->push_select($1->fake_select_lex ?
$1->fake_select_lex :
@@ -9149,10 +9161,11 @@ select:
opt_procedure_or_into
{
Lex->pop_select();
+ $1->set_with_clause(NULL);
if (Lex->select_finalize($1, $3))
MYSQL_YYABORT;
}
- | with_clause query_expression_body
+ | with_clause query_expression_no_with_clause
{
if (Lex->push_select($2->fake_select_lex ?
$2->fake_select_lex :
@@ -9169,7 +9182,6 @@ select:
}
;
-
select_into:
select_into_query_specification
{
@@ -9178,14 +9190,15 @@ select_into:
}
opt_order_limit_lock
{
- st_select_lex_unit *unit;
- if (!(unit= Lex->parsed_body_select($1, $3)))
+ SELECT_LEX_UNIT *unit;
+ if (!(unit = Lex->create_unit($1)))
MYSQL_YYABORT;
+ if ($3)
+ unit= Lex->add_tail_to_query_expression_body(unit, $3);
if (Lex->select_finalize(unit))
MYSQL_YYABORT;
- }
- ;
-
+ }
+ ;
simple_table:
query_specification { $$= $1; }
@@ -9251,108 +9264,258 @@ select_into_query_specification:
}
;
-opt_from_clause:
- /* Empty */
- | from_clause
+/**
+
+ The following grammar for query expressions conformant to
+ the latest SQL Standard is supported:
+
+ <query expression> ::=
+ [ <with clause> ] <query expression body>
+ [ <order by clause> ] [ <result offset clause> ] [ <fetch first clause> ]
+
+ <with clause> ::=
+ WITH [ RECURSIVE ] <with_list
+
+ <with list> ::=
+ <with list element> [ { <comma> <with list element> }... ]
+
+ <with list element> ::=
+ <query name> [ '(' <with column list> ')' ]
+ AS <table subquery>
+
+ <with column list> ::=
+ <column name list>
+
+ <query expression body> ::
+ <query term>
+ | <query expression body> UNION [ ALL | DISTINCT ] <query term>
+ | <query expression body> EXCEPT [ DISTINCT ]
+
+ <query term> ::=
+ <query primary>
+ | <query term> INTERSECT [ DISTINCT ] <query primary>
+
+ <query primary> ::=
+ <simple table>
+ | '(' <query expression body>
+ [ <order by clause> ] [ <result offset clause> ] [ <fetch first clause> ]
+ ')'
+
+ <simple table>
+ <query specification>
+ | <table value constructor>
+
+ <subquery>
+ '(' <query_expression> ')'
+
+*/
+
+/*
+ query_expression produces the same expressions as
+ <query expression>
+*/
+
+query_expression:
+ query_expression_no_with_clause
+ {
+ $1->set_with_clause(NULL);
+ $$= $1;
+ }
+ | with_clause
+ query_expression_no_with_clause
+ {
+ $2->set_with_clause($1);
+ $1->attach_to($2->first_select());
+ $$= $2;
+ }
;
+/*
+ query_expression_no_with_clause produces the same expressions as
+ <query expression> without [ <with clause> ]
+*/
-query_primary:
- simple_table
- { $$= $1; }
- | query_primary_parens
- { $$= $1; }
+query_expression_no_with_clause:
+ query_expression_body_ext { $$= $1; }
+ | query_expression_body_ext_parens { $$= $1; }
;
-query_primary_parens:
- '(' query_expression_unit
+/*
+ query_expression_body_ext produces the same expressions as
+ <query expression body>
+ [ <order by clause> ] [ <result offset clause> ] [ <fetch first clause> ]
+ | '('... <query expression body>
+ [ <order by clause> ] [ <result offset clause> ] [ <fetch first clause> ]
+ ')'...
+ Note: number of ')' must be equal to the number of '(' in the rule above
+*/
+
+query_expression_body_ext:
+ query_expression_body
{
- if (Lex->parsed_unit_in_brackets($2))
- MYSQL_YYABORT;
+ if ($1->first_select()->next_select())
+ {
+ if (Lex->parsed_multi_operand_query_expression_body($1))
+ MYSQL_YYABORT;
+ }
}
- query_expression_tail ')'
+ opt_query_expression_tail
{
- $$= Lex->parsed_unit_in_brackets_tail($2, $4);
+ if (!$3)
+ $$= $1;
+ else
+ $$= Lex->add_tail_to_query_expression_body($1, $3);
}
- | '(' query_primary
+ | query_expression_body_ext_parens
{
- Lex->push_select($2);
+ Lex->push_select(!$1->first_select()->next_select() ?
+ $1->first_select() : $1->fake_select_lex);
}
- query_expression_tail ')'
+ query_expression_tail
{
- if (!($$= Lex->parsed_select_in_brackets($2, $4)))
- YYABORT;
+ if (!($$= Lex->add_tail_to_query_expression_body_ext_parens($1, $3)))
+ MYSQL_YYABORT;
}
;
-query_expression_unit:
- query_primary
- unit_type_decl
- query_primary
- {
- if (!($$= Lex->parsed_select_expr_start($1, $3, $2.unit_type,
- $2.distinct)))
- YYABORT;
- }
- | query_expression_unit
- unit_type_decl
- query_primary
+query_expression_body_ext_parens:
+ '(' query_expression_body_ext_parens ')'
+ { $$= $2; }
+ | '(' query_expression_body_ext ')'
{
- if (!($$= Lex->parsed_select_expr_cont($1, $3, $2.unit_type,
- $2.distinct, FALSE)))
- YYABORT;
+ SELECT_LEX *sel= $2->first_select()->next_select() ?
+ $2->fake_select_lex : $2->first_select();
+ sel->braces= true;
+ $$= $2;
}
;
+/*
+ query_expression_body produces the same expressions as
+ <query expression body>
+*/
+
query_expression_body:
- query_primary
+ query_simple
{
Lex->push_select($1);
+ if (!($$= Lex->create_unit($1)))
+ MYSQL_YYABORT;
}
- query_expression_tail
+ | query_expression_body
+ unit_type_decl
{
- if (!($$= Lex->parsed_body_select($1, $3)))
- MYSQL_YYABORT;
+ if (!$1->first_select()->next_select())
+ {
+ Lex->pop_select();
+ }
}
- | query_expression_unit
+ query_primary
{
- if (Lex->parsed_body_unit($1))
+ if (!($$= Lex->add_primary_to_query_expression_body($1, $4,
+ $2.unit_type,
+ $2.distinct,
+ FALSE)))
MYSQL_YYABORT;
}
- query_expression_tail
+ | query_expression_body_ext_parens
+ unit_type_decl
+ query_primary
{
- if (!($$= Lex->parsed_body_unit_tail($1, $3)))
+ if (!($$= Lex->add_primary_to_query_expression_body_ext_parens(
+ $1, $3,
+ $2.unit_type,
+ $2.distinct)))
MYSQL_YYABORT;
}
;
-query_expression:
- opt_with_clause
- query_expression_body
- {
- if ($1)
- {
- $2->set_with_clause($1);
- $1->attach_to($2->first_select());
- }
- $$= $2;
- }
+/*
+ query_primary produces the same expressions as
+ <query primary>
+*/
+
+query_primary:
+ query_simple
+ { $$= $1; }
+ | query_expression_body_ext_parens
+ { $$= $1->first_select(); }
+ ;
+
+/*
+ query_simple produces the same expressions as
+ <simple table>
+*/
+
+query_simple:
+ simple_table { $$= $1;}
;
subselect:
- remember_tok_start
query_expression
{
- if (!($$= Lex->parsed_subselect($2, $1)))
+ if (!($$= Lex->parsed_subselect($1, NULL)))
YYABORT;
}
;
-
-/**
- <table expression>, as in the SQL standard.
+/*
+ subquery produces the same expressions as
+ <subquery>
+
+ Consider the production rule of the SQL Standard
+ subquery:
+ '(' query_expression_no_with_clause ')'
+
+ This rule is equivalent to the rule
+ subquery:
+ '(' query_expression_no_with_clause ')'
+ | '(' with_clause query_expression_no_with_clause ')'
+ that in its turn is equivalent to
+ subquery:
+ '(' query_expression_body_ext ')'
+ | '(' query_expression_body_ext_parens ')'
+ | '(' with_clause query_expression_no_with_clause ')'
+
+ The latter can be re-written into
+ subquery:
+ '(' query_expression_body_ext_parens ')'
+ | '(' with_clause query_expression_no_with_clause ')'
+
+ The last rule allows us to resolve properly the shift/reduce conflict
+ when subquery is used in expressions such as in the following queries
+ select (select * from t1 limit 1) + t2.a from t2
+ select * from t1 where t1.a [not] in (select t2.a from t2)
+
+ In the rule below %prec SUBQUERY_AS_EXPR forces the parser to perform a shift
+ operation rather then a reduce operation when ')' is encountered and can be
+ considered as the last symbol a query expression.
*/
+subquery:
+ query_expression_body_ext_parens %prec SUBQUERY_AS_EXPR
+ {
+ if (!$1->fake_select_lex)
+ $1->first_select()->braces= false;
+ else
+ $1->fake_select_lex->braces= false;
+ if (!($$= Lex->parsed_subselect($1, NULL)))
+ YYABORT;
+ }
+ | '(' with_clause query_expression_no_with_clause ')'
+ {
+ $3->set_with_clause($2);
+ $2->attach_to($3->first_select());
+ if (!($$= Lex->parsed_subselect($3, NULL)))
+ YYABORT;
+ }
+ ;
+
+opt_from_clause:
+ /* empty */ %prec EMPTY_FROM_CLAUSE
+ | from_clause
+ ;
+
from_clause:
FROM table_reference_list
;
@@ -9516,6 +9679,7 @@ select_lock_type:
}
;
+
opt_select_lock_type:
/* empty */
{
@@ -9527,6 +9691,7 @@ opt_select_lock_type:
}
;
+
opt_lock_wait_timeout_new:
/* empty */
{
@@ -9819,15 +9984,15 @@ bool_pri:
;
predicate:
- bit_expr IN_SYM '(' subselect ')'
+ bit_expr IN_SYM subquery
{
- $$= new (thd->mem_root) Item_in_subselect(thd, $1, $4);
+ $$= new (thd->mem_root) Item_in_subselect(thd, $1, $3);
if (unlikely($$ == NULL))
MYSQL_YYABORT;
}
- | bit_expr not IN_SYM '(' subselect ')'
+ | bit_expr not IN_SYM subquery
{
- Item *item= new (thd->mem_root) Item_in_subselect(thd, $1, $5);
+ Item *item= new (thd->mem_root) Item_in_subselect(thd, $1, $4);
if (unlikely(item == NULL))
MYSQL_YYABORT;
$$= negate_expression(thd, item);
@@ -10346,6 +10511,12 @@ primary_expr:
column_default_non_parenthesized_expr
| explicit_cursor_attr
| '(' parenthesized_expr ')' { $$= $2; }
+ | subquery
+ {
+ if (!($$= Lex->create_item_query_expression(thd, NULL,
+ $1->master_unit())))
+ MYSQL_YYABORT;
+ }
;
string_factor_expr:
@@ -12148,35 +12319,12 @@ table_primary_ident:
}
;
-
-/*
- Represents a flattening of the following rules from the SQL:2003
- standard. This sub-rule corresponds to the sub-rule
- <table primary> ::= ... | <derived table> [ AS ] <correlation name>
-
- <derived table> ::= <table subquery>
- <table subquery> ::= <subquery>
- <subquery> ::= <left paren> <query expression> <right paren>
- <query expression> ::= [ <with clause> ] <query expression body>
-
- For the time being we use the non-standard rule
- select_derived_union which is a compromise between the standard
- and our parser. Possibly this rule could be replaced by our
- query_expression_body.
-*/
-
table_primary_derived:
- query_primary_parens opt_for_system_time_clause table_alias_clause
+ subquery
+ opt_for_system_time_clause table_alias_clause
{
- if (!($$= Lex->parsed_derived_select($1, $2, $3)))
- YYABORT;
- }
- | '('
- query_expression
- ')' opt_for_system_time_clause table_alias_clause
- {
- if (!($$= Lex->parsed_derived_unit($2, $4, $5)))
- YYABORT;
+ if (!($$= Lex->parsed_derived_table($1->master_unit(), $2, $3)))
+ MYSQL_YYABORT;
}
;
@@ -12312,7 +12460,6 @@ table_alias:
opt_table_alias_clause:
/* empty */ { $$=0; }
-
| table_alias_clause { $$= $1; }
;
@@ -12446,7 +12593,7 @@ opt_window_clause:
{}
| WINDOW_SYM
window_def_list
- {}
+ {}
;
window_def_list:
@@ -12774,10 +12921,8 @@ delete_limit_clause:
| LIMIT limit_option ROWS_SYM EXAMINED_SYM { thd->parse_error(); MYSQL_YYABORT; }
;
-opt_order_limit_lock:
- /* empty */
- { $$= NULL; }
- | order_or_limit
+order_limit_lock:
+ order_or_limit
{
$$= $1;
$$->lock.empty();
@@ -12797,32 +12942,45 @@ opt_order_limit_lock:
$$->lock= $1;
}
;
+
+opt_order_limit_lock:
+ /* empty */
+ {
+ Lex->pop_select();
+ $$= NULL;
+ }
+ | order_limit_lock { $$= $1; }
+ ;
+
query_expression_tail:
+ order_limit_lock
+ ;
+
+opt_query_expression_tail:
opt_order_limit_lock
;
opt_procedure_or_into:
- /* empty */
- {
- $$.empty();
- }
+ /* empty */
+ {
+ $$.empty();
+ }
| procedure_clause opt_select_lock_type
- {
- $$= $2;
- }
+ {
+ $$= $2;
+ }
| into opt_select_lock_type
- {
- push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
- ER_WARN_DEPRECATED_SYNTAX,
- ER_THD(thd, ER_WARN_DEPRECATED_SYNTAX),
- "<select expression> INTO <destination>;",
- "'SELECT <select list> INTO <destination>"
- " FROM...'");
- $$= $2;
- }
+ {
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
+ ER_WARN_DEPRECATED_SYNTAX,
+ ER_THD(thd, ER_WARN_DEPRECATED_SYNTAX),
+ "<select expression> INTO <destination>;",
+ "'SELECT <select list> INTO <destination>"
+ " FROM...'");
+ $$= $2;
+ }
;
-
order_or_limit:
order_clause opt_limit_clause
{
@@ -15208,16 +15366,6 @@ temporal_literal:
}
;
-
-opt_with_clause:
- /*empty */ { $$= 0; }
- | with_clause
- {
- $$= $1;
- }
- ;
-
-
with_clause:
WITH opt_recursive
{
diff --git a/sql/sql_yacc_ora.yy b/sql/sql_yacc_ora.yy
index f789cc0..cbbee0d 100644
--- a/sql/sql_yacc_ora.yy
+++ b/sql/sql_yacc_ora.yy
@@ -295,10 +295,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
%parse-param { THD *thd }
%lex-param { THD *thd }
/*
- Currently there are 51 shift/reduce conflicts.
+ Currently there are 42 shift/reduce conflicts.
We should not introduce new conflicts any more.
*/
-%expect 51
+%expect 42
/*
Comments for TOKENS.
@@ -1115,6 +1115,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
%left '^'
%left MYSQL_CONCAT_SYM
%left NEG '~' NOT2_SYM BINARY
+%left SUBQUERY_AS_EXPR
%left COLLATE_SYM
/*
@@ -1206,7 +1207,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
ALTER TABLE t1 ADD SYSTEM VERSIONING;
*/
%left PREC_BELOW_CONTRACTION_TOKEN2
-%left TEXT_STRING '(' VALUE_SYM VERSIONING_SYM
+%left TEXT_STRING '(' ')' VALUE_SYM VERSIONING_SYM
+%left EMPTY_FROM_CLAUSE
+%right INTO
%type <lex_str>
DECIMAL_NUM FLOAT_NUM NUM LONG_NUM
@@ -1478,16 +1481,18 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
query_specification
table_value_constructor
simple_table
+ query_simple
query_primary
- query_primary_parens
+ subquery
select_into_query_specification
-
%type <select_lex_unit>
- query_specification_start
- query_expression_body
query_expression
- query_expression_unit
+ query_expression_no_with_clause
+ query_expression_body_ext
+ query_expression_body_ext_parens
+ query_expression_body
+ query_specification_start
%type <boolfunc2creator> comp_op
@@ -1512,7 +1517,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
%type <order_limit_lock>
query_expression_tail
+ opt_query_expression_tail
order_or_limit
+ order_limit_lock
opt_order_limit_lock
%type <select_order> opt_order_clause order_clause order_list
@@ -1678,7 +1685,7 @@ END_OF_INPUT
THEN_SYM WHEN_SYM DIV_SYM MOD_SYM OR2_SYM AND_AND_SYM DELETE_SYM
MYSQL_CONCAT_SYM ORACLE_CONCAT_SYM
-%type <with_clause> opt_with_clause with_clause
+%type <with_clause> with_clause
%type <lex_str_ptr> query_name
@@ -5273,7 +5280,7 @@ create_select_query_expression:
if (Lex->parsed_insert_select($1->first_select()))
MYSQL_YYABORT;
}
- | LEFT_PAREN_WITH with_clause query_expression_body ')'
+ | LEFT_PAREN_WITH with_clause query_expression_no_with_clause ')'
{
SELECT_LEX *first_select= $3->first_select();
$3->set_with_clause($2);
@@ -6782,13 +6789,7 @@ parse_vcol_expr:
;
parenthesized_expr:
- remember_tok_start
- query_expression
- {
- if (!($$= Lex->create_item_query_expression(thd, $1, $2)))
- MYSQL_YYABORT;
- }
- | expr
+ expr
| expr ',' expr_list
{
$3->push_front($1, thd->mem_root);
@@ -6807,6 +6808,16 @@ virtual_column_func:
MYSQL_YYABORT;
$$= v;
}
+ | subquery
+ {
+ Item *item;
+ if (!(item= new (thd->mem_root) Item_singlerow_subselect(thd, $1)))
+ MYSQL_YYABORT;
+ Virtual_column_info *v= add_virtual_expression(thd, item);
+ if (unlikely(!v))
+ MYSQL_YYABORT;
+ $$= v;
+ }
;
expr_or_literal: column_default_non_parenthesized_expr | signed_literal ;
@@ -9240,7 +9251,7 @@ opt_ignore_leaves:
*/
select:
- query_expression_body
+ query_expression_no_with_clause
{
if (Lex->push_select($1->fake_select_lex ?
$1->fake_select_lex :
@@ -9250,10 +9261,11 @@ select:
opt_procedure_or_into
{
Lex->pop_select();
+ $1->set_with_clause(NULL);
if (Lex->select_finalize($1, $3))
MYSQL_YYABORT;
}
- | with_clause query_expression_body
+ | with_clause query_expression_no_with_clause
{
if (Lex->push_select($2->fake_select_lex ?
$2->fake_select_lex :
@@ -9279,9 +9291,11 @@ select_into:
}
opt_order_limit_lock
{
- st_select_lex_unit *unit;
- if (!(unit= Lex->parsed_body_select($1, $3)))
+ SELECT_LEX_UNIT *unit;
+ if (!(unit = Lex->create_unit($1)))
MYSQL_YYABORT;
+ if ($3)
+ unit= Lex->add_tail_to_query_expression_body(unit, $3);
if (Lex->select_finalize(unit))
MYSQL_YYABORT;
}
@@ -9352,108 +9366,258 @@ select_into_query_specification:
}
;
-opt_from_clause:
- /* Empty */
- | from_clause
+/**
+
+ The following grammar for query expressions conformant to
+ the latest SQL Standard is supported:
+
+ <query expression> ::=
+ [ <with clause> ] <query expression body>
+ [ <order by clause> ] [ <result offset clause> ] [ <fetch first clause> ]
+
+ <with clause> ::=
+ WITH [ RECURSIVE ] <with_list
+
+ <with list> ::=
+ <with list element> [ { <comma> <with list element> }... ]
+
+ <with list element> ::=
+ <query name> [ '(' <with column list> ')' ]
+ AS <table subquery>
+
+ <with column list> ::=
+ <column name list>
+
+ <query expression body> ::
+ <query term>
+ | <query expression body> UNION [ ALL | DISTINCT ] <query term>
+ | <query expression body> EXCEPT [ DISTINCT ]
+
+ <query term> ::=
+ <query primary>
+ | <query term> INTERSECT [ DISTINCT ] <query primary>
+
+ <query primary> ::=
+ <simple table>
+ | '(' <query expression body>
+ [ <order by clause> ] [ <result offset clause> ] [ <fetch first clause> ]
+ ')'
+
+ <simple table>
+ <query specification>
+ | <table value constructor>
+
+ <subquery>
+ '(' <query_expression> ')'
+
+*/
+
+/*
+ query_expression produces the same expressions as
+ <query expression>
+*/
+
+query_expression:
+ query_expression_no_with_clause
+ {
+ $1->set_with_clause(NULL);
+ $$= $1;
+ }
+ | with_clause
+ query_expression_no_with_clause
+ {
+ $2->set_with_clause($1);
+ $1->attach_to($2->first_select());
+ $$= $2;
+ }
;
+/*
+ query_expression_no_with_clause produces the same expressions as
+ <query expression> without [ <with clause> ]
+*/
-query_primary:
- simple_table
- { $$= $1; }
- | query_primary_parens
- { $$= $1; }
+query_expression_no_with_clause:
+ query_expression_body_ext { $$= $1; }
+ | query_expression_body_ext_parens { $$= $1; }
;
-query_primary_parens:
- '(' query_expression_unit
+/*
+ query_expression_body_ext produces the same expressions as
+ <query expression body>
+ [ <order by clause> ] [ <result offset clause> ] [ <fetch first clause> ]
+ | '('... <query expression body>
+ [ <order by clause> ] [ <result offset clause> ] [ <fetch first clause> ]
+ ')'...
+ Note: number of ')' must be equal to the number of '(' in the rule above
+*/
+
+query_expression_body_ext:
+ query_expression_body
{
- if (Lex->parsed_unit_in_brackets($2))
- MYSQL_YYABORT;
+ if ($1->first_select()->next_select())
+ {
+ if (Lex->parsed_multi_operand_query_expression_body($1))
+ MYSQL_YYABORT;
+ }
}
- query_expression_tail ')'
+ opt_query_expression_tail
{
- $$= Lex->parsed_unit_in_brackets_tail($2, $4);
+ if (!$3)
+ $$= $1;
+ else
+ $$= Lex->add_tail_to_query_expression_body($1, $3);
}
- | '(' query_primary
+ | query_expression_body_ext_parens
{
- Lex->push_select($2);
+ Lex->push_select(!$1->first_select()->next_select() ?
+ $1->first_select() : $1->fake_select_lex);
}
- query_expression_tail ')'
+ query_expression_tail
{
- if (!($$= Lex->parsed_select_in_brackets($2, $4)))
- YYABORT;
+ if (!($$= Lex->add_tail_to_query_expression_body_ext_parens($1, $3)))
+ MYSQL_YYABORT;
}
;
-query_expression_unit:
- query_primary
- unit_type_decl
- query_primary
- {
- if (!($$= Lex->parsed_select_expr_start($1, $3, $2.unit_type,
- $2.distinct)))
- YYABORT;
- }
- | query_expression_unit
- unit_type_decl
- query_primary
+query_expression_body_ext_parens:
+ '(' query_expression_body_ext_parens ')'
+ { $$= $2; }
+ | '(' query_expression_body_ext ')'
{
- if (!($$= Lex->parsed_select_expr_cont($1, $3, $2.unit_type,
- $2.distinct, TRUE)))
- YYABORT;
+ SELECT_LEX *sel= $2->first_select()->next_select() ?
+ $2->fake_select_lex : $2->first_select();
+ sel->braces= true;
+ $$= $2;
}
;
+/*
+ query_expression_body produces the same expressions as
+ <query expression body>
+*/
+
query_expression_body:
- query_primary
+ query_simple
{
Lex->push_select($1);
+ if (!($$= Lex->create_unit($1)))
+ MYSQL_YYABORT;
}
- query_expression_tail
+ | query_expression_body
+ unit_type_decl
{
- if (!($$= Lex->parsed_body_select($1, $3)))
- MYSQL_YYABORT;
+ if (!$1->first_select()->next_select())
+ {
+ Lex->pop_select();
+ }
}
- | query_expression_unit
+ query_primary
{
- if (Lex->parsed_body_unit($1))
+ if (!($$= Lex->add_primary_to_query_expression_body($1, $4,
+ $2.unit_type,
+ $2.distinct,
+ TRUE)))
MYSQL_YYABORT;
}
- query_expression_tail
+ | query_expression_body_ext_parens
+ unit_type_decl
+ query_primary
{
- if (!($$= Lex->parsed_body_unit_tail($1, $3)))
+ if (!($$= Lex->add_primary_to_query_expression_body_ext_parens(
+ $1, $3,
+ $2.unit_type,
+ $2.distinct)))
MYSQL_YYABORT;
}
;
-query_expression:
- opt_with_clause
- query_expression_body
- {
- if ($1)
- {
- $2->set_with_clause($1);
- $1->attach_to($2->first_select());
- }
- $$= $2;
- }
+/*
+ query_primary produces the same expressions as
+ <query primary>
+*/
+
+query_primary:
+ query_simple
+ { $$= $1; }
+ | query_expression_body_ext_parens
+ { $$= $1->first_select(); }
+ ;
+
+/*
+ query_simple produces the same expressions as
+ <simple table>
+*/
+
+query_simple:
+ simple_table { $$= $1;}
;
subselect:
- remember_tok_start
query_expression
{
- if (!($$= Lex->parsed_subselect($2, $1)))
+ if (!($$= Lex->parsed_subselect($1, NULL)))
YYABORT;
}
;
-
-/**
- <table expression>, as in the SQL standard.
+/*
+ subquery produces the same expressions as
+ <subquery>
+
+ Consider the production rule of the SQL Standard
+ subquery:
+ '(' query_expression_no_with_clause ')'
+
+ This rule is equivalent to the rule
+ subquery:
+ '(' query_expression_no_with_clause ')'
+ | '(' with_clause query_expression_no_with_clause ')'
+ that in its turn is equivalent to
+ subquery:
+ '(' query_expression_body_ext ')'
+ | '(' query_expression_body_ext_parens ')'
+ | '(' with_clause query_expression_no_with_clause ')'
+
+ The latter can be re-written into
+ subquery:
+ '(' query_expression_body_ext_parens ')'
+ | '(' with_clause query_expression_no_with_clause ')'
+
+ The last rule allows us to resolve properly the shift/reduce conflict
+ when subquery is used in expressions such as in the following queries
+ select (select * from t1 limit 1) + t2.a from t2
+ select * from t1 where t1.a [not] in (select t2.a from t2)
+
+ In the rule below %prec SUBQUERY_AS_EXPR forces the parser to perform a shift
+ operation rather then a reduce operation when ')' is encountered and can be
+ considered as the last symbol a query expression.
*/
+subquery:
+ query_expression_body_ext_parens %prec SUBQUERY_AS_EXPR
+ {
+ if (!$1->fake_select_lex)
+ $1->first_select()->braces= false;
+ else
+ $1->fake_select_lex->braces= false;
+ if (!($$= Lex->parsed_subselect($1, NULL)))
+ YYABORT;
+ }
+ | '(' with_clause query_expression_no_with_clause ')'
+ {
+ $3->set_with_clause($2);
+ $2->attach_to($3->first_select());
+ if (!($$= Lex->parsed_subselect($3, NULL)))
+ YYABORT;
+ }
+ ;
+
+opt_from_clause:
+ /* empty */ %prec EMPTY_FROM_CLAUSE
+ | from_clause
+ ;
+
from_clause:
FROM table_reference_list
;
@@ -9929,15 +10093,15 @@ bool_pri:
;
predicate:
- bit_expr IN_SYM '(' subselect ')'
+ bit_expr IN_SYM subquery
{
- $$= new (thd->mem_root) Item_in_subselect(thd, $1, $4);
+ $$= new (thd->mem_root) Item_in_subselect(thd, $1, $3);
if (unlikely($$ == NULL))
MYSQL_YYABORT;
}
- | bit_expr not IN_SYM '(' subselect ')'
+ | bit_expr not IN_SYM subquery
{
- Item *item= new (thd->mem_root) Item_in_subselect(thd, $1, $5);
+ Item *item= new (thd->mem_root) Item_in_subselect(thd, $1, $4);
if (unlikely(item == NULL))
MYSQL_YYABORT;
$$= negate_expression(thd, item);
@@ -10456,6 +10620,12 @@ primary_expr:
column_default_non_parenthesized_expr
| explicit_cursor_attr
| '(' parenthesized_expr ')' { $$= $2; }
+ | subquery
+ {
+ if (!($$= Lex->create_item_query_expression(thd, NULL,
+ $1->master_unit())))
+ MYSQL_YYABORT;
+ }
;
string_factor_expr:
@@ -12258,37 +12428,15 @@ table_primary_ident:
}
;
-
-/*
- Represents a flattening of the following rules from the SQL:2003
- standard. This sub-rule corresponds to the sub-rule
- <table primary> ::= ... | <derived table> [ AS ] <correlation name>
-
- <derived table> ::= <table subquery>
- <table subquery> ::= <subquery>
- <subquery> ::= <left paren> <query expression> <right paren>
- <query expression> ::= [ <with clause> ] <query expression body>
-
- For the time being we use the non-standard rule
- select_derived_union which is a compromise between the standard
- and our parser. Possibly this rule could be replaced by our
- query_expression_body.
-*/
-
table_primary_derived:
- query_primary_parens opt_for_system_time_clause table_alias_clause
- {
- if (!($$= Lex->parsed_derived_select($1, $2, $3)))
- YYABORT;
- }
- | '('
- query_expression
- ')' opt_for_system_time_clause table_alias_clause
+ subquery
+ opt_for_system_time_clause table_alias_clause
{
- if (!($$= Lex->parsed_derived_unit($2, $4, $5)))
- YYABORT;
+ if (!($$= Lex->parsed_derived_table($1->master_unit(), $2, $3)))
+ MYSQL_YYABORT;
}
;
+ ;
opt_outer:
/* empty */ {}
@@ -12422,7 +12570,6 @@ table_alias:
opt_table_alias_clause:
/* empty */ { $$=0; }
-
| table_alias_clause { $$= $1; }
;
@@ -12884,10 +13031,8 @@ delete_limit_clause:
| LIMIT limit_option ROWS_SYM EXAMINED_SYM { thd->parse_error(); MYSQL_YYABORT; }
;
-opt_order_limit_lock:
- /* empty */
- { $$= NULL; }
- | order_or_limit
+order_limit_lock:
+ order_or_limit
{
$$= $1;
$$->lock.empty();
@@ -12907,29 +13052,42 @@ opt_order_limit_lock:
$$->lock= $1;
}
;
+opt_order_limit_lock:
+ /* empty */
+ {
+ Lex->pop_select();
+ $$= NULL;
+ }
+ | order_limit_lock { $$= $1; }
+ ;
+
query_expression_tail:
+ order_limit_lock
+ ;
+
+opt_query_expression_tail:
opt_order_limit_lock
;
opt_procedure_or_into:
/* empty */
- {
- $$.empty();
- }
+ {
+ $$.empty();
+ }
| procedure_clause opt_select_lock_type
- {
- $$= $2;
- }
+ {
+ $$= $2;
+ }
| into opt_select_lock_type
- {
- push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
- ER_WARN_DEPRECATED_SYNTAX,
- ER_THD(thd, ER_WARN_DEPRECATED_SYNTAX),
- "<select expression> INTO <destination>;",
- "'SELECT <select list> INTO <destination>"
- " FROM...'");
- $$= $2;
- }
+ {
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
+ ER_WARN_DEPRECATED_SYNTAX,
+ ER_THD(thd, ER_WARN_DEPRECATED_SYNTAX),
+ "<select expression> INTO <destination>;",
+ "'SELECT <select list> INTO <destination>"
+ " FROM...'");
+ $$= $2;
+ }
;
@@ -15340,16 +15498,6 @@ temporal_literal:
}
;
-
-opt_with_clause:
- /*empty */ { $$= 0; }
- | with_clause
- {
- $$= $1;
- }
- ;
-
-
with_clause:
WITH opt_recursive
{
1
0
[Commits] ff51e6038a6: Issue #790, MyRocks/MRR: Fix a problem with ORDER BY queries
by psergey 14 Sep '19
by psergey 14 Sep '19
14 Sep '19
revision-id: ff51e6038a6d64cf596f0ecda6c28aaf3dcfa3bf (fb-prod201903-163-gff51e6038a6)
parent(s): c2789fdd09f84fbf4321c5bde74851e5b58d01f7
author: Sergei Petrunia
committer: Sergei Petrunia
timestamp: 2019-09-15 00:27:02 +0300
message:
Issue #790, MyRocks/MRR: Fix a problem with ORDER BY queries
SQL layer can request Sorted Mode, even if we indicated we don't support
it. When this happens, the expected action is to switch to the default
MRR implementation.
(EXPLAIN will still work correctly, see the issue comment on github for
explanations how)
---
mysql-test/suite/rocksdb/r/rocksdb_mrr.result | 29 +++++++++++++++++++++++++++
mysql-test/suite/rocksdb/t/rocksdb_mrr.test | 19 ++++++++++++++++++
storage/rocksdb/ha_rocksdb.cc | 3 ++-
3 files changed, 50 insertions(+), 1 deletion(-)
diff --git a/mysql-test/suite/rocksdb/r/rocksdb_mrr.result b/mysql-test/suite/rocksdb/r/rocksdb_mrr.result
index bf90d75e696..7ece91c1fa4 100644
--- a/mysql-test/suite/rocksdb/r/rocksdb_mrr.result
+++ b/mysql-test/suite/rocksdb/r/rocksdb_mrr.result
@@ -344,4 +344,33 @@ attached_conditions_computation": [
set optimizer_trace=0;
drop table t0, t2;
+#
+# Test for the "fallback to default MRR implementation if SQL layer
+# requests the sorted mode".
+#
+create table t0(a int primary key);
+insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+create table t1 (kp1 int, kp2 int, kp3 int, col1 int, key (kp1, kp2, kp3));
+insert into t1 select A.a, B.a, C.a, 123456 from t0 A, t0 B, t0 C;
+set global rocksdb_force_flush_memtable_now=1;
+analyze table t1;
+Table Op Msg_type Msg_text
+test.t1 analyze status OK
+explain
+select * from t1 where kp1=1 order by kp2 limit 10;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range kp1 kp1 5 NULL # Using index condition
+select * from t1 where kp1=1 order by kp2 limit 10;
+kp1 kp2 kp3 col1
+1 0 0 123456
+1 0 1 123456
+1 0 2 123456
+1 0 3 123456
+1 0 4 123456
+1 0 5 123456
+1 0 6 123456
+1 0 7 123456
+1 0 8 123456
+1 0 9 123456
+drop table t0, t1;
set optimizer_switch=@save_optimizer_switch;
diff --git a/mysql-test/suite/rocksdb/t/rocksdb_mrr.test b/mysql-test/suite/rocksdb/t/rocksdb_mrr.test
index 77a78cff6d1..dc8c260f754 100644
--- a/mysql-test/suite/rocksdb/t/rocksdb_mrr.test
+++ b/mysql-test/suite/rocksdb/t/rocksdb_mrr.test
@@ -252,4 +252,23 @@ set optimizer_trace=0;
drop table t0, t2;
+--echo #
+--echo # Test for the "fallback to default MRR implementation if SQL layer
+--echo # requests the sorted mode".
+--echo #
+create table t0(a int primary key);
+insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+
+create table t1 (kp1 int, kp2 int, kp3 int, col1 int, key (kp1, kp2, kp3));
+insert into t1 select A.a, B.a, C.a, 123456 from t0 A, t0 B, t0 C;
+
+set global rocksdb_force_flush_memtable_now=1;
+analyze table t1;
+--replace_column 9 #
+explain
+select * from t1 where kp1=1 order by kp2 limit 10;
+# This shouldn't fail an assert:
+select * from t1 where kp1=1 order by kp2 limit 10;
+
+drop table t0, t1;
set optimizer_switch=@save_optimizer_switch;
diff --git a/storage/rocksdb/ha_rocksdb.cc b/storage/rocksdb/ha_rocksdb.cc
index cd2a195f088..94b8c3741f3 100644
--- a/storage/rocksdb/ha_rocksdb.cc
+++ b/storage/rocksdb/ha_rocksdb.cc
@@ -15312,7 +15312,8 @@ int ha_rocksdb::multi_range_read_init(RANGE_SEQ_IF *seq, void *seq_init_param,
if (!current_thd->optimizer_switch_flag(OPTIMIZER_SWITCH_MRR) ||
(mode & HA_MRR_USE_DEFAULT_IMPL) ||
- (buf->buffer_end - buf->buffer < mrr_get_length_per_rec())) {
+ (buf->buffer_end - buf->buffer < mrr_get_length_per_rec()) ||
+ (active_index != table->s->primary_key && (mode & HA_MRR_SORTED))) {
mrr_uses_default_impl = true;
res = handler::multi_range_read_init(seq, seq_init_param, n_ranges, mode,
buf);
1
0