summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2021-11-16 16:30:45 +0200
committerMarko Mäkelä <marko.makela@mariadb.com>2021-11-16 16:30:45 +0200
commitdc8def73f7204d13da9b2c38ae13625ebb7ca2d1 (patch)
treeaeffa802c0e1fcb110a976f61022a41b78933007
parente58a312e42ad4df55fd9d25d8793f8cf1d2d45cf (diff)
parent09205a1c9a3003bd4367eb87e408918215e33fd7 (diff)
downloadmariadb-git-dc8def73f7204d13da9b2c38ae13625ebb7ca2d1.tar.gz
Merge 10.5 into 10.6
-rw-r--r--mysql-test/main/mysql_binary_zero_insert.result4
-rw-r--r--mysql-test/main/mysql_binary_zero_insert.test6
-rw-r--r--mysql-test/suite/gcol/r/virtual_index_drop.result3
-rw-r--r--mysql-test/suite/gcol/t/virtual_index_drop.test2
-rw-r--r--mysql-test/suite/innodb/r/alter_candidate_key.result3
-rw-r--r--mysql-test/suite/innodb/r/alter_not_null_debug.result2
-rw-r--r--mysql-test/suite/innodb/r/alter_primary_key.result2
-rw-r--r--mysql-test/suite/innodb/r/ddl_purge.result1
-rw-r--r--mysql-test/suite/innodb/r/innodb-alter-tempfile.result2
-rw-r--r--mysql-test/suite/innodb/r/innodb-index-debug.result5
-rw-r--r--mysql-test/suite/innodb/r/innodb-index-online.result3
-rw-r--r--mysql-test/suite/innodb/r/innodb-table-online.result2
-rw-r--r--mysql-test/suite/innodb/r/instant_alter_debug.result3
-rw-r--r--mysql-test/suite/innodb/t/alter_candidate_key.test5
-rw-r--r--mysql-test/suite/innodb/t/alter_not_null_debug.test2
-rw-r--r--mysql-test/suite/innodb/t/alter_primary_key.test1
-rw-r--r--mysql-test/suite/innodb/t/ddl_purge.test3
-rw-r--r--mysql-test/suite/innodb/t/innodb-alter-tempfile.test2
-rw-r--r--mysql-test/suite/innodb/t/innodb-index-debug.test2
-rw-r--r--mysql-test/suite/innodb/t/innodb-index-online.test2
-rw-r--r--mysql-test/suite/innodb/t/innodb-table-online.test1
-rw-r--r--mysql-test/suite/innodb/t/instant_alter_debug.test3
-rw-r--r--mysql-test/suite/innodb_fts/r/misc_debug.result2
-rw-r--r--mysql-test/suite/innodb_fts/t/misc_debug.test1
-rw-r--r--mysql-test/suite/rpl/r/rpl_query_cache.result29
-rw-r--r--mysql-test/suite/rpl/t/rpl_query_cache.test27
-rw-r--r--sql/handler.h3
-rw-r--r--sql/log_event_server.cc8
-rw-r--r--sql/my_json_writer.cc118
-rw-r--r--sql/my_json_writer.h71
-rw-r--r--sql/mysqld.cc2
-rw-r--r--sql/opt_range.cc11
-rw-r--r--sql/opt_subselect.cc6
-rw-r--r--sql/sql_table.cc7
-rw-r--r--storage/innobase/buf/buf0flu.cc4
-rw-r--r--storage/innobase/handler/handler0alter.cc36
-rw-r--r--unittest/sql/CMakeLists.txt5
-rw-r--r--unittest/sql/my_json_writer-t.cc128
38 files changed, 426 insertions, 91 deletions
diff --git a/mysql-test/main/mysql_binary_zero_insert.result b/mysql-test/main/mysql_binary_zero_insert.result
index 0bed7487b3e..3e43c070f07 100644
--- a/mysql-test/main/mysql_binary_zero_insert.result
+++ b/mysql-test/main/mysql_binary_zero_insert.result
@@ -32,8 +32,8 @@ COUNT(*)=8
# Note: We only look for 00 because the 5c only served as an escape
# in parsing.
#
-# MYSQL_DUMP test tb --hex-blob | grep INSERT > MYSQL_TMP_DIR/dump.sql
-FOUND 10 /00/ in dump.sql
+# MYSQL_DUMP test tb --hex-blob > MYSQL_TMP_DIR/dump.sql
+FOUND 8 /\([0-9]+,0x([1-9][0-9])*00([1-9][0-9])*\)/ in dump.sql
#
# Ensure data consistency on mysqlbinlog replay
#
diff --git a/mysql-test/main/mysql_binary_zero_insert.test b/mysql-test/main/mysql_binary_zero_insert.test
index b327c8a4d1e..37a1f1f79ff 100644
--- a/mysql-test/main/mysql_binary_zero_insert.test
+++ b/mysql-test/main/mysql_binary_zero_insert.test
@@ -114,9 +114,9 @@ SELECT COUNT(*)=8 from tb;
--echo # Note: We only look for 00 because the 5c only served as an escape
--echo # in parsing.
--echo #
---echo # MYSQL_DUMP test tb --hex-blob | grep INSERT > MYSQL_TMP_DIR/dump.sql
---exec $MYSQL_DUMP test tb --hex-blob | grep INSERT > $MYSQL_TMP_DIR/dump.sql
---let SEARCH_PATTERN= 00
+--echo # MYSQL_DUMP test tb --hex-blob > MYSQL_TMP_DIR/dump.sql
+--exec $MYSQL_DUMP test tb --hex-blob > $MYSQL_TMP_DIR/dump.sql
+--let SEARCH_PATTERN= \([0-9]+,0x([1-9][0-9])*00([1-9][0-9])*\)
--let SEARCH_FILE= $MYSQL_TMP_DIR/dump.sql
--source include/search_pattern_in_file.inc
diff --git a/mysql-test/suite/gcol/r/virtual_index_drop.result b/mysql-test/suite/gcol/r/virtual_index_drop.result
index 012e61be459..45ee4843b7c 100644
--- a/mysql-test/suite/gcol/r/virtual_index_drop.result
+++ b/mysql-test/suite/gcol/r/virtual_index_drop.result
@@ -25,6 +25,7 @@ t1 CREATE TABLE `t1` (
) ENGINE=InnoDB DEFAULT CHARSET=latin1
DROP TABLE t1;
CREATE TABLE t1(f1 INT, f2 INT AS (f1) VIRTUAL)ENGINE=InnoDB;
+INSERT INTO t1(f1) VALUES(1);
SET DEBUG_DBUG="+d,create_index_fail";
SET DEBUG_SYNC="innodb_inplace_alter_table_enter SIGNAL con1_go WAIT_FOR alter_signal";
ALTER TABLE t1 ADD COLUMN f3 INT AS (f1) VIRTUAL, ADD INDEX(f2, f3);
@@ -33,6 +34,7 @@ SET DEBUG_SYNC="now WAIT_FOR con1_go";
BEGIN;
SELECT * FROM t1;
f1 f2
+1 1
SET DEBUG_SYNC="now SIGNAL alter_signal";
connection default;
ERROR 23000: Duplicate entry '' for key '*UNKNOWN*'
@@ -47,6 +49,7 @@ t1 CREATE TABLE `t1` (
) ENGINE=InnoDB DEFAULT CHARSET=latin1
DROP TABLE t1;
CREATE TABLE t1(f1 INT, f2 INT AS (f1) VIRTUAL)ENGINE=InnoDB;
+INSERT INTO t1(f1) VALUES(1);
SET DEBUG_DBUG="+d,create_index_fail";
SET DEBUG_SYNC="innodb_inplace_alter_table_enter SIGNAL con1_go WAIT_FOR alter_signal";
ALTER TABLE t1 ADD INDEX(f2);
diff --git a/mysql-test/suite/gcol/t/virtual_index_drop.test b/mysql-test/suite/gcol/t/virtual_index_drop.test
index 016832b9e6d..e1ec43f75e5 100644
--- a/mysql-test/suite/gcol/t/virtual_index_drop.test
+++ b/mysql-test/suite/gcol/t/virtual_index_drop.test
@@ -29,6 +29,7 @@ DROP TABLE t1;
# new_vcol_info in index when rollback of alter happens
CREATE TABLE t1(f1 INT, f2 INT AS (f1) VIRTUAL)ENGINE=InnoDB;
+INSERT INTO t1(f1) VALUES(1);
SET DEBUG_DBUG="+d,create_index_fail";
SET DEBUG_SYNC="innodb_inplace_alter_table_enter SIGNAL con1_go WAIT_FOR alter_signal";
SEND ALTER TABLE t1 ADD COLUMN f3 INT AS (f1) VIRTUAL, ADD INDEX(f2, f3);
@@ -47,6 +48,7 @@ SHOW CREATE TABLE t1;
DROP TABLE t1;
CREATE TABLE t1(f1 INT, f2 INT AS (f1) VIRTUAL)ENGINE=InnoDB;
+INSERT INTO t1(f1) VALUES(1);
SET DEBUG_DBUG="+d,create_index_fail";
SET DEBUG_SYNC="innodb_inplace_alter_table_enter SIGNAL con1_go WAIT_FOR alter_signal";
send ALTER TABLE t1 ADD INDEX(f2);
diff --git a/mysql-test/suite/innodb/r/alter_candidate_key.result b/mysql-test/suite/innodb/r/alter_candidate_key.result
index b0b56047abc..79cb225e3b5 100644
--- a/mysql-test/suite/innodb/r/alter_candidate_key.result
+++ b/mysql-test/suite/innodb/r/alter_candidate_key.result
@@ -34,6 +34,7 @@ CREATE TABLE t1(f1 INT, f2 INT,
PRIMARY KEY(f1, f2),
UNIQUE INDEX uidx2 (f1, f2),
UNIQUE INDEX uidx1 (f2))ENGINE=InnoDB;
+INSERT INTO t1 VALUES(2, 2);
ALTER TABLE t1 DROP PRIMARY KEY;
SHOW CREATE TABLE t1;
Table Create Table
@@ -66,7 +67,7 @@ test.t1 check status OK
DROP TABLE t1;
SET SQL_MODE= strict_trans_tables;
CREATE TABLE t1(a INT UNIQUE) ENGINE=InnoDB;
-INSERT INTO t1 VALUES(3);
+INSERT INTO t1 VALUES(1);
SET DEBUG_SYNC='row_log_table_apply1_before SIGNAL dml WAIT_FOR dml_done';
ALTER TABLE t1 MODIFY COLUMN a INT NOT NULL;
connection con1;
diff --git a/mysql-test/suite/innodb/r/alter_not_null_debug.result b/mysql-test/suite/innodb/r/alter_not_null_debug.result
index 0c1af03159d..ff77eaf54c5 100644
--- a/mysql-test/suite/innodb/r/alter_not_null_debug.result
+++ b/mysql-test/suite/innodb/r/alter_not_null_debug.result
@@ -80,6 +80,7 @@ SET DEBUG_SYNC='RESET';
#
CREATE TABLE t1 (f VARCHAR(8) CHARACTER SET latin1 COLLATE latin1_swedish_ci)
ENGINE=InnoDB;
+INSERT INTO t1 VALUES('ZERO');
connection con1;
SET DEBUG_SYNC = 'row_log_table_apply1_before SIGNAL scanned WAIT_FOR insert_done';
ALTER TABLE t1 MODIFY f VARCHAR(256) COLLATE latin1_german2_ci NOT NULL;
@@ -96,5 +97,6 @@ ALTER TABLE t1 CHANGE f eins VARCHAR(257) COLLATE latin1_german1_ci NOT NULL,
ALGORITHM=INSTANT;
SELECT * FROM t1;
eins
+ZERO
one
DROP TABLE t1;
diff --git a/mysql-test/suite/innodb/r/alter_primary_key.result b/mysql-test/suite/innodb/r/alter_primary_key.result
index afe687871f3..b478691af1f 100644
--- a/mysql-test/suite/innodb/r/alter_primary_key.result
+++ b/mysql-test/suite/innodb/r/alter_primary_key.result
@@ -4,6 +4,7 @@
#
CREATE TABLE t0 (pk INT PRIMARY KEY) ENGINE=InnoDB;
CREATE TABLE t1 (c CHAR(2) NOT NULL) ENGINE=InnoDB;
+INSERT INTO t1 VALUES('cd');
connect con1,localhost,root,,;
BEGIN;
INSERT INTO t0 VALUES(1);
@@ -21,6 +22,7 @@ ERROR 23000: Duplicate entry 'a' for key 'PRIMARY'
SET DEBUG_SYNC='RESET';
SELECT * FROM t1;
c
+cd
ab
ac
DROP TABLE t0,t1;
diff --git a/mysql-test/suite/innodb/r/ddl_purge.result b/mysql-test/suite/innodb/r/ddl_purge.result
index a1d96de24ca..724a2a027b6 100644
--- a/mysql-test/suite/innodb/r/ddl_purge.result
+++ b/mysql-test/suite/innodb/r/ddl_purge.result
@@ -1,6 +1,7 @@
CREATE TABLE t0 (pk INT PRIMARY KEY) ENGINE=InnoDB;
CREATE TABLE t1 (pk INT PRIMARY KEY, b INT) ENGINE=InnoDB;
INSERT INTO t0 VALUES(100);
+INSERT INTO t1 VALUES(100, 100);
connect con1,localhost,root,,test;
BEGIN;
INSERT INTO t0 SET pk=1;
diff --git a/mysql-test/suite/innodb/r/innodb-alter-tempfile.result b/mysql-test/suite/innodb/r/innodb-alter-tempfile.result
index a64b2339a39..845dbacbada 100644
--- a/mysql-test/suite/innodb/r/innodb-alter-tempfile.result
+++ b/mysql-test/suite/innodb/r/innodb-alter-tempfile.result
@@ -55,7 +55,7 @@ connect con1,localhost,root,,;
BEGIN;
DELETE FROM mysql.innodb_table_stats;
connect con2,localhost,root,,;
-SET DEBUG_SYNC='inplace_after_index_build SIGNAL blocked WAIT_FOR ever';
+SET DEBUG_SYNC='innodb_inplace_alter_table_enter SIGNAL blocked WAIT_FOR ever';
ALTER TABLE t1 FORCE;
connection default;
SET DEBUG_SYNC='now WAIT_FOR blocked';
diff --git a/mysql-test/suite/innodb/r/innodb-index-debug.result b/mysql-test/suite/innodb/r/innodb-index-debug.result
index 8a1091266a9..f6b23eea41a 100644
--- a/mysql-test/suite/innodb/r/innodb-index-debug.result
+++ b/mysql-test/suite/innodb/r/innodb-index-debug.result
@@ -81,6 +81,7 @@ COUNT(k1) k2 k3
drop table t1;
create table t1(k1 int auto_increment primary key,
k2 char(200),k3 char(200))engine=innodb;
+INSERT INTO t1 VALUES(1, "test", "test");
SET DEBUG_SYNC= 'row_merge_after_scan
SIGNAL opened WAIT_FOR flushed';
ALTER TABLE t1 FORCE, ADD COLUMN k4 int;
@@ -100,6 +101,7 @@ SELECT COUNT(k1),k2,k3 FROM t1 GROUP BY k2,k3;
COUNT(k1) k2 k3
480 aaa bbb
480 aaaa bbbb
+1 test test
disconnect con1;
connection default;
show create table t1;
@@ -109,7 +111,7 @@ t1 CREATE TABLE `t1` (
`k2` char(200) DEFAULT NULL,
`k3` char(200) DEFAULT NULL,
PRIMARY KEY (`k1`)
-) ENGINE=InnoDB AUTO_INCREMENT=1023 DEFAULT CHARSET=latin1
+) ENGINE=InnoDB AUTO_INCREMENT=1024 DEFAULT CHARSET=latin1
drop table t1;
drop table t480;
#
@@ -117,6 +119,7 @@ drop table t480;
# in online table rebuild
#
CREATE TABLE t1 (j INT UNIQUE, i INT UNIQUE) ENGINE=InnoDB;
+INSERT INTO t1 VALUES(2, 2);
connect con1,localhost,root,,test;
SET DEBUG_SYNC='row_log_table_apply1_before SIGNAL built WAIT_FOR log';
ALTER TABLE t1 DROP j, FORCE;
diff --git a/mysql-test/suite/innodb/r/innodb-index-online.result b/mysql-test/suite/innodb/r/innodb-index-online.result
index 6ad5c20ffed..1ee352cd402 100644
--- a/mysql-test/suite/innodb/r/innodb-index-online.result
+++ b/mysql-test/suite/innodb/r/innodb-index-online.result
@@ -493,6 +493,7 @@ DROP TABLE t1;
# MDEV-13205 assertion !dict_index_is_online_ddl(index) upon ALTER TABLE
#
CREATE TABLE t1 (c VARCHAR(64)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES('foo');
SET DEBUG_SYNC = 'row_log_apply_before SIGNAL t1u_created WAIT_FOR dup_done';
ALTER TABLE t1 ADD UNIQUE(c);
connection con1;
@@ -509,6 +510,7 @@ ALTER TABLE t2 ADD FOREIGN KEY (c) REFERENCES t1 (c);
ERROR HY000: Can't create table `test`.`t2` (errno: 150 "Foreign key constraint is incorrectly formed")
DROP TABLE t2,t1;
CREATE TABLE t1 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
+INSERT INTO t1 VALUES(0,0);
connect con1,localhost,root,,;
SET DEBUG_SYNC = 'row_log_apply_before SIGNAL created WAIT_FOR inserted';
ALTER TABLE t1 ADD INDEX(b);
@@ -523,6 +525,7 @@ disconnect con1;
connection default;
SELECT * FROM t1;
a b
+0 0
CHECK TABLE t1;
Table Op Msg_type Msg_text
test.t1 check status OK
diff --git a/mysql-test/suite/innodb/r/innodb-table-online.result b/mysql-test/suite/innodb/r/innodb-table-online.result
index 8f06576f2ed..9ef5316e17d 100644
--- a/mysql-test/suite/innodb/r/innodb-table-online.result
+++ b/mysql-test/suite/innodb/r/innodb-table-online.result
@@ -434,6 +434,7 @@ t1 CREATE TABLE `t1` (
SET GLOBAL innodb_monitor_disable = module_ddl;
DROP TABLE t1;
CREATE TABLE t1 (a INT PRIMARY KEY, b blob) ENGINE=InnoDB;
+INSERT INTO t1 VALUES(0,NULL);
connection con1;
SET DEBUG_SYNC = 'row_log_table_apply1_before SIGNAL created WAIT_FOR ins';
ALTER TABLE t1 FORCE;
@@ -448,6 +449,7 @@ disconnect con1;
connection default;
SELECT * FROM t1;
a b
+0 NULL
DROP TABLE t1;
SET DEBUG_SYNC = 'RESET';
SET GLOBAL innodb_file_per_table = @global_innodb_file_per_table_orig;
diff --git a/mysql-test/suite/innodb/r/instant_alter_debug.result b/mysql-test/suite/innodb/r/instant_alter_debug.result
index fa7ebabd0af..c74ec0a4bc4 100644
--- a/mysql-test/suite/innodb/r/instant_alter_debug.result
+++ b/mysql-test/suite/innodb/r/instant_alter_debug.result
@@ -171,6 +171,7 @@ connect stop_purge,localhost,root;
START TRANSACTION WITH CONSISTENT SNAPSHOT;
connect ddl,localhost,root,,test;
DELETE FROM t1;
+INSERT INTO t1 VALUES(1, 2);
SET DEBUG_SYNC='row_log_table_apply1_before SIGNAL copied WAIT_FOR logged';
ALTER TABLE t1 FORCE;
connection default;
@@ -449,6 +450,7 @@ DROP TABLE t1;
CREATE TABLE t1
(a INT NOT NULL, b INT, c INT, d INT, e INT, f INT, g INT, h INT, i TEXT)
ENGINE=InnoDB;
+INSERT INTO t1 VALUES(1, 2, 3, 4, 5, 6, 7, 8, "test");
ALTER TABLE t1 MODIFY a INT NULL;
SET DEBUG_SYNC='innodb_inplace_alter_table_enter SIGNAL alter WAIT_FOR go';
ALTER TABLE t1 ADD PRIMARY KEY (a);
@@ -462,6 +464,7 @@ connection default;
disconnect con1;
SELECT * FROM t1;
a b c d e f g h i
+1 2 3 4 5 6 7 8 test
DROP TABLE t1;
SET DEBUG_SYNC=RESET;
# End of 10.4 tests
diff --git a/mysql-test/suite/innodb/t/alter_candidate_key.test b/mysql-test/suite/innodb/t/alter_candidate_key.test
index 979d8fa4fee..7c8f5e30993 100644
--- a/mysql-test/suite/innodb/t/alter_candidate_key.test
+++ b/mysql-test/suite/innodb/t/alter_candidate_key.test
@@ -24,6 +24,7 @@ CREATE TABLE t1(f1 INT, f2 INT,
PRIMARY KEY(f1, f2),
UNIQUE INDEX uidx2 (f1, f2),
UNIQUE INDEX uidx1 (f2))ENGINE=InnoDB;
+INSERT INTO t1 VALUES(2, 2);
ALTER TABLE t1 DROP PRIMARY KEY;
SHOW CREATE TABLE t1;
SET DEBUG_SYNC = 'innodb_inplace_alter_table_enter
@@ -42,9 +43,7 @@ DROP TABLE t1;
SET SQL_MODE= strict_trans_tables;
CREATE TABLE t1(a INT UNIQUE) ENGINE=InnoDB;
-# MDEV-515 takes X-lock on the table for the first insert.
-# So concurrent insert won't happen on the table
-INSERT INTO t1 VALUES(3);
+INSERT INTO t1 VALUES(1);
SET DEBUG_SYNC='row_log_table_apply1_before SIGNAL dml WAIT_FOR dml_done';
--send ALTER TABLE t1 MODIFY COLUMN a INT NOT NULL
connection con1;
diff --git a/mysql-test/suite/innodb/t/alter_not_null_debug.test b/mysql-test/suite/innodb/t/alter_not_null_debug.test
index 7a965fd413a..9c5ba0faff0 100644
--- a/mysql-test/suite/innodb/t/alter_not_null_debug.test
+++ b/mysql-test/suite/innodb/t/alter_not_null_debug.test
@@ -75,7 +75,7 @@ SET DEBUG_SYNC='RESET';
--echo #
CREATE TABLE t1 (f VARCHAR(8) CHARACTER SET latin1 COLLATE latin1_swedish_ci)
ENGINE=InnoDB;
-
+INSERT INTO t1 VALUES('ZERO');
connection con1;
SET DEBUG_SYNC = 'row_log_table_apply1_before SIGNAL scanned WAIT_FOR insert_done';
send ALTER TABLE t1 MODIFY f VARCHAR(256) COLLATE latin1_german2_ci NOT NULL;
diff --git a/mysql-test/suite/innodb/t/alter_primary_key.test b/mysql-test/suite/innodb/t/alter_primary_key.test
index 4edc0cc023e..bf961c14b43 100644
--- a/mysql-test/suite/innodb/t/alter_primary_key.test
+++ b/mysql-test/suite/innodb/t/alter_primary_key.test
@@ -9,6 +9,7 @@
CREATE TABLE t0 (pk INT PRIMARY KEY) ENGINE=InnoDB;
CREATE TABLE t1 (c CHAR(2) NOT NULL) ENGINE=InnoDB;
+INSERT INTO t1 VALUES('cd');
connect (con1,localhost,root,,);
BEGIN;
diff --git a/mysql-test/suite/innodb/t/ddl_purge.test b/mysql-test/suite/innodb/t/ddl_purge.test
index 678cb597c03..8f84206c52a 100644
--- a/mysql-test/suite/innodb/t/ddl_purge.test
+++ b/mysql-test/suite/innodb/t/ddl_purge.test
@@ -7,6 +7,9 @@ CREATE TABLE t1 (pk INT PRIMARY KEY, b INT) ENGINE=InnoDB;
# MDEV-515 takes X-lock on the table for the first insert.
# So concurrent insert won't happen on the table
INSERT INTO t0 VALUES(100);
+
+INSERT INTO t1 VALUES(100, 100);
+
--connect (con1,localhost,root,,test)
BEGIN;
INSERT INTO t0 SET pk=1;
diff --git a/mysql-test/suite/innodb/t/innodb-alter-tempfile.test b/mysql-test/suite/innodb/t/innodb-alter-tempfile.test
index 769ac8fa4bc..ab6e1586897 100644
--- a/mysql-test/suite/innodb/t/innodb-alter-tempfile.test
+++ b/mysql-test/suite/innodb/t/innodb-alter-tempfile.test
@@ -79,7 +79,7 @@ BEGIN;
DELETE FROM mysql.innodb_table_stats;
connect (con2,localhost,root,,);
-SET DEBUG_SYNC='inplace_after_index_build SIGNAL blocked WAIT_FOR ever';
+SET DEBUG_SYNC='innodb_inplace_alter_table_enter SIGNAL blocked WAIT_FOR ever';
send ALTER TABLE t1 FORCE;
connection default;
diff --git a/mysql-test/suite/innodb/t/innodb-index-debug.test b/mysql-test/suite/innodb/t/innodb-index-debug.test
index 9083dc80720..204bdfe5540 100644
--- a/mysql-test/suite/innodb/t/innodb-index-debug.test
+++ b/mysql-test/suite/innodb/t/innodb-index-debug.test
@@ -96,6 +96,7 @@ drop table t1;
# Log file creation failure.
create table t1(k1 int auto_increment primary key,
k2 char(200),k3 char(200))engine=innodb;
+INSERT INTO t1 VALUES(1, "test", "test");
SET DEBUG_SYNC= 'row_merge_after_scan
SIGNAL opened WAIT_FOR flushed';
send ALTER TABLE t1 FORCE, ADD COLUMN k4 int;
@@ -122,6 +123,7 @@ drop table t480;
--echo #
CREATE TABLE t1 (j INT UNIQUE, i INT UNIQUE) ENGINE=InnoDB;
+INSERT INTO t1 VALUES(2, 2);
--connect (con1,localhost,root,,test)
SET DEBUG_SYNC='row_log_table_apply1_before SIGNAL built WAIT_FOR log';
--send
diff --git a/mysql-test/suite/innodb/t/innodb-index-online.test b/mysql-test/suite/innodb/t/innodb-index-online.test
index 08711aa1a5d..6f30dad531d 100644
--- a/mysql-test/suite/innodb/t/innodb-index-online.test
+++ b/mysql-test/suite/innodb/t/innodb-index-online.test
@@ -475,6 +475,7 @@ DROP TABLE t1;
--echo # MDEV-13205 assertion !dict_index_is_online_ddl(index) upon ALTER TABLE
--echo #
CREATE TABLE t1 (c VARCHAR(64)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES('foo');
SET DEBUG_SYNC = 'row_log_apply_before SIGNAL t1u_created WAIT_FOR dup_done';
send ALTER TABLE t1 ADD UNIQUE(c);
@@ -497,6 +498,7 @@ ALTER TABLE t2 ADD FOREIGN KEY (c) REFERENCES t1 (c);
DROP TABLE t2,t1;
CREATE TABLE t1 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
+INSERT INTO t1 VALUES(0,0);
connect (con1,localhost,root,,);
SET DEBUG_SYNC = 'row_log_apply_before SIGNAL created WAIT_FOR inserted';
diff --git a/mysql-test/suite/innodb/t/innodb-table-online.test b/mysql-test/suite/innodb/t/innodb-table-online.test
index d799221cb13..978af891157 100644
--- a/mysql-test/suite/innodb/t/innodb-table-online.test
+++ b/mysql-test/suite/innodb/t/innodb-table-online.test
@@ -395,6 +395,7 @@ SET GLOBAL innodb_monitor_disable = module_ddl;
DROP TABLE t1;
CREATE TABLE t1 (a INT PRIMARY KEY, b blob) ENGINE=InnoDB;
+INSERT INTO t1 VALUES(0,NULL);
connection con1;
SET DEBUG_SYNC = 'row_log_table_apply1_before SIGNAL created WAIT_FOR ins';
diff --git a/mysql-test/suite/innodb/t/instant_alter_debug.test b/mysql-test/suite/innodb/t/instant_alter_debug.test
index b553dc3ad74..9b174a1974b 100644
--- a/mysql-test/suite/innodb/t/instant_alter_debug.test
+++ b/mysql-test/suite/innodb/t/instant_alter_debug.test
@@ -186,6 +186,7 @@ connect stop_purge,localhost,root;
START TRANSACTION WITH CONSISTENT SNAPSHOT;
connect ddl,localhost,root,,test;
DELETE FROM t1;
+INSERT INTO t1 VALUES(1, 2);
SET DEBUG_SYNC='row_log_table_apply1_before SIGNAL copied WAIT_FOR logged';
send ALTER TABLE t1 FORCE;
connection default;
@@ -519,7 +520,7 @@ DROP TABLE t1;
CREATE TABLE t1
(a INT NOT NULL, b INT, c INT, d INT, e INT, f INT, g INT, h INT, i TEXT)
ENGINE=InnoDB;
-
+INSERT INTO t1 VALUES(1, 2, 3, 4, 5, 6, 7, 8, "test");
ALTER TABLE t1 MODIFY a INT NULL;
SET DEBUG_SYNC='innodb_inplace_alter_table_enter SIGNAL alter WAIT_FOR go';
diff --git a/mysql-test/suite/innodb_fts/r/misc_debug.result b/mysql-test/suite/innodb_fts/r/misc_debug.result
index d012fa5a9c8..2a2afacb052 100644
--- a/mysql-test/suite/innodb_fts/r/misc_debug.result
+++ b/mysql-test/suite/innodb_fts/r/misc_debug.result
@@ -31,6 +31,7 @@ SET SESSION debug_dbug=@saved_debug_dbug;
# MDEV-25200 Index count mismatch due to aborted FULLTEXT INDEX
#
CREATE TABLE t1(a INT, b TEXT, c TEXT, FULLTEXT INDEX(b)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES(1, "test", "test_1");
connect con1,localhost,root,,test;
SET DEBUG_DBUG="+d,innodb_OOM_inplace_alter";
SET DEBUG_SYNC='innodb_commit_inplace_alter_table_enter SIGNAL s2 WAIT_FOR g2';
@@ -40,6 +41,7 @@ SET DEBUG_SYNC='now WAIT_FOR s2';
START TRANSACTION;
SELECT * FROM t1;
a b c
+1 test test_1
SET DEBUG_SYNC='now SIGNAL g2';
connection con1;
ERROR HY000: Out of memory.
diff --git a/mysql-test/suite/innodb_fts/t/misc_debug.test b/mysql-test/suite/innodb_fts/t/misc_debug.test
index bbf3afe69e5..84da1320264 100644
--- a/mysql-test/suite/innodb_fts/t/misc_debug.test
+++ b/mysql-test/suite/innodb_fts/t/misc_debug.test
@@ -60,6 +60,7 @@ SET SESSION debug_dbug=@saved_debug_dbug;
--echo # MDEV-25200 Index count mismatch due to aborted FULLTEXT INDEX
--echo #
CREATE TABLE t1(a INT, b TEXT, c TEXT, FULLTEXT INDEX(b)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES(1, "test", "test_1");
connect(con1,localhost,root,,test);
SET DEBUG_DBUG="+d,innodb_OOM_inplace_alter";
SET DEBUG_SYNC='innodb_commit_inplace_alter_table_enter SIGNAL s2 WAIT_FOR g2';
diff --git a/mysql-test/suite/rpl/r/rpl_query_cache.result b/mysql-test/suite/rpl/r/rpl_query_cache.result
new file mode 100644
index 00000000000..6256ddb37f4
--- /dev/null
+++ b/mysql-test/suite/rpl/r/rpl_query_cache.result
@@ -0,0 +1,29 @@
+include/master-slave.inc
+[connection master]
+connection slave;
+SET @qtype= @@global.query_cache_type;
+SET GLOBAL query_cache_type= ON;
+SET query_cache_type= ON;
+connection master;
+create table t1 (i int) engine=innodb;
+insert into t1 set i=1;
+connection slave;
+select * from t1;
+i
+1
+connection master;
+insert into t1 set i=2;
+connection slave;
+select * from t1;
+i
+1
+2
+select sql_no_cache * from t1;
+i
+1
+2
+connection master;
+DROP TABLE t1;
+connection slave;
+SET GLOBAL query_cache_type= @qtype;
+include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_query_cache.test b/mysql-test/suite/rpl/t/rpl_query_cache.test
new file mode 100644
index 00000000000..b23f2b20b47
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_query_cache.test
@@ -0,0 +1,27 @@
+-- source include/have_binlog_format_row.inc
+-- source include/have_innodb.inc
+-- source include/master-slave.inc
+
+--connection slave
+SET @qtype= @@global.query_cache_type;
+SET GLOBAL query_cache_type= ON;
+SET query_cache_type= ON;
+
+--connection master
+create table t1 (i int) engine=innodb;
+insert into t1 set i=1;
+
+--sync_slave_with_master
+select * from t1;
+--connection master
+insert into t1 set i=2;
+
+--sync_slave_with_master
+select * from t1;
+select sql_no_cache * from t1;
+
+--connection master
+DROP TABLE t1;
+--sync_slave_with_master
+SET GLOBAL query_cache_type= @qtype;
+--source include/rpl_end.inc
diff --git a/sql/handler.h b/sql/handler.h
index 5fe06ecd0bc..14a306f7774 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -2700,6 +2700,9 @@ public:
/** true when InnoDB should abort the alter when table is not empty */
const bool error_if_not_empty;
+ /** True when DDL should avoid downgrading the MDL */
+ bool mdl_exclusive_after_prepare= false;
+
Alter_inplace_info(HA_CREATE_INFO *create_info_arg,
Alter_info *alter_info_arg,
KEY *key_info_arg, uint key_count_arg,
diff --git a/sql/log_event_server.cc b/sql/log_event_server.cc
index b665f40e3bc..1d8b65f20dd 100644
--- a/sql/log_event_server.cc
+++ b/sql/log_event_server.cc
@@ -5622,14 +5622,16 @@ int Rows_log_event::do_apply_event(rpl_group_info *rgi)
}
}
-#if defined(WITH_WSREP) && defined(HAVE_QUERY_CACHE)
+#ifdef HAVE_QUERY_CACHE
/*
Moved invalidation right before the call to rows_event_stmt_cleanup(),
to avoid query cache being polluted with stale entries,
*/
- if (WSREP(thd) && wsrep_thd_is_applying(thd))
+# ifdef WITH_WSREP
+ if (!WSREP(thd) && !wsrep_thd_is_applying(thd))
+# endif /* WITH_WSREP */
query_cache.invalidate_locked_for_write(thd, rgi->tables_to_lock);
-#endif /* WITH_WSREP && HAVE_QUERY_CACHE */
+#endif /* HAVE_QUERY_CACHE */
}
table= m_table= rgi->m_table_map.get_table(m_table_id);
diff --git a/sql/my_json_writer.cc b/sql/my_json_writer.cc
index 55e71bc1b52..9470ba57855 100644
--- a/sql/my_json_writer.cc
+++ b/sql/my_json_writer.cc
@@ -1,4 +1,4 @@
-/* Copyright (C) 2014, 2020, MariaDB Corporation.
+/* Copyright (C) 2014, 2021, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -18,6 +18,14 @@
#include "sql_string.h"
#include "my_json_writer.h"
+#if !defined(NDEBUG) || defined(JSON_WRITER_UNIT_TEST)
+bool Json_writer::named_item_expected() const
+{
+ return named_items_expectation.size()
+ && named_items_expectation.back();
+}
+#endif
+
void Json_writer::append_indent()
{
if (!document_start)
@@ -26,9 +34,21 @@ void Json_writer::append_indent()
output.append(' ');
}
-void Json_writer::start_object()
+inline void Json_writer::on_start_object()
{
+#if !defined(NDEBUG) || defined(JSON_WRITER_UNIT_TEST)
+ if(!fmt_helper.is_making_writer_calls())
+ {
+ VALIDITY_ASSERT(got_name == named_item_expected());
+ named_items_expectation.push_back(true);
+ }
+#endif
fmt_helper.on_start_object();
+}
+
+void Json_writer::start_object()
+{
+ on_start_object();
if (!element_started)
start_element();
@@ -38,10 +58,22 @@ void Json_writer::start_object()
first_child=true;
element_started= false;
document_start= false;
+#if !defined(NDEBUG) || defined(JSON_WRITER_UNIT_TEST)
+ got_name= false;
+#endif
}
void Json_writer::start_array()
{
+#if !defined(NDEBUG) || defined(JSON_WRITER_UNIT_TEST)
+ if(!fmt_helper.is_making_writer_calls())
+ {
+ VALIDITY_ASSERT(got_name == named_item_expected());
+ named_items_expectation.push_back(false);
+ got_name= false;
+ }
+#endif
+
if (fmt_helper.on_start_array())
return;
@@ -58,6 +90,12 @@ void Json_writer::start_array()
void Json_writer::end_object()
{
+#if !defined(NDEBUG) || defined(JSON_WRITER_UNIT_TEST)
+ VALIDITY_ASSERT(named_item_expected());
+ named_items_expectation.pop_back();
+ VALIDITY_ASSERT(!got_name);
+ got_name= false;
+#endif
indent_level-=INDENT_SIZE;
if (!first_child)
append_indent();
@@ -68,6 +106,11 @@ void Json_writer::end_object()
void Json_writer::end_array()
{
+#if !defined(NDEBUG) || defined(JSON_WRITER_UNIT_TEST)
+ VALIDITY_ASSERT(!named_item_expected());
+ named_items_expectation.pop_back();
+ got_name= false;
+#endif
if (fmt_helper.on_end_array())
return;
indent_level-=INDENT_SIZE;
@@ -80,31 +123,25 @@ void Json_writer::end_array()
Json_writer& Json_writer::add_member(const char *name)
{
size_t len= strlen(name);
- if (fmt_helper.on_add_member(name, len))
- return *this; // handled
-
- // assert that we are in an object
- DBUG_ASSERT(!element_started);
- start_element();
-
- output.append('"');
- output.append(name, len);
- output.append("\": ", 3);
- return *this;
+ return add_member(name, len);
}
Json_writer& Json_writer::add_member(const char *name, size_t len)
{
- if (fmt_helper.on_add_member(name, len))
- return *this; // handled
-
- // assert that we are in an object
- DBUG_ASSERT(!element_started);
- start_element();
+ if (!fmt_helper.on_add_member(name, len))
+ {
+ // assert that we are in an object
+ DBUG_ASSERT(!element_started);
+ start_element();
- output.append('"');
- output.append(name, len);
- output.append(STRING_WITH_LEN("\": "));
+ output.append('"');
+ output.append(name, len);
+ output.append(STRING_WITH_LEN("\": "));
+ }
+#if !defined(NDEBUG) || defined(JSON_WRITER_UNIT_TEST)
+ if (!fmt_helper.is_making_writer_calls())
+ got_name= true;
+#endif
return *this;
}
@@ -200,19 +237,14 @@ void Json_writer::add_null()
void Json_writer::add_unquoted_str(const char* str)
{
size_t len= strlen(str);
- if (fmt_helper.on_add_str(str, len))
- return;
-
- if (!element_started)
- start_element();
-
- output.append(str, len);
- element_started= false;
+ add_unquoted_str(str, len);
}
void Json_writer::add_unquoted_str(const char* str, size_t len)
{
- if (fmt_helper.on_add_str(str, len))
+ VALIDITY_ASSERT(fmt_helper.is_making_writer_calls() ||
+ got_name == named_item_expected());
+ if (on_add_str(str, len))
return;
if (!element_started)
@@ -222,19 +254,19 @@ void Json_writer::add_unquoted_str(const char* str, size_t len)
element_started= false;
}
+inline bool Json_writer::on_add_str(const char *str, size_t num_bytes)
+{
+#if !defined(NDEBUG) || defined(JSON_WRITER_UNIT_TEST)
+ got_name= false;
+#endif
+ bool helped= fmt_helper.on_add_str(str, num_bytes);
+ return helped;
+}
+
void Json_writer::add_str(const char *str)
{
size_t len= strlen(str);
- if (fmt_helper.on_add_str(str, len))
- return;
-
- if (!element_started)
- start_element();
-
- output.append('"');
- output.append(str, len);
- output.append('"');
- element_started= false;
+ add_str(str, len);
}
/*
@@ -243,7 +275,9 @@ void Json_writer::add_str(const char *str)
void Json_writer::add_str(const char* str, size_t num_bytes)
{
- if (fmt_helper.on_add_str(str, num_bytes))
+ VALIDITY_ASSERT(fmt_helper.is_making_writer_calls() ||
+ got_name == named_item_expected());
+ if (on_add_str(str, num_bytes))
return;
if (!element_started)
diff --git a/sql/my_json_writer.h b/sql/my_json_writer.h
index d82313f996f..e2d60df4bf5 100644
--- a/sql/my_json_writer.h
+++ b/sql/my_json_writer.h
@@ -17,9 +17,20 @@
#define JSON_WRITER_INCLUDED
#include "my_base.h"
-#include "sql_select.h"
+#if !defined(NDEBUG) || defined(JSON_WRITER_UNIT_TEST) || defined ENABLED_JSON_WRITER_CONSISTENCY_CHECKS
#include <vector>
+#endif
+
+#ifdef JSON_WRITER_UNIT_TEST
+#include "sql_string.h"
+constexpr uint FAKE_SELECT_LEX_ID= UINT_MAX;
+// Also, mock objects are defined in my_json_writer-t.cc
+#define VALIDITY_ASSERT(x) if (!(x)) this->invalid_json= true;
+#else
+#include "sql_select.h"
+#define VALIDITY_ASSERT(x) DBUG_ASSERT(x)
+#endif
class Opt_trace_stmt;
class Opt_trace_context;
@@ -96,9 +107,18 @@ public:
bool on_end_array();
void on_start_object();
// on_end_object() is not needed.
-
+
bool on_add_str(const char *str, size_t num_bytes);
+ /*
+ Returns true if the helper is flushing its buffer and is probably
+ making calls back to its Json_writer. (The Json_writer uses this
+ function to avoid re-doing the processing that it has already done
+ before making a call to fmt_helper)
+ */
+ bool is_making_writer_calls() const { return state == DISABLED; }
+
+private:
void flush_on_one_line();
void disable_and_flush();
};
@@ -185,6 +205,25 @@ private:
class Json_writer
{
+#if !defined(NDEBUG) || defined(JSON_WRITER_UNIT_TEST)
+ /*
+ In debug mode, Json_writer will fail and assertion if one attempts to
+ produce an invalid JSON document (e.g. JSON array having named elements).
+ */
+ std::vector<bool> named_items_expectation;
+
+ bool named_item_expected() const;
+
+ bool got_name;
+
+#ifdef JSON_WRITER_UNIT_TEST
+public:
+ // When compiled for unit test, creating invalid JSON will set this to true
+ // instead of an assertion.
+ bool invalid_json= false;
+#endif
+#endif
+
public:
/* Add a member. We must be in an object. */
Json_writer& add_member(const char *name);
@@ -208,6 +247,10 @@ public:
private:
void add_unquoted_str(const char* val);
void add_unquoted_str(const char* val, size_t len);
+
+ bool on_add_str(const char *str, size_t num_bytes);
+ void on_start_object();
+
public:
/* Start a child object */
void start_object();
@@ -225,6 +268,9 @@ public:
size_t get_truncated_bytes() { return output.get_truncated_bytes(); }
Json_writer() :
+#if !defined(NDEBUG) || defined(JSON_WRITER_UNIT_TEST)
+ got_name(false),
+#endif
indent_level(0), document_start(true), element_started(false),
first_child(true)
{
@@ -312,6 +358,9 @@ public:
/* A common base for Json_writer_object and Json_writer_array */
class Json_writer_struct
{
+ Json_writer_struct(const Json_writer_struct&)= delete;
+ Json_writer_struct& operator=(const Json_writer_struct&)= delete;
+
#ifdef ENABLED_JSON_WRITER_CONSISTENCY_CHECKS
static thread_local std::vector<bool> named_items_expectation;
#endif
@@ -372,24 +421,18 @@ private:
my_writer->add_member(name);
}
public:
- explicit Json_writer_object(THD *thd)
- : Json_writer_struct(thd, true)
- {
-#ifdef ENABLED_JSON_WRITER_CONSISTENCY_CHECKS
- DBUG_ASSERT(!named_item_expected());
-#endif
- if (unlikely(my_writer))
- my_writer->start_object();
- }
-
- explicit Json_writer_object(THD* thd, const char *str)
+ explicit Json_writer_object(THD* thd, const char *str= nullptr)
: Json_writer_struct(thd, true)
{
#ifdef ENABLED_JSON_WRITER_CONSISTENCY_CHECKS
DBUG_ASSERT(named_item_expected());
#endif
if (unlikely(my_writer))
- my_writer->add_member(str).start_object();
+ {
+ if (str)
+ my_writer->add_member(str);
+ my_writer->start_object();
+ }
}
~Json_writer_object()
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 1ab3cbad4af..f896a593d7d 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -7615,7 +7615,7 @@ static int mysql_init_variables(void)
disable_log_notes= 0;
mqh_used= 0;
cleanup_done= 0;
- test_flags= select_errors= dropping_tables= ha_open_options=0;
+ select_errors= dropping_tables= ha_open_options=0;
THD_count::count= CONNECT::count= 0;
slave_open_temp_tables= 0;
opt_endinfo= using_udf_functions= 0;
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 698c709e22e..27d2bb9ca1c 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -370,7 +370,7 @@ TRP_ROR_INTERSECT *get_best_covering_ror_intersect(PARAM *param,
double read_time);
static
TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge,
- double read_time);
+ double read_time, bool named_trace= false);
static
TABLE_READ_PLAN *merge_same_index_scans(PARAM *param, SEL_IMERGE *imerge,
TRP_INDEX_MERGE *imerge_trp,
@@ -5085,7 +5085,7 @@ double get_sweep_read_cost(const PARAM *param, ha_rows records)
static
TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge,
- double read_time)
+ double read_time, bool named_trace)
{
SEL_TREE **ptree;
TRP_INDEX_MERGE *imerge_trp= NULL;
@@ -5133,7 +5133,8 @@ TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge,
n_child_scans)))
DBUG_RETURN(NULL);
- Json_writer_object trace_best_disjunct(thd);
+ const char* trace_best_disjunct_obj_name= named_trace ? "best_disjunct_quick" : nullptr;
+ Json_writer_object trace_best_disjunct(thd, trace_best_disjunct_obj_name);
Json_writer_array to_merge(thd, "indexes_to_merge");
/*
Collect best 'range' scan for each of disjuncts, and, while doing so,
@@ -5489,7 +5490,7 @@ TABLE_READ_PLAN *merge_same_index_scans(PARAM *param, SEL_IMERGE *imerge,
DBUG_ASSERT(imerge->trees_next>imerge->trees);
if (imerge->trees_next-imerge->trees > 1)
- trp= get_best_disjunct_quick(param, imerge, read_time);
+ trp= get_best_disjunct_quick(param, imerge, read_time, true);
else
{
/*
@@ -5677,7 +5678,7 @@ void print_keyparts(THD *thd, KEY *key, uint key_parts)
DBUG_ASSERT(thd->trace_started());
KEY_PART_INFO *part= key->key_part;
- Json_writer_array keyparts= Json_writer_array(thd, "keyparts");
+ Json_writer_array keyparts(thd, "keyparts");
for(uint i= 0; i < key_parts; i++, part++)
keyparts.add(part->field->field_name);
}
diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc
index 859ee5f16ff..dc93535bd87 100644
--- a/sql/opt_subselect.cc
+++ b/sql/opt_subselect.cc
@@ -3839,9 +3839,9 @@ void fix_semijoin_strategies_for_picked_join_order(JOIN *join)
Json_writer_array semijoin_plan(thd, "join_order");
for (i= first + sjm->tables; i <= tablenr; i++)
{
+ Json_writer_object trace_one_table(thd);
if (unlikely(thd->trace_started()))
{
- Json_writer_object trace_one_table(thd);
trace_one_table.add_table_name(join->best_positions[i].table);
}
best_access_path(join, join->best_positions[i].table, rem_tables,
@@ -3878,9 +3878,9 @@ void fix_semijoin_strategies_for_picked_join_order(JOIN *join)
Json_writer_array semijoin_plan(thd, "join_order");
for (idx= first; idx <= tablenr; idx++)
{
+ Json_writer_object trace_one_table(thd);
if (unlikely(thd->trace_started()))
{
- Json_writer_object trace_one_table(thd);
trace_one_table.add_table_name(join->best_positions[idx].table);
}
if (join->best_positions[idx].use_join_buffer)
@@ -3917,9 +3917,9 @@ void fix_semijoin_strategies_for_picked_join_order(JOIN *join)
Json_writer_array semijoin_plan(thd, "join_order");
for (idx= first; idx <= tablenr; idx++)
{
+ Json_writer_object trace_one_table(thd);
if (unlikely(thd->trace_started()))
{
- Json_writer_object trace_one_table(thd);
trace_one_table.add_table_name(join->best_positions[idx].table);
}
if (join->best_positions[idx].use_join_buffer || (idx == first))
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 6ab73458755..297f3eaa5e0 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -7247,15 +7247,16 @@ static bool mysql_inplace_alter_table(THD *thd,
lock for prepare phase under LOCK TABLES in the same way as when
exclusive lock is required for duration of the whole statement.
*/
- if (inplace_supported == HA_ALTER_INPLACE_EXCLUSIVE_LOCK ||
- ((inplace_supported == HA_ALTER_INPLACE_COPY_NO_LOCK ||
+ if (!ha_alter_info->mdl_exclusive_after_prepare &&
+ (inplace_supported == HA_ALTER_INPLACE_EXCLUSIVE_LOCK ||
+ ((inplace_supported == HA_ALTER_INPLACE_COPY_NO_LOCK ||
inplace_supported == HA_ALTER_INPLACE_COPY_LOCK ||
inplace_supported == HA_ALTER_INPLACE_NOCOPY_NO_LOCK ||
inplace_supported == HA_ALTER_INPLACE_NOCOPY_LOCK ||
inplace_supported == HA_ALTER_INPLACE_INSTANT) &&
(thd->locked_tables_mode == LTM_LOCK_TABLES ||
thd->locked_tables_mode == LTM_PRELOCKED_UNDER_LOCK_TABLES)) ||
- alter_info->requested_lock == Alter_info::ALTER_TABLE_LOCK_EXCLUSIVE)
+ alter_info->requested_lock == Alter_info::ALTER_TABLE_LOCK_EXCLUSIVE))
{
if (wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN))
goto cleanup;
diff --git a/storage/innobase/buf/buf0flu.cc b/storage/innobase/buf/buf0flu.cc
index 1f720989f6f..725f18ec25f 100644
--- a/storage/innobase/buf/buf0flu.cc
+++ b/storage/innobase/buf/buf0flu.cc
@@ -972,7 +972,9 @@ static page_id_t buf_flush_check_neighbors(const fil_space_t &space,
page_id_t &id, bool contiguous,
bool lru)
{
- ut_ad(id.page_no() < space.size);
+ ut_ad(id.page_no() < space.size +
+ (space.physical_size() == 2048 ? 1
+ : space.physical_size() == 1024 ? 3 : 0));
/* When flushed, dirty blocks are searched in neighborhoods of this
size, and flushed along with the original page. */
const ulint s= buf_pool.curr_size / 16;
diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc
index 2a5cccca38f..23608749abf 100644
--- a/storage/innobase/handler/handler0alter.cc
+++ b/storage/innobase/handler/handler0alter.cc
@@ -1914,10 +1914,15 @@ innobase_fts_check_doc_id_col(
}
/** Check whether the table is empty.
-@param[in] table table to be checked
+@param[in] table table to be checked
+@param[in] ignore_delete_marked Ignore the delete marked
+ flag record
@return true if table is empty */
-static bool innobase_table_is_empty(const dict_table_t *table)
+static bool innobase_table_is_empty(const dict_table_t *table,
+ bool ignore_delete_marked=true)
{
+ if (!table->space)
+ return false;
dict_index_t *clust_index= dict_table_get_first_index(table);
mtr_t mtr;
btr_pcur_t pcur;
@@ -1955,12 +1960,16 @@ next_page:
}
rec= page_cur_get_rec(cur);
- if (rec_get_deleted_flag(rec, dict_table_is_comp(table)));
- else if (!page_rec_is_supremum(rec))
+ if (rec_get_deleted_flag(rec, dict_table_is_comp(table)))
{
+ if (ignore_delete_marked)
+ goto scan_leaf;
+non_empty:
mtr.commit();
return false;
}
+ else if (!page_rec_is_supremum(rec))
+ goto non_empty;
else
{
next_page= true;
@@ -6753,6 +6762,7 @@ wrong_column_name:
DBUG_ASSERT(num_fts_index <= 1);
DBUG_ASSERT(!ctx->online || num_fts_index == 0);
DBUG_ASSERT(!ctx->online
+ || !ha_alter_info->mdl_exclusive_after_prepare
|| ctx->add_autoinc == ULINT_UNDEFINED);
DBUG_ASSERT(!ctx->online
|| !innobase_need_rebuild(ha_alter_info, old_table)
@@ -7548,6 +7558,20 @@ ha_innobase::prepare_inplace_alter_table(
DBUG_RETURN(false);
}
+#ifdef WITH_PARTITION_STORAGE_ENGINE
+ if (table->part_info == NULL) {
+#endif
+ /* Ignore the MDL downgrade when table is empty.
+ This optimization is disabled for partition table. */
+ ha_alter_info->mdl_exclusive_after_prepare =
+ innobase_table_is_empty(m_prebuilt->table, false);
+ if (ha_alter_info->online
+ && ha_alter_info->mdl_exclusive_after_prepare) {
+ ha_alter_info->online = false;
+ }
+#ifdef WITH_PARTITION_STORAGE_ENGINE
+ }
+#endif
indexed_table = m_prebuilt->table;
/* ALTER TABLE will not implicitly move a table from a single-table
@@ -8344,7 +8368,9 @@ ha_innobase::inplace_alter_table(
DEBUG_SYNC(m_user_thd, "innodb_inplace_alter_table_enter");
- if (!(ha_alter_info->handler_flags & INNOBASE_ALTER_DATA)) {
+ /* Ignore the inplace alter phase when table is empty */
+ if (!(ha_alter_info->handler_flags & INNOBASE_ALTER_DATA)
+ || ha_alter_info->mdl_exclusive_after_prepare) {
ok_exit:
DEBUG_SYNC(m_user_thd, "innodb_after_inplace_alter_table");
DBUG_RETURN(false);
diff --git a/unittest/sql/CMakeLists.txt b/unittest/sql/CMakeLists.txt
index b7923511b97..b8682de74c3 100644
--- a/unittest/sql/CMakeLists.txt
+++ b/unittest/sql/CMakeLists.txt
@@ -29,3 +29,8 @@ ADD_EXECUTABLE(mf_iocache-t mf_iocache-t.cc ../../sql/mf_iocache_encr.cc)
TARGET_LINK_LIBRARIES(mf_iocache-t mysys mytap mysys_ssl)
ADD_DEPENDENCIES(mf_iocache-t GenError)
MY_ADD_TEST(mf_iocache)
+
+# Json writer needs String which needs sql library
+ADD_EXECUTABLE(my_json_writer-t my_json_writer-t.cc dummy_builtins.cc)
+TARGET_LINK_LIBRARIES(my_json_writer-t sql mytap)
+MY_ADD_TEST(my_json_writer)
diff --git a/unittest/sql/my_json_writer-t.cc b/unittest/sql/my_json_writer-t.cc
new file mode 100644
index 00000000000..6398a589c33
--- /dev/null
+++ b/unittest/sql/my_json_writer-t.cc
@@ -0,0 +1,128 @@
+/*
+ Copyright (c) 2021, MariaDB Corporation.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */
+
+#include <my_global.h>
+#include <my_pthread.h>
+#include <my_sys.h>
+#include <stdio.h>
+#include <tap.h>
+
+/*
+ Unit tests for class Json_writer. At the moment there are only tests for the
+ "Fail an assertion if one attempts to produce invalid JSON" feature.
+*/
+
+struct TABLE;
+struct JOIN_TAB;
+class Json_writer;
+
+
+/* Several fake objects */
+class Opt_trace
+{
+public:
+ void enable_tracing_if_required() {}
+ void disable_tracing_if_required() {}
+ Json_writer *get_current_json() { return nullptr; }
+};
+
+class THD
+{
+public:
+ Opt_trace opt_trace;
+};
+
+#define JSON_WRITER_UNIT_TEST
+#include "../sql/my_json_writer.h"
+#include "../sql/my_json_writer.cc"
+
+int main(int args, char **argv)
+{
+ plan(NO_PLAN);
+ diag("Testing Json_writer checks");
+
+ {
+ Json_writer w;
+ w.start_object();
+ w.add_member("foo");
+ w.end_object();
+ ok(w.invalid_json, "Started a name but didn't add a value");
+ }
+
+ {
+ Json_writer w;
+ w.start_object();
+ w.add_ull(123);
+ ok(w.invalid_json, "Unnamed value in an object");
+ }
+
+ {
+ Json_writer w;
+ w.start_array();
+ w.add_member("bebebe").add_ull(345);
+ ok(w.invalid_json, "Named member in array");
+ }
+
+ {
+ Json_writer w;
+ w.start_object();
+ w.start_array();
+ ok(w.invalid_json, "Unnamed array in an object");
+ }
+
+ {
+ Json_writer w;
+ w.start_object();
+ w.start_object();
+ ok(w.invalid_json, "Unnamed object in an object");
+ }
+
+ {
+ Json_writer w;
+ w.start_array();
+ w.add_member("zzz");
+ w.start_object();
+ ok(w.invalid_json, "Named object in an array");
+ }
+ {
+ Json_writer w;
+ w.start_array();
+ w.add_member("zzz");
+ w.start_array();
+ ok(w.invalid_json, "Named array in an array");
+ }
+
+ {
+ Json_writer w;
+ w.start_array();
+ w.end_object();
+ ok(w.invalid_json, "JSON object end of array");
+ }
+
+ {
+ Json_writer w;
+ w.start_object();
+ w.end_array();
+ ok(w.invalid_json, "JSON array end of object");
+ }
+
+
+
+ diag("Done");
+
+ return exit_status();
+}
+