diff --git a/client/client_priv.h b/client/client_priv.h
index 039b008c883..cde3a4c51e2 100644
--- a/client/client_priv.h
+++ b/client/client_priv.h
@@ -1,6 +1,6 @@
/*
Copyright (c) 2001, 2012, Oracle and/or its affiliates.
- Copyright (c) 2009, 2020, MariaDB
+ Copyright (c) 2009, 2022, MariaDB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -102,6 +102,7 @@ enum options_client
OPT_IGNORE_DATA,
OPT_PRINT_ROW_COUNT, OPT_PRINT_ROW_EVENT_POSITIONS,
OPT_CHECK_IF_UPGRADE_NEEDED,
+ OPT_COMPATIBILTY_CLEARTEXT_PLUGIN,
OPT_SHUTDOWN_WAIT_FOR_SLAVES,
OPT_COPY_S3_TABLES,
OPT_PRINT_TABLE_METADATA,
diff --git a/client/mysql.cc b/client/mysql.cc
index 37f506a99cd..db0780cba74 100644
--- a/client/mysql.cc
+++ b/client/mysql.cc
@@ -1527,6 +1527,8 @@ static struct my_option my_long_options[] =
&delimiter_str, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"execute", 'e', "Execute command and quit. (Disables --force and history file.)", 0,
0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"enable-cleartext-plugin", OPT_COMPATIBILTY_CLEARTEXT_PLUGIN, "Obsolete option. Exists only for MySQL compatibility.",
+ 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{"vertical", 'E', "Print the output of a query (rows) vertically.",
&vertical, &vertical, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0,
0},
@@ -1836,6 +1838,14 @@ get_one_option(const struct my_option *opt, const char *argument, const char *fi
printf("WARNING: --server-arg option not supported in this configuration.\n");
#endif
break;
+ case OPT_COMPATIBILTY_CLEARTEXT_PLUGIN:
+ /*
+ This option exists in MySQL client but not in MariaDB. Users switching from
+ MySQL might still have this option in their commands, and it will not work
+ in MariaDB unless it is handled. Therefore output a warning and continue.
+ */
+ printf("WARNING: option '--enable-cleartext-plugin' is obsolete.\n");
+ break;
case 'A':
opt_rehash= 0;
break;
diff --git a/extra/mariabackup/ds_compress.cc b/extra/mariabackup/ds_compress.cc
index 40566a1a8b1..eed3467b7f4 100644
--- a/extra/mariabackup/ds_compress.cc
+++ b/extra/mariabackup/ds_compress.cc
@@ -1,5 +1,6 @@
/******************************************************
Copyright (c) 2011-2013 Percona LLC and/or its affiliates.
+Copyright (c) 2022, MariaDB Corporation.
Compressing datasink implementation for XtraBackup.
@@ -32,11 +33,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA
typedef struct {
pthread_t id;
uint num;
- pthread_mutex_t ctrl_mutex;
- pthread_cond_t ctrl_cond;
pthread_mutex_t data_mutex;
pthread_cond_t data_cond;
- my_bool started;
my_bool data_avail;
my_bool cancelled;
const char *from;
@@ -206,14 +204,13 @@ compress_write(ds_file_t *file, const uchar *buf, size_t len)
thd = threads + i;
- pthread_mutex_lock(&thd->ctrl_mutex);
+ pthread_mutex_lock(&thd->data_mutex);
chunk_len = (len > COMPRESS_CHUNK_SIZE) ?
COMPRESS_CHUNK_SIZE : len;
thd->from = ptr;
thd->from_len = chunk_len;
- pthread_mutex_lock(&thd->data_mutex);
thd->data_avail = TRUE;
pthread_cond_signal(&thd->data_cond);
pthread_mutex_unlock(&thd->data_mutex);
@@ -239,26 +236,24 @@ compress_write(ds_file_t *file, const uchar *buf, size_t len)
xb_a(threads[i].to_len > 0);
- if (ds_write(dest_file, "NEWBNEWB", 8) ||
- write_uint64_le(dest_file,
- comp_file->bytes_processed)) {
- msg("compress: write to the destination stream "
- "failed.");
- return 1;
- }
-
+ bool fail = ds_write(dest_file, "NEWBNEWB", 8) ||
+ write_uint64_le(dest_file,
+ comp_file->bytes_processed);
comp_file->bytes_processed += threads[i].from_len;
- if (write_uint32_le(dest_file, threads[i].adler) ||
- ds_write(dest_file, threads[i].to,
- threads[i].to_len)) {
- msg("compress: write to the destination stream "
- "failed.");
- return 1;
+ if (!fail) {
+ fail = write_uint32_le(dest_file, threads[i].adler) ||
+ ds_write(dest_file, threads[i].to,
+ threads[i].to_len);
}
pthread_mutex_unlock(&threads[i].data_mutex);
- pthread_mutex_unlock(&threads[i].ctrl_mutex);
+
+ if (fail) {
+ msg("compress: write to the destination stream "
+ "failed.");
+ return 1;
+ }
}
}
@@ -328,6 +323,23 @@ write_uint64_le(ds_file_t *file, ulonglong n)
return ds_write(file, tmp, sizeof(tmp));
}
+static
+void
+destroy_worker_thread(comp_thread_ctxt_t *thd)
+{
+ pthread_mutex_lock(&thd->data_mutex);
+ thd->cancelled = TRUE;
+ pthread_cond_signal(&thd->data_cond);
+ pthread_mutex_unlock(&thd->data_mutex);
+
+ pthread_join(thd->id, NULL);
+
+ pthread_cond_destroy(&thd->data_cond);
+ pthread_mutex_destroy(&thd->data_mutex);
+
+ my_free(thd->to);
+}
+
static
comp_thread_ctxt_t *
create_worker_threads(uint n)
@@ -342,53 +354,31 @@ create_worker_threads(uint n)
comp_thread_ctxt_t *thd = threads + i;
thd->num = i + 1;
- thd->started = FALSE;
thd->cancelled = FALSE;
thd->data_avail = FALSE;
thd->to = (char *) my_malloc(PSI_NOT_INSTRUMENTED,
COMPRESS_CHUNK_SIZE + MY_QLZ_COMPRESS_OVERHEAD, MYF(MY_FAE));
- /* Initialize the control mutex and condition var */
- if (pthread_mutex_init(&thd->ctrl_mutex, NULL) ||
- pthread_cond_init(&thd->ctrl_cond, NULL)) {
- goto err;
- }
-
/* Initialize and data mutex and condition var */
if (pthread_mutex_init(&thd->data_mutex, NULL) ||
pthread_cond_init(&thd->data_cond, NULL)) {
goto err;
}
- pthread_mutex_lock(&thd->ctrl_mutex);
-
if (pthread_create(&thd->id, NULL, compress_worker_thread_func,
thd)) {
msg("compress: pthread_create() failed: "
"errno = %d", errno);
- pthread_mutex_unlock(&thd->ctrl_mutex);
goto err;
}
}
- /* Wait for the threads to start */
- for (i = 0; i < n; i++) {
- comp_thread_ctxt_t *thd = threads + i;
-
- while (thd->started == FALSE)
- pthread_cond_wait(&thd->ctrl_cond, &thd->ctrl_mutex);
- pthread_mutex_unlock(&thd->ctrl_mutex);
- }
-
return threads;
err:
- while (i > 0) {
- comp_thread_ctxt_t *thd;
- i--;
- thd = threads + i;
- pthread_mutex_unlock(&thd->ctrl_mutex);
+ for (; i; i--) {
+ destroy_worker_thread(threads + i);
}
my_free(threads);
@@ -402,21 +392,7 @@ destroy_worker_threads(comp_thread_ctxt_t *threads, uint n)
uint i;
for (i = 0; i < n; i++) {
- comp_thread_ctxt_t *thd = threads + i;
-
- pthread_mutex_lock(&thd->data_mutex);
- threads[i].cancelled = TRUE;
- pthread_cond_signal(&thd->data_cond);
- pthread_mutex_unlock(&thd->data_mutex);
-
- pthread_join(thd->id, NULL);
-
- pthread_cond_destroy(&thd->data_cond);
- pthread_mutex_destroy(&thd->data_mutex);
- pthread_cond_destroy(&thd->ctrl_cond);
- pthread_mutex_destroy(&thd->ctrl_mutex);
-
- my_free(thd->to);
+ destroy_worker_thread(threads + i);
}
my_free(threads);
@@ -428,19 +404,9 @@ compress_worker_thread_func(void *arg)
{
comp_thread_ctxt_t *thd = (comp_thread_ctxt_t *) arg;
- pthread_mutex_lock(&thd->ctrl_mutex);
-
pthread_mutex_lock(&thd->data_mutex);
- thd->started = TRUE;
- pthread_cond_signal(&thd->ctrl_cond);
-
- pthread_mutex_unlock(&thd->ctrl_mutex);
-
while (1) {
- thd->data_avail = FALSE;
- pthread_cond_signal(&thd->data_cond);
-
while (!thd->data_avail && !thd->cancelled) {
pthread_cond_wait(&thd->data_cond, &thd->data_mutex);
}
diff --git a/extra/mariabackup/xtrabackup.cc b/extra/mariabackup/xtrabackup.cc
index 528dbaac898..06c4eccd3d6 100644
--- a/extra/mariabackup/xtrabackup.cc
+++ b/extra/mariabackup/xtrabackup.cc
@@ -584,8 +584,8 @@ void CorruptedPages::zero_out_free_pages()
space_it->second.pages.begin();
page_it != space_it->second.pages.end(); ++page_it)
{
- bool is_free= fseg_page_is_free(space, *page_it);
- if (!is_free) {
+ if (fseg_page_is_allocated(space, *page_it))
+ {
space_info_t &space_info = non_free_pages[space_id];
space_info.pages.insert(*page_it);
if (space_info.space_name.empty())
diff --git a/man/mysql.1 b/man/mysql.1
index 8e36acdd3be..dc93ef8092e 100644
--- a/man/mysql.1
+++ b/man/mysql.1
@@ -507,6 +507,21 @@ the section called \(lqMYSQL COMMANDS\(rq\&.
.sp -1
.IP \(bu 2.3
.\}
+.\" mysql: enable cleartext plugin option
+.\" enable cleartext plugin option: mysql
+\fB\-\-enable\-cleartext\-plugin\fR
+.sp
+Obsolete option\&. Exists only for MySQL compatibility\&.
+.RE
+.sp
+.RS 4
+.ie n \{\
+\h'-04'\(bu\h'+03'\c
+.\}
+.el \{\
+.sp -1
+.IP \(bu 2.3
+.\}
.\" mysql: execute option
.\" execute option: mysql
\fB\-\-execute=\fR\fB\fIstatement\fR\fR,
diff --git a/mysql-test/include/not_valgrind.inc b/mysql-test/include/not_valgrind.inc
index 8bda3497878..a2372db4c4f 100644
--- a/mysql-test/include/not_valgrind.inc
+++ b/mysql-test/include/not_valgrind.inc
@@ -1,4 +1,4 @@
--require include/not_valgrind.require
--disable_query_log
-eval select $VALGRIND_TEST as using_valgrind;
+eval select $VALGRIND_TEST+0 as using_valgrind;
--enable_query_log
diff --git a/mysql-test/main/alter_table.result b/mysql-test/main/alter_table.result
index e9977bd0d5e..4a88aead022 100644
--- a/mysql-test/main/alter_table.result
+++ b/mysql-test/main/alter_table.result
@@ -1,5 +1,3 @@
-drop table if exists t1,t2;
-drop database if exists mysqltest;
set @save_max_allowed_packet=@@global.max_allowed_packet;
create table t1 (
col1 int not null auto_increment primary key,
@@ -2588,22 +2586,6 @@ set max_statement_time= 0;
drop table t1;
drop view v1;
#
-# MDEV-25803 Inplace ALTER breaks MyISAM/Aria tables when order of keys is changed
-#
-set @save_default_engine= @@default_storage_engine;
-create or replace table t1 (x int, y int, unique (y), unique (x), primary key(x)) engine myisam;
-alter table t1 change x xx int, algorithm=inplace;
-check table t1;
-Table Op Msg_type Msg_text
-test.t1 check status OK
-create or replace table t1 (x int, y int, unique (y), unique (x), primary key(x));
-alter table t1 change x xx int, algorithm=inplace;
-check table t1;
-Table Op Msg_type Msg_text
-test.t1 check status OK
-drop table t1;
-set @@default_storage_engine= @save_default_engine;
-#
# End of 10.3 tests
#
#
@@ -2650,296 +2632,6 @@ DROP TABLE t1;
# End of 10.4 tests
#
#
-# MDEV-16290 ALTER TABLE ... RENAME COLUMN syntax
-#
-SET @save_default_engine= @@DEFAULT_STORAGE_ENGINE;
-CREATE TABLE t1(a INT, b VARCHAR(30), c FLOAT);
-SHOW CREATE TABLE t1;
-Table Create Table
-t1 CREATE TABLE `t1` (
- `a` int(11) DEFAULT NULL,
- `b` varchar(30) DEFAULT NULL,
- `c` float DEFAULT NULL
-) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1
-INSERT INTO t1 VALUES(1,'abcd',1.234);
-CREATE TABLE t2(a INT, b VARCHAR(30), c FLOAT) ENGINE=MyIsam;
-SHOW CREATE TABLE t2;
-Table Create Table
-t2 CREATE TABLE `t2` (
- `a` int(11) DEFAULT NULL,
- `b` varchar(30) DEFAULT NULL,
- `c` float DEFAULT NULL
-) ENGINE=MyISAM DEFAULT CHARSET=latin1
-INSERT INTO t2 VALUES(1,'abcd',1.234);
-ALTER TABLE t1 RENAME COLUMN a TO a;
-SHOW CREATE TABLE t1;
-Table Create Table
-t1 CREATE TABLE `t1` (
- `a` int(11) DEFAULT NULL,
- `b` varchar(30) DEFAULT NULL,
- `c` float DEFAULT NULL
-) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1
-ALTER TABLE t1 RENAME COLUMN a TO m;
-ALTER TABLE t1 RENAME COLUMN a TO m;
-ERROR 42S22: Unknown column 'a' in 't1'
-ALTER TABLE t1 RENAME COLUMN IF EXISTS a TO m;
-Warnings:
-Note 1054 Unknown column 'a' in 't1'
-SHOW CREATE TABLE t1;
-Table Create Table
-t1 CREATE TABLE `t1` (
- `m` int(11) DEFAULT NULL,
- `b` varchar(30) DEFAULT NULL,
- `c` float DEFAULT NULL
-) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1
-SELECT * FROM t1;
-m b c
-1 abcd 1.234
-ALTER TABLE t1 RENAME COLUMN m TO x,
-RENAME COLUMN b TO y,
-RENAME COLUMN c TO z;
-SHOW CREATE TABLE t1;
-Table Create Table
-t1 CREATE TABLE `t1` (
- `x` int(11) DEFAULT NULL,
- `y` varchar(30) DEFAULT NULL,
- `z` float DEFAULT NULL
-) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1
-SELECT * FROM t1;
-x y z
-1 abcd 1.234
-ALTER TABLE t2 RENAME COLUMN a TO d, RENAME COLUMN b TO e, RENAME COLUMN c to f;
-SHOW CREATE TABLE t2;
-Table Create Table
-t2 CREATE TABLE `t2` (
- `d` int(11) DEFAULT NULL,
- `e` varchar(30) DEFAULT NULL,
- `f` float DEFAULT NULL
-) ENGINE=MyISAM DEFAULT CHARSET=latin1
-SELECT * FROM t2;
-d e f
-1 abcd 1.234
-ALTER TABLE t1 CHANGE COLUMN x a INT, RENAME COLUMN y TO b;
-SHOW CREATE TABLE t1;
-Table Create Table
-t1 CREATE TABLE `t1` (
- `a` int(11) DEFAULT NULL,
- `b` varchar(30) DEFAULT NULL,
- `z` float DEFAULT NULL
-) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1
-ALTER TABLE t1 CHANGE COLUMN z c DOUBLE, RENAME COLUMN b to b;
-SHOW CREATE TABLE t1;
-Table Create Table
-t1 CREATE TABLE `t1` (
- `a` int(11) DEFAULT NULL,
- `b` varchar(30) DEFAULT NULL,
- `c` double DEFAULT NULL
-) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1
-ALTER TABLE t1 CHANGE COLUMN a b int, RENAME COLUMN b TO c, CHANGE COLUMN c d FLOAT;
-SHOW CREATE TABLE t1;
-Table Create Table
-t1 CREATE TABLE `t1` (
- `b` int(11) DEFAULT NULL,
- `c` varchar(30) DEFAULT NULL,
- `d` float DEFAULT NULL
-) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1
-ALTER TABLE t1 ADD COLUMN zz INT, RENAME COLUMN d TO f;
-SHOW CREATE TABLE t1;
-Table Create Table
-t1 CREATE TABLE `t1` (
- `b` int(11) DEFAULT NULL,
- `c` varchar(30) DEFAULT NULL,
- `f` float DEFAULT NULL,
- `zz` int(11) DEFAULT NULL
-) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1
-ALTER TABLE t1 DROP COLUMN zz, RENAME COLUMN c TO zz;
-SHOW CREATE TABLE t1;
-Table Create Table
-t1 CREATE TABLE `t1` (
- `b` int(11) DEFAULT NULL,
- `zz` varchar(30) DEFAULT NULL,
- `f` float DEFAULT NULL
-) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1
-ALTER TABLE t1 RENAME COLUMN zz to c, DROP COLUMN f;
-SHOW CREATE TABLE t1;
-Table Create Table
-t1 CREATE TABLE `t1` (
- `b` int(11) DEFAULT NULL,
- `c` varchar(30) DEFAULT NULL
-) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1
-ALTER TABLE t1 ADD COLUMN d INT DEFAULT 5, RENAME COLUMN c TO b, DROP COLUMN b;
-SHOW CREATE TABLE t1;
-Table Create Table
-t1 CREATE TABLE `t1` (
- `b` varchar(30) DEFAULT NULL,
- `d` int(11) DEFAULT 5
-) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1
-ALTER TABLE t1 RENAME COLUMN b TO d, RENAME COLUMN d TO b;
-SHOW CREATE TABLE t1;
-Table Create Table
-t1 CREATE TABLE `t1` (
- `d` varchar(30) DEFAULT NULL,
- `b` int(11) DEFAULT 5
-) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1
-ALTER TABLE t1 ADD KEY(b);
-SHOW CREATE TABLE t1;
-Table Create Table
-t1 CREATE TABLE `t1` (
- `d` varchar(30) DEFAULT NULL,
- `b` int(11) DEFAULT 5,
- KEY `b` (`b`)
-) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1
-ALTER TABLE t1 RENAME COLUMN b TO bb;
-SHOW CREATE TABLE t1;
-Table Create Table
-t1 CREATE TABLE `t1` (
- `d` varchar(30) DEFAULT NULL,
- `bb` int(11) DEFAULT 5,
- KEY `b` (`bb`)
-) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1
-SELECT * FROM t1;
-d bb
-abcd 5
-CREATE TABLE t3(a int, b int, KEY(b));
-ALTER TABLE t3 ADD CONSTRAINT FOREIGN KEY(b) REFERENCES t1(bb);
-SHOW CREATE TABLE t3;
-Table Create Table
-t3 CREATE TABLE `t3` (
- `a` int(11) DEFAULT NULL,
- `b` int(11) DEFAULT NULL,
- KEY `b` (`b`),
- CONSTRAINT `t3_ibfk_1` FOREIGN KEY (`b`) REFERENCES `t1` (`bb`)
-) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1
-ALTER TABLE t1 RENAME COLUMN bb TO b;
-SHOW CREATE TABLE t1;
-Table Create Table
-t1 CREATE TABLE `t1` (
- `d` varchar(30) DEFAULT NULL,
- `b` int(11) DEFAULT 5,
- KEY `b` (`b`)
-) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1
-ALTER TABLE t3 RENAME COLUMN b TO c;
-SHOW CREATE TABLE t3;
-Table Create Table
-t3 CREATE TABLE `t3` (
- `a` int(11) DEFAULT NULL,
- `c` int(11) DEFAULT NULL,
- KEY `b` (`c`),
- CONSTRAINT `t3_ibfk_1` FOREIGN KEY (`c`) REFERENCES `t1` (`b`)
-) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1
-CREATE TABLE t4(a int);
-ALTER TABLE t4 RENAME COLUMN a TO aa, ALGORITHM = INPLACE;
-SHOW CREATE TABLE t4;
-Table Create Table
-t4 CREATE TABLE `t4` (
- `aa` int(11) DEFAULT NULL
-) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1
-ALTER TABLE t4 RENAME COLUMN aa TO a, ALGORITHM = COPY;
-SHOW CREATE TABLE t4;
-Table Create Table
-t4 CREATE TABLE `t4` (
- `a` int(11) DEFAULT NULL
-) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1
-DROP TABLE t4;
-CREATE VIEW v1 AS SELECT d,e,f FROM t2;
-CREATE TRIGGER trg1 BEFORE UPDATE on t2 FOR EACH ROW SET NEW.d=OLD.d + 10;
-CREATE PROCEDURE sp1() INSERT INTO t2(d) VALUES(10);
-ALTER TABLE t2 RENAME COLUMN d TO g;
-SHOW CREATE TABLE t2;
-Table Create Table
-t2 CREATE TABLE `t2` (
- `g` int(11) DEFAULT NULL,
- `e` varchar(30) DEFAULT NULL,
- `f` float DEFAULT NULL
-) ENGINE=MyISAM DEFAULT CHARSET=latin1
-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`.`t2`.`d` AS `d`,`test`.`t2`.`e` AS `e`,`test`.`t2`.`f` AS `f` from `t2` koi8r koi8r_general_ci
-Warnings:
-Warning 1356 View 'test.v1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
-SELECT * FROM v1;
-ERROR HY000: View 'test.v1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
-UPDATE t2 SET f = f + 10;
-ERROR 42S22: Unknown column 'd' in 'OLD'
-CALL sp1();
-ERROR 42S22: Unknown column 'd' in 'field list'
-DROP TRIGGER trg1;
-DROP PROCEDURE sp1;
-CREATE TABLE t_gen(a INT, b DOUBLE GENERATED ALWAYS AS (SQRT(a)));
-INSERT INTO t_gen(a) VALUES(4);
-SELECT * FROM t_gen;
-a b
-4 2
-SHOW CREATE TABLE t_gen;
-Table Create Table
-t_gen CREATE TABLE `t_gen` (
- `a` int(11) DEFAULT NULL,
- `b` double GENERATED ALWAYS AS (sqrt(`a`)) VIRTUAL
-) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1
-ALTER TABLE t_gen RENAME COLUMN a TO c, CHANGE COLUMN b b DOUBLE GENERATED ALWAYS AS (SQRT(c));
-SELECT * FROM t_gen;
-c b
-4 2
-SHOW CREATE TABLE t_gen;
-Table Create Table
-t_gen CREATE TABLE `t_gen` (
- `c` int(11) DEFAULT NULL,
- `b` double GENERATED ALWAYS AS (sqrt(`c`)) VIRTUAL
-) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1
-ALTER TABLE t_gen CHANGE COLUMN c x INT;
-show create table t_gen;
-Table Create Table
-t_gen CREATE TABLE `t_gen` (
- `x` int(11) DEFAULT NULL,
- `b` double GENERATED ALWAYS AS (sqrt(`x`)) VIRTUAL
-) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1
-ALTER TABLE t_gen RENAME COLUMN x TO a;
-DROP TABLE t_gen;
-SHOW CREATE TABLE t1;
-Table Create Table
-t1 CREATE TABLE `t1` (
- `d` varchar(30) DEFAULT NULL,
- `b` int(11) DEFAULT 5,
- KEY `b` (`b`)
-) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1
-ALTER TABLE t1 RENAME COLUMN b z;
-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 'z' at line 1
-ALTER TABLE t1 RENAME COLUMN FROM b TO z;
-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 'FROM b TO z' at line 1
-ALTER TABLE t1 RENAME COLUMN b TO 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 '1' at line 1
-ALTER TABLE t1 RENAME COLUMN b TO e, RENAME COLUMN c TO e;
-ERROR 42S22: Unknown column 'c' in 't1'
-ALTER TABLE t1 ADD COLUMN z INT, RENAME COLUMN b TO z;
-ERROR 42S21: Duplicate column name 'z'
-ALTER TABLE t1 DROP COLUMN b, RENAME COLUMN b TO z;
-ERROR 42S22: Unknown column 'b' in 't1'
-ALTER TABLE t1 RENAME COLUMN b TO b, RENAME COLUMN b TO b;
-ERROR 42S22: Unknown column 'b' in 't1'
-ALTER TABLE t1 RENAME COLUMN b TO c3, DROP COLUMN c3;
-ERROR 42000: Can't DROP COLUMN `c3`; check that it exists
-ALTER TABLE t1 ADD COLUMN z INT, CHANGE COLUMN z y INT, DROP COLUMN y;
-ERROR 42S22: Unknown column 'z' in 't1'
-ALTER TABLE t1 ADD COLUMN z INT, RENAME COLUMN z TO y, DROP COLUMN y;
-ERROR 42S22: Unknown column 'z' in 't1'
-ALTER TABLE t1 RENAME COLUMN b TO `nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn`;
-ERROR 42000: Incorrect column name 'nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn'
-ALTER TABLE t1 CHANGE b `nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn` int;
-ERROR 42000: Identifier name 'nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn' is too long
-SHOW CREATE TABLE t1;
-Table Create Table
-t1 CREATE TABLE `t1` (
- `d` varchar(30) DEFAULT NULL,
- `b` int(11) DEFAULT 5,
- KEY `b` (`b`)
-) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1
-SELECT * FROM t1;
-d b
-abcd 5
-DROP VIEW v1;
-DROP TABLE t3,t1,t2;
-SET DEFAULT_STORAGE_ENGINE= @save_default_engine;
-#
# MDEV-7318 RENAME INDEX
#
#
@@ -3389,22 +3081,6 @@ t1 CREATE TABLE `t1` (
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
#
-# MDEV-25803 Inplace ALTER breaks MyISAM/Aria tables when order of keys is changed
-#
-set @save_default_engine= @@default_storage_engine;
-create or replace table t1 (x int, y int, unique (y), unique (x), primary key(x)) engine myisam;
-alter table t1 change x xx int, algorithm=inplace;
-check table t1;
-Table Op Msg_type Msg_text
-test.t1 check status OK
-create or replace table t1 (x int, y int, unique (y), unique (x), primary key(x));
-alter table t1 change x xx int, algorithm=inplace;
-check table t1;
-Table Op Msg_type Msg_text
-test.t1 check status OK
-drop table t1;
-set @@default_storage_engine= @save_default_engine;
-#
# MDEV-25555 Server crashes in tree_record_pos after INPLACE-recreating index on HEAP table
#
create table t1 (a int, key idx1(a), key idx2 using btree(a)) engine=memory;
diff --git a/mysql-test/main/alter_table.test b/mysql-test/main/alter_table.test
index 31c69783248..05e04f11f9e 100644
--- a/mysql-test/main/alter_table.test
+++ b/mysql-test/main/alter_table.test
@@ -2,10 +2,6 @@
#
# Test of alter table
#
---disable_warnings
-drop table if exists t1,t2;
-drop database if exists mysqltest;
---enable_warnings
set @save_max_allowed_packet=@@global.max_allowed_packet;
create table t1 (
@@ -2099,47 +2095,6 @@ set max_statement_time= 0;
drop table t1;
drop view v1;
---echo #
---echo # MDEV-25803 Inplace ALTER breaks MyISAM/Aria tables when order of keys is changed
---echo #
-set @save_default_engine= @@default_storage_engine;
---disable_query_log
-if ($MTR_COMBINATION_INNODB)
-{
- set default_storage_engine= innodb;
-}
-if ($MTR_COMBINATION_ARIA)
-{
- set default_storage_engine= aria;
-}
---enable_query_log
-
-if (!$MTR_COMBINATION_INNODB)
-{
- --disable_query_log
- --disable_result_log
- # There is no inplace ADD INDEX for MyISAM/Aria:
- create or replace table t1 (x int);
- --error ER_ALTER_OPERATION_NOT_SUPPORTED
- alter table t1 add unique (x), algorithm=inplace;
- --error ER_ALTER_OPERATION_NOT_SUPPORTED
- alter table t1 add primary key(x), algorithm=inplace;
- --error ER_ALTER_OPERATION_NOT_SUPPORTED
- alter table t1 add index(x), algorithm=inplace;
- --enable_query_log
- --enable_result_log
-}
-
-create or replace table t1 (x int, y int, unique (y), unique (x), primary key(x)) engine myisam;
-alter table t1 change x xx int, algorithm=inplace;
-check table t1;
-create or replace table t1 (x int, y int, unique (y), unique (x), primary key(x));
-alter table t1 change x xx int, algorithm=inplace;
-check table t1;
-# cleanup
-drop table t1;
-set @@default_storage_engine= @save_default_engine;
-
--echo #
--echo # End of 10.3 tests
--echo #
@@ -2192,205 +2147,6 @@ DROP TABLE t1;
--echo # End of 10.4 tests
--echo #
---echo #
---echo # MDEV-16290 ALTER TABLE ... RENAME COLUMN syntax
---echo #
-SET @save_default_engine= @@DEFAULT_STORAGE_ENGINE;
---disable_query_log
-if ($MTR_COMBINATION_INNODB)
-{
-SET DEFAULT_STORAGE_ENGINE= INNODB;
-}
-if ($MTR_COMBINATION_ARIA)
-{
-SET DEFAULT_STORAGE_ENGINE= ARIA;
-}
-if ($MTR_COMBINATION_HEAP)
-{
-SET DEFAULT_STORAGE_ENGINE= MEMORY;
-}
---enable_query_log
-let $default_engine= `select @@default_storage_engine`;
-
-CREATE TABLE t1(a INT, b VARCHAR(30), c FLOAT);
---replace_result $default_engine DEFAULT_ENGINE " PAGE_CHECKSUM=1" ""
-SHOW CREATE TABLE t1;
-INSERT INTO t1 VALUES(1,'abcd',1.234);
-CREATE TABLE t2(a INT, b VARCHAR(30), c FLOAT) ENGINE=MyIsam;
-SHOW CREATE TABLE t2;
-INSERT INTO t2 VALUES(1,'abcd',1.234);
-
-# Rename one column
-ALTER TABLE t1 RENAME COLUMN a TO a;
---replace_result $default_engine DEFAULT_ENGINE " PAGE_CHECKSUM=1" ""
-SHOW CREATE TABLE t1;
-ALTER TABLE t1 RENAME COLUMN a TO m;
---error ER_BAD_FIELD_ERROR
-ALTER TABLE t1 RENAME COLUMN a TO m;
-ALTER TABLE t1 RENAME COLUMN IF EXISTS a TO m;
---replace_result $default_engine DEFAULT_ENGINE " PAGE_CHECKSUM=1" ""
-SHOW CREATE TABLE t1;
-SELECT * FROM t1;
-
-# Rename multiple column
-ALTER TABLE t1 RENAME COLUMN m TO x,
- RENAME COLUMN b TO y,
- RENAME COLUMN c TO z;
---replace_result $default_engine DEFAULT_ENGINE " PAGE_CHECKSUM=1" ""
-SHOW CREATE TABLE t1;
-SELECT * FROM t1;
-
-# Rename multiple columns with MyIsam Engine
-ALTER TABLE t2 RENAME COLUMN a TO d, RENAME COLUMN b TO e, RENAME COLUMN c to f;
-SHOW CREATE TABLE t2;
-SELECT * FROM t2;
-
-# Mix different ALTER operations with RENAME COLUMN
-ALTER TABLE t1 CHANGE COLUMN x a INT, RENAME COLUMN y TO b;
---replace_result $default_engine DEFAULT_ENGINE " PAGE_CHECKSUM=1" ""
-SHOW CREATE TABLE t1;
-ALTER TABLE t1 CHANGE COLUMN z c DOUBLE, RENAME COLUMN b to b;
---replace_result $default_engine DEFAULT_ENGINE " PAGE_CHECKSUM=1" ""
-SHOW CREATE TABLE t1;
-ALTER TABLE t1 CHANGE COLUMN a b int, RENAME COLUMN b TO c, CHANGE COLUMN c d FLOAT;
---replace_result $default_engine DEFAULT_ENGINE " PAGE_CHECKSUM=1" ""
-SHOW CREATE TABLE t1;
-ALTER TABLE t1 ADD COLUMN zz INT, RENAME COLUMN d TO f;
---replace_result $default_engine DEFAULT_ENGINE " PAGE_CHECKSUM=1" ""
-SHOW CREATE TABLE t1;
-ALTER TABLE t1 DROP COLUMN zz, RENAME COLUMN c TO zz;
---replace_result $default_engine DEFAULT_ENGINE " PAGE_CHECKSUM=1" ""
-SHOW CREATE TABLE t1;
-ALTER TABLE t1 RENAME COLUMN zz to c, DROP COLUMN f;
---replace_result $default_engine DEFAULT_ENGINE " PAGE_CHECKSUM=1" ""
-SHOW CREATE TABLE t1;
-ALTER TABLE t1 ADD COLUMN d INT DEFAULT 5, RENAME COLUMN c TO b, DROP COLUMN b;
---replace_result $default_engine DEFAULT_ENGINE " PAGE_CHECKSUM=1" ""
-SHOW CREATE TABLE t1;
-
-#Cyclic Rename
-ALTER TABLE t1 RENAME COLUMN b TO d, RENAME COLUMN d TO b;
---replace_result $default_engine DEFAULT_ENGINE " PAGE_CHECKSUM=1" ""
-SHOW CREATE TABLE t1;
-
-# Rename with Indexes
-ALTER TABLE t1 ADD KEY(b);
---replace_result $default_engine DEFAULT_ENGINE " PAGE_CHECKSUM=1" ""
-SHOW CREATE TABLE t1;
-ALTER TABLE t1 RENAME COLUMN b TO bb;
---replace_result $default_engine DEFAULT_ENGINE " PAGE_CHECKSUM=1" ""
-SHOW CREATE TABLE t1;
-SELECT * FROM t1;
-
-# Rename with Foreign keys.
-CREATE TABLE t3(a int, b int, KEY(b));
-ALTER TABLE t3 ADD CONSTRAINT FOREIGN KEY(b) REFERENCES t1(bb);
---replace_result $default_engine DEFAULT_ENGINE " PAGE_CHECKSUM=1" ""
-SHOW CREATE TABLE t3;
-ALTER TABLE t1 RENAME COLUMN bb TO b;
---replace_result $default_engine DEFAULT_ENGINE " PAGE_CHECKSUM=1" ""
-SHOW CREATE TABLE t1;
-ALTER TABLE t3 RENAME COLUMN b TO c;
---replace_result $default_engine DEFAULT_ENGINE " PAGE_CHECKSUM=1" ""
-SHOW CREATE TABLE t3;
-
-# Different Algorithm
-CREATE TABLE t4(a int);
-ALTER TABLE t4 RENAME COLUMN a TO aa, ALGORITHM = INPLACE;
---replace_result $default_engine DEFAULT_ENGINE " PAGE_CHECKSUM=1" ""
-SHOW CREATE TABLE t4;
-ALTER TABLE t4 RENAME COLUMN aa TO a, ALGORITHM = COPY;
---replace_result $default_engine DEFAULT_ENGINE " PAGE_CHECKSUM=1" ""
-SHOW CREATE TABLE t4;
-DROP TABLE t4;
-
-# View, Trigger and SP
-CREATE VIEW v1 AS SELECT d,e,f FROM t2;
-CREATE TRIGGER trg1 BEFORE UPDATE on t2 FOR EACH ROW SET NEW.d=OLD.d + 10;
-CREATE PROCEDURE sp1() INSERT INTO t2(d) VALUES(10);
-ALTER TABLE t2 RENAME COLUMN d TO g;
---replace_result $default_engine DEFAULT_ENGINE " PAGE_CHECKSUM=1" ""
-SHOW CREATE TABLE t2;
-SHOW CREATE VIEW v1;
---error ER_VIEW_INVALID
-SELECT * FROM v1;
---error ER_BAD_FIELD_ERROR
-UPDATE t2 SET f = f + 10;
---error ER_BAD_FIELD_ERROR
-CALL sp1();
-DROP TRIGGER trg1;
-DROP PROCEDURE sp1;
-
-# Generated Columns
-if (!$MTR_COMBINATION_HEAP)
-{
-CREATE TABLE t_gen(a INT, b DOUBLE GENERATED ALWAYS AS (SQRT(a)));
-INSERT INTO t_gen(a) VALUES(4);
-SELECT * FROM t_gen;
---replace_result $default_engine DEFAULT_ENGINE " PAGE_CHECKSUM=1" ""
-SHOW CREATE TABLE t_gen;
-ALTER TABLE t_gen RENAME COLUMN a TO c, CHANGE COLUMN b b DOUBLE GENERATED ALWAYS AS (SQRT(c));
-SELECT * FROM t_gen;
---replace_result $default_engine DEFAULT_ENGINE " PAGE_CHECKSUM=1" ""
-SHOW CREATE TABLE t_gen;
-#--error ER_DEPENDENT_BY_GENERATED_COLUMN
-ALTER TABLE t_gen CHANGE COLUMN c x INT;
---replace_result $default_engine DEFAULT_ENGINE " PAGE_CHECKSUM=1" ""
-show create table t_gen;
-#--error ER_DEPENDENT_BY_GENERATED_COLUMN
-ALTER TABLE t_gen RENAME COLUMN x TO a;
-DROP TABLE t_gen;
-}
-
-
-#
-# Negative tests
-#
---replace_result $default_engine DEFAULT_ENGINE " PAGE_CHECKSUM=1" ""
-SHOW CREATE TABLE t1;
-
-# Invalid Syntax
---error ER_PARSE_ERROR
-ALTER TABLE t1 RENAME COLUMN b z;
---error ER_PARSE_ERROR
-ALTER TABLE t1 RENAME COLUMN FROM b TO z;
---error ER_PARSE_ERROR
-ALTER TABLE t1 RENAME COLUMN b TO 1;
-
-# Duplicate column name
---error ER_BAD_FIELD_ERROR
-ALTER TABLE t1 RENAME COLUMN b TO e, RENAME COLUMN c TO e;
---error ER_DUP_FIELDNAME
-ALTER TABLE t1 ADD COLUMN z INT, RENAME COLUMN b TO z;
-
-# Multiple operation on same column
---error ER_BAD_FIELD_ERROR
-ALTER TABLE t1 DROP COLUMN b, RENAME COLUMN b TO z;
---error ER_BAD_FIELD_ERROR
-ALTER TABLE t1 RENAME COLUMN b TO b, RENAME COLUMN b TO b;
---error ER_CANT_DROP_FIELD_OR_KEY
-ALTER TABLE t1 RENAME COLUMN b TO c3, DROP COLUMN c3;
---error ER_BAD_FIELD_ERROR
-ALTER TABLE t1 ADD COLUMN z INT, CHANGE COLUMN z y INT, DROP COLUMN y;
---error ER_BAD_FIELD_ERROR
-ALTER TABLE t1 ADD COLUMN z INT, RENAME COLUMN z TO y, DROP COLUMN y;
-
-# Invalid column name while renaming
---error ER_WRONG_COLUMN_NAME
-ALTER TABLE t1 RENAME COLUMN b TO `nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn`;
-# This error is different compared to ALTER TABLE ... CHANGE command
---error ER_TOO_LONG_IDENT
-ALTER TABLE t1 CHANGE b `nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn` int;
-
---replace_result $default_engine DEFAULT_ENGINE " PAGE_CHECKSUM=1" ""
-SHOW CREATE TABLE t1;
-SELECT * FROM t1;
-
-# Cleanup
-DROP VIEW v1;
-DROP TABLE t3,t1,t2;
-SET DEFAULT_STORAGE_ENGINE= @save_default_engine;
-
--echo #
--echo # MDEV-7318 RENAME INDEX
--echo #
@@ -2608,47 +2364,6 @@ alter table t1 rename column abc to ABC;
show create table t1;
drop table t1;
---echo #
---echo # MDEV-25803 Inplace ALTER breaks MyISAM/Aria tables when order of keys is changed
---echo #
-set @save_default_engine= @@default_storage_engine;
---disable_query_log
-if ($MTR_COMBINATION_INNODB)
-{
- set default_storage_engine= innodb;
-}
-if ($MTR_COMBINATION_ARIA)
-{
- set default_storage_engine= aria;
-}
---enable_query_log
-
-if (!$MTR_COMBINATION_INNODB)
-{
- --disable_query_log
- --disable_result_log
- # There is no inplace ADD INDEX for MyISAM/Aria:
- create or replace table t1 (x int);
- --error ER_ALTER_OPERATION_NOT_SUPPORTED
- alter table t1 add unique (x), algorithm=inplace;
- --error ER_ALTER_OPERATION_NOT_SUPPORTED
- alter table t1 add primary key(x), algorithm=inplace;
- --error ER_ALTER_OPERATION_NOT_SUPPORTED
- alter table t1 add index(x), algorithm=inplace;
- --enable_query_log
- --enable_result_log
-}
-
-create or replace table t1 (x int, y int, unique (y), unique (x), primary key(x)) engine myisam;
-alter table t1 change x xx int, algorithm=inplace;
-check table t1;
-create or replace table t1 (x int, y int, unique (y), unique (x), primary key(x));
-alter table t1 change x xx int, algorithm=inplace;
-check table t1;
-# cleanup
-drop table t1;
-set @@default_storage_engine= @save_default_engine;
-
--echo #
--echo # MDEV-25555 Server crashes in tree_record_pos after INPLACE-recreating index on HEAP table
--echo #
diff --git a/mysql-test/main/alter_table,aria.rdiff b/mysql-test/main/alter_table_combinations,aria.rdiff
similarity index 75%
rename from mysql-test/main/alter_table,aria.rdiff
rename to mysql-test/main/alter_table_combinations,aria.rdiff
index 40bbf95494c..c549f307d1f 100644
--- a/mysql-test/main/alter_table,aria.rdiff
+++ b/mysql-test/main/alter_table_combinations,aria.rdiff
@@ -1,6 +1,6 @@
---- ./mysql-test/main/alter_table.result 2020-02-27 19:35:41.279992329 +0300
-+++ ./mysql-test/main/alter_table,aria.reject 2020-02-27 19:37:13.251994491 +0300
-@@ -2716,8 +2716,7 @@
+--- main/alter_table_combinations.result 2022-05-24 17:16:56.769146869 +0200
++++ main/alter_table_combinations.reject 2022-05-24 17:25:20.847126357 +0200
+@@ -173,8 +173,7 @@
t3 CREATE TABLE `t3` (
`a` int(11) DEFAULT NULL,
`b` int(11) DEFAULT NULL,
@@ -10,7 +10,7 @@
) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1
ALTER TABLE t1 RENAME COLUMN bb TO b;
SHOW CREATE TABLE t1;
-@@ -2733,8 +2732,7 @@
+@@ -190,8 +189,7 @@
t3 CREATE TABLE `t3` (
`a` int(11) DEFAULT NULL,
`c` int(11) DEFAULT NULL,
diff --git a/mysql-test/main/alter_table,heap.rdiff b/mysql-test/main/alter_table_combinations,heap.rdiff
similarity index 70%
rename from mysql-test/main/alter_table,heap.rdiff
rename to mysql-test/main/alter_table_combinations,heap.rdiff
index ad6fd194cc9..ed84bbe73c1 100644
--- a/mysql-test/main/alter_table,heap.rdiff
+++ b/mysql-test/main/alter_table_combinations,heap.rdiff
@@ -1,6 +1,15 @@
---- ./mysql-test/main/alter_table.result 2020-02-27 19:35:41.279992329 +0300
-+++ ./mysql-test/main/alter_table,heap.reject 2020-02-27 19:39:44.175998039 +0300
-@@ -2716,8 +2716,7 @@
+--- main/alter_table_combinations.result 2022-05-24 17:16:56.769146869 +0200
++++ main/alter_table_combinations.reject 2022-05-24 17:25:01.216127156 +0200
+@@ -11,7 +11,7 @@
+ alter table t1 change x xx int, algorithm=inplace;
+ check table t1;
+ Table Op Msg_type Msg_text
+-test.t1 check status OK
++test.t1 check note The storage engine for the table doesn't support check
+ drop table t1;
+ #
+ # End of 10.3 tests
+@@ -173,8 +173,7 @@
t3 CREATE TABLE `t3` (
`a` int(11) DEFAULT NULL,
`b` int(11) DEFAULT NULL,
@@ -10,7 +19,7 @@
) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1
ALTER TABLE t1 RENAME COLUMN bb TO b;
SHOW CREATE TABLE t1;
-@@ -2733,8 +2732,7 @@
+@@ -190,8 +189,7 @@
t3 CREATE TABLE `t3` (
`a` int(11) DEFAULT NULL,
`c` int(11) DEFAULT NULL,
@@ -20,7 +29,7 @@
) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1
CREATE TABLE t4(a int);
ALTER TABLE t4 RENAME COLUMN a TO aa, ALGORITHM = INPLACE;
-@@ -2774,36 +2772,6 @@
+@@ -231,36 +229,6 @@
ERROR 42S22: Unknown column 'd' in 'field list'
DROP TRIGGER trg1;
DROP PROCEDURE sp1;
@@ -57,3 +66,12 @@
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
+@@ -316,7 +284,7 @@
+ alter table t1 change x xx int, algorithm=inplace;
+ check table t1;
+ Table Op Msg_type Msg_text
+-test.t1 check status OK
++test.t1 check note The storage engine for the table doesn't support check
+ drop table t1;
+ #
+ # End of 10.5 tests
diff --git a/mysql-test/main/alter_table.combinations b/mysql-test/main/alter_table_combinations.combinations
similarity index 78%
rename from mysql-test/main/alter_table.combinations
rename to mysql-test/main/alter_table_combinations.combinations
index 824e0a3be04..01c0e4b31b2 100644
--- a/mysql-test/main/alter_table.combinations
+++ b/mysql-test/main/alter_table_combinations.combinations
@@ -1,4 +1,5 @@
[innodb]
+innodb
[aria]
diff --git a/mysql-test/main/alter_table_combinations.result b/mysql-test/main/alter_table_combinations.result
new file mode 100644
index 00000000000..459447f343e
--- /dev/null
+++ b/mysql-test/main/alter_table_combinations.result
@@ -0,0 +1,324 @@
+set @save_default_engine= @@default_storage_engine;
+#
+# MDEV-25803 Inplace ALTER breaks MyISAM/Aria tables when order of keys is changed
+#
+create or replace table t1 (x int, y int, unique (y), unique (x), primary key(x)) engine myisam;
+alter table t1 change x xx int, algorithm=inplace;
+check table t1;
+Table Op Msg_type Msg_text
+test.t1 check status OK
+create or replace table t1 (x int, y int, unique (y), unique (x), primary key(x));
+alter table t1 change x xx int, algorithm=inplace;
+check table t1;
+Table Op Msg_type Msg_text
+test.t1 check status OK
+drop table t1;
+#
+# End of 10.3 tests
+#
+#
+# MDEV-16290 ALTER TABLE ... RENAME COLUMN syntax
+#
+CREATE TABLE t1(a INT, b VARCHAR(30), c FLOAT);
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` varchar(30) DEFAULT NULL,
+ `c` float DEFAULT NULL
+) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1
+INSERT INTO t1 VALUES(1,'abcd',1.234);
+CREATE TABLE t2(a INT, b VARCHAR(30), c FLOAT) ENGINE=MyIsam;
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `a` int(11) DEFAULT NULL,
+ `b` varchar(30) DEFAULT NULL,
+ `c` float DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+INSERT INTO t2 VALUES(1,'abcd',1.234);
+ALTER TABLE t1 RENAME COLUMN a TO a;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` varchar(30) DEFAULT NULL,
+ `c` float DEFAULT NULL
+) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1
+ALTER TABLE t1 RENAME COLUMN a TO m;
+ALTER TABLE t1 RENAME COLUMN a TO m;
+ERROR 42S22: Unknown column 'a' in 't1'
+ALTER TABLE t1 RENAME COLUMN IF EXISTS a TO m;
+Warnings:
+Note 1054 Unknown column 'a' in 't1'
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `m` int(11) DEFAULT NULL,
+ `b` varchar(30) DEFAULT NULL,
+ `c` float DEFAULT NULL
+) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1
+SELECT * FROM t1;
+m b c
+1 abcd 1.234
+ALTER TABLE t1 RENAME COLUMN m TO x,
+RENAME COLUMN b TO y,
+RENAME COLUMN c TO z;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `x` int(11) DEFAULT NULL,
+ `y` varchar(30) DEFAULT NULL,
+ `z` float DEFAULT NULL
+) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1
+SELECT * FROM t1;
+x y z
+1 abcd 1.234
+ALTER TABLE t2 RENAME COLUMN a TO d, RENAME COLUMN b TO e, RENAME COLUMN c to f;
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `d` int(11) DEFAULT NULL,
+ `e` varchar(30) DEFAULT NULL,
+ `f` float DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+SELECT * FROM t2;
+d e f
+1 abcd 1.234
+ALTER TABLE t1 CHANGE COLUMN x a INT, RENAME COLUMN y TO b;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` varchar(30) DEFAULT NULL,
+ `z` float DEFAULT NULL
+) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1
+ALTER TABLE t1 CHANGE COLUMN z c DOUBLE, RENAME COLUMN b to b;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` varchar(30) DEFAULT NULL,
+ `c` double DEFAULT NULL
+) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1
+ALTER TABLE t1 CHANGE COLUMN a b int, RENAME COLUMN b TO c, CHANGE COLUMN c d FLOAT;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `b` int(11) DEFAULT NULL,
+ `c` varchar(30) DEFAULT NULL,
+ `d` float DEFAULT NULL
+) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1
+ALTER TABLE t1 ADD COLUMN zz INT, RENAME COLUMN d TO f;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `b` int(11) DEFAULT NULL,
+ `c` varchar(30) DEFAULT NULL,
+ `f` float DEFAULT NULL,
+ `zz` int(11) DEFAULT NULL
+) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1
+ALTER TABLE t1 DROP COLUMN zz, RENAME COLUMN c TO zz;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `b` int(11) DEFAULT NULL,
+ `zz` varchar(30) DEFAULT NULL,
+ `f` float DEFAULT NULL
+) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1
+ALTER TABLE t1 RENAME COLUMN zz to c, DROP COLUMN f;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `b` int(11) DEFAULT NULL,
+ `c` varchar(30) DEFAULT NULL
+) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1
+ALTER TABLE t1 ADD COLUMN d INT DEFAULT 5, RENAME COLUMN c TO b, DROP COLUMN b;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `b` varchar(30) DEFAULT NULL,
+ `d` int(11) DEFAULT 5
+) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1
+ALTER TABLE t1 RENAME COLUMN b TO d, RENAME COLUMN d TO b;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `d` varchar(30) DEFAULT NULL,
+ `b` int(11) DEFAULT 5
+) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1
+ALTER TABLE t1 ADD KEY(b);
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `d` varchar(30) DEFAULT NULL,
+ `b` int(11) DEFAULT 5,
+ KEY `b` (`b`)
+) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1
+ALTER TABLE t1 RENAME COLUMN b TO bb;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `d` varchar(30) DEFAULT NULL,
+ `bb` int(11) DEFAULT 5,
+ KEY `b` (`bb`)
+) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1
+SELECT * FROM t1;
+d bb
+abcd 5
+CREATE TABLE t3(a int, b int, KEY(b));
+ALTER TABLE t3 ADD CONSTRAINT FOREIGN KEY(b) REFERENCES t1(bb);
+SHOW CREATE TABLE t3;
+Table Create Table
+t3 CREATE TABLE `t3` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) DEFAULT NULL,
+ KEY `b` (`b`),
+ CONSTRAINT `t3_ibfk_1` FOREIGN KEY (`b`) REFERENCES `t1` (`bb`)
+) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1
+ALTER TABLE t1 RENAME COLUMN bb TO b;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `d` varchar(30) DEFAULT NULL,
+ `b` int(11) DEFAULT 5,
+ KEY `b` (`b`)
+) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1
+ALTER TABLE t3 RENAME COLUMN b TO c;
+SHOW CREATE TABLE t3;
+Table Create Table
+t3 CREATE TABLE `t3` (
+ `a` int(11) DEFAULT NULL,
+ `c` int(11) DEFAULT NULL,
+ KEY `b` (`c`),
+ CONSTRAINT `t3_ibfk_1` FOREIGN KEY (`c`) REFERENCES `t1` (`b`)
+) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1
+CREATE TABLE t4(a int);
+ALTER TABLE t4 RENAME COLUMN a TO aa, ALGORITHM = INPLACE;
+SHOW CREATE TABLE t4;
+Table Create Table
+t4 CREATE TABLE `t4` (
+ `aa` int(11) DEFAULT NULL
+) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1
+ALTER TABLE t4 RENAME COLUMN aa TO a, ALGORITHM = COPY;
+SHOW CREATE TABLE t4;
+Table Create Table
+t4 CREATE TABLE `t4` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1
+DROP TABLE t4;
+CREATE VIEW v1 AS SELECT d,e,f FROM t2;
+CREATE TRIGGER trg1 BEFORE UPDATE on t2 FOR EACH ROW SET NEW.d=OLD.d + 10;
+CREATE PROCEDURE sp1() INSERT INTO t2(d) VALUES(10);
+ALTER TABLE t2 RENAME COLUMN d TO g;
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `g` int(11) DEFAULT NULL,
+ `e` varchar(30) DEFAULT NULL,
+ `f` float DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+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`.`t2`.`d` AS `d`,`test`.`t2`.`e` AS `e`,`test`.`t2`.`f` AS `f` from `t2` latin1 latin1_swedish_ci
+Warnings:
+Warning 1356 View 'test.v1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
+SELECT * FROM v1;
+ERROR HY000: View 'test.v1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
+UPDATE t2 SET f = f + 10;
+ERROR 42S22: Unknown column 'd' in 'OLD'
+CALL sp1();
+ERROR 42S22: Unknown column 'd' in 'field list'
+DROP TRIGGER trg1;
+DROP PROCEDURE sp1;
+CREATE TABLE t_gen(a INT, b DOUBLE GENERATED ALWAYS AS (SQRT(a)));
+INSERT INTO t_gen(a) VALUES(4);
+SELECT * FROM t_gen;
+a b
+4 2
+SHOW CREATE TABLE t_gen;
+Table Create Table
+t_gen CREATE TABLE `t_gen` (
+ `a` int(11) DEFAULT NULL,
+ `b` double GENERATED ALWAYS AS (sqrt(`a`)) VIRTUAL
+) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1
+ALTER TABLE t_gen RENAME COLUMN a TO c, CHANGE COLUMN b b DOUBLE GENERATED ALWAYS AS (SQRT(c));
+SELECT * FROM t_gen;
+c b
+4 2
+SHOW CREATE TABLE t_gen;
+Table Create Table
+t_gen CREATE TABLE `t_gen` (
+ `c` int(11) DEFAULT NULL,
+ `b` double GENERATED ALWAYS AS (sqrt(`c`)) VIRTUAL
+) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1
+ALTER TABLE t_gen CHANGE COLUMN c x INT;
+show create table t_gen;
+Table Create Table
+t_gen CREATE TABLE `t_gen` (
+ `x` int(11) DEFAULT NULL,
+ `b` double GENERATED ALWAYS AS (sqrt(`x`)) VIRTUAL
+) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1
+ALTER TABLE t_gen RENAME COLUMN x TO a;
+DROP TABLE t_gen;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `d` varchar(30) DEFAULT NULL,
+ `b` int(11) DEFAULT 5,
+ KEY `b` (`b`)
+) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1
+ALTER TABLE t1 RENAME COLUMN b z;
+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 'z' at line 1
+ALTER TABLE t1 RENAME COLUMN FROM b TO z;
+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 'FROM b TO z' at line 1
+ALTER TABLE t1 RENAME COLUMN b TO 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 '1' at line 1
+ALTER TABLE t1 RENAME COLUMN b TO e, RENAME COLUMN c TO e;
+ERROR 42S22: Unknown column 'c' in 't1'
+ALTER TABLE t1 ADD COLUMN z INT, RENAME COLUMN b TO z;
+ERROR 42S21: Duplicate column name 'z'
+ALTER TABLE t1 DROP COLUMN b, RENAME COLUMN b TO z;
+ERROR 42S22: Unknown column 'b' in 't1'
+ALTER TABLE t1 RENAME COLUMN b TO b, RENAME COLUMN b TO b;
+ERROR 42S22: Unknown column 'b' in 't1'
+ALTER TABLE t1 RENAME COLUMN b TO c3, DROP COLUMN c3;
+ERROR 42000: Can't DROP COLUMN `c3`; check that it exists
+ALTER TABLE t1 ADD COLUMN z INT, CHANGE COLUMN z y INT, DROP COLUMN y;
+ERROR 42S22: Unknown column 'z' in 't1'
+ALTER TABLE t1 ADD COLUMN z INT, RENAME COLUMN z TO y, DROP COLUMN y;
+ERROR 42S22: Unknown column 'z' in 't1'
+ALTER TABLE t1 RENAME COLUMN b TO `nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn`;
+ERROR 42000: Incorrect column name 'nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn'
+ALTER TABLE t1 CHANGE b `nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn` int;
+ERROR 42000: Identifier name 'nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn' is too long
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `d` varchar(30) DEFAULT NULL,
+ `b` int(11) DEFAULT 5,
+ KEY `b` (`b`)
+) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1
+SELECT * FROM t1;
+d b
+abcd 5
+DROP VIEW v1;
+DROP TABLE t3,t1,t2;
+#
+# MDEV-25803 Inplace ALTER breaks MyISAM/Aria tables when order of keys is changed
+#
+create or replace table t1 (x int, y int, unique (y), unique (x), primary key(x)) engine myisam;
+alter table t1 change x xx int, algorithm=inplace;
+check table t1;
+Table Op Msg_type Msg_text
+test.t1 check status OK
+create or replace table t1 (x int, y int, unique (y), unique (x), primary key(x));
+alter table t1 change x xx int, algorithm=inplace;
+check table t1;
+Table Op Msg_type Msg_text
+test.t1 check status OK
+drop table t1;
+#
+# End of 10.5 tests
+#
+set @@default_storage_engine= @save_default_engine;
diff --git a/mysql-test/main/alter_table_combinations.test b/mysql-test/main/alter_table_combinations.test
new file mode 100644
index 00000000000..7c8d7f42096
--- /dev/null
+++ b/mysql-test/main/alter_table_combinations.test
@@ -0,0 +1,263 @@
+set @save_default_engine= @@default_storage_engine;
+--disable_query_log
+if ($MTR_COMBINATION_INNODB)
+{
+set default_storage_engine= innodb;
+}
+if ($MTR_COMBINATION_ARIA)
+{
+set default_storage_engine= aria;
+}
+if ($MTR_COMBINATION_HEAP)
+{
+set default_storage_engine= memory;
+}
+--enable_query_log
+let $default_engine= `select @@default_storage_engine`;
+
+--echo #
+--echo # MDEV-25803 Inplace ALTER breaks MyISAM/Aria tables when order of keys is changed
+--echo #
+
+if (!$MTR_COMBINATION_INNODB)
+{
+ --disable_query_log
+ --disable_result_log
+ # There is no inplace ADD INDEX for MyISAM/Aria:
+ create or replace table t1 (x int);
+ --error ER_ALTER_OPERATION_NOT_SUPPORTED
+ alter table t1 add unique (x), algorithm=inplace;
+ --error ER_ALTER_OPERATION_NOT_SUPPORTED
+ alter table t1 add primary key(x), algorithm=inplace;
+ --error ER_ALTER_OPERATION_NOT_SUPPORTED
+ alter table t1 add index(x), algorithm=inplace;
+ --enable_query_log
+ --enable_result_log
+}
+
+create or replace table t1 (x int, y int, unique (y), unique (x), primary key(x)) engine myisam;
+alter table t1 change x xx int, algorithm=inplace;
+check table t1;
+create or replace table t1 (x int, y int, unique (y), unique (x), primary key(x));
+alter table t1 change x xx int, algorithm=inplace;
+check table t1;
+drop table t1;
+
+--echo #
+--echo # End of 10.3 tests
+--echo #
+
+--echo #
+--echo # MDEV-16290 ALTER TABLE ... RENAME COLUMN syntax
+--echo #
+
+CREATE TABLE t1(a INT, b VARCHAR(30), c FLOAT);
+--replace_result $default_engine DEFAULT_ENGINE " PAGE_CHECKSUM=1" ""
+SHOW CREATE TABLE t1;
+INSERT INTO t1 VALUES(1,'abcd',1.234);
+CREATE TABLE t2(a INT, b VARCHAR(30), c FLOAT) ENGINE=MyIsam;
+SHOW CREATE TABLE t2;
+INSERT INTO t2 VALUES(1,'abcd',1.234);
+
+# Rename one column
+ALTER TABLE t1 RENAME COLUMN a TO a;
+--replace_result $default_engine DEFAULT_ENGINE " PAGE_CHECKSUM=1" ""
+SHOW CREATE TABLE t1;
+ALTER TABLE t1 RENAME COLUMN a TO m;
+--error ER_BAD_FIELD_ERROR
+ALTER TABLE t1 RENAME COLUMN a TO m;
+ALTER TABLE t1 RENAME COLUMN IF EXISTS a TO m;
+--replace_result $default_engine DEFAULT_ENGINE " PAGE_CHECKSUM=1" ""
+SHOW CREATE TABLE t1;
+SELECT * FROM t1;
+
+# Rename multiple column
+ALTER TABLE t1 RENAME COLUMN m TO x,
+ RENAME COLUMN b TO y,
+ RENAME COLUMN c TO z;
+--replace_result $default_engine DEFAULT_ENGINE " PAGE_CHECKSUM=1" ""
+SHOW CREATE TABLE t1;
+SELECT * FROM t1;
+
+# Rename multiple columns with MyIsam Engine
+ALTER TABLE t2 RENAME COLUMN a TO d, RENAME COLUMN b TO e, RENAME COLUMN c to f;
+SHOW CREATE TABLE t2;
+SELECT * FROM t2;
+
+# Mix different ALTER operations with RENAME COLUMN
+ALTER TABLE t1 CHANGE COLUMN x a INT, RENAME COLUMN y TO b;
+--replace_result $default_engine DEFAULT_ENGINE " PAGE_CHECKSUM=1" ""
+SHOW CREATE TABLE t1;
+ALTER TABLE t1 CHANGE COLUMN z c DOUBLE, RENAME COLUMN b to b;
+--replace_result $default_engine DEFAULT_ENGINE " PAGE_CHECKSUM=1" ""
+SHOW CREATE TABLE t1;
+ALTER TABLE t1 CHANGE COLUMN a b int, RENAME COLUMN b TO c, CHANGE COLUMN c d FLOAT;
+--replace_result $default_engine DEFAULT_ENGINE " PAGE_CHECKSUM=1" ""
+SHOW CREATE TABLE t1;
+ALTER TABLE t1 ADD COLUMN zz INT, RENAME COLUMN d TO f;
+--replace_result $default_engine DEFAULT_ENGINE " PAGE_CHECKSUM=1" ""
+SHOW CREATE TABLE t1;
+ALTER TABLE t1 DROP COLUMN zz, RENAME COLUMN c TO zz;
+--replace_result $default_engine DEFAULT_ENGINE " PAGE_CHECKSUM=1" ""
+SHOW CREATE TABLE t1;
+ALTER TABLE t1 RENAME COLUMN zz to c, DROP COLUMN f;
+--replace_result $default_engine DEFAULT_ENGINE " PAGE_CHECKSUM=1" ""
+SHOW CREATE TABLE t1;
+ALTER TABLE t1 ADD COLUMN d INT DEFAULT 5, RENAME COLUMN c TO b, DROP COLUMN b;
+--replace_result $default_engine DEFAULT_ENGINE " PAGE_CHECKSUM=1" ""
+SHOW CREATE TABLE t1;
+
+#Cyclic Rename
+ALTER TABLE t1 RENAME COLUMN b TO d, RENAME COLUMN d TO b;
+--replace_result $default_engine DEFAULT_ENGINE " PAGE_CHECKSUM=1" ""
+SHOW CREATE TABLE t1;
+
+# Rename with Indexes
+ALTER TABLE t1 ADD KEY(b);
+--replace_result $default_engine DEFAULT_ENGINE " PAGE_CHECKSUM=1" ""
+SHOW CREATE TABLE t1;
+ALTER TABLE t1 RENAME COLUMN b TO bb;
+--replace_result $default_engine DEFAULT_ENGINE " PAGE_CHECKSUM=1" ""
+SHOW CREATE TABLE t1;
+SELECT * FROM t1;
+
+# Rename with Foreign keys.
+CREATE TABLE t3(a int, b int, KEY(b));
+ALTER TABLE t3 ADD CONSTRAINT FOREIGN KEY(b) REFERENCES t1(bb);
+--replace_result $default_engine DEFAULT_ENGINE " PAGE_CHECKSUM=1" ""
+SHOW CREATE TABLE t3;
+ALTER TABLE t1 RENAME COLUMN bb TO b;
+--replace_result $default_engine DEFAULT_ENGINE " PAGE_CHECKSUM=1" ""
+SHOW CREATE TABLE t1;
+ALTER TABLE t3 RENAME COLUMN b TO c;
+--replace_result $default_engine DEFAULT_ENGINE " PAGE_CHECKSUM=1" ""
+SHOW CREATE TABLE t3;
+
+# Different Algorithm
+CREATE TABLE t4(a int);
+ALTER TABLE t4 RENAME COLUMN a TO aa, ALGORITHM = INPLACE;
+--replace_result $default_engine DEFAULT_ENGINE " PAGE_CHECKSUM=1" ""
+SHOW CREATE TABLE t4;
+ALTER TABLE t4 RENAME COLUMN aa TO a, ALGORITHM = COPY;
+--replace_result $default_engine DEFAULT_ENGINE " PAGE_CHECKSUM=1" ""
+SHOW CREATE TABLE t4;
+DROP TABLE t4;
+
+# View, Trigger and SP
+CREATE VIEW v1 AS SELECT d,e,f FROM t2;
+CREATE TRIGGER trg1 BEFORE UPDATE on t2 FOR EACH ROW SET NEW.d=OLD.d + 10;
+CREATE PROCEDURE sp1() INSERT INTO t2(d) VALUES(10);
+ALTER TABLE t2 RENAME COLUMN d TO g;
+--replace_result $default_engine DEFAULT_ENGINE " PAGE_CHECKSUM=1" ""
+SHOW CREATE TABLE t2;
+SHOW CREATE VIEW v1;
+--error ER_VIEW_INVALID
+SELECT * FROM v1;
+--error ER_BAD_FIELD_ERROR
+UPDATE t2 SET f = f + 10;
+--error ER_BAD_FIELD_ERROR
+CALL sp1();
+DROP TRIGGER trg1;
+DROP PROCEDURE sp1;
+
+# Generated Columns
+if (!$MTR_COMBINATION_HEAP)
+{
+CREATE TABLE t_gen(a INT, b DOUBLE GENERATED ALWAYS AS (SQRT(a)));
+INSERT INTO t_gen(a) VALUES(4);
+SELECT * FROM t_gen;
+--replace_result $default_engine DEFAULT_ENGINE " PAGE_CHECKSUM=1" ""
+SHOW CREATE TABLE t_gen;
+ALTER TABLE t_gen RENAME COLUMN a TO c, CHANGE COLUMN b b DOUBLE GENERATED ALWAYS AS (SQRT(c));
+SELECT * FROM t_gen;
+--replace_result $default_engine DEFAULT_ENGINE " PAGE_CHECKSUM=1" ""
+SHOW CREATE TABLE t_gen;
+#--error ER_DEPENDENT_BY_GENERATED_COLUMN
+ALTER TABLE t_gen CHANGE COLUMN c x INT;
+--replace_result $default_engine DEFAULT_ENGINE " PAGE_CHECKSUM=1" ""
+show create table t_gen;
+#--error ER_DEPENDENT_BY_GENERATED_COLUMN
+ALTER TABLE t_gen RENAME COLUMN x TO a;
+DROP TABLE t_gen;
+}
+
+#
+# Negative tests
+#
+--replace_result $default_engine DEFAULT_ENGINE " PAGE_CHECKSUM=1" ""
+SHOW CREATE TABLE t1;
+
+# Invalid Syntax
+--error ER_PARSE_ERROR
+ALTER TABLE t1 RENAME COLUMN b z;
+--error ER_PARSE_ERROR
+ALTER TABLE t1 RENAME COLUMN FROM b TO z;
+--error ER_PARSE_ERROR
+ALTER TABLE t1 RENAME COLUMN b TO 1;
+
+# Duplicate column name
+--error ER_BAD_FIELD_ERROR
+ALTER TABLE t1 RENAME COLUMN b TO e, RENAME COLUMN c TO e;
+--error ER_DUP_FIELDNAME
+ALTER TABLE t1 ADD COLUMN z INT, RENAME COLUMN b TO z;
+
+# Multiple operation on same column
+--error ER_BAD_FIELD_ERROR
+ALTER TABLE t1 DROP COLUMN b, RENAME COLUMN b TO z;
+--error ER_BAD_FIELD_ERROR
+ALTER TABLE t1 RENAME COLUMN b TO b, RENAME COLUMN b TO b;
+--error ER_CANT_DROP_FIELD_OR_KEY
+ALTER TABLE t1 RENAME COLUMN b TO c3, DROP COLUMN c3;
+--error ER_BAD_FIELD_ERROR
+ALTER TABLE t1 ADD COLUMN z INT, CHANGE COLUMN z y INT, DROP COLUMN y;
+--error ER_BAD_FIELD_ERROR
+ALTER TABLE t1 ADD COLUMN z INT, RENAME COLUMN z TO y, DROP COLUMN y;
+
+# Invalid column name while renaming
+--error ER_WRONG_COLUMN_NAME
+ALTER TABLE t1 RENAME COLUMN b TO `nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn`;
+# This error is different compared to ALTER TABLE ... CHANGE command
+--error ER_TOO_LONG_IDENT
+ALTER TABLE t1 CHANGE b `nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn` int;
+
+--replace_result $default_engine DEFAULT_ENGINE " PAGE_CHECKSUM=1" ""
+SHOW CREATE TABLE t1;
+SELECT * FROM t1;
+
+# Cleanup
+DROP VIEW v1;
+DROP TABLE t3,t1,t2;
+
+--echo #
+--echo # MDEV-25803 Inplace ALTER breaks MyISAM/Aria tables when order of keys is changed
+--echo #
+
+if (!$MTR_COMBINATION_INNODB)
+{
+ --disable_query_log
+ --disable_result_log
+ # There is no inplace ADD INDEX for MyISAM/Aria:
+ create or replace table t1 (x int);
+ --error ER_ALTER_OPERATION_NOT_SUPPORTED
+ alter table t1 add unique (x), algorithm=inplace;
+ --error ER_ALTER_OPERATION_NOT_SUPPORTED
+ alter table t1 add primary key(x), algorithm=inplace;
+ --error ER_ALTER_OPERATION_NOT_SUPPORTED
+ alter table t1 add index(x), algorithm=inplace;
+ --enable_query_log
+ --enable_result_log
+}
+
+create or replace table t1 (x int, y int, unique (y), unique (x), primary key(x)) engine myisam;
+alter table t1 change x xx int, algorithm=inplace;
+check table t1;
+create or replace table t1 (x int, y int, unique (y), unique (x), primary key(x));
+alter table t1 change x xx int, algorithm=inplace;
+check table t1;
+drop table t1;
+
+--echo #
+--echo # End of 10.5 tests
+--echo #
+
+set @@default_storage_engine= @save_default_engine;
diff --git a/mysql-test/main/mysql.result b/mysql-test/main/mysql.result
index 70dde06600e..d889738bf6a 100644
--- a/mysql-test/main/mysql.result
+++ b/mysql-test/main/mysql.result
@@ -633,4 +633,7 @@ drop table t1;
#
# MDEV-15538 '-N' Produce html output wrong
#
-
\ No newline at end of file
+
+WARNING: option '--enable-cleartext-plugin' is obsolete.
+1
+1
diff --git a/mysql-test/main/mysql.test b/mysql-test/main/mysql.test
index 1cb4977a32d..0f41add821a 100644
--- a/mysql-test/main/mysql.test
+++ b/mysql-test/main/mysql.test
@@ -708,3 +708,11 @@ drop table t1;
--echo # MDEV-15538 '-N' Produce html output wrong
--echo #
--exec $MYSQL -NHe "select 1 as a"
+
+
+#
+# Test obsolete option --enable-cleartext-plugin
+# This should proceed with a warning
+#
+--echo
+--exec $MYSQL test --enable-cleartext-plugin -e "select 1"
diff --git a/mysql-test/main/partition_error.result b/mysql-test/main/partition_error.result
index bff08c0d447..4e12b6ade8e 100644
--- a/mysql-test/main/partition_error.result
+++ b/mysql-test/main/partition_error.result
@@ -6,7 +6,18 @@ drop table if exists t1, t2;
CREATE TABLE t1 (a int);
CREATE OR REPLACE VIEW v1 AS SELECT * FROM t1;
ALTER TABLE t1 EXCHANGE PARTITION p0 WITH TABLE v1;
-ERROR 42000: Can't open table
+ERROR HY000: 'test.v1' is not of type 'BASE TABLE'
+DROP VIEW v1;
+DROP TABLE t1;
+#
+# MDEV-28599 EXCHANGE PARTITION on view causes ER_CHECK_NO_SUCH_TABLE instead of ER_WRONG_OBJECT
+#
+CREATE TABLE t1 (a int)
+PARTITION BY HASH (a)
+PARTITIONS 2;
+CREATE OR REPLACE VIEW v1 AS SELECT * FROM t1;
+ALTER TABLE t1 EXCHANGE PARTITION p0 WITH TABLE v1;
+ERROR HY000: 'test.v1' is not of type 'BASE TABLE'
DROP VIEW v1;
DROP TABLE t1;
#
diff --git a/mysql-test/main/partition_error.test b/mysql-test/main/partition_error.test
index 25b15578248..b8d07e595e5 100644
--- a/mysql-test/main/partition_error.test
+++ b/mysql-test/main/partition_error.test
@@ -16,7 +16,19 @@ let $MYSQLD_DATADIR= `SELECT @@datadir`;
--echo #
CREATE TABLE t1 (a int);
CREATE OR REPLACE VIEW v1 AS SELECT * FROM t1;
---error ER_CHECK_NO_SUCH_TABLE
+--error ER_WRONG_OBJECT
+ALTER TABLE t1 EXCHANGE PARTITION p0 WITH TABLE v1;
+DROP VIEW v1;
+DROP TABLE t1;
+
+--echo #
+--echo # MDEV-28599 EXCHANGE PARTITION on view causes ER_CHECK_NO_SUCH_TABLE instead of ER_WRONG_OBJECT
+--echo #
+CREATE TABLE t1 (a int)
+PARTITION BY HASH (a)
+PARTITIONS 2;
+CREATE OR REPLACE VIEW v1 AS SELECT * FROM t1;
+--error ER_WRONG_OBJECT
ALTER TABLE t1 EXCHANGE PARTITION p0 WITH TABLE v1;
DROP VIEW v1;
DROP TABLE t1;
diff --git a/mysql-test/suite/encryption/r/innodb-bad-key-change.result b/mysql-test/suite/encryption/r/innodb-bad-key-change.result
index 3c83a23b4be..e2034f14e31 100644
--- a/mysql-test/suite/encryption/r/innodb-bad-key-change.result
+++ b/mysql-test/suite/encryption/r/innodb-bad-key-change.result
@@ -2,8 +2,8 @@ call mtr.add_suppression("Plugin 'file_key_management' init function returned er
call mtr.add_suppression("Plugin 'file_key_management' registration.*failed");
call mtr.add_suppression("InnoDB: Table `test`\\.`t[12]` has an unreadable root page");
call mtr.add_suppression("Table .*t[12].* is corrupted");
-call mtr.add_suppression("InnoDB: The page \\[page id: space=[1-9][0-9]*, page number=[1-9][0-9]*\\] in file '.*test.t[12]\\.ibd' cannot be decrypted\\.");
-call mtr.add_suppression("failed to read or decrypt \\[page id: space=[1-9][0-9]*, page number=[1-9][0-9]*\\]");
+call mtr.add_suppression("InnoDB: The page \\[page id: space=[1-9][0-9]*, page number=[1-9][0-9]*\\] in file '.*test.t[12]\\.ibd' cannot be decrypted; key_version=1");
+call mtr.add_suppression("failed to read \\[page id: space=[1-9][0-9]*, page number=[1-9][0-9]*\\]");
call mtr.add_suppression("InnoDB: Encrypted page \\[page id: space=[1-9][0-9]*, page number=3\\] in file .*test.t1.ibd looks corrupted; key_version=1");
call mtr.add_suppression("File '.*mysql-test.std_data.keysbad3\\.txt' not found");
call mtr.add_suppression("\\[ERROR\\] InnoDB: Cannot decrypt \\[page id: space=");
diff --git a/mysql-test/suite/encryption/r/innodb-bad-key-change2.result b/mysql-test/suite/encryption/r/innodb-bad-key-change2.result
index ca73643ba83..d2ea45dc949 100644
--- a/mysql-test/suite/encryption/r/innodb-bad-key-change2.result
+++ b/mysql-test/suite/encryption/r/innodb-bad-key-change2.result
@@ -1,5 +1,5 @@
call mtr.add_suppression("InnoDB: Table `test`\\.`t1` (has an unreadable root page|does not exist.*is trying to rename)");
-call mtr.add_suppression("InnoDB: The page \\[page id: space=[1-9][0-9]*, page number=[1-9][0-9]*\\] in file '.*test.t1(new)?\\.ibd' cannot be decrypted\\.");
+call mtr.add_suppression("InnoDB: The page \\[page id: space=[1-9][0-9]*, page number=[1-9][0-9]*\\] in file '.*test.t1(new)?\\.ibd' cannot be decrypted; key_version=1");
call mtr.add_suppression("failed to read or decrypt \\[page id: space=[1-9][0-9]*, page number=[1-9][0-9]*\\]");
call mtr.add_suppression("Couldn't load plugins from 'file_key_management");
call mtr.add_suppression("InnoDB: Tablespace for table \`test\`.\`t1\` is set as discarded\\.");
diff --git a/mysql-test/suite/encryption/r/innodb-bad-key-change4.result b/mysql-test/suite/encryption/r/innodb-bad-key-change4.result
index 90b24799808..a5a6d65e4a2 100644
--- a/mysql-test/suite/encryption/r/innodb-bad-key-change4.result
+++ b/mysql-test/suite/encryption/r/innodb-bad-key-change4.result
@@ -1,5 +1,5 @@
-call mtr.add_suppression("InnoDB: Table `test`\\.`t1` has an unreadable root page");
-call mtr.add_suppression("InnoDB: The page \\[page id: space=[1-9][0-9]*, page number=[1-9][0-9]*\\] in file '.*test.t1\\.ibd' cannot be decrypted\\.");
+call mtr.add_suppression("InnoDB: Table `test`\\.`t1` (has an unreadable root page)");
+call mtr.add_suppression("InnoDB: The page \\[page id: space=[1-9][0-9]*, page number=[1-9][0-9]*\\] in file '.*test.t1\\.ibd' cannot be decrypted; key_version=1");
call mtr.add_suppression("failed to read or decrypt \\[page id: space=[1-9][0-9]*, page number=[1-9][0-9]*\\]");
call mtr.add_suppression("Couldn't load plugins from 'file_key_management");
call mtr.add_suppression("Table .*t1.* is corrupted");
diff --git a/mysql-test/suite/encryption/r/innodb-compressed-blob.result b/mysql-test/suite/encryption/r/innodb-compressed-blob.result
index de20b554a67..39f482b2422 100644
--- a/mysql-test/suite/encryption/r/innodb-compressed-blob.result
+++ b/mysql-test/suite/encryption/r/innodb-compressed-blob.result
@@ -1,4 +1,4 @@
-call mtr.add_suppression("InnoDB: The page \\[page id: space=[1-9][0-9]*, page number=[1-9][0-9]*\\] in file '.*test.t[123]\\.ibd' cannot be decrypted\\.");
+call mtr.add_suppression("InnoDB: The page \\[page id: space=[1-9][0-9]*, page number=[1-9][0-9]*\\] in file '.*test.t[123]\\.ibd' cannot be decrypted; key_version=1");
call mtr.add_suppression("failed to read or decrypt \\[page id: space=[1-9][0-9]*, page number=[1-9][0-9]*\\]");
call mtr.add_suppression("InnoDB: Unable to decompress ..test.t[1-3]\\.ibd\\[page id: space=[1-9][0-9]*, page number=[0-9]+\\]");
call mtr.add_suppression("InnoDB: Table `test`\\.`t[12]` is corrupted");
diff --git a/mysql-test/suite/encryption/r/innodb-redo-badkey.result b/mysql-test/suite/encryption/r/innodb-redo-badkey.result
index 87377a01479..b1c4ae913fa 100644
--- a/mysql-test/suite/encryption/r/innodb-redo-badkey.result
+++ b/mysql-test/suite/encryption/r/innodb-redo-badkey.result
@@ -1,6 +1,7 @@
call mtr.add_suppression("Plugin 'file_key_management'");
call mtr.add_suppression("Plugin 'InnoDB' init function returned error.");
-call mtr.add_suppression("InnoDB: The page \\[page id: space=[1-9][0-9]*, page number=[1-9][0-9]*\\] in file '.*test.t[1-4]\\.ibd' cannot be decrypted");
+call mtr.add_suppression("InnoDB: The page \\[page id: space=[1-9][0-9]*, page number=[1-9][0-9]*\\] in file '.*test.t[1-4]\\.ibd' cannot be decrypted; key_version=1");
+call mtr.add_suppression("InnoDB: File '.*test/t[1234]\\.ibd' is corrupted");
call mtr.add_suppression("failed to read or decrypt \\[page id: space=[1-9][0-9]*, page number=[1-9][0-9]*\\]");
call mtr.add_suppression("InnoDB: Unable to decompress .*.test.t[12]\\.ibd\\[page id: space=[1-9][0-9]*, page number=[0-9]+\\]");
call mtr.add_suppression("InnoDB: Database page corruption on disk or a failed read of file '.*test.t[12]\\.ibd'");
diff --git a/mysql-test/suite/encryption/t/innodb-bad-key-change.test b/mysql-test/suite/encryption/t/innodb-bad-key-change.test
index 942038dedc4..05a3b5f4d06 100644
--- a/mysql-test/suite/encryption/t/innodb-bad-key-change.test
+++ b/mysql-test/suite/encryption/t/innodb-bad-key-change.test
@@ -12,8 +12,8 @@ call mtr.add_suppression("Plugin 'file_key_management' init function returned er
call mtr.add_suppression("Plugin 'file_key_management' registration.*failed");
call mtr.add_suppression("InnoDB: Table `test`\\.`t[12]` has an unreadable root page");
call mtr.add_suppression("Table .*t[12].* is corrupted");
-call mtr.add_suppression("InnoDB: The page \\[page id: space=[1-9][0-9]*, page number=[1-9][0-9]*\\] in file '.*test.t[12]\\.ibd' cannot be decrypted\\.");
-call mtr.add_suppression("failed to read or decrypt \\[page id: space=[1-9][0-9]*, page number=[1-9][0-9]*\\]");
+call mtr.add_suppression("InnoDB: The page \\[page id: space=[1-9][0-9]*, page number=[1-9][0-9]*\\] in file '.*test.t[12]\\.ibd' cannot be decrypted; key_version=1");
+call mtr.add_suppression("failed to read \\[page id: space=[1-9][0-9]*, page number=[1-9][0-9]*\\]");
call mtr.add_suppression("InnoDB: Encrypted page \\[page id: space=[1-9][0-9]*, page number=3\\] in file .*test.t1.ibd looks corrupted; key_version=1");
call mtr.add_suppression("File '.*mysql-test.std_data.keysbad3\\.txt' not found");
# for innodb_checksum_algorithm=full_crc32 only
diff --git a/mysql-test/suite/encryption/t/innodb-bad-key-change2.test b/mysql-test/suite/encryption/t/innodb-bad-key-change2.test
index ad0f06ab5ff..8a3ecf9deb0 100644
--- a/mysql-test/suite/encryption/t/innodb-bad-key-change2.test
+++ b/mysql-test/suite/encryption/t/innodb-bad-key-change2.test
@@ -9,7 +9,7 @@
# MDEV-8727: Server/InnoDB hangs on shutdown after trying to read an encrypted table with a wrong key
#
call mtr.add_suppression("InnoDB: Table `test`\\.`t1` (has an unreadable root page|does not exist.*is trying to rename)");
-call mtr.add_suppression("InnoDB: The page \\[page id: space=[1-9][0-9]*, page number=[1-9][0-9]*\\] in file '.*test.t1(new)?\\.ibd' cannot be decrypted\\.");
+call mtr.add_suppression("InnoDB: The page \\[page id: space=[1-9][0-9]*, page number=[1-9][0-9]*\\] in file '.*test.t1(new)?\\.ibd' cannot be decrypted; key_version=1");
call mtr.add_suppression("failed to read or decrypt \\[page id: space=[1-9][0-9]*, page number=[1-9][0-9]*\\]");
# Suppression for builds where file_key_management plugin is linked statically
call mtr.add_suppression("Couldn't load plugins from 'file_key_management");
diff --git a/mysql-test/suite/encryption/t/innodb-bad-key-change4.test b/mysql-test/suite/encryption/t/innodb-bad-key-change4.test
index bc060776ecd..3b4dfb8c1f2 100644
--- a/mysql-test/suite/encryption/t/innodb-bad-key-change4.test
+++ b/mysql-test/suite/encryption/t/innodb-bad-key-change4.test
@@ -7,8 +7,8 @@
# MDEV-8768: Server crash at file btr0btr.ic line 122 when checking encrypted table using incorrect keys
#
-call mtr.add_suppression("InnoDB: Table `test`\\.`t1` has an unreadable root page");
-call mtr.add_suppression("InnoDB: The page \\[page id: space=[1-9][0-9]*, page number=[1-9][0-9]*\\] in file '.*test.t1\\.ibd' cannot be decrypted\\.");
+call mtr.add_suppression("InnoDB: Table `test`\\.`t1` (has an unreadable root page)");
+call mtr.add_suppression("InnoDB: The page \\[page id: space=[1-9][0-9]*, page number=[1-9][0-9]*\\] in file '.*test.t1\\.ibd' cannot be decrypted; key_version=1");
call mtr.add_suppression("failed to read or decrypt \\[page id: space=[1-9][0-9]*, page number=[1-9][0-9]*\\]");
# Suppression for builds where file_key_management plugin is linked statically
call mtr.add_suppression("Couldn't load plugins from 'file_key_management");
diff --git a/mysql-test/suite/encryption/t/innodb-compressed-blob.test b/mysql-test/suite/encryption/t/innodb-compressed-blob.test
index 261fdd73aa1..1bc9e2a879a 100644
--- a/mysql-test/suite/encryption/t/innodb-compressed-blob.test
+++ b/mysql-test/suite/encryption/t/innodb-compressed-blob.test
@@ -4,7 +4,7 @@
# embedded does not support restart
-- source include/not_embedded.inc
-call mtr.add_suppression("InnoDB: The page \\[page id: space=[1-9][0-9]*, page number=[1-9][0-9]*\\] in file '.*test.t[123]\\.ibd' cannot be decrypted\\.");
+call mtr.add_suppression("InnoDB: The page \\[page id: space=[1-9][0-9]*, page number=[1-9][0-9]*\\] in file '.*test.t[123]\\.ibd' cannot be decrypted; key_version=1");
call mtr.add_suppression("failed to read or decrypt \\[page id: space=[1-9][0-9]*, page number=[1-9][0-9]*\\]");
call mtr.add_suppression("InnoDB: Unable to decompress ..test.t[1-3]\\.ibd\\[page id: space=[1-9][0-9]*, page number=[0-9]+\\]");
call mtr.add_suppression("InnoDB: Table `test`\\.`t[12]` is corrupted");
diff --git a/mysql-test/suite/encryption/t/innodb-redo-badkey.test b/mysql-test/suite/encryption/t/innodb-redo-badkey.test
index 09ad7a7d5a3..81febb92c5b 100644
--- a/mysql-test/suite/encryption/t/innodb-redo-badkey.test
+++ b/mysql-test/suite/encryption/t/innodb-redo-badkey.test
@@ -9,7 +9,8 @@
call mtr.add_suppression("Plugin 'file_key_management'");
call mtr.add_suppression("Plugin 'InnoDB' init function returned error.");
-call mtr.add_suppression("InnoDB: The page \\[page id: space=[1-9][0-9]*, page number=[1-9][0-9]*\\] in file '.*test.t[1-4]\\.ibd' cannot be decrypted");
+call mtr.add_suppression("InnoDB: The page \\[page id: space=[1-9][0-9]*, page number=[1-9][0-9]*\\] in file '.*test.t[1-4]\\.ibd' cannot be decrypted; key_version=1");
+call mtr.add_suppression("InnoDB: File '.*test/t[1234]\\.ibd' is corrupted");
call mtr.add_suppression("failed to read or decrypt \\[page id: space=[1-9][0-9]*, page number=[1-9][0-9]*\\]");
call mtr.add_suppression("InnoDB: Unable to decompress .*.test.t[12]\\.ibd\\[page id: space=[1-9][0-9]*, page number=[0-9]+\\]");
call mtr.add_suppression("InnoDB: Database page corruption on disk or a failed read of file '.*test.t[12]\\.ibd'");
diff --git a/mysql-test/suite/galera/r/MDEV-18832.result b/mysql-test/suite/galera/r/MDEV-18832.result
index 700a0bbefb1..2e0872b9f2e 100644
--- a/mysql-test/suite/galera/r/MDEV-18832.result
+++ b/mysql-test/suite/galera/r/MDEV-18832.result
@@ -12,3 +12,6 @@ INSERT INTO t1 VALUES (NEXT VALUE FOR Seq1_1);
ERROR 23000: Duplicate entry '1' for key 'PRIMARY'
DROP SEQUENCE Seq1_1;
DROP TABLE t1;
+CALL mtr.add_suppression("SEQUENCES declared without `NOCACHE` will not behave correctly in galera cluster.");
+connection node_2;
+CALL mtr.add_suppression("SEQUENCES declared without `NOCACHE` will not behave correctly in galera cluster.");
diff --git a/mysql-test/suite/galera/r/MDEV-27862.result b/mysql-test/suite/galera/r/MDEV-27862.result
new file mode 100644
index 00000000000..25b7bc6cfd2
--- /dev/null
+++ b/mysql-test/suite/galera/r/MDEV-27862.result
@@ -0,0 +1,54 @@
+connection node_2;
+connection node_1;
+CREATE SEQUENCE seq_nocache ENGINE=InnoDB;
+DROP SEQUENCE seq_nocache;
+CALL mtr.add_suppression("SEQUENCES declared without `NOCACHE` will not behave correctly in galera cluster.");
+connection node_2;
+CALL mtr.add_suppression("SEQUENCES declared without `NOCACHE` will not behave correctly in galera cluster.");
+connection node_1;
+CREATE SEQUENCE seq NOCACHE ENGINE=InnoDB;
+SELECT NEXTVAL(seq) = 1;
+NEXTVAL(seq) = 1
+1
+connection node_2;
+SELECT NEXTVAL(seq) = 2;
+NEXTVAL(seq) = 2
+1
+connection node_1;
+SELECT NEXTVAL(seq) = 3;
+NEXTVAL(seq) = 3
+1
+SELECT SETVAL(seq, 100);
+SETVAL(seq, 100)
+100
+connection node_2;
+SELECT NEXTVAL(seq) = 101;
+NEXTVAL(seq) = 101
+1
+connection node_1;
+SELECT NEXTVAL(seq) = 102;
+NEXTVAL(seq) = 102
+1
+DROP SEQUENCE seq;
+CREATE TABLE t1(f1 INT);
+CREATE SEQUENCE seq_transaction NOCACHE ENGINE=InnoDB;
+START TRANSACTION;
+INSERT INTO t1 VALUES (0);
+SELECT NEXTVAL(seq_transaction);
+NEXTVAL(seq_transaction)
+1
+INSERT INTO t1 VALUES (NEXTVAL(seq_transaction));
+COMMIT;
+connection node_2;
+SELECT COUNT(*) = 2 FROM t1;
+COUNT(*) = 2
+1
+SELECT NEXTVAL(seq_transaction) = 3;
+NEXTVAL(seq_transaction) = 3
+1
+connection node_1;
+SELECT NEXTVAL(seq_transaction) = 4;
+NEXTVAL(seq_transaction) = 4
+1
+DROP SEQUENCE seq_transaction;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera/r/galera_ist_MDEV-28423,debug.rdiff b/mysql-test/suite/galera/r/galera_ist_MDEV-28423,debug.rdiff
index 8c84321e774..f9f81ea3b40 100644
--- a/mysql-test/suite/galera/r/galera_ist_MDEV-28423,debug.rdiff
+++ b/mysql-test/suite/galera/r/galera_ist_MDEV-28423,debug.rdiff
@@ -1,27 +1,27 @@
--- r/galera_ist_MDEV-28423.result
-+++ r/galera_ist_MDEV-28423,debug.reject
-@@ -517,3 +517,187 @@
- 1
++++ r/galera_ist_MDEV-28423.reject
+@@ -286,3 +286,111 @@
DROP TABLE t1;
COMMIT;
+ SET AUTOCOMMIT=ON;
+Performing State Transfer on a server that has been killed and restarted
+while a DDL was in progress on it
+connection node_1;
-+CREATE TABLE t1 (id int not null primary key,f1 CHAR(255)) ENGINE=InnoDB;
++CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
-+INSERT INTO t1 VALUES (1,'node1_committed_before');
-+INSERT INTO t1 VALUES (2,'node1_committed_before');
-+INSERT INTO t1 VALUES (3,'node1_committed_before');
-+INSERT INTO t1 VALUES (4,'node1_committed_before');
-+INSERT INTO t1 VALUES (5,'node1_committed_before');
++INSERT INTO t1 VALUES ('node1_committed_before');
++INSERT INTO t1 VALUES ('node1_committed_before');
++INSERT INTO t1 VALUES ('node1_committed_before');
++INSERT INTO t1 VALUES ('node1_committed_before');
++INSERT INTO t1 VALUES ('node1_committed_before');
+connection node_2;
+START TRANSACTION;
-+INSERT INTO t1 VALUES (6,'node2_committed_before');
-+INSERT INTO t1 VALUES (7,'node2_committed_before');
-+INSERT INTO t1 VALUES (8,'node2_committed_before');
-+INSERT INTO t1 VALUES (9,'node2_committed_before');
-+INSERT INTO t1 VALUES (10,'node2_committed_before');
++INSERT INTO t1 VALUES ('node2_committed_before');
++INSERT INTO t1 VALUES ('node2_committed_before');
++INSERT INTO t1 VALUES ('node2_committed_before');
++INSERT INTO t1 VALUES ('node2_committed_before');
++INSERT INTO t1 VALUES ('node2_committed_before');
+COMMIT;
+SET GLOBAL debug_dbug = 'd,sync.alter_opened_table';
+connection node_1;
@@ -32,26 +32,26 @@
+connection node_1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
-+INSERT INTO t1 (id,f1) VALUES (11,'node1_committed_during');
-+INSERT INTO t1 (id,f1) VALUES (12,'node1_committed_during');
-+INSERT INTO t1 (id,f1) VALUES (13,'node1_committed_during');
-+INSERT INTO t1 (id,f1) VALUES (14,'node1_committed_during');
-+INSERT INTO t1 (id,f1) VALUES (15,'node1_committed_during');
++INSERT INTO t1 (f1) VALUES ('node1_committed_during');
++INSERT INTO t1 (f1) VALUES ('node1_committed_during');
++INSERT INTO t1 (f1) VALUES ('node1_committed_during');
++INSERT INTO t1 (f1) VALUES ('node1_committed_during');
++INSERT INTO t1 (f1) VALUES ('node1_committed_during');
+COMMIT;
+START TRANSACTION;
-+INSERT INTO t1 (id,f1) VALUES (16,'node1_to_be_committed_after');
-+INSERT INTO t1 (id,f1) VALUES (17,'node1_to_be_committed_after');
-+INSERT INTO t1 (id,f1) VALUES (18,'node1_to_be_committed_after');
-+INSERT INTO t1 (id,f1) VALUES (19,'node1_to_be_committed_after');
-+INSERT INTO t1 (id,f1) VALUES (20,'node1_to_be_committed_after');
++INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
++INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
++INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
++INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
++INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
+connect node_1a_galera_st_kill_slave_ddl, 127.0.0.1, root, , test, $NODE_MYPORT_1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
-+INSERT INTO t1 (id,f1) VALUES (21,'node1_to_be_rollbacked_after');
-+INSERT INTO t1 (id,f1) VALUES (22,'node1_to_be_rollbacked_after');
-+INSERT INTO t1 (id,f1) VALUES (23,'node1_to_be_rollbacked_after');
-+INSERT INTO t1 (id,f1) VALUES (24,'node1_to_be_rollbacked_after');
-+INSERT INTO t1 (id,f1) VALUES (25,'node1_to_be_rollbacked_after');
++INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
++INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
++INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
++INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
++INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
+connection node_2;
+Performing --wsrep-recover ...
+connection node_2;
@@ -59,132 +59,56 @@
+Using --wsrep-start-position when starting mysqld ...
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
-+INSERT INTO t1 (id,f1) VALUES (26,'node2_committed_after');
-+INSERT INTO t1 (id,f1) VALUES (27,'node2_committed_after');
-+INSERT INTO t1 (id,f1) VALUES (28,'node2_committed_after');
-+INSERT INTO t1 (id,f1) VALUES (29,'node2_committed_after');
-+INSERT INTO t1 (id,f1) VALUES (30,'node2_committed_after');
++INSERT INTO t1 (f1) VALUES ('node2_committed_after');
++INSERT INTO t1 (f1) VALUES ('node2_committed_after');
++INSERT INTO t1 (f1) VALUES ('node2_committed_after');
++INSERT INTO t1 (f1) VALUES ('node2_committed_after');
++INSERT INTO t1 (f1) VALUES ('node2_committed_after');
+COMMIT;
+connection node_1;
-+INSERT INTO t1 (id,f1) VALUES (31,'node1_to_be_committed_after');
-+INSERT INTO t1 (id,f1) VALUES (32,'node1_to_be_committed_after');
-+INSERT INTO t1 (id,f1) VALUES (33,'node1_to_be_committed_after');
-+INSERT INTO t1 (id,f1) VALUES (34,'node1_to_be_committed_after');
-+INSERT INTO t1 (id,f1) VALUES (35,'node1_to_be_committed_after');
++INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
++INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
++INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
++INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
++INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
+COMMIT;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
-+INSERT INTO t1 (id,f1) VALUES (36,'node1_committed_after');
-+INSERT INTO t1 (id,f1) VALUES (37,'node1_committed_after');
-+INSERT INTO t1 (id,f1) VALUES (38,'node1_committed_after');
-+INSERT INTO t1 (id,f1) VALUES (39,'node1_committed_after');
-+INSERT INTO t1 (id,f1) VALUES (40,'node1_committed_after');
++INSERT INTO t1 (f1) VALUES ('node1_committed_after');
++INSERT INTO t1 (f1) VALUES ('node1_committed_after');
++INSERT INTO t1 (f1) VALUES ('node1_committed_after');
++INSERT INTO t1 (f1) VALUES ('node1_committed_after');
++INSERT INTO t1 (f1) VALUES ('node1_committed_after');
+COMMIT;
+connection node_1a_galera_st_kill_slave_ddl;
-+INSERT INTO t1 (id,f1) VALUES (41,'node1_to_be_rollbacked_after');
-+INSERT INTO t1 (id,f1) VALUES (42,'node1_to_be_rollbacked_after');
-+INSERT INTO t1 (id,f1) VALUES (43,'node1_to_be_rollbacked_after');
-+INSERT INTO t1 (id,f1) VALUES (44,'node1_to_be_rollbacked_after');
-+INSERT INTO t1 (id,f1) VALUES (45,'node1_to_be_rollbacked_after');
++INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
++INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
++INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
++INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
++INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
+ROLLBACK;
-+SET AUTOCOMMIT=ON;
-+SET SESSION wsrep_sync_wait=15;
-+SELECT COUNT(*) AS EXPECT_3 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
-+EXPECT_3
-+3
-+SELECT COUNT(*) AS EXPECT_35 FROM t1;
-+EXPECT_35
-+35
-+SELECT * FROM t1;
-+id f1 f2
-+1 node1_committed_before NULL
-+2 node1_committed_before NULL
-+3 node1_committed_before NULL
-+4 node1_committed_before NULL
-+5 node1_committed_before NULL
-+6 node2_committed_before NULL
-+7 node2_committed_before NULL
-+8 node2_committed_before NULL
-+9 node2_committed_before NULL
-+10 node2_committed_before NULL
-+11 node1_committed_during NULL
-+12 node1_committed_during NULL
-+13 node1_committed_during NULL
-+14 node1_committed_during NULL
-+15 node1_committed_during NULL
-+16 node1_to_be_committed_after NULL
-+17 node1_to_be_committed_after NULL
-+18 node1_to_be_committed_after NULL
-+19 node1_to_be_committed_after NULL
-+20 node1_to_be_committed_after NULL
-+26 node2_committed_after NULL
-+27 node2_committed_after NULL
-+28 node2_committed_after NULL
-+29 node2_committed_after NULL
-+30 node2_committed_after NULL
-+31 node1_to_be_committed_after NULL
-+32 node1_to_be_committed_after NULL
-+33 node1_to_be_committed_after NULL
-+34 node1_to_be_committed_after NULL
-+35 node1_to_be_committed_after NULL
-+36 node1_committed_after NULL
-+37 node1_committed_after NULL
-+38 node1_committed_after NULL
-+39 node1_committed_after NULL
-+40 node1_committed_after NULL
++SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
++COUNT(*) = 2
++1
++SELECT COUNT(*) = 35 FROM t1;
++COUNT(*) = 35
++1
+SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1;
+COUNT(*) = 0
+1
+COMMIT;
-+connection node_1;
+SET AUTOCOMMIT=ON;
-+SET SESSION wsrep_sync_wait=15;
-+SELECT COUNT(*) AS EXPECT_3 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
-+EXPECT_3
-+3
-+SELECT COUNT(*) AS EXPECT_35 FROM t1;
-+EXPECT_35
-+35
-+SELECT * FROM t1;
-+id f1 f2
-+1 node1_committed_before NULL
-+2 node1_committed_before NULL
-+3 node1_committed_before NULL
-+4 node1_committed_before NULL
-+5 node1_committed_before NULL
-+6 node2_committed_before NULL
-+7 node2_committed_before NULL
-+8 node2_committed_before NULL
-+9 node2_committed_before NULL
-+10 node2_committed_before NULL
-+11 node1_committed_during NULL
-+12 node1_committed_during NULL
-+13 node1_committed_during NULL
-+14 node1_committed_during NULL
-+15 node1_committed_during NULL
-+16 node1_to_be_committed_after NULL
-+17 node1_to_be_committed_after NULL
-+18 node1_to_be_committed_after NULL
-+19 node1_to_be_committed_after NULL
-+20 node1_to_be_committed_after NULL
-+26 node2_committed_after NULL
-+27 node2_committed_after NULL
-+28 node2_committed_after NULL
-+29 node2_committed_after NULL
-+30 node2_committed_after NULL
-+31 node1_to_be_committed_after NULL
-+32 node1_to_be_committed_after NULL
-+33 node1_to_be_committed_after NULL
-+34 node1_to_be_committed_after NULL
-+35 node1_to_be_committed_after NULL
-+36 node1_committed_after NULL
-+37 node1_committed_after NULL
-+38 node1_committed_after NULL
-+39 node1_committed_after NULL
-+40 node1_committed_after NULL
++connection node_1;
++SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
++COUNT(*) = 2
++1
++SELECT COUNT(*) = 35 FROM t1;
++COUNT(*) = 35
++1
+SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1;
+COUNT(*) = 0
+1
+DROP TABLE t1;
+COMMIT;
++SET AUTOCOMMIT=ON;
+SET GLOBAL debug_dbug = $debug_orig;
diff --git a/mysql-test/suite/galera/r/galera_ist_MDEV-28423.result b/mysql-test/suite/galera/r/galera_ist_MDEV-28423.result
index 5a71b490a80..80a28d349ba 100644
--- a/mysql-test/suite/galera/r/galera_ist_MDEV-28423.result
+++ b/mysql-test/suite/galera/r/galera_ist_MDEV-28423.result
@@ -1,519 +1,287 @@
-connection node_2;
-connection node_1;
connection node_1;
connection node_2;
Performing State Transfer on a server that has been temporarily disconnected
connection node_1;
-CREATE TABLE t1 (id int not null primary key,f1 CHAR(255)) ENGINE=InnoDB;
+CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
-INSERT INTO t1 VALUES (1,'node1_committed_before');
-INSERT INTO t1 VALUES (2,'node1_committed_before');
-INSERT INTO t1 VALUES (3,'node1_committed_before');
-INSERT INTO t1 VALUES (4,'node1_committed_before');
-INSERT INTO t1 VALUES (5,'node1_committed_before');
+INSERT INTO t1 VALUES ('node1_committed_before');
+INSERT INTO t1 VALUES ('node1_committed_before');
+INSERT INTO t1 VALUES ('node1_committed_before');
+INSERT INTO t1 VALUES ('node1_committed_before');
+INSERT INTO t1 VALUES ('node1_committed_before');
COMMIT;
connection node_2;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
-INSERT INTO t1 VALUES (6,'node2_committed_before');
-INSERT INTO t1 VALUES (7,'node2_committed_before');
-INSERT INTO t1 VALUES (8,'node2_committed_before');
-INSERT INTO t1 VALUES (9,'node2_committed_before');
-INSERT INTO t1 VALUES (10,'node2_committed_before');
+INSERT INTO t1 VALUES ('node2_committed_before');
+INSERT INTO t1 VALUES ('node2_committed_before');
+INSERT INTO t1 VALUES ('node2_committed_before');
+INSERT INTO t1 VALUES ('node2_committed_before');
+INSERT INTO t1 VALUES ('node2_committed_before');
COMMIT;
Unloading wsrep provider ...
SET GLOBAL wsrep_cluster_address = '';
connection node_1;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
-INSERT INTO t1 VALUES (11,'node1_committed_during');
-INSERT INTO t1 VALUES (12,'node1_committed_during');
-INSERT INTO t1 VALUES (13,'node1_committed_during');
-INSERT INTO t1 VALUES (14,'node1_committed_during');
-INSERT INTO t1 VALUES (15,'node1_committed_during');
+INSERT INTO t1 VALUES ('node1_committed_during');
+INSERT INTO t1 VALUES ('node1_committed_during');
+INSERT INTO t1 VALUES ('node1_committed_during');
+INSERT INTO t1 VALUES ('node1_committed_during');
+INSERT INTO t1 VALUES ('node1_committed_during');
COMMIT;
START TRANSACTION;
-INSERT INTO t1 VALUES (16,'node1_to_be_committed_after');
-INSERT INTO t1 VALUES (17,'node1_to_be_committed_after');
-INSERT INTO t1 VALUES (18,'node1_to_be_committed_after');
-INSERT INTO t1 VALUES (19,'node1_to_be_committed_after');
-INSERT INTO t1 VALUES (20,'node1_to_be_committed_after');
+INSERT INTO t1 VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 VALUES ('node1_to_be_committed_after');
connect node_1a_galera_st_disconnect_slave, 127.0.0.1, root, , test, $NODE_MYPORT_1;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
-INSERT INTO t1 VALUES (21,'node1_to_be_rollbacked_after');
-INSERT INTO t1 VALUES (22,'node1_to_be_rollbacked_after');
-INSERT INTO t1 VALUES (23,'node1_to_be_rollbacked_after');
-INSERT INTO t1 VALUES (24,'node1_to_be_rollbacked_after');
-INSERT INTO t1 VALUES (25,'node1_to_be_rollbacked_after');
+INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
connection node_2;
Loading wsrep provider ...
-disconnect node_2;
-connect node_2, 127.0.0.1, root, , test, $NODE_MYPORT_2;
-connection node_2;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
-INSERT INTO t1 VALUES (26,'node2_committed_after');
-INSERT INTO t1 VALUES (27,'node2_committed_after');
-INSERT INTO t1 VALUES (28,'node2_committed_after');
-INSERT INTO t1 VALUES (29,'node2_committed_after');
-INSERT INTO t1 VALUES (30,'node2_committed_after');
+INSERT INTO t1 VALUES ('node2_committed_after');
+INSERT INTO t1 VALUES ('node2_committed_after');
+INSERT INTO t1 VALUES ('node2_committed_after');
+INSERT INTO t1 VALUES ('node2_committed_after');
+INSERT INTO t1 VALUES ('node2_committed_after');
COMMIT;
connection node_1;
-INSERT INTO t1 VALUES (31,'node1_to_be_committed_after');
-INSERT INTO t1 VALUES (32,'node1_to_be_committed_after');
-INSERT INTO t1 VALUES (33,'node1_to_be_committed_after');
-INSERT INTO t1 VALUES (34,'node1_to_be_committed_after');
-INSERT INTO t1 VALUES (35,'node1_to_be_committed_after');
+INSERT INTO t1 VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 VALUES ('node1_to_be_committed_after');
COMMIT;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
-INSERT INTO t1 VALUES (36,'node1_committed_after');
-INSERT INTO t1 VALUES (37,'node1_committed_after');
-INSERT INTO t1 VALUES (38,'node1_committed_after');
-INSERT INTO t1 VALUES (39,'node1_committed_after');
-INSERT INTO t1 VALUES (40,'node1_committed_after');
+INSERT INTO t1 VALUES ('node1_committed_after');
+INSERT INTO t1 VALUES ('node1_committed_after');
+INSERT INTO t1 VALUES ('node1_committed_after');
+INSERT INTO t1 VALUES ('node1_committed_after');
+INSERT INTO t1 VALUES ('node1_committed_after');
COMMIT;
connection node_1a_galera_st_disconnect_slave;
-INSERT INTO t1 VALUES (41,'node1_to_be_rollbacked_after');
-INSERT INTO t1 VALUES (42,'node1_to_be_rollbacked_after');
-INSERT INTO t1 VALUES (43,'node1_to_be_rollbacked_after');
-INSERT INTO t1 VALUES (44,'node1_to_be_rollbacked_after');
-INSERT INTO t1 VALUES (45,'node1_to_be_rollbacked_after');
+INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
ROLLBACK;
-SET AUTOCOMMIT=ON;
-SET SESSION wsrep_sync_wait=15;
-SELECT COUNT(*) AS EXPECT_35 FROM t1;
-EXPECT_35
-35
-SELECT * FROM t1;
-id f1
-1 node1_committed_before
-2 node1_committed_before
-3 node1_committed_before
-4 node1_committed_before
-5 node1_committed_before
-6 node2_committed_before
-7 node2_committed_before
-8 node2_committed_before
-9 node2_committed_before
-10 node2_committed_before
-11 node1_committed_during
-12 node1_committed_during
-13 node1_committed_during
-14 node1_committed_during
-15 node1_committed_during
-16 node1_to_be_committed_after
-17 node1_to_be_committed_after
-18 node1_to_be_committed_after
-19 node1_to_be_committed_after
-20 node1_to_be_committed_after
-26 node2_committed_after
-27 node2_committed_after
-28 node2_committed_after
-29 node2_committed_after
-30 node2_committed_after
-31 node1_to_be_committed_after
-32 node1_to_be_committed_after
-33 node1_to_be_committed_after
-34 node1_to_be_committed_after
-35 node1_to_be_committed_after
-36 node1_committed_after
-37 node1_committed_after
-38 node1_committed_after
-39 node1_committed_after
-40 node1_committed_after
+SELECT COUNT(*) = 35 FROM t1;
+COUNT(*) = 35
+1
SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1;
COUNT(*) = 0
1
-connection node_1;
+COMMIT;
SET AUTOCOMMIT=ON;
-SET SESSION wsrep_sync_wait=15;
-SELECT COUNT(*) AS EXPECT_35 FROM t1;
-EXPECT_35
-35
-SELECT * FROM t1;
-id f1
-1 node1_committed_before
-2 node1_committed_before
-3 node1_committed_before
-4 node1_committed_before
-5 node1_committed_before
-6 node2_committed_before
-7 node2_committed_before
-8 node2_committed_before
-9 node2_committed_before
-10 node2_committed_before
-11 node1_committed_during
-12 node1_committed_during
-13 node1_committed_during
-14 node1_committed_during
-15 node1_committed_during
-16 node1_to_be_committed_after
-17 node1_to_be_committed_after
-18 node1_to_be_committed_after
-19 node1_to_be_committed_after
-20 node1_to_be_committed_after
-26 node2_committed_after
-27 node2_committed_after
-28 node2_committed_after
-29 node2_committed_after
-30 node2_committed_after
-31 node1_to_be_committed_after
-32 node1_to_be_committed_after
-33 node1_to_be_committed_after
-34 node1_to_be_committed_after
-35 node1_to_be_committed_after
-36 node1_committed_after
-37 node1_committed_after
-38 node1_committed_after
-39 node1_committed_after
-40 node1_committed_after
+connection node_1;
+SELECT COUNT(*) = 35 FROM t1;
+COUNT(*) = 35
+1
SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1;
COUNT(*) = 0
1
DROP TABLE t1;
COMMIT;
+SET AUTOCOMMIT=ON;
Performing State Transfer on a server that has been shut down cleanly and restarted
connection node_1;
-CREATE TABLE t1 (id int not null primary key,f1 CHAR(255)) ENGINE=InnoDB;
+CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
-INSERT INTO t1 VALUES (1,'node1_committed_before');
-INSERT INTO t1 VALUES (2,'node1_committed_before');
-INSERT INTO t1 VALUES (3,'node1_committed_before');
-INSERT INTO t1 VALUES (4,'node1_committed_before');
-INSERT INTO t1 VALUES (5,'node1_committed_before');
+INSERT INTO t1 VALUES ('node1_committed_before');
+INSERT INTO t1 VALUES ('node1_committed_before');
+INSERT INTO t1 VALUES ('node1_committed_before');
+INSERT INTO t1 VALUES ('node1_committed_before');
+INSERT INTO t1 VALUES ('node1_committed_before');
COMMIT;
connection node_2;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
-INSERT INTO t1 VALUES (6,'node2_committed_before');
-INSERT INTO t1 VALUES (7,'node2_committed_before');
-INSERT INTO t1 VALUES (8,'node2_committed_before');
-INSERT INTO t1 VALUES (9,'node2_committed_before');
-INSERT INTO t1 VALUES (10,'node2_committed_before');
+INSERT INTO t1 VALUES ('node2_committed_before');
+INSERT INTO t1 VALUES ('node2_committed_before');
+INSERT INTO t1 VALUES ('node2_committed_before');
+INSERT INTO t1 VALUES ('node2_committed_before');
+INSERT INTO t1 VALUES ('node2_committed_before');
COMMIT;
Shutting down server ...
connection node_1;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
-INSERT INTO t1 VALUES (11,'node1_committed_during');
-INSERT INTO t1 VALUES (12,'node1_committed_during');
-INSERT INTO t1 VALUES (13,'node1_committed_during');
-INSERT INTO t1 VALUES (14,'node1_committed_during');
-INSERT INTO t1 VALUES (15,'node1_committed_during');
+INSERT INTO t1 VALUES ('node1_committed_during');
+INSERT INTO t1 VALUES ('node1_committed_during');
+INSERT INTO t1 VALUES ('node1_committed_during');
+INSERT INTO t1 VALUES ('node1_committed_during');
+INSERT INTO t1 VALUES ('node1_committed_during');
COMMIT;
START TRANSACTION;
-INSERT INTO t1 VALUES (16,'node1_to_be_committed_after');
-INSERT INTO t1 VALUES (17,'node1_to_be_committed_after');
-INSERT INTO t1 VALUES (18,'node1_to_be_committed_after');
-INSERT INTO t1 VALUES (19,'node1_to_be_committed_after');
-INSERT INTO t1 VALUES (20,'node1_to_be_committed_after');
+INSERT INTO t1 VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 VALUES ('node1_to_be_committed_after');
connect node_1a_galera_st_shutdown_slave, 127.0.0.1, root, , test, $NODE_MYPORT_1;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
-INSERT INTO t1 VALUES (21,'node1_to_be_rollbacked_after');
-INSERT INTO t1 VALUES (22,'node1_to_be_rollbacked_after');
-INSERT INTO t1 VALUES (23,'node1_to_be_rollbacked_after');
-INSERT INTO t1 VALUES (24,'node1_to_be_rollbacked_after');
-INSERT INTO t1 VALUES (25,'node1_to_be_rollbacked_after');
+INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
connection node_2;
Starting server ...
SET AUTOCOMMIT=OFF;
START TRANSACTION;
-INSERT INTO t1 VALUES (26,'node2_committed_after');
-INSERT INTO t1 VALUES (27,'node2_committed_after');
-INSERT INTO t1 VALUES (28,'node2_committed_after');
-INSERT INTO t1 VALUES (29,'node2_committed_after');
-INSERT INTO t1 VALUES (30,'node2_committed_after');
+INSERT INTO t1 VALUES ('node2_committed_after');
+INSERT INTO t1 VALUES ('node2_committed_after');
+INSERT INTO t1 VALUES ('node2_committed_after');
+INSERT INTO t1 VALUES ('node2_committed_after');
+INSERT INTO t1 VALUES ('node2_committed_after');
COMMIT;
connection node_1;
-INSERT INTO t1 VALUES (31,'node1_to_be_committed_after');
-INSERT INTO t1 VALUES (32,'node1_to_be_committed_after');
-INSERT INTO t1 VALUES (33,'node1_to_be_committed_after');
-INSERT INTO t1 VALUES (34,'node1_to_be_committed_after');
-INSERT INTO t1 VALUES (35,'node1_to_be_committed_after');
+INSERT INTO t1 VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 VALUES ('node1_to_be_committed_after');
COMMIT;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
-INSERT INTO t1 VALUES (36,'node1_committed_after');
-INSERT INTO t1 VALUES (37,'node1_committed_after');
-INSERT INTO t1 VALUES (38,'node1_committed_after');
-INSERT INTO t1 VALUES (39,'node1_committed_after');
-INSERT INTO t1 VALUES (40,'node1_committed_after');
+INSERT INTO t1 VALUES ('node1_committed_after');
+INSERT INTO t1 VALUES ('node1_committed_after');
+INSERT INTO t1 VALUES ('node1_committed_after');
+INSERT INTO t1 VALUES ('node1_committed_after');
+INSERT INTO t1 VALUES ('node1_committed_after');
COMMIT;
connection node_1a_galera_st_shutdown_slave;
-INSERT INTO t1 VALUES (41,'node1_to_be_rollbacked_after');
-INSERT INTO t1 VALUES (42,'node1_to_be_rollbacked_after');
-INSERT INTO t1 VALUES (43,'node1_to_be_rollbacked_after');
-INSERT INTO t1 VALUES (44,'node1_to_be_rollbacked_after');
-INSERT INTO t1 VALUES (45,'node1_to_be_rollbacked_after');
+INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
ROLLBACK;
-SET AUTOCOMMIT=ON;
-SET SESSION wsrep_sync_wait=15;
-SELECT COUNT(*) AS EXPECT_15 FROM t1;
-EXPECT_15
-35
-SELECT * from t1;
-id f1
-1 node1_committed_before
-2 node1_committed_before
-3 node1_committed_before
-4 node1_committed_before
-5 node1_committed_before
-6 node2_committed_before
-7 node2_committed_before
-8 node2_committed_before
-9 node2_committed_before
-10 node2_committed_before
-11 node1_committed_during
-12 node1_committed_during
-13 node1_committed_during
-14 node1_committed_during
-15 node1_committed_during
-16 node1_to_be_committed_after
-17 node1_to_be_committed_after
-18 node1_to_be_committed_after
-19 node1_to_be_committed_after
-20 node1_to_be_committed_after
-26 node2_committed_after
-27 node2_committed_after
-28 node2_committed_after
-29 node2_committed_after
-30 node2_committed_after
-31 node1_to_be_committed_after
-32 node1_to_be_committed_after
-33 node1_to_be_committed_after
-34 node1_to_be_committed_after
-35 node1_to_be_committed_after
-36 node1_committed_after
-37 node1_committed_after
-38 node1_committed_after
-39 node1_committed_after
-40 node1_committed_after
+SELECT COUNT(*) = 35 FROM t1;
+COUNT(*) = 35
+1
SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1;
COUNT(*) = 0
1
COMMIT;
-connection node_1;
SET AUTOCOMMIT=ON;
-SET SESSION wsrep_sync_wait=15;
-SELECT COUNT(*) AS EXPECT_15 FROM t1;
-EXPECT_15
-35
-SELECT * from t1;
-id f1
-1 node1_committed_before
-2 node1_committed_before
-3 node1_committed_before
-4 node1_committed_before
-5 node1_committed_before
-6 node2_committed_before
-7 node2_committed_before
-8 node2_committed_before
-9 node2_committed_before
-10 node2_committed_before
-11 node1_committed_during
-12 node1_committed_during
-13 node1_committed_during
-14 node1_committed_during
-15 node1_committed_during
-16 node1_to_be_committed_after
-17 node1_to_be_committed_after
-18 node1_to_be_committed_after
-19 node1_to_be_committed_after
-20 node1_to_be_committed_after
-26 node2_committed_after
-27 node2_committed_after
-28 node2_committed_after
-29 node2_committed_after
-30 node2_committed_after
-31 node1_to_be_committed_after
-32 node1_to_be_committed_after
-33 node1_to_be_committed_after
-34 node1_to_be_committed_after
-35 node1_to_be_committed_after
-36 node1_committed_after
-37 node1_committed_after
-38 node1_committed_after
-39 node1_committed_after
-40 node1_committed_after
+connection node_1;
+SELECT COUNT(*) = 35 FROM t1;
+COUNT(*) = 35
+1
SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1;
COUNT(*) = 0
1
DROP TABLE t1;
COMMIT;
+SET AUTOCOMMIT=ON;
Performing State Transfer on a server that has been killed and restarted
connection node_1;
-CREATE TABLE t1 (id int not null primary key,f1 CHAR(255)) ENGINE=InnoDB;
+CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
-INSERT INTO t1 VALUES (1,'node1_committed_before');
-INSERT INTO t1 VALUES (2,'node1_committed_before');
-INSERT INTO t1 VALUES (3,'node1_committed_before');
-INSERT INTO t1 VALUES (4,'node1_committed_before');
-INSERT INTO t1 VALUES (5,'node1_committed_before');
+INSERT INTO t1 VALUES ('node1_committed_before');
+INSERT INTO t1 VALUES ('node1_committed_before');
+INSERT INTO t1 VALUES ('node1_committed_before');
+INSERT INTO t1 VALUES ('node1_committed_before');
+INSERT INTO t1 VALUES ('node1_committed_before');
COMMIT;
connection node_2;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
-INSERT INTO t1 VALUES (6,'node2_committed_before');
-INSERT INTO t1 VALUES (7,'node2_committed_before');
-INSERT INTO t1 VALUES (8,'node2_committed_before');
-INSERT INTO t1 VALUES (9,'node2_committed_before');
-INSERT INTO t1 VALUES (10,'node2_committed_before');
+INSERT INTO t1 VALUES ('node2_committed_before');
+INSERT INTO t1 VALUES ('node2_committed_before');
+INSERT INTO t1 VALUES ('node2_committed_before');
+INSERT INTO t1 VALUES ('node2_committed_before');
+INSERT INTO t1 VALUES ('node2_committed_before');
COMMIT;
Killing server ...
connection node_1;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
-INSERT INTO t1 VALUES (11,'node1_committed_during');
-INSERT INTO t1 VALUES (12,'node1_committed_during');
-INSERT INTO t1 VALUES (13,'node1_committed_during');
-INSERT INTO t1 VALUES (14,'node1_committed_during');
-INSERT INTO t1 VALUES (15,'node1_committed_during');
+INSERT INTO t1 VALUES ('node1_committed_during');
+INSERT INTO t1 VALUES ('node1_committed_during');
+INSERT INTO t1 VALUES ('node1_committed_during');
+INSERT INTO t1 VALUES ('node1_committed_during');
+INSERT INTO t1 VALUES ('node1_committed_during');
COMMIT;
START TRANSACTION;
-INSERT INTO t1 VALUES (16,'node1_to_be_committed_after');
-INSERT INTO t1 VALUES (17,'node1_to_be_committed_after');
-INSERT INTO t1 VALUES (18,'node1_to_be_committed_after');
-INSERT INTO t1 VALUES (19,'node1_to_be_committed_after');
-INSERT INTO t1 VALUES (20,'node1_to_be_committed_after');
+INSERT INTO t1 VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 VALUES ('node1_to_be_committed_after');
connect node_1a_galera_st_kill_slave, 127.0.0.1, root, , test, $NODE_MYPORT_1;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
-INSERT INTO t1 VALUES (21,'node1_to_be_rollbacked_after');
-INSERT INTO t1 VALUES (22,'node1_to_be_rollbacked_after');
-INSERT INTO t1 VALUES (23,'node1_to_be_rollbacked_after');
-INSERT INTO t1 VALUES (24,'node1_to_be_rollbacked_after');
-INSERT INTO t1 VALUES (25,'node1_to_be_rollbacked_after');
+INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
connection node_2;
Performing --wsrep-recover ...
Starting server ...
Using --wsrep-start-position when starting mysqld ...
SET AUTOCOMMIT=OFF;
START TRANSACTION;
-INSERT INTO t1 VALUES (26,'node2_committed_after');
-INSERT INTO t1 VALUES (27,'node2_committed_after');
-INSERT INTO t1 VALUES (28,'node2_committed_after');
-INSERT INTO t1 VALUES (29,'node2_committed_after');
-INSERT INTO t1 VALUES (30,'node2_committed_after');
+INSERT INTO t1 VALUES ('node2_committed_after');
+INSERT INTO t1 VALUES ('node2_committed_after');
+INSERT INTO t1 VALUES ('node2_committed_after');
+INSERT INTO t1 VALUES ('node2_committed_after');
+INSERT INTO t1 VALUES ('node2_committed_after');
COMMIT;
connection node_1;
-INSERT INTO t1 VALUES (31,'node1_to_be_committed_after');
-INSERT INTO t1 VALUES (32,'node1_to_be_committed_after');
-INSERT INTO t1 VALUES (33,'node1_to_be_committed_after');
-INSERT INTO t1 VALUES (34,'node1_to_be_committed_after');
-INSERT INTO t1 VALUES (35,'node1_to_be_committed_after');
+INSERT INTO t1 VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 VALUES ('node1_to_be_committed_after');
COMMIT;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
-INSERT INTO t1 VALUES (36,'node1_committed_after');
-INSERT INTO t1 VALUES (37,'node1_committed_after');
-INSERT INTO t1 VALUES (38,'node1_committed_after');
-INSERT INTO t1 VALUES (39,'node1_committed_after');
-INSERT INTO t1 VALUES (40,'node1_committed_after');
+INSERT INTO t1 VALUES ('node1_committed_after');
+INSERT INTO t1 VALUES ('node1_committed_after');
+INSERT INTO t1 VALUES ('node1_committed_after');
+INSERT INTO t1 VALUES ('node1_committed_after');
+INSERT INTO t1 VALUES ('node1_committed_after');
COMMIT;
connection node_1a_galera_st_kill_slave;
-INSERT INTO t1 VALUES (41,'node1_to_be_rollbacked_after');
-INSERT INTO t1 VALUES (42,'node1_to_be_rollbacked_after');
-INSERT INTO t1 VALUES (43,'node1_to_be_rollbacked_after');
-INSERT INTO t1 VALUES (45,'node1_to_be_rollbacked_after');
-INSERT INTO t1 VALUES (46,'node1_to_be_rollbacked_after');
+INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
ROLLBACK;
-SET AUTOCOMMIT=ON;
-SET SESSION wsrep_sync_wait=15;
-SELECT COUNT(*) AS EXPECT_35 FROM t1;
-EXPECT_35
-35
-SELECT * FROM t1;
-id f1
-1 node1_committed_before
-2 node1_committed_before
-3 node1_committed_before
-4 node1_committed_before
-5 node1_committed_before
-6 node2_committed_before
-7 node2_committed_before
-8 node2_committed_before
-9 node2_committed_before
-10 node2_committed_before
-11 node1_committed_during
-12 node1_committed_during
-13 node1_committed_during
-14 node1_committed_during
-15 node1_committed_during
-16 node1_to_be_committed_after
-17 node1_to_be_committed_after
-18 node1_to_be_committed_after
-19 node1_to_be_committed_after
-20 node1_to_be_committed_after
-26 node2_committed_after
-27 node2_committed_after
-28 node2_committed_after
-29 node2_committed_after
-30 node2_committed_after
-31 node1_to_be_committed_after
-32 node1_to_be_committed_after
-33 node1_to_be_committed_after
-34 node1_to_be_committed_after
-35 node1_to_be_committed_after
-36 node1_committed_after
-37 node1_committed_after
-38 node1_committed_after
-39 node1_committed_after
-40 node1_committed_after
+SELECT COUNT(*) = 35 FROM t1;
+COUNT(*) = 35
+1
SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1;
COUNT(*) = 0
1
COMMIT;
-connection node_1;
SET AUTOCOMMIT=ON;
-SET SESSION wsrep_sync_wait=15;
-SELECT COUNT(*) AS EXPECT_35 FROM t1;
-EXPECT_35
-35
-SELECT * FROM t1;
-id f1
-1 node1_committed_before
-2 node1_committed_before
-3 node1_committed_before
-4 node1_committed_before
-5 node1_committed_before
-6 node2_committed_before
-7 node2_committed_before
-8 node2_committed_before
-9 node2_committed_before
-10 node2_committed_before
-11 node1_committed_during
-12 node1_committed_during
-13 node1_committed_during
-14 node1_committed_during
-15 node1_committed_during
-16 node1_to_be_committed_after
-17 node1_to_be_committed_after
-18 node1_to_be_committed_after
-19 node1_to_be_committed_after
-20 node1_to_be_committed_after
-26 node2_committed_after
-27 node2_committed_after
-28 node2_committed_after
-29 node2_committed_after
-30 node2_committed_after
-31 node1_to_be_committed_after
-32 node1_to_be_committed_after
-33 node1_to_be_committed_after
-34 node1_to_be_committed_after
-35 node1_to_be_committed_after
-36 node1_committed_after
-37 node1_committed_after
-38 node1_committed_after
-39 node1_committed_after
-40 node1_committed_after
+connection node_1;
+SELECT COUNT(*) = 35 FROM t1;
+COUNT(*) = 35
+1
SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1;
COUNT(*) = 0
1
DROP TABLE t1;
COMMIT;
+SET AUTOCOMMIT=ON;
diff --git a/mysql-test/suite/galera/r/galera_ist_MDEV-28583,debug.rdiff b/mysql-test/suite/galera/r/galera_ist_MDEV-28583,debug.rdiff
index 51d2a6bf157..ce78050538d 100644
--- a/mysql-test/suite/galera/r/galera_ist_MDEV-28583,debug.rdiff
+++ b/mysql-test/suite/galera/r/galera_ist_MDEV-28583,debug.rdiff
@@ -1,27 +1,27 @@
--- r/galera_ist_MDEV-28583.result
-+++ r/galera_ist_MDEV-28583,debug.reject
-@@ -517,3 +517,187 @@
- 1
++++ r/galera_ist_MDEV-28583.reject
+@@ -285,3 +285,111 @@
DROP TABLE t1;
COMMIT;
+ SET AUTOCOMMIT=ON;
+Performing State Transfer on a server that has been killed and restarted
+while a DDL was in progress on it
+connection node_1;
-+CREATE TABLE t1 (id int not null primary key,f1 CHAR(255)) ENGINE=InnoDB;
++CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
-+INSERT INTO t1 VALUES (1,'node1_committed_before');
-+INSERT INTO t1 VALUES (2,'node1_committed_before');
-+INSERT INTO t1 VALUES (3,'node1_committed_before');
-+INSERT INTO t1 VALUES (4,'node1_committed_before');
-+INSERT INTO t1 VALUES (5,'node1_committed_before');
++INSERT INTO t1 VALUES ('node1_committed_before');
++INSERT INTO t1 VALUES ('node1_committed_before');
++INSERT INTO t1 VALUES ('node1_committed_before');
++INSERT INTO t1 VALUES ('node1_committed_before');
++INSERT INTO t1 VALUES ('node1_committed_before');
+connection node_2;
+START TRANSACTION;
-+INSERT INTO t1 VALUES (6,'node2_committed_before');
-+INSERT INTO t1 VALUES (7,'node2_committed_before');
-+INSERT INTO t1 VALUES (8,'node2_committed_before');
-+INSERT INTO t1 VALUES (9,'node2_committed_before');
-+INSERT INTO t1 VALUES (10,'node2_committed_before');
++INSERT INTO t1 VALUES ('node2_committed_before');
++INSERT INTO t1 VALUES ('node2_committed_before');
++INSERT INTO t1 VALUES ('node2_committed_before');
++INSERT INTO t1 VALUES ('node2_committed_before');
++INSERT INTO t1 VALUES ('node2_committed_before');
+COMMIT;
+SET GLOBAL debug_dbug = 'd,sync.alter_opened_table';
+connection node_1;
@@ -32,26 +32,26 @@
+connection node_1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
-+INSERT INTO t1 (id,f1) VALUES (11,'node1_committed_during');
-+INSERT INTO t1 (id,f1) VALUES (12,'node1_committed_during');
-+INSERT INTO t1 (id,f1) VALUES (13,'node1_committed_during');
-+INSERT INTO t1 (id,f1) VALUES (14,'node1_committed_during');
-+INSERT INTO t1 (id,f1) VALUES (15,'node1_committed_during');
++INSERT INTO t1 (f1) VALUES ('node1_committed_during');
++INSERT INTO t1 (f1) VALUES ('node1_committed_during');
++INSERT INTO t1 (f1) VALUES ('node1_committed_during');
++INSERT INTO t1 (f1) VALUES ('node1_committed_during');
++INSERT INTO t1 (f1) VALUES ('node1_committed_during');
+COMMIT;
+START TRANSACTION;
-+INSERT INTO t1 (id,f1) VALUES (16,'node1_to_be_committed_after');
-+INSERT INTO t1 (id,f1) VALUES (17,'node1_to_be_committed_after');
-+INSERT INTO t1 (id,f1) VALUES (18,'node1_to_be_committed_after');
-+INSERT INTO t1 (id,f1) VALUES (19,'node1_to_be_committed_after');
-+INSERT INTO t1 (id,f1) VALUES (20,'node1_to_be_committed_after');
++INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
++INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
++INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
++INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
++INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
+connect node_1a_galera_st_kill_slave_ddl, 127.0.0.1, root, , test, $NODE_MYPORT_1;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
-+INSERT INTO t1 (id,f1) VALUES (21,'node1_to_be_rollbacked_after');
-+INSERT INTO t1 (id,f1) VALUES (22,'node1_to_be_rollbacked_after');
-+INSERT INTO t1 (id,f1) VALUES (23,'node1_to_be_rollbacked_after');
-+INSERT INTO t1 (id,f1) VALUES (24,'node1_to_be_rollbacked_after');
-+INSERT INTO t1 (id,f1) VALUES (25,'node1_to_be_rollbacked_after');
++INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
++INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
++INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
++INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
++INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
+connection node_2;
+Performing --wsrep-recover ...
+connection node_2;
@@ -59,132 +59,56 @@
+Using --wsrep-start-position when starting mysqld ...
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
-+INSERT INTO t1 (id,f1) VALUES (26,'node2_committed_after');
-+INSERT INTO t1 (id,f1) VALUES (27,'node2_committed_after');
-+INSERT INTO t1 (id,f1) VALUES (28,'node2_committed_after');
-+INSERT INTO t1 (id,f1) VALUES (29,'node2_committed_after');
-+INSERT INTO t1 (id,f1) VALUES (30,'node2_committed_after');
++INSERT INTO t1 (f1) VALUES ('node2_committed_after');
++INSERT INTO t1 (f1) VALUES ('node2_committed_after');
++INSERT INTO t1 (f1) VALUES ('node2_committed_after');
++INSERT INTO t1 (f1) VALUES ('node2_committed_after');
++INSERT INTO t1 (f1) VALUES ('node2_committed_after');
+COMMIT;
+connection node_1;
-+INSERT INTO t1 (id,f1) VALUES (31,'node1_to_be_committed_after');
-+INSERT INTO t1 (id,f1) VALUES (32,'node1_to_be_committed_after');
-+INSERT INTO t1 (id,f1) VALUES (33,'node1_to_be_committed_after');
-+INSERT INTO t1 (id,f1) VALUES (34,'node1_to_be_committed_after');
-+INSERT INTO t1 (id,f1) VALUES (35,'node1_to_be_committed_after');
++INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
++INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
++INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
++INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
++INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after');
+COMMIT;
+SET AUTOCOMMIT=OFF;
+START TRANSACTION;
-+INSERT INTO t1 (id,f1) VALUES (36,'node1_committed_after');
-+INSERT INTO t1 (id,f1) VALUES (37,'node1_committed_after');
-+INSERT INTO t1 (id,f1) VALUES (38,'node1_committed_after');
-+INSERT INTO t1 (id,f1) VALUES (39,'node1_committed_after');
-+INSERT INTO t1 (id,f1) VALUES (40,'node1_committed_after');
++INSERT INTO t1 (f1) VALUES ('node1_committed_after');
++INSERT INTO t1 (f1) VALUES ('node1_committed_after');
++INSERT INTO t1 (f1) VALUES ('node1_committed_after');
++INSERT INTO t1 (f1) VALUES ('node1_committed_after');
++INSERT INTO t1 (f1) VALUES ('node1_committed_after');
+COMMIT;
+connection node_1a_galera_st_kill_slave_ddl;
-+INSERT INTO t1 (id,f1) VALUES (41,'node1_to_be_rollbacked_after');
-+INSERT INTO t1 (id,f1) VALUES (42,'node1_to_be_rollbacked_after');
-+INSERT INTO t1 (id,f1) VALUES (43,'node1_to_be_rollbacked_after');
-+INSERT INTO t1 (id,f1) VALUES (44,'node1_to_be_rollbacked_after');
-+INSERT INTO t1 (id,f1) VALUES (45,'node1_to_be_rollbacked_after');
++INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
++INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
++INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
++INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
++INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after');
+ROLLBACK;
-+SET AUTOCOMMIT=ON;
-+SET SESSION wsrep_sync_wait=15;
-+SELECT COUNT(*) AS EXPECT_3 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
-+EXPECT_3
-+3
-+SELECT COUNT(*) AS EXPECT_35 FROM t1;
-+EXPECT_35
-+35
-+SELECT * FROM t1;
-+id f1 f2
-+1 node1_committed_before NULL
-+2 node1_committed_before NULL
-+3 node1_committed_before NULL
-+4 node1_committed_before NULL
-+5 node1_committed_before NULL
-+6 node2_committed_before NULL
-+7 node2_committed_before NULL
-+8 node2_committed_before NULL
-+9 node2_committed_before NULL
-+10 node2_committed_before NULL
-+11 node1_committed_during NULL
-+12 node1_committed_during NULL
-+13 node1_committed_during NULL
-+14 node1_committed_during NULL
-+15 node1_committed_during NULL
-+16 node1_to_be_committed_after NULL
-+17 node1_to_be_committed_after NULL
-+18 node1_to_be_committed_after NULL
-+19 node1_to_be_committed_after NULL
-+20 node1_to_be_committed_after NULL
-+26 node2_committed_after NULL
-+27 node2_committed_after NULL
-+28 node2_committed_after NULL
-+29 node2_committed_after NULL
-+30 node2_committed_after NULL
-+31 node1_to_be_committed_after NULL
-+32 node1_to_be_committed_after NULL
-+33 node1_to_be_committed_after NULL
-+34 node1_to_be_committed_after NULL
-+35 node1_to_be_committed_after NULL
-+36 node1_committed_after NULL
-+37 node1_committed_after NULL
-+38 node1_committed_after NULL
-+39 node1_committed_after NULL
-+40 node1_committed_after NULL
++SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
++COUNT(*) = 2
++1
++SELECT COUNT(*) = 35 FROM t1;
++COUNT(*) = 35
++1
+SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1;
+COUNT(*) = 0
+1
+COMMIT;
-+connection node_1;
+SET AUTOCOMMIT=ON;
-+SET SESSION wsrep_sync_wait=15;
-+SELECT COUNT(*) AS EXPECT_3 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
-+EXPECT_3
-+3
-+SELECT COUNT(*) AS EXPECT_35 FROM t1;
-+EXPECT_35
-+35
-+SELECT * FROM t1;
-+id f1 f2
-+1 node1_committed_before NULL
-+2 node1_committed_before NULL
-+3 node1_committed_before NULL
-+4 node1_committed_before NULL
-+5 node1_committed_before NULL
-+6 node2_committed_before NULL
-+7 node2_committed_before NULL
-+8 node2_committed_before NULL
-+9 node2_committed_before NULL
-+10 node2_committed_before NULL
-+11 node1_committed_during NULL
-+12 node1_committed_during NULL
-+13 node1_committed_during NULL
-+14 node1_committed_during NULL
-+15 node1_committed_during NULL
-+16 node1_to_be_committed_after NULL
-+17 node1_to_be_committed_after NULL
-+18 node1_to_be_committed_after NULL
-+19 node1_to_be_committed_after NULL
-+20 node1_to_be_committed_after NULL
-+26 node2_committed_after NULL
-+27 node2_committed_after NULL
-+28 node2_committed_after NULL
-+29 node2_committed_after NULL
-+30 node2_committed_after NULL
-+31 node1_to_be_committed_after NULL
-+32 node1_to_be_committed_after NULL
-+33 node1_to_be_committed_after NULL
-+34 node1_to_be_committed_after NULL
-+35 node1_to_be_committed_after NULL
-+36 node1_committed_after NULL
-+37 node1_committed_after NULL
-+38 node1_committed_after NULL
-+39 node1_committed_after NULL
-+40 node1_committed_after NULL
++connection node_1;
++SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
++COUNT(*) = 2
++1
++SELECT COUNT(*) = 35 FROM t1;
++COUNT(*) = 35
++1
+SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1;
+COUNT(*) = 0
+1
+DROP TABLE t1;
+COMMIT;
++SET AUTOCOMMIT=ON;
+SET GLOBAL debug_dbug = $debug_orig;
diff --git a/mysql-test/suite/galera/r/galera_ist_MDEV-28583.result b/mysql-test/suite/galera/r/galera_ist_MDEV-28583.result
index 5a71b490a80..80a28d349ba 100644
--- a/mysql-test/suite/galera/r/galera_ist_MDEV-28583.result
+++ b/mysql-test/suite/galera/r/galera_ist_MDEV-28583.result
@@ -1,519 +1,287 @@
-connection node_2;
-connection node_1;
connection node_1;
connection node_2;
Performing State Transfer on a server that has been temporarily disconnected
connection node_1;
-CREATE TABLE t1 (id int not null primary key,f1 CHAR(255)) ENGINE=InnoDB;
+CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
-INSERT INTO t1 VALUES (1,'node1_committed_before');
-INSERT INTO t1 VALUES (2,'node1_committed_before');
-INSERT INTO t1 VALUES (3,'node1_committed_before');
-INSERT INTO t1 VALUES (4,'node1_committed_before');
-INSERT INTO t1 VALUES (5,'node1_committed_before');
+INSERT INTO t1 VALUES ('node1_committed_before');
+INSERT INTO t1 VALUES ('node1_committed_before');
+INSERT INTO t1 VALUES ('node1_committed_before');
+INSERT INTO t1 VALUES ('node1_committed_before');
+INSERT INTO t1 VALUES ('node1_committed_before');
COMMIT;
connection node_2;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
-INSERT INTO t1 VALUES (6,'node2_committed_before');
-INSERT INTO t1 VALUES (7,'node2_committed_before');
-INSERT INTO t1 VALUES (8,'node2_committed_before');
-INSERT INTO t1 VALUES (9,'node2_committed_before');
-INSERT INTO t1 VALUES (10,'node2_committed_before');
+INSERT INTO t1 VALUES ('node2_committed_before');
+INSERT INTO t1 VALUES ('node2_committed_before');
+INSERT INTO t1 VALUES ('node2_committed_before');
+INSERT INTO t1 VALUES ('node2_committed_before');
+INSERT INTO t1 VALUES ('node2_committed_before');
COMMIT;
Unloading wsrep provider ...
SET GLOBAL wsrep_cluster_address = '';
connection node_1;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
-INSERT INTO t1 VALUES (11,'node1_committed_during');
-INSERT INTO t1 VALUES (12,'node1_committed_during');
-INSERT INTO t1 VALUES (13,'node1_committed_during');
-INSERT INTO t1 VALUES (14,'node1_committed_during');
-INSERT INTO t1 VALUES (15,'node1_committed_during');
+INSERT INTO t1 VALUES ('node1_committed_during');
+INSERT INTO t1 VALUES ('node1_committed_during');
+INSERT INTO t1 VALUES ('node1_committed_during');
+INSERT INTO t1 VALUES ('node1_committed_during');
+INSERT INTO t1 VALUES ('node1_committed_during');
COMMIT;
START TRANSACTION;
-INSERT INTO t1 VALUES (16,'node1_to_be_committed_after');
-INSERT INTO t1 VALUES (17,'node1_to_be_committed_after');
-INSERT INTO t1 VALUES (18,'node1_to_be_committed_after');
-INSERT INTO t1 VALUES (19,'node1_to_be_committed_after');
-INSERT INTO t1 VALUES (20,'node1_to_be_committed_after');
+INSERT INTO t1 VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 VALUES ('node1_to_be_committed_after');
connect node_1a_galera_st_disconnect_slave, 127.0.0.1, root, , test, $NODE_MYPORT_1;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
-INSERT INTO t1 VALUES (21,'node1_to_be_rollbacked_after');
-INSERT INTO t1 VALUES (22,'node1_to_be_rollbacked_after');
-INSERT INTO t1 VALUES (23,'node1_to_be_rollbacked_after');
-INSERT INTO t1 VALUES (24,'node1_to_be_rollbacked_after');
-INSERT INTO t1 VALUES (25,'node1_to_be_rollbacked_after');
+INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
connection node_2;
Loading wsrep provider ...
-disconnect node_2;
-connect node_2, 127.0.0.1, root, , test, $NODE_MYPORT_2;
-connection node_2;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
-INSERT INTO t1 VALUES (26,'node2_committed_after');
-INSERT INTO t1 VALUES (27,'node2_committed_after');
-INSERT INTO t1 VALUES (28,'node2_committed_after');
-INSERT INTO t1 VALUES (29,'node2_committed_after');
-INSERT INTO t1 VALUES (30,'node2_committed_after');
+INSERT INTO t1 VALUES ('node2_committed_after');
+INSERT INTO t1 VALUES ('node2_committed_after');
+INSERT INTO t1 VALUES ('node2_committed_after');
+INSERT INTO t1 VALUES ('node2_committed_after');
+INSERT INTO t1 VALUES ('node2_committed_after');
COMMIT;
connection node_1;
-INSERT INTO t1 VALUES (31,'node1_to_be_committed_after');
-INSERT INTO t1 VALUES (32,'node1_to_be_committed_after');
-INSERT INTO t1 VALUES (33,'node1_to_be_committed_after');
-INSERT INTO t1 VALUES (34,'node1_to_be_committed_after');
-INSERT INTO t1 VALUES (35,'node1_to_be_committed_after');
+INSERT INTO t1 VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 VALUES ('node1_to_be_committed_after');
COMMIT;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
-INSERT INTO t1 VALUES (36,'node1_committed_after');
-INSERT INTO t1 VALUES (37,'node1_committed_after');
-INSERT INTO t1 VALUES (38,'node1_committed_after');
-INSERT INTO t1 VALUES (39,'node1_committed_after');
-INSERT INTO t1 VALUES (40,'node1_committed_after');
+INSERT INTO t1 VALUES ('node1_committed_after');
+INSERT INTO t1 VALUES ('node1_committed_after');
+INSERT INTO t1 VALUES ('node1_committed_after');
+INSERT INTO t1 VALUES ('node1_committed_after');
+INSERT INTO t1 VALUES ('node1_committed_after');
COMMIT;
connection node_1a_galera_st_disconnect_slave;
-INSERT INTO t1 VALUES (41,'node1_to_be_rollbacked_after');
-INSERT INTO t1 VALUES (42,'node1_to_be_rollbacked_after');
-INSERT INTO t1 VALUES (43,'node1_to_be_rollbacked_after');
-INSERT INTO t1 VALUES (44,'node1_to_be_rollbacked_after');
-INSERT INTO t1 VALUES (45,'node1_to_be_rollbacked_after');
+INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
ROLLBACK;
-SET AUTOCOMMIT=ON;
-SET SESSION wsrep_sync_wait=15;
-SELECT COUNT(*) AS EXPECT_35 FROM t1;
-EXPECT_35
-35
-SELECT * FROM t1;
-id f1
-1 node1_committed_before
-2 node1_committed_before
-3 node1_committed_before
-4 node1_committed_before
-5 node1_committed_before
-6 node2_committed_before
-7 node2_committed_before
-8 node2_committed_before
-9 node2_committed_before
-10 node2_committed_before
-11 node1_committed_during
-12 node1_committed_during
-13 node1_committed_during
-14 node1_committed_during
-15 node1_committed_during
-16 node1_to_be_committed_after
-17 node1_to_be_committed_after
-18 node1_to_be_committed_after
-19 node1_to_be_committed_after
-20 node1_to_be_committed_after
-26 node2_committed_after
-27 node2_committed_after
-28 node2_committed_after
-29 node2_committed_after
-30 node2_committed_after
-31 node1_to_be_committed_after
-32 node1_to_be_committed_after
-33 node1_to_be_committed_after
-34 node1_to_be_committed_after
-35 node1_to_be_committed_after
-36 node1_committed_after
-37 node1_committed_after
-38 node1_committed_after
-39 node1_committed_after
-40 node1_committed_after
+SELECT COUNT(*) = 35 FROM t1;
+COUNT(*) = 35
+1
SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1;
COUNT(*) = 0
1
-connection node_1;
+COMMIT;
SET AUTOCOMMIT=ON;
-SET SESSION wsrep_sync_wait=15;
-SELECT COUNT(*) AS EXPECT_35 FROM t1;
-EXPECT_35
-35
-SELECT * FROM t1;
-id f1
-1 node1_committed_before
-2 node1_committed_before
-3 node1_committed_before
-4 node1_committed_before
-5 node1_committed_before
-6 node2_committed_before
-7 node2_committed_before
-8 node2_committed_before
-9 node2_committed_before
-10 node2_committed_before
-11 node1_committed_during
-12 node1_committed_during
-13 node1_committed_during
-14 node1_committed_during
-15 node1_committed_during
-16 node1_to_be_committed_after
-17 node1_to_be_committed_after
-18 node1_to_be_committed_after
-19 node1_to_be_committed_after
-20 node1_to_be_committed_after
-26 node2_committed_after
-27 node2_committed_after
-28 node2_committed_after
-29 node2_committed_after
-30 node2_committed_after
-31 node1_to_be_committed_after
-32 node1_to_be_committed_after
-33 node1_to_be_committed_after
-34 node1_to_be_committed_after
-35 node1_to_be_committed_after
-36 node1_committed_after
-37 node1_committed_after
-38 node1_committed_after
-39 node1_committed_after
-40 node1_committed_after
+connection node_1;
+SELECT COUNT(*) = 35 FROM t1;
+COUNT(*) = 35
+1
SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1;
COUNT(*) = 0
1
DROP TABLE t1;
COMMIT;
+SET AUTOCOMMIT=ON;
Performing State Transfer on a server that has been shut down cleanly and restarted
connection node_1;
-CREATE TABLE t1 (id int not null primary key,f1 CHAR(255)) ENGINE=InnoDB;
+CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
-INSERT INTO t1 VALUES (1,'node1_committed_before');
-INSERT INTO t1 VALUES (2,'node1_committed_before');
-INSERT INTO t1 VALUES (3,'node1_committed_before');
-INSERT INTO t1 VALUES (4,'node1_committed_before');
-INSERT INTO t1 VALUES (5,'node1_committed_before');
+INSERT INTO t1 VALUES ('node1_committed_before');
+INSERT INTO t1 VALUES ('node1_committed_before');
+INSERT INTO t1 VALUES ('node1_committed_before');
+INSERT INTO t1 VALUES ('node1_committed_before');
+INSERT INTO t1 VALUES ('node1_committed_before');
COMMIT;
connection node_2;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
-INSERT INTO t1 VALUES (6,'node2_committed_before');
-INSERT INTO t1 VALUES (7,'node2_committed_before');
-INSERT INTO t1 VALUES (8,'node2_committed_before');
-INSERT INTO t1 VALUES (9,'node2_committed_before');
-INSERT INTO t1 VALUES (10,'node2_committed_before');
+INSERT INTO t1 VALUES ('node2_committed_before');
+INSERT INTO t1 VALUES ('node2_committed_before');
+INSERT INTO t1 VALUES ('node2_committed_before');
+INSERT INTO t1 VALUES ('node2_committed_before');
+INSERT INTO t1 VALUES ('node2_committed_before');
COMMIT;
Shutting down server ...
connection node_1;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
-INSERT INTO t1 VALUES (11,'node1_committed_during');
-INSERT INTO t1 VALUES (12,'node1_committed_during');
-INSERT INTO t1 VALUES (13,'node1_committed_during');
-INSERT INTO t1 VALUES (14,'node1_committed_during');
-INSERT INTO t1 VALUES (15,'node1_committed_during');
+INSERT INTO t1 VALUES ('node1_committed_during');
+INSERT INTO t1 VALUES ('node1_committed_during');
+INSERT INTO t1 VALUES ('node1_committed_during');
+INSERT INTO t1 VALUES ('node1_committed_during');
+INSERT INTO t1 VALUES ('node1_committed_during');
COMMIT;
START TRANSACTION;
-INSERT INTO t1 VALUES (16,'node1_to_be_committed_after');
-INSERT INTO t1 VALUES (17,'node1_to_be_committed_after');
-INSERT INTO t1 VALUES (18,'node1_to_be_committed_after');
-INSERT INTO t1 VALUES (19,'node1_to_be_committed_after');
-INSERT INTO t1 VALUES (20,'node1_to_be_committed_after');
+INSERT INTO t1 VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 VALUES ('node1_to_be_committed_after');
connect node_1a_galera_st_shutdown_slave, 127.0.0.1, root, , test, $NODE_MYPORT_1;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
-INSERT INTO t1 VALUES (21,'node1_to_be_rollbacked_after');
-INSERT INTO t1 VALUES (22,'node1_to_be_rollbacked_after');
-INSERT INTO t1 VALUES (23,'node1_to_be_rollbacked_after');
-INSERT INTO t1 VALUES (24,'node1_to_be_rollbacked_after');
-INSERT INTO t1 VALUES (25,'node1_to_be_rollbacked_after');
+INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
connection node_2;
Starting server ...
SET AUTOCOMMIT=OFF;
START TRANSACTION;
-INSERT INTO t1 VALUES (26,'node2_committed_after');
-INSERT INTO t1 VALUES (27,'node2_committed_after');
-INSERT INTO t1 VALUES (28,'node2_committed_after');
-INSERT INTO t1 VALUES (29,'node2_committed_after');
-INSERT INTO t1 VALUES (30,'node2_committed_after');
+INSERT INTO t1 VALUES ('node2_committed_after');
+INSERT INTO t1 VALUES ('node2_committed_after');
+INSERT INTO t1 VALUES ('node2_committed_after');
+INSERT INTO t1 VALUES ('node2_committed_after');
+INSERT INTO t1 VALUES ('node2_committed_after');
COMMIT;
connection node_1;
-INSERT INTO t1 VALUES (31,'node1_to_be_committed_after');
-INSERT INTO t1 VALUES (32,'node1_to_be_committed_after');
-INSERT INTO t1 VALUES (33,'node1_to_be_committed_after');
-INSERT INTO t1 VALUES (34,'node1_to_be_committed_after');
-INSERT INTO t1 VALUES (35,'node1_to_be_committed_after');
+INSERT INTO t1 VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 VALUES ('node1_to_be_committed_after');
COMMIT;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
-INSERT INTO t1 VALUES (36,'node1_committed_after');
-INSERT INTO t1 VALUES (37,'node1_committed_after');
-INSERT INTO t1 VALUES (38,'node1_committed_after');
-INSERT INTO t1 VALUES (39,'node1_committed_after');
-INSERT INTO t1 VALUES (40,'node1_committed_after');
+INSERT INTO t1 VALUES ('node1_committed_after');
+INSERT INTO t1 VALUES ('node1_committed_after');
+INSERT INTO t1 VALUES ('node1_committed_after');
+INSERT INTO t1 VALUES ('node1_committed_after');
+INSERT INTO t1 VALUES ('node1_committed_after');
COMMIT;
connection node_1a_galera_st_shutdown_slave;
-INSERT INTO t1 VALUES (41,'node1_to_be_rollbacked_after');
-INSERT INTO t1 VALUES (42,'node1_to_be_rollbacked_after');
-INSERT INTO t1 VALUES (43,'node1_to_be_rollbacked_after');
-INSERT INTO t1 VALUES (44,'node1_to_be_rollbacked_after');
-INSERT INTO t1 VALUES (45,'node1_to_be_rollbacked_after');
+INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
ROLLBACK;
-SET AUTOCOMMIT=ON;
-SET SESSION wsrep_sync_wait=15;
-SELECT COUNT(*) AS EXPECT_15 FROM t1;
-EXPECT_15
-35
-SELECT * from t1;
-id f1
-1 node1_committed_before
-2 node1_committed_before
-3 node1_committed_before
-4 node1_committed_before
-5 node1_committed_before
-6 node2_committed_before
-7 node2_committed_before
-8 node2_committed_before
-9 node2_committed_before
-10 node2_committed_before
-11 node1_committed_during
-12 node1_committed_during
-13 node1_committed_during
-14 node1_committed_during
-15 node1_committed_during
-16 node1_to_be_committed_after
-17 node1_to_be_committed_after
-18 node1_to_be_committed_after
-19 node1_to_be_committed_after
-20 node1_to_be_committed_after
-26 node2_committed_after
-27 node2_committed_after
-28 node2_committed_after
-29 node2_committed_after
-30 node2_committed_after
-31 node1_to_be_committed_after
-32 node1_to_be_committed_after
-33 node1_to_be_committed_after
-34 node1_to_be_committed_after
-35 node1_to_be_committed_after
-36 node1_committed_after
-37 node1_committed_after
-38 node1_committed_after
-39 node1_committed_after
-40 node1_committed_after
+SELECT COUNT(*) = 35 FROM t1;
+COUNT(*) = 35
+1
SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1;
COUNT(*) = 0
1
COMMIT;
-connection node_1;
SET AUTOCOMMIT=ON;
-SET SESSION wsrep_sync_wait=15;
-SELECT COUNT(*) AS EXPECT_15 FROM t1;
-EXPECT_15
-35
-SELECT * from t1;
-id f1
-1 node1_committed_before
-2 node1_committed_before
-3 node1_committed_before
-4 node1_committed_before
-5 node1_committed_before
-6 node2_committed_before
-7 node2_committed_before
-8 node2_committed_before
-9 node2_committed_before
-10 node2_committed_before
-11 node1_committed_during
-12 node1_committed_during
-13 node1_committed_during
-14 node1_committed_during
-15 node1_committed_during
-16 node1_to_be_committed_after
-17 node1_to_be_committed_after
-18 node1_to_be_committed_after
-19 node1_to_be_committed_after
-20 node1_to_be_committed_after
-26 node2_committed_after
-27 node2_committed_after
-28 node2_committed_after
-29 node2_committed_after
-30 node2_committed_after
-31 node1_to_be_committed_after
-32 node1_to_be_committed_after
-33 node1_to_be_committed_after
-34 node1_to_be_committed_after
-35 node1_to_be_committed_after
-36 node1_committed_after
-37 node1_committed_after
-38 node1_committed_after
-39 node1_committed_after
-40 node1_committed_after
+connection node_1;
+SELECT COUNT(*) = 35 FROM t1;
+COUNT(*) = 35
+1
SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1;
COUNT(*) = 0
1
DROP TABLE t1;
COMMIT;
+SET AUTOCOMMIT=ON;
Performing State Transfer on a server that has been killed and restarted
connection node_1;
-CREATE TABLE t1 (id int not null primary key,f1 CHAR(255)) ENGINE=InnoDB;
+CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
-INSERT INTO t1 VALUES (1,'node1_committed_before');
-INSERT INTO t1 VALUES (2,'node1_committed_before');
-INSERT INTO t1 VALUES (3,'node1_committed_before');
-INSERT INTO t1 VALUES (4,'node1_committed_before');
-INSERT INTO t1 VALUES (5,'node1_committed_before');
+INSERT INTO t1 VALUES ('node1_committed_before');
+INSERT INTO t1 VALUES ('node1_committed_before');
+INSERT INTO t1 VALUES ('node1_committed_before');
+INSERT INTO t1 VALUES ('node1_committed_before');
+INSERT INTO t1 VALUES ('node1_committed_before');
COMMIT;
connection node_2;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
-INSERT INTO t1 VALUES (6,'node2_committed_before');
-INSERT INTO t1 VALUES (7,'node2_committed_before');
-INSERT INTO t1 VALUES (8,'node2_committed_before');
-INSERT INTO t1 VALUES (9,'node2_committed_before');
-INSERT INTO t1 VALUES (10,'node2_committed_before');
+INSERT INTO t1 VALUES ('node2_committed_before');
+INSERT INTO t1 VALUES ('node2_committed_before');
+INSERT INTO t1 VALUES ('node2_committed_before');
+INSERT INTO t1 VALUES ('node2_committed_before');
+INSERT INTO t1 VALUES ('node2_committed_before');
COMMIT;
Killing server ...
connection node_1;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
-INSERT INTO t1 VALUES (11,'node1_committed_during');
-INSERT INTO t1 VALUES (12,'node1_committed_during');
-INSERT INTO t1 VALUES (13,'node1_committed_during');
-INSERT INTO t1 VALUES (14,'node1_committed_during');
-INSERT INTO t1 VALUES (15,'node1_committed_during');
+INSERT INTO t1 VALUES ('node1_committed_during');
+INSERT INTO t1 VALUES ('node1_committed_during');
+INSERT INTO t1 VALUES ('node1_committed_during');
+INSERT INTO t1 VALUES ('node1_committed_during');
+INSERT INTO t1 VALUES ('node1_committed_during');
COMMIT;
START TRANSACTION;
-INSERT INTO t1 VALUES (16,'node1_to_be_committed_after');
-INSERT INTO t1 VALUES (17,'node1_to_be_committed_after');
-INSERT INTO t1 VALUES (18,'node1_to_be_committed_after');
-INSERT INTO t1 VALUES (19,'node1_to_be_committed_after');
-INSERT INTO t1 VALUES (20,'node1_to_be_committed_after');
+INSERT INTO t1 VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 VALUES ('node1_to_be_committed_after');
connect node_1a_galera_st_kill_slave, 127.0.0.1, root, , test, $NODE_MYPORT_1;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
-INSERT INTO t1 VALUES (21,'node1_to_be_rollbacked_after');
-INSERT INTO t1 VALUES (22,'node1_to_be_rollbacked_after');
-INSERT INTO t1 VALUES (23,'node1_to_be_rollbacked_after');
-INSERT INTO t1 VALUES (24,'node1_to_be_rollbacked_after');
-INSERT INTO t1 VALUES (25,'node1_to_be_rollbacked_after');
+INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
connection node_2;
Performing --wsrep-recover ...
Starting server ...
Using --wsrep-start-position when starting mysqld ...
SET AUTOCOMMIT=OFF;
START TRANSACTION;
-INSERT INTO t1 VALUES (26,'node2_committed_after');
-INSERT INTO t1 VALUES (27,'node2_committed_after');
-INSERT INTO t1 VALUES (28,'node2_committed_after');
-INSERT INTO t1 VALUES (29,'node2_committed_after');
-INSERT INTO t1 VALUES (30,'node2_committed_after');
+INSERT INTO t1 VALUES ('node2_committed_after');
+INSERT INTO t1 VALUES ('node2_committed_after');
+INSERT INTO t1 VALUES ('node2_committed_after');
+INSERT INTO t1 VALUES ('node2_committed_after');
+INSERT INTO t1 VALUES ('node2_committed_after');
COMMIT;
connection node_1;
-INSERT INTO t1 VALUES (31,'node1_to_be_committed_after');
-INSERT INTO t1 VALUES (32,'node1_to_be_committed_after');
-INSERT INTO t1 VALUES (33,'node1_to_be_committed_after');
-INSERT INTO t1 VALUES (34,'node1_to_be_committed_after');
-INSERT INTO t1 VALUES (35,'node1_to_be_committed_after');
+INSERT INTO t1 VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 VALUES ('node1_to_be_committed_after');
+INSERT INTO t1 VALUES ('node1_to_be_committed_after');
COMMIT;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
-INSERT INTO t1 VALUES (36,'node1_committed_after');
-INSERT INTO t1 VALUES (37,'node1_committed_after');
-INSERT INTO t1 VALUES (38,'node1_committed_after');
-INSERT INTO t1 VALUES (39,'node1_committed_after');
-INSERT INTO t1 VALUES (40,'node1_committed_after');
+INSERT INTO t1 VALUES ('node1_committed_after');
+INSERT INTO t1 VALUES ('node1_committed_after');
+INSERT INTO t1 VALUES ('node1_committed_after');
+INSERT INTO t1 VALUES ('node1_committed_after');
+INSERT INTO t1 VALUES ('node1_committed_after');
COMMIT;
connection node_1a_galera_st_kill_slave;
-INSERT INTO t1 VALUES (41,'node1_to_be_rollbacked_after');
-INSERT INTO t1 VALUES (42,'node1_to_be_rollbacked_after');
-INSERT INTO t1 VALUES (43,'node1_to_be_rollbacked_after');
-INSERT INTO t1 VALUES (45,'node1_to_be_rollbacked_after');
-INSERT INTO t1 VALUES (46,'node1_to_be_rollbacked_after');
+INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
+INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after');
ROLLBACK;
-SET AUTOCOMMIT=ON;
-SET SESSION wsrep_sync_wait=15;
-SELECT COUNT(*) AS EXPECT_35 FROM t1;
-EXPECT_35
-35
-SELECT * FROM t1;
-id f1
-1 node1_committed_before
-2 node1_committed_before
-3 node1_committed_before
-4 node1_committed_before
-5 node1_committed_before
-6 node2_committed_before
-7 node2_committed_before
-8 node2_committed_before
-9 node2_committed_before
-10 node2_committed_before
-11 node1_committed_during
-12 node1_committed_during
-13 node1_committed_during
-14 node1_committed_during
-15 node1_committed_during
-16 node1_to_be_committed_after
-17 node1_to_be_committed_after
-18 node1_to_be_committed_after
-19 node1_to_be_committed_after
-20 node1_to_be_committed_after
-26 node2_committed_after
-27 node2_committed_after
-28 node2_committed_after
-29 node2_committed_after
-30 node2_committed_after
-31 node1_to_be_committed_after
-32 node1_to_be_committed_after
-33 node1_to_be_committed_after
-34 node1_to_be_committed_after
-35 node1_to_be_committed_after
-36 node1_committed_after
-37 node1_committed_after
-38 node1_committed_after
-39 node1_committed_after
-40 node1_committed_after
+SELECT COUNT(*) = 35 FROM t1;
+COUNT(*) = 35
+1
SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1;
COUNT(*) = 0
1
COMMIT;
-connection node_1;
SET AUTOCOMMIT=ON;
-SET SESSION wsrep_sync_wait=15;
-SELECT COUNT(*) AS EXPECT_35 FROM t1;
-EXPECT_35
-35
-SELECT * FROM t1;
-id f1
-1 node1_committed_before
-2 node1_committed_before
-3 node1_committed_before
-4 node1_committed_before
-5 node1_committed_before
-6 node2_committed_before
-7 node2_committed_before
-8 node2_committed_before
-9 node2_committed_before
-10 node2_committed_before
-11 node1_committed_during
-12 node1_committed_during
-13 node1_committed_during
-14 node1_committed_during
-15 node1_committed_during
-16 node1_to_be_committed_after
-17 node1_to_be_committed_after
-18 node1_to_be_committed_after
-19 node1_to_be_committed_after
-20 node1_to_be_committed_after
-26 node2_committed_after
-27 node2_committed_after
-28 node2_committed_after
-29 node2_committed_after
-30 node2_committed_after
-31 node1_to_be_committed_after
-32 node1_to_be_committed_after
-33 node1_to_be_committed_after
-34 node1_to_be_committed_after
-35 node1_to_be_committed_after
-36 node1_committed_after
-37 node1_committed_after
-38 node1_committed_after
-39 node1_committed_after
-40 node1_committed_after
+connection node_1;
+SELECT COUNT(*) = 35 FROM t1;
+COUNT(*) = 35
+1
SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1;
COUNT(*) = 0
1
DROP TABLE t1;
COMMIT;
+SET AUTOCOMMIT=ON;
diff --git a/mysql-test/suite/galera/r/galera_sequences.result b/mysql-test/suite/galera/r/galera_sequences.result
index 48593d2a258..7276cb8dbde 100644
--- a/mysql-test/suite/galera/r/galera_sequences.result
+++ b/mysql-test/suite/galera/r/galera_sequences.result
@@ -44,6 +44,9 @@ Table Create Table
Seq1_1 CREATE SEQUENCE `Seq1_1` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=InnoDB
select NEXT VALUE FOR Seq1_1;
NEXT VALUE FOR Seq1_1
-1
+3001
connection node_1;
DROP SEQUENCE Seq1_1;
+CALL mtr.add_suppression("SEQUENCES declared without `NOCACHE` will not behave correctly in galera cluster.");
+connection node_2;
+CALL mtr.add_suppression("SEQUENCES declared without `NOCACHE` will not behave correctly in galera cluster.");
diff --git a/mysql-test/suite/galera/t/MDEV-18832.test b/mysql-test/suite/galera/t/MDEV-18832.test
index e2f1b2afd45..ba93761435a 100644
--- a/mysql-test/suite/galera/t/MDEV-18832.test
+++ b/mysql-test/suite/galera/t/MDEV-18832.test
@@ -13,3 +13,11 @@ CREATE SEQUENCE Seq1_1 START WITH 1 INCREMENT BY 1;
INSERT INTO t1 VALUES (NEXT VALUE FOR Seq1_1);
DROP SEQUENCE Seq1_1;
DROP TABLE t1;
+
+# Supress warning for SEQUENCES that are declared without `NOCACHE` introduced with MDEV-27862
+
+CALL mtr.add_suppression("SEQUENCES declared without `NOCACHE` will not behave correctly in galera cluster.");
+
+--connection node_2
+
+CALL mtr.add_suppression("SEQUENCES declared without `NOCACHE` will not behave correctly in galera cluster.");
diff --git a/mysql-test/suite/galera/t/MDEV-27862.combinations b/mysql-test/suite/galera/t/MDEV-27862.combinations
new file mode 100644
index 00000000000..1eeb8fb4614
--- /dev/null
+++ b/mysql-test/suite/galera/t/MDEV-27862.combinations
@@ -0,0 +1,4 @@
+[binlogoff]
+
+[binlogon]
+log-bin
diff --git a/mysql-test/suite/galera/t/MDEV-27862.test b/mysql-test/suite/galera/t/MDEV-27862.test
new file mode 100644
index 00000000000..89d3465b91f
--- /dev/null
+++ b/mysql-test/suite/galera/t/MDEV-27862.test
@@ -0,0 +1,67 @@
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+# Report WARNING when SEQUENCE is created without `NOCACHE`
+
+CREATE SEQUENCE seq_nocache ENGINE=InnoDB;
+DROP SEQUENCE seq_nocache;
+
+CALL mtr.add_suppression("SEQUENCES declared without `NOCACHE` will not behave correctly in galera cluster.");
+
+--connection node_2
+
+CALL mtr.add_suppression("SEQUENCES declared without `NOCACHE` will not behave correctly in galera cluster.");
+
+# NEXTVAL
+
+--connection node_1
+
+CREATE SEQUENCE seq NOCACHE ENGINE=InnoDB;
+
+SELECT NEXTVAL(seq) = 1;
+
+--connection node_2
+
+SELECT NEXTVAL(seq) = 2;
+
+--connection node_1
+
+SELECT NEXTVAL(seq) = 3;
+
+
+# SETVAL
+
+SELECT SETVAL(seq, 100);
+
+--connection node_2
+
+SELECT NEXTVAL(seq) = 101;
+
+--connection node_1
+
+SELECT NEXTVAL(seq) = 102;
+
+DROP SEQUENCE seq;
+
+# TRANSACTIONS
+
+CREATE TABLE t1(f1 INT);
+CREATE SEQUENCE seq_transaction NOCACHE ENGINE=InnoDB;
+
+START TRANSACTION;
+INSERT INTO t1 VALUES (0);
+SELECT NEXTVAL(seq_transaction);
+INSERT INTO t1 VALUES (NEXTVAL(seq_transaction));
+COMMIT;
+
+--connection node_2
+
+SELECT COUNT(*) = 2 FROM t1;
+SELECT NEXTVAL(seq_transaction) = 3;
+
+--connection node_1
+SELECT NEXTVAL(seq_transaction) = 4;
+
+DROP SEQUENCE seq_transaction;
+DROP TABLE t1;
+
diff --git a/mysql-test/suite/galera/t/galera_sequences.test b/mysql-test/suite/galera/t/galera_sequences.test
index 480366f6a6f..d469cc73516 100644
--- a/mysql-test/suite/galera/t/galera_sequences.test
+++ b/mysql-test/suite/galera/t/galera_sequences.test
@@ -44,3 +44,9 @@ select NEXT VALUE FOR Seq1_1;
--connection node_1
DROP SEQUENCE Seq1_1;
+
+CALL mtr.add_suppression("SEQUENCES declared without `NOCACHE` will not behave correctly in galera cluster.");
+
+--connection node_2
+
+CALL mtr.add_suppression("SEQUENCES declared without `NOCACHE` will not behave correctly in galera cluster.");
diff --git a/mysql-test/suite/innodb/disabled.def b/mysql-test/suite/innodb/disabled.def
deleted file mode 100644
index 35c941f8af7..00000000000
--- a/mysql-test/suite/innodb/disabled.def
+++ /dev/null
@@ -1,13 +0,0 @@
-##############################################################################
-#
-# List the test cases that are to be disabled temporarily.
-#
-# Separate the test case name and the comment with ':'.
-#
-# : BUG#
-#
-# Do not use any TAB characters for whitespace.
-#
-##############################################################################
-
-create-index-debug : MDEV-13680 InnoDB may crash when btr_page_alloc() fails
diff --git a/mysql-test/suite/innodb/r/create-index-debug.result b/mysql-test/suite/innodb/r/create-index-debug.result
deleted file mode 100644
index 9d266c68af3..00000000000
--- a/mysql-test/suite/innodb/r/create-index-debug.result
+++ /dev/null
@@ -1,23 +0,0 @@
-SET @saved_debug_dbug = @@SESSION.debug_dbug;
-#
-#BUG#21326304 INNODB ONLINE ALTER TABLE ENDS IN CRASH ON DISK FULL
-#
-CREATE TABLE t1(f1 CHAR(255) NOT NULL, f2 CHAR(255) NOT NULL, f3
-CHAR(255) NOT NULL, f4 CHAR(255) NOT NULL, f5 CHAR(255) NOT NULL,f6
-CHAR(255) NOT NULL, f7 CHAR(255) NOT NULL, f8 CHAR(255) NOT NULL,f9
-CHAR(255) NOT NULL, f10 CHAR(255) NOT NULL, f11 CHAR(255) NOT NULL,f12
-CHAR(255) NOT NULL, f13 CHAR(255) NOT NULL, f14 CHAR(255) NOT NULL,f15
-CHAR(255) NOT NULL, f16 CHAR(255) NOT NULL, f17 CHAR(255) NOT NULL,f18
-CHAR(255) NOT NULL)
-ENGINE=INNODB ROW_FORMAT=DYNAMIC;
-INSERT INTO t1
-VALUES('a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r');
-INSERT INTO t1 SELECT * FROM t1;
-INSERT INTO t1 SELECT * FROM t1;
-INSERT INTO t1 SELECT * FROM t1;
-INSERT INTO t1 SELECT * FROM t1;
-SET debug_dbug = '+d,disk_is_full';
-ALTER TABLE t1 FORCE, ALGORITHM=INPLACE;
-ERROR HY000: The table 't1' is full
-SET debug_dbug= @saved_debug_dbug;
-DROP TABLE t1;
diff --git a/mysql-test/suite/innodb/r/import_corrupted.result b/mysql-test/suite/innodb/r/import_corrupted.result
index 149a48dccfe..bc24a28f22f 100644
--- a/mysql-test/suite/innodb/r/import_corrupted.result
+++ b/mysql-test/suite/innodb/r/import_corrupted.result
@@ -1,6 +1,7 @@
call mtr.add_suppression("Table `test`.`t2` should have 2 indexes but the tablespace has 1 indexes");
call mtr.add_suppression("Index for table 't2' is corrupt; try to repair it");
call mtr.add_suppression("Trying to read .* bytes at .* outside the bounds of the file: \\..test.t2\\.ibd");
+call mtr.add_suppression("InnoDB: File '.*test/t2\\.ibd' is corrupted");
CREATE TABLE t1 (
id INT AUTO_INCREMENT PRIMARY KEY,
not_id INT,
diff --git a/mysql-test/suite/innodb/r/innodb-wl5522-debug.result b/mysql-test/suite/innodb/r/innodb-wl5522-debug.result
index 2973e5de550..08f4bb93899 100644
--- a/mysql-test/suite/innodb/r/innodb-wl5522-debug.result
+++ b/mysql-test/suite/innodb/r/innodb-wl5522-debug.result
@@ -9,6 +9,8 @@ call mtr.add_suppression("InnoDB: Page for tablespace ");
call mtr.add_suppression("InnoDB: Invalid FSP_SPACE_FLAGS=");
call mtr.add_suppression("InnoDB: Unknown index id .* on page");
call mtr.add_suppression("InnoDB: Cannot save statistics for table `test`\\.`t1` because the \\.ibd file is missing");
+call mtr.add_suppression("InnoDB: Database page corruption on disk or a failed read of file '.*ibdata1' page");
+call mtr.add_suppression("InnoDB: File '.*ibdata1' is corrupted");
FLUSH TABLES;
SET GLOBAL innodb_file_per_table = 1;
CREATE TABLE t1 (c1 INT) ENGINE = InnoDB;
@@ -862,10 +864,8 @@ ALTER TABLE t1 DISCARD TABLESPACE;
SELECT COUNT(*) FROM t1;
ERROR HY000: Tablespace has been discarded for table `t1`
restore: t1 .ibd and .cfg files
-SET SESSION debug_dbug="+d,buf_page_import_corrupt_failure";
ALTER TABLE t1 IMPORT TABLESPACE;
-ERROR HY000: Internal error: Cannot reset LSNs in table `test`.`t1` : Data structure corruption
-SET SESSION debug_dbug=@saved_debug_dbug;
+ERROR HY000: Index for table 't1' is corrupt; try to repair it
DROP TABLE t1;
unlink: t1.ibd
unlink: t1.cfg
diff --git a/mysql-test/suite/innodb/r/page_id_innochecksum.result b/mysql-test/suite/innodb/r/page_id_innochecksum.result
index e2c13442fe6..7a5f44b21e6 100644
--- a/mysql-test/suite/innodb/r/page_id_innochecksum.result
+++ b/mysql-test/suite/innodb/r/page_id_innochecksum.result
@@ -3,4 +3,7 @@ create table t1(f1 int not null)engine=innodb;
insert into t1 values(1), (2), (3);
# Change the page offset
FOUND 1 /page id mismatch/ in result.log
+SET GLOBAL innodb_purge_rseg_truncate_frequency=1;
+InnoDB 0 transactions not purged
drop table t1;
+call mtr.add_suppression("InnoDB: Failed to read page 3 from file '.*test/t1\\.ibd': Page read from tablespace is corrupted\\.");
diff --git a/mysql-test/suite/innodb/t/corrupted_during_recovery.test b/mysql-test/suite/innodb/t/corrupted_during_recovery.test
index 4893a638dda..a7858dd1e26 100644
--- a/mysql-test/suite/innodb/t/corrupted_during_recovery.test
+++ b/mysql-test/suite/innodb/t/corrupted_during_recovery.test
@@ -6,8 +6,8 @@ call mtr.add_suppression("Plugin 'InnoDB' init function returned error");
call mtr.add_suppression("Plugin 'InnoDB' registration as a STORAGE ENGINE failed");
call mtr.add_suppression("InnoDB: Database page corruption on disk or a failed read of file '.*test.t1\\.ibd' page");
call mtr.add_suppression("InnoDB: Failed to read page 3 from file '.*test.t1\\.ibd': Page read from tablespace is corrupted.");
-call mtr.add_suppression("InnoDB: Background Page read failed to read or decrypt \\[page id: space=\\d+, page number=3\\]");
-call mtr.add_suppression("Table .*t1.* is corrupted. Please drop the table and recreate.");
+call mtr.add_suppression("Table test/t1 is corrupted. Please drop the table and recreate\\.");
+call mtr.add_suppression("InnoDB: File '.*test/t1\\.ibd' is corrupted");
--enable_query_log
let INNODB_PAGE_SIZE=`select @@innodb_page_size`;
diff --git a/mysql-test/suite/innodb/t/create-index-debug.test b/mysql-test/suite/innodb/t/create-index-debug.test
deleted file mode 100644
index 9ea416fbe1e..00000000000
--- a/mysql-test/suite/innodb/t/create-index-debug.test
+++ /dev/null
@@ -1,34 +0,0 @@
---source include/have_innodb.inc
---source include/have_innodb_16k.inc
---source include/have_debug.inc
-
-SET @saved_debug_dbug = @@SESSION.debug_dbug;
-
---echo #
---echo #BUG#21326304 INNODB ONLINE ALTER TABLE ENDS IN CRASH ON DISK FULL
---echo #
-CREATE TABLE t1(f1 CHAR(255) NOT NULL, f2 CHAR(255) NOT NULL, f3
-CHAR(255) NOT NULL, f4 CHAR(255) NOT NULL, f5 CHAR(255) NOT NULL,f6
-CHAR(255) NOT NULL, f7 CHAR(255) NOT NULL, f8 CHAR(255) NOT NULL,f9
-CHAR(255) NOT NULL, f10 CHAR(255) NOT NULL, f11 CHAR(255) NOT NULL,f12
-CHAR(255) NOT NULL, f13 CHAR(255) NOT NULL, f14 CHAR(255) NOT NULL,f15
-CHAR(255) NOT NULL, f16 CHAR(255) NOT NULL, f17 CHAR(255) NOT NULL,f18
-CHAR(255) NOT NULL)
-ENGINE=INNODB ROW_FORMAT=DYNAMIC;
-
-INSERT INTO t1
-VALUES('a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r');
-
-INSERT INTO t1 SELECT * FROM t1;
-INSERT INTO t1 SELECT * FROM t1;
-INSERT INTO t1 SELECT * FROM t1;
-INSERT INTO t1 SELECT * FROM t1;
-
-SET debug_dbug = '+d,disk_is_full';
-
---error ER_RECORD_FILE_FULL
-ALTER TABLE t1 FORCE, ALGORITHM=INPLACE;
-
-SET debug_dbug= @saved_debug_dbug;
-
-DROP TABLE t1;
diff --git a/mysql-test/suite/innodb/t/import_corrupted.test b/mysql-test/suite/innodb/t/import_corrupted.test
index 3a9b9a40493..57c8c6dd9be 100644
--- a/mysql-test/suite/innodb/t/import_corrupted.test
+++ b/mysql-test/suite/innodb/t/import_corrupted.test
@@ -3,6 +3,7 @@
call mtr.add_suppression("Table `test`.`t2` should have 2 indexes but the tablespace has 1 indexes");
call mtr.add_suppression("Index for table 't2' is corrupt; try to repair it");
call mtr.add_suppression("Trying to read .* bytes at .* outside the bounds of the file: \\..test.t2\\.ibd");
+call mtr.add_suppression("InnoDB: File '.*test/t2\\.ibd' is corrupted");
let MYSQLD_DATADIR = `SELECT @@datadir`;
diff --git a/mysql-test/suite/innodb/t/innodb-wl5522-debug.test b/mysql-test/suite/innodb/t/innodb-wl5522-debug.test
index b460cba9322..76c7346b521 100644
--- a/mysql-test/suite/innodb/t/innodb-wl5522-debug.test
+++ b/mysql-test/suite/innodb/t/innodb-wl5522-debug.test
@@ -29,6 +29,8 @@ call mtr.add_suppression("InnoDB: Page for tablespace ");
call mtr.add_suppression("InnoDB: Invalid FSP_SPACE_FLAGS=");
call mtr.add_suppression("InnoDB: Unknown index id .* on page");
call mtr.add_suppression("InnoDB: Cannot save statistics for table `test`\\.`t1` because the \\.ibd file is missing");
+call mtr.add_suppression("InnoDB: Database page corruption on disk or a failed read of file '.*ibdata1' page");
+call mtr.add_suppression("InnoDB: File '.*ibdata1' is corrupted");
FLUSH TABLES;
let MYSQLD_DATADIR =`SELECT @@datadir`;
@@ -1173,20 +1175,29 @@ ALTER TABLE t1 DISCARD TABLESPACE;
SELECT COUNT(*) FROM t1;
# Restore files
+let INNODB_PAGE_SIZE=`select @@innodb_page_size`;
+
perl;
do "$ENV{MTR_SUITE_DIR}/include/innodb-util.pl";
ib_restore_tablespaces("test", "t1");
+my $page;
+my $ps = $ENV{INNODB_PAGE_SIZE};
+my $file = "$ENV{MYSQLD_DATADIR}/test/t1.ibd";
+open(FILE, "+<$file") || die "Unable to open $file";
+binmode FILE;
+sysseek(FILE, 3*$ps, 0) || die "Unable to seek $file\n";
+die "Unable to read $file" unless sysread(FILE, $page, $ps) == $ps;
+substr($page,24,2)='42';
+sysseek(FILE, 3*$ps, 0) || die "Unable to rewind $file\n";
+syswrite(FILE, $page, $ps)==$ps || die "Unable to write $file\n";
+close(FILE) || die "Unable to close $file";
EOF
-SET SESSION debug_dbug="+d,buf_page_import_corrupt_failure";
-
--replace_regex /'.*t1.cfg'/'t1.cfg'/
---error ER_INTERNAL_ERROR
+--error ER_NOT_KEYFILE
ALTER TABLE t1 IMPORT TABLESPACE;
-SET SESSION debug_dbug=@saved_debug_dbug;
-
DROP TABLE t1;
perl;
diff --git a/mysql-test/suite/innodb/t/innodb_bug14147491.test b/mysql-test/suite/innodb/t/innodb_bug14147491.test
index c6e4f01a642..3c37f1b7cce 100644
--- a/mysql-test/suite/innodb/t/innodb_bug14147491.test
+++ b/mysql-test/suite/innodb/t/innodb_bug14147491.test
@@ -12,6 +12,7 @@ call mtr.add_suppression("InnoDB: Table `test`\\.`t1` is corrupted\\. Please dro
call mtr.add_suppression("InnoDB: Database page corruption on disk or a failed read of file '.*test.t1\\.ibd' page");
call mtr.add_suppression("InnoDB: We detected index corruption in an InnoDB type table");
call mtr.add_suppression("Index for table 't1' is corrupt; try to repair it");
+call mtr.add_suppression("InnoDB: File '.*test/t1\\.ibd' is corrupted");
--enable_query_log
--echo # Ensure that purge will not crash on the table after we corrupt it.
@@ -70,13 +71,13 @@ EOF
--echo # Now t1 is corrupted but we should not crash
---error 1030,1712,1932
+--error ER_GET_ERRNO,ER_NOT_KEYFILE,ER_INDEX_CORRUPT,ER_NO_SUCH_TABLE_IN_ENGINE
SELECT * FROM t1;
---error 126,1030,1034,1712,1932
+--error 126,ER_GET_ERRNO,ER_NOT_KEYFILE,ER_INDEX_CORRUPT,ER_NO_SUCH_TABLE_IN_ENGINE
INSERT INTO t1(b) VALUES('abcdef');
---error 1030,1712,1932
+--error ER_GET_ERRNO,ER_NOT_KEYFILE,ER_INDEX_CORRUPT,ER_NO_SUCH_TABLE_IN_ENGINE
UPDATE t1 set b = 'deadbeef' where a = 1;
--echo # Cleanup, this must be possible
diff --git a/mysql-test/suite/innodb/t/leaf_page_corrupted_during_recovery.test b/mysql-test/suite/innodb/t/leaf_page_corrupted_during_recovery.test
index ac5f14ba9ad..d4391f89ec1 100644
--- a/mysql-test/suite/innodb/t/leaf_page_corrupted_during_recovery.test
+++ b/mysql-test/suite/innodb/t/leaf_page_corrupted_during_recovery.test
@@ -3,13 +3,13 @@
--disable_query_log
call mtr.add_suppression("InnoDB: Database page corruption on disk or a failed read of file '.*test.t1\\.ibd' page");
-call mtr.add_suppression("InnoDB: Background Page read failed to read or decrypt \\[page id: space=\\d+, page number=19\\]");
call mtr.add_suppression("\\[ERROR\\] InnoDB: Failed to read page 19 from file '.*test.t1\\.ibd': Page read from tablespace is corrupted\\.");
call mtr.add_suppression("\\[ERROR\\] InnoDB: Plugin initialization aborted at srv0start\\.cc.* with error Data structure corruption");
call mtr.add_suppression("\\[ERROR\\] Plugin 'InnoDB' (init function|registration)");
call mtr.add_suppression("\\[ERROR\\] InnoDB: We detected index corruption");
call mtr.add_suppression("\\[ERROR\\] (mysqld|mariadbd).*: Index for table 't1' is corrupt; try to repair it");
call mtr.add_suppression("InnoDB: btr_pcur_open_low level: 0 table: `test`\\.`t1` index: `PRIMARY`");
+call mtr.add_suppression("InnoDB: File '.*test/t1\\.ibd' is corrupted");
--enable_query_log
CREATE TABLE t1 (pk INT PRIMARY KEY, c CHAR(255))ENGINE=InnoDB STATS_PERSISTENT=0;
diff --git a/mysql-test/suite/innodb/t/page_id_innochecksum.test b/mysql-test/suite/innodb/t/page_id_innochecksum.test
index f5166018dd1..2a2c14844fa 100644
--- a/mysql-test/suite/innodb/t/page_id_innochecksum.test
+++ b/mysql-test/suite/innodb/t/page_id_innochecksum.test
@@ -61,9 +61,11 @@ let SEARCH_PATTERN=page id mismatch;
--source include/search_pattern_in_file.inc
--remove_file $resultlog
-# prevent purge from crashing on page ID mismatch
-let $restart_parameters=--innodb-force-recovery=2;
+let $restart_parameters=--innodb-force-recovery=1;
--source include/start_mysqld.inc
+SET GLOBAL innodb_purge_rseg_truncate_frequency=1;
+--source include/wait_all_purged.inc
drop table t1;
+call mtr.add_suppression("InnoDB: Failed to read page 3 from file '.*test/t1\\.ibd': Page read from tablespace is corrupted\\.");
let $restart_parameters=;
--source include/restart_mysqld.inc
diff --git a/mysql-test/suite/innodb_fts/r/fulltext.result b/mysql-test/suite/innodb_fts/r/fulltext.result
index ce72d797ac1..38df74f6939 100644
--- a/mysql-test/suite/innodb_fts/r/fulltext.result
+++ b/mysql-test/suite/innodb_fts/r/fulltext.result
@@ -716,4 +716,18 @@ t1 CREATE TABLE `t1` (
FULLTEXT KEY `a_2` (`a`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
DROP TABLE t1;
+#
+# MDEV-25257 SEGV in fts_get_next_doc_id upon some INSERT
+#
+SET @save = @@global.innodb_file_per_table;
+SET @@global.innodb_file_per_table = 0;
+CREATE TABLE t1 (
+col_int INTEGER, col_text TEXT,
+col_int_g INTEGER GENERATED ALWAYS AS (col_int)
+) ENGINE = InnoDB ROW_FORMAT = Redundant ;
+ALTER TABLE t1 ADD FULLTEXT KEY `ftidx` ( col_text ) ;
+ALTER TABLE t1 DROP KEY `ftidx` ;
+INSERT INTO t1 (col_int, col_text) VALUES ( 1255, NULL);
+DROP TABLE t1;
+SET @@global.innodb_file_per_table = @save;
# End of 10.3 tests
diff --git a/mysql-test/suite/innodb_fts/t/fulltext.test b/mysql-test/suite/innodb_fts/t/fulltext.test
index 18baf56281f..4b73e2ea15b 100644
--- a/mysql-test/suite/innodb_fts/t/fulltext.test
+++ b/mysql-test/suite/innodb_fts/t/fulltext.test
@@ -743,4 +743,20 @@ SHOW CREATE TABLE t1;
DROP TABLE t1;
--enable_warnings
+--echo #
+--echo # MDEV-25257 SEGV in fts_get_next_doc_id upon some INSERT
+--echo #
+SET @save = @@global.innodb_file_per_table;
+SET @@global.innodb_file_per_table = 0;
+
+CREATE TABLE t1 (
+ col_int INTEGER, col_text TEXT,
+ col_int_g INTEGER GENERATED ALWAYS AS (col_int)
+) ENGINE = InnoDB ROW_FORMAT = Redundant ;
+ALTER TABLE t1 ADD FULLTEXT KEY `ftidx` ( col_text ) ;
+ALTER TABLE t1 DROP KEY `ftidx` ;
+INSERT INTO t1 (col_int, col_text) VALUES ( 1255, NULL);
+DROP TABLE t1;
+SET @@global.innodb_file_per_table = @save;
+
--echo # End of 10.3 tests
diff --git a/mysql-test/suite/innodb_zip/r/wl5522_debug_zip.result b/mysql-test/suite/innodb_zip/r/wl5522_debug_zip.result
index c69c30c5b25..63369c9b41f 100644
--- a/mysql-test/suite/innodb_zip/r/wl5522_debug_zip.result
+++ b/mysql-test/suite/innodb_zip/r/wl5522_debug_zip.result
@@ -9,6 +9,8 @@ call mtr.add_suppression("InnoDB: The error means");
call mtr.add_suppression("InnoDB: Cannot open datafile .*t1\\.ibd");
call mtr.add_suppression("InnoDB: Ignoring tablespace for test/t1 ");
call mtr.add_suppression("InnoDB: Cannot save statistics for table `test`\\.`t1` because the \\.ibd file is missing");
+call mtr.add_suppression("InnoDB: Database page corruption on disk or a failed read of file '.*ibdata1' page");
+call mtr.add_suppression("InnoDB: File '.*ibdata1' is corrupted");
FLUSH TABLES;
SET SESSION innodb_strict_mode=1;
CREATE TABLE t1 (c1 INT) ENGINE = Innodb
@@ -325,10 +327,8 @@ ALTER TABLE t1 DISCARD TABLESPACE;
SELECT COUNT(*) FROM t1;
ERROR HY000: Tablespace has been discarded for table `t1`
restore: t1 .ibd and .cfg files
-SET SESSION debug_dbug="+d,buf_page_import_corrupt_failure";
ALTER TABLE t1 IMPORT TABLESPACE;
-ERROR HY000: Internal error: Cannot reset LSNs in table `test`.`t1` : Data structure corruption
-SET SESSION debug_dbug=@saved_debug_dbug;
+Got one of the listed errors
DROP TABLE t1;
unlink: t1.ibd
unlink: t1.cfg
diff --git a/mysql-test/suite/innodb_zip/t/wl5522_debug_zip.test b/mysql-test/suite/innodb_zip/t/wl5522_debug_zip.test
index 8d328dea576..c30a4f8f000 100644
--- a/mysql-test/suite/innodb_zip/t/wl5522_debug_zip.test
+++ b/mysql-test/suite/innodb_zip/t/wl5522_debug_zip.test
@@ -25,6 +25,8 @@ call mtr.add_suppression("InnoDB: The error means");
call mtr.add_suppression("InnoDB: Cannot open datafile .*t1\\.ibd");
call mtr.add_suppression("InnoDB: Ignoring tablespace for test/t1 ");
call mtr.add_suppression("InnoDB: Cannot save statistics for table `test`\\.`t1` because the \\.ibd file is missing");
+call mtr.add_suppression("InnoDB: Database page corruption on disk or a failed read of file '.*ibdata1' page");
+call mtr.add_suppression("InnoDB: File '.*ibdata1' is corrupted");
FLUSH TABLES;
let MYSQLD_DATADIR =`SELECT @@datadir`;
@@ -435,19 +437,29 @@ ALTER TABLE t1 DISCARD TABLESPACE;
SELECT COUNT(*) FROM t1;
# Restore files
+let INNODB_PAGE_SIZE=`select @@innodb_page_size`;
+let MYSQLD_DATADIR=`select @@datadir`;
+
perl;
do "$ENV{MTR_SUITE_DIR}/../innodb/include/innodb-util.pl";
ib_restore_tablespaces("test", "t1");
+my $page;
+my $ps = $ENV{INNODB_PAGE_SIZE};
+my $file = "$ENV{MYSQLD_DATADIR}/test/t1.ibd";
+open(FILE, "+<$file") || die "Unable to open $file";
+binmode FILE;
+sysseek(FILE, 4*$ps, 0) || die "Unable to seek $file\n";
+die "Unable to read $file" unless sysread(FILE, $page, $ps) == $ps;
+substr($page,24,2)='42';
+sysseek(FILE, 4*$ps, 0) || die "Unable to rewind $file\n";
+syswrite(FILE, $page, $ps)==$ps || die "Unable to write $file\n";
+close(FILE) || die "Unable to close $file";
EOF
-SET SESSION debug_dbug="+d,buf_page_import_corrupt_failure";
-
# Following alter is failing
---error ER_INTERNAL_ERROR
+--error ER_INTERNAL_ERROR,ER_NOT_KEYFILE
ALTER TABLE t1 IMPORT TABLESPACE;
-SET SESSION debug_dbug=@saved_debug_dbug;
-
DROP TABLE t1;
perl;
diff --git a/scripts/wsrep_sst_mariabackup.sh b/scripts/wsrep_sst_mariabackup.sh
index a3fc4b78718..a66a792b5ea 100644
--- a/scripts/wsrep_sst_mariabackup.sh
+++ b/scripts/wsrep_sst_mariabackup.sh
@@ -86,7 +86,6 @@ encrypt_threads=""
encrypt_chunk=""
readonly SECRET_TAG='secret'
-readonly TOTAL_TAG='secret /total'
# Required for backup locks
# For backup locks it is 1 sent by joiner
@@ -419,7 +418,7 @@ get_transfer()
get_footprint()
{
- pushd "$WSREP_SST_OPT_DATA" 1>/dev/null
+ cd "$DATA_DIR"
payload=$(find . -regex '.*\.ibd$\|.*\.MYI$\|.*\.MYD$\|.*ibdata1$' \
-type f -print0 | du --files0-from=- --block-size=1 -c -s | \
awk 'END { print $1 }')
@@ -428,7 +427,7 @@ get_footprint()
# When compression/compaction used, the progress is only an approximate.
payload=$(( payload*1/2 ))
fi
- popd 1>/dev/null
+ cd "$OLD_PWD"
pcmd="$pcmd -s $payload"
adjust_progress
}
diff --git a/sql/ha_sequence.cc b/sql/ha_sequence.cc
index 2447242593c..b348e6e7025 100644
--- a/sql/ha_sequence.cc
+++ b/sql/ha_sequence.cc
@@ -452,6 +452,9 @@ static int sequence_initialize(void *p)
HTON_HIDDEN |
HTON_TEMPORARY_NOT_SUPPORTED |
HTON_ALTER_NOT_SUPPORTED |
+#ifdef WITH_WSREP
+ HTON_WSREP_REPLICATION |
+#endif
HTON_NO_PARTITION);
DBUG_RETURN(0);
}
diff --git a/sql/log.cc b/sql/log.cc
index 3d92fde335e..468f171ae2c 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -2139,7 +2139,13 @@ int binlog_commit(THD *thd, bool all, bool ro_1pc)
thd->backup_stage(&org_stage);
THD_STAGE_INFO(thd, stage_binlog_write);
+#ifdef WITH_WSREP
+ // DON'T clear stmt cache in case we are in transaction
+ if (!cache_mngr->stmt_cache.empty() &&
+ (!wsrep_on(thd) || ending_trans(thd, all)))
+#else
if (!cache_mngr->stmt_cache.empty())
+#endif
{
error= binlog_commit_flush_stmt_cache(thd, all, cache_mngr);
}
@@ -11757,13 +11763,13 @@ maria_declare_plugin_end;
#ifdef WITH_WSREP
#include "wsrep_mysqld.h"
-IO_CACHE *wsrep_get_trans_cache(THD * thd)
+IO_CACHE *wsrep_get_cache(THD * thd, bool is_transactional)
{
DBUG_ASSERT(binlog_hton->slot != HA_SLOT_UNDEF);
binlog_cache_mngr *cache_mngr = (binlog_cache_mngr*)
thd_get_ha_data(thd, binlog_hton);
if (cache_mngr)
- return cache_mngr->get_binlog_cache_log(true);
+ return cache_mngr->get_binlog_cache_log(is_transactional);
WSREP_DEBUG("binlog cache not initialized, conn: %llu",
thd->thread_id);
diff --git a/sql/log.h b/sql/log.h
index 964b0dcfef7..516fb36adb9 100644
--- a/sql/log.h
+++ b/sql/log.h
@@ -1253,7 +1253,7 @@ static inline TC_LOG *get_tc_log_implementation()
}
#ifdef WITH_WSREP
-IO_CACHE* wsrep_get_trans_cache(THD *);
+IO_CACHE* wsrep_get_cache(THD *, bool);
void wsrep_thd_binlog_trx_reset(THD * thd);
void wsrep_thd_binlog_stmt_rollback(THD * thd);
#endif /* WITH_WSREP */
diff --git a/sql/partition_info.cc b/sql/partition_info.cc
index 6f3f6ec211a..3d0669e249a 100644
--- a/sql/partition_info.cc
+++ b/sql/partition_info.cc
@@ -887,10 +887,12 @@ void partition_info::vers_check_limit(THD *thd)
bitmap_set_all(), but this is not optimal since there can be quite a number
of partitions.
*/
+#ifndef DBUG_OFF
const uint32 sub_factor= num_subparts ? num_subparts : 1;
uint32 part_id= vers_info->hist_part->id * sub_factor;
const uint32 part_id_end= part_id + sub_factor;
DBUG_ASSERT(part_id_end <= num_parts * sub_factor);
+#endif
ha_partition *hp= (ha_partition*)(table->file);
ha_rows hist_rows= hp->part_records(vers_info->hist_part);
diff --git a/sql/sql_partition_admin.cc b/sql/sql_partition_admin.cc
index b1989f79051..a2d2a833285 100644
--- a/sql/sql_partition_admin.cc
+++ b/sql/sql_partition_admin.cc
@@ -578,6 +578,14 @@ bool Sql_cmd_alter_table_exchange_partition::
part_table= table_list->table;
swap_table= swap_table_list->table;
+ /* Don't allow to exchange with a VIEW */
+ if (unlikely(swap_table_list->view))
+ {
+ my_error(ER_WRONG_OBJECT, MYF(0), table_list->db.str,
+ swap_table_list->table_name.str, "BASE TABLE");
+ DBUG_RETURN(TRUE);
+ }
+
if (unlikely(check_exchange_partition(swap_table, part_table)))
DBUG_RETURN(TRUE);
diff --git a/sql/sql_sequence.cc b/sql/sql_sequence.cc
index 7ef30641888..07571c3bbac 100644
--- a/sql/sql_sequence.cc
+++ b/sql/sql_sequence.cc
@@ -309,6 +309,11 @@ bool sequence_insert(THD *thd, LEX *lex, TABLE_LIST *org_table_list)
DBUG_RETURN(TRUE);
}
+#ifdef WITH_WSREP
+ if (WSREP_ON && seq->cache != 0)
+ WSREP_WARN("CREATE SEQUENCES declared without `NOCACHE` will not behave correctly in galera cluster.");
+#endif
+
/* If not temporary table */
if (!temporary_table)
{
@@ -901,12 +906,18 @@ bool Sql_cmd_alter_sequence::execute(THD *thd)
No_such_table_error_handler no_such_table_handler;
DBUG_ENTER("Sql_cmd_alter_sequence::execute");
+
if (check_access(thd, ALTER_ACL, first_table->db.str,
&first_table->grant.privilege,
&first_table->grant.m_internal,
0, 0))
DBUG_RETURN(TRUE); /* purecov: inspected */
+#ifdef WITH_WSREP
+ if (WSREP_ON && new_seq->cache != 0)
+ WSREP_WARN("ALTER SEQUENCES declared without `NOCACHE` will not behave correctly in galera cluster.");
+#endif
+
if (check_grant(thd, ALTER_ACL, first_table, FALSE, 1, FALSE))
DBUG_RETURN(TRUE); /* purecov: inspected */
diff --git a/sql/table.h b/sql/table.h
index 8d609fbf1bb..1c09f463d9e 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -1,7 +1,7 @@
#ifndef TABLE_INCLUDED
#define TABLE_INCLUDED
/* Copyright (c) 2000, 2017, Oracle and/or its affiliates.
- Copyright (c) 2009, 2021, MariaDB
+ Copyright (c) 2009, 2022, MariaDB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -3183,9 +3183,6 @@ enum open_frm_error open_table_from_share(THD *thd, TABLE_SHARE *share,
bool is_create_table,
List *partitions_to_open= NULL);
bool copy_keys_from_share(TABLE *outparam, MEM_ROOT *root);
-bool fix_session_vcol_expr(THD *thd, Virtual_column_info *vcol);
-bool fix_session_vcol_expr_for_read(THD *thd, Field *field,
- Virtual_column_info *vcol);
bool parse_vcol_defs(THD *thd, MEM_ROOT *mem_root, TABLE *table,
bool *error_reported, vcol_init_mode expr);
TABLE_SHARE *alloc_table_share(const char *db, const char *table_name,
diff --git a/sql/wsrep_binlog.cc b/sql/wsrep_binlog.cc
index 3fe0792d83e..bcc5d2fe46d 100644
--- a/sql/wsrep_binlog.cc
+++ b/sql/wsrep_binlog.cc
@@ -155,10 +155,10 @@ static int wsrep_write_cache_inc(THD* const thd,
goto cleanup;
cache->read_pos= cache->read_end;
} while ((cache->file >= 0) && (length= my_b_fill(cache)));
- }
- if (ret == 0)
- {
- assert(total_length + thd->wsrep_sr().log_position() == saved_pos);
+ if (ret == 0)
+ {
+ assert(total_length + thd->wsrep_sr().log_position() == saved_pos);
+ }
}
cleanup:
diff --git a/sql/wsrep_client_service.cc b/sql/wsrep_client_service.cc
index ab746dfa1fb..fee9fefdd44 100644
--- a/sql/wsrep_client_service.cc
+++ b/sql/wsrep_client_service.cc
@@ -83,18 +83,37 @@ int Wsrep_client_service::prepare_data_for_replication()
DBUG_ASSERT(m_thd == current_thd);
DBUG_ENTER("Wsrep_client_service::prepare_data_for_replication");
size_t data_len= 0;
- IO_CACHE* cache= wsrep_get_trans_cache(m_thd);
+ IO_CACHE* transactional_cache= wsrep_get_cache(m_thd, true);
+ IO_CACHE* stmt_cache= wsrep_get_cache(m_thd, false);
- if (cache)
+ if (transactional_cache || stmt_cache)
{
m_thd->binlog_flush_pending_rows_event(true);
- if (wsrep_write_cache(m_thd, cache, &data_len))
+
+ size_t transactional_data_len= 0;
+ size_t stmt_data_len= 0;
+
+ // Write transactional cache
+ if (transactional_cache &&
+ wsrep_write_cache(m_thd, transactional_cache, &transactional_data_len))
{
WSREP_ERROR("rbr write fail, data_len: %zu",
data_len);
// wsrep_override_error(m_thd, ER_ERROR_DURING_COMMIT);
DBUG_RETURN(1);
}
+
+ // Write stmt cache
+ if (stmt_cache && wsrep_write_cache(m_thd, stmt_cache, &stmt_data_len))
+ {
+ WSREP_ERROR("rbr write fail, data_len: %zu",
+ data_len);
+ // wsrep_override_error(m_thd, ER_ERROR_DURING_COMMIT);
+ DBUG_RETURN(1);
+ }
+
+ // Complete data written from both caches
+ data_len = transactional_data_len + stmt_data_len;
}
if (data_len == 0)
@@ -136,7 +155,7 @@ int Wsrep_client_service::prepare_fragment_for_replication(
DBUG_ASSERT(m_thd == current_thd);
THD* thd= m_thd;
DBUG_ENTER("Wsrep_client_service::prepare_fragment_for_replication");
- IO_CACHE* cache= wsrep_get_trans_cache(thd);
+ IO_CACHE* cache= wsrep_get_cache(thd, true);
thd->binlog_flush_pending_rows_event(true);
if (!cache)
@@ -218,7 +237,7 @@ bool Wsrep_client_service::statement_allowed_for_streaming() const
size_t Wsrep_client_service::bytes_generated() const
{
- IO_CACHE* cache= wsrep_get_trans_cache(m_thd);
+ IO_CACHE* cache= wsrep_get_cache(m_thd, true);
if (cache)
{
size_t pending_rows_event_length= 0;
diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc
index eef1fde8c7d..f43e641c8f3 100644
--- a/sql/wsrep_mysqld.cc
+++ b/sql/wsrep_mysqld.cc
@@ -648,7 +648,7 @@ static std::string wsrep_server_incoming_address()
bool is_ipv6= false;
unsigned int my_bind_ip= INADDR_ANY; // default if not set
- if (my_bind_addr_str && strlen(my_bind_addr_str) &&
+ if (my_bind_addr_str && strlen(my_bind_addr_str) &&
strcmp(my_bind_addr_str, "*") != 0)
{
my_bind_ip= wsrep_check_ip(my_bind_addr_str, &is_ipv6);
@@ -713,9 +713,13 @@ static std::string wsrep_server_incoming_address()
snprintf(inc_addr, inc_addr_max, fmt, addr.get_address(), port);
}
-
+
done:
- ret= wsrep_node_incoming_address;
+ if (!strlen(inc_addr))
+ ret= wsrep_node_incoming_address;
+ else
+ ret= inc_addr;
+ WSREP_DEBUG("wsrep_incoming_address = %s", ret.c_str());
return ret;
}
diff --git a/storage/connect/tabmysql.cpp b/storage/connect/tabmysql.cpp
index fb5d1b35bc2..464b94a7cbd 100644
--- a/storage/connect/tabmysql.cpp
+++ b/storage/connect/tabmysql.cpp
@@ -946,15 +946,6 @@ bool TDBMYSQL::OpenDB(PGLOBAL g)
} // endif MakeInsert
- if (m_Rc != RC_FX) {
- char cmd[64];
- int w;
-
- sprintf(cmd, "ALTER TABLE `%s` DISABLE KEYS", TableName);
-
- m_Rc = Myc.ExecSQL(g, cmd, &w); // may fail for some engines
- } // endif m_Rc
-
} else
// m_Rc = (Mode == MODE_DELETE) ? MakeDelete(g) : MakeUpdate(g);
m_Rc = (MakeCommand(g)) ? RC_FX : RC_OK;
@@ -1216,16 +1207,6 @@ int TDBMYSQL::DeleteDB(PGLOBAL g, int irc)
void TDBMYSQL::CloseDB(PGLOBAL g)
{
if (Myc.Connected()) {
- if (Mode == MODE_INSERT) {
- char cmd[64];
- int w;
- PDBUSER dup = PlgGetUser(g);
-
- dup->Step = "Enabling indexes";
- sprintf(cmd, "ALTER TABLE `%s` ENABLE KEYS", TableName);
- Myc.m_Rows = -1; // To execute the query
- m_Rc = Myc.ExecSQL(g, cmd, &w); // May fail for some engines
- } // endif m_Rc
Myc.Close();
} // endif Myc
diff --git a/storage/innobase/CMakeLists.txt b/storage/innobase/CMakeLists.txt
index 25ab30fe5bc..cc31b3c5dcc 100644
--- a/storage/innobase/CMakeLists.txt
+++ b/storage/innobase/CMakeLists.txt
@@ -148,7 +148,6 @@ SET(INNOBASE_SOURCES
include/fts0types.h
include/fts0types.inl
include/fts0vlc.h
- include/fut0fut.h
include/fut0lst.h
include/gis0geo.h
include/gis0rtree.h
@@ -241,7 +240,6 @@ SET(INNOBASE_SOURCES
include/trx0rec.inl
include/trx0roll.h
include/trx0rseg.h
- include/trx0rseg.inl
include/trx0sys.h
include/trx0trx.h
include/trx0trx.inl
diff --git a/storage/innobase/btr/btr0btr.cc b/storage/innobase/btr/btr0btr.cc
index 6772e5ca3a7..63add138703 100644
--- a/storage/innobase/btr/btr0btr.cc
+++ b/storage/innobase/btr/btr0btr.cc
@@ -43,6 +43,7 @@ Created 6/2/1994 Heikki Tuuri
#include "gis0geo.h"
#include "dict0boot.h"
#include "row0sel.h" /* row_search_max_autoinc() */
+#include "log.h"
/**************************************************************//**
Checks if the page in the cursor can be merged with given page.
@@ -57,17 +58,6 @@ btr_can_merge_with_page(
buf_block_t** merge_block, /*!< out: the merge block */
mtr_t* mtr); /*!< in: mini-transaction */
-/** Report that an index page is corrupted.
-@param[in] buffer block
-@param[in] index tree */
-void btr_corruption_report(const buf_block_t* block, const dict_index_t* index)
-{
- ib::fatal()
- << "Flag mismatch in page " << block->page.id()
- << " index " << index->name
- << " of table " << index->table->name;
-}
-
/*
Latching strategy of the InnoDB B-tree
--------------------------------------
@@ -186,25 +176,75 @@ make them consecutive on disk if possible. From the other file segment
we allocate pages for the non-leaf levels of the tree.
*/
-#ifdef UNIV_BTR_DEBUG
-/**************************************************************//**
-Checks a file segment header within a B-tree root page.
-@return TRUE if valid */
-static
-ibool
-btr_root_fseg_validate(
-/*===================*/
- const fseg_header_t* seg_header, /*!< in: segment header */
- ulint space) /*!< in: tablespace identifier */
+/** Check a file segment header within a B-tree root page.
+@param offset file segment header offset
+@param block B-tree root page
+@param space tablespace
+@return whether the segment header is valid */
+static bool btr_root_fseg_validate(ulint offset,
+ const buf_block_t &block,
+ const fil_space_t &space)
{
- ulint offset = mach_read_from_2(seg_header + FSEG_HDR_OFFSET);
-
- ut_a(mach_read_from_4(seg_header + FSEG_HDR_SPACE) == space);
- ut_a(offset >= FIL_PAGE_DATA);
- ut_a(offset <= srv_page_size - FIL_PAGE_DATA_END);
- return(TRUE);
+ ut_ad(block.page.id().space() == space.id);
+ const uint16_t hdr= mach_read_from_2(offset + FSEG_HDR_OFFSET +
+ block.page.frame);
+ if (FIL_PAGE_DATA <= hdr && hdr <= srv_page_size - FIL_PAGE_DATA_END &&
+ mach_read_from_4(block.page.frame + offset + FSEG_HDR_SPACE) == space.id)
+ return true;
+ sql_print_error("InnoDB: Index root page " UINT32PF " in %s is corrupted "
+ "at " ULINTPF,
+ block.page.id().page_no(),
+ UT_LIST_GET_FIRST(space.chain)->name);
+ return false;
+}
+
+/** Report a decryption failure. */
+ATTRIBUTE_COLD void btr_decryption_failed(const dict_index_t &index)
+{
+ ib_push_warning(static_cast(nullptr), DB_DECRYPTION_FAILED,
+ "Table %s is encrypted but encryption service or"
+ " used key_id is not available. "
+ " Can't continue reading table.",
+ index.table->name.m_name);
+ index.table->file_unreadable= true;
+}
+
+/** Get an index page and declare its latching order level.
+@param[in] index index tree
+@param[in] page page number
+@param[in] mode latch mode
+@param[in] merge whether change buffer merge should be attempted
+@param[in,out] mtr mini-transaction
+@param[out] err error code
+@return block */
+buf_block_t *btr_block_get(const dict_index_t &index,
+ uint32_t page, ulint mode, bool merge,
+ mtr_t *mtr, dberr_t *err)
+{
+ dberr_t local_err;
+ if (!err)
+ err= &local_err;
+ buf_block_t *block=
+ buf_page_get_gen(page_id_t{index.table->space->id, page},
+ index.table->space->zip_size(), mode, nullptr, BUF_GET,
+ mtr, err, merge && !index.is_clust());
+ ut_ad(!block == (*err != DB_SUCCESS));
+
+ if (UNIV_LIKELY(block != nullptr))
+ {
+ if (!!page_is_comp(block->page.frame) != index.table->not_redundant() ||
+ btr_page_get_index_id(block->page.frame) != index.id ||
+ !fil_page_index_page_check(block->page.frame))
+ {
+ *err= DB_PAGE_CORRUPTED;
+ block= nullptr;
+ }
+ }
+ else if (*err == DB_DECRYPTION_FAILED)
+ btr_decryption_failed(index);
+
+ return block;
}
-#endif /* UNIV_BTR_DEBUG */
/**************************************************************//**
Gets the root node of a tree and x- or s-latches it.
@@ -215,43 +255,30 @@ btr_root_block_get(
const dict_index_t* index, /*!< in: index tree */
rw_lock_type_t mode, /*!< in: either RW_S_LATCH
or RW_X_LATCH */
- mtr_t* mtr) /*!< in: mtr */
+ mtr_t* mtr, /*!< in: mtr */
+ dberr_t* err) /*!< out: error code */
{
- if (!index->table || !index->table->space || index->page == FIL_NULL) {
- return NULL;
- }
+ if (!index->table || !index->table->space)
+ {
+ *err= DB_TABLESPACE_NOT_FOUND;
+ return nullptr;
+ }
- buf_block_t* block = btr_block_get(*index, index->page, mode, false,
- mtr);
-
- if (!block) {
- index->table->file_unreadable = true;
-
- ib_push_warning(
- static_cast(NULL), DB_DECRYPTION_FAILED,
- "Table %s in file %s is encrypted but encryption service or"
- " used key_id is not available. "
- " Can't continue reading table.",
- index->table->name.m_name,
- UT_LIST_GET_FIRST(index->table->space->chain)->name);
-
- return NULL;
- }
-
- btr_assert_not_corrupted(block, index);
-
-#ifdef UNIV_BTR_DEBUG
- if (!dict_index_is_ibuf(index)) {
- const page_t* root = buf_block_get_frame(block);
-
- ut_a(btr_root_fseg_validate(FIL_PAGE_DATA + PAGE_BTR_SEG_LEAF
- + root, index->table->space_id));
- ut_a(btr_root_fseg_validate(FIL_PAGE_DATA + PAGE_BTR_SEG_TOP
- + root, index->table->space_id));
- }
-#endif /* UNIV_BTR_DEBUG */
-
- return(block);
+ buf_block_t *block = btr_block_get(*index, index->page, mode, false, mtr,
+ err);
+ if (block)
+ {
+ if (index->is_ibuf());
+ else if (!btr_root_fseg_validate(FIL_PAGE_DATA + PAGE_BTR_SEG_LEAF,
+ *block, *index->table->space) ||
+ !btr_root_fseg_validate(FIL_PAGE_DATA + PAGE_BTR_SEG_TOP,
+ *block, *index->table->space))
+ {
+ *err= DB_CORRUPTION;
+ block= nullptr;
+ }
+ }
+ return block;
}
/**************************************************************//**
@@ -262,13 +289,14 @@ page_t*
btr_root_get(
/*=========*/
const dict_index_t* index, /*!< in: index tree */
- mtr_t* mtr) /*!< in: mtr */
+ mtr_t* mtr, /*!< in: mtr */
+ dberr_t* err) /*!< out: error code */
{
- /* Intended to be used for segment list access.
- SX lock doesn't block reading user data by other threads.
- And block the segment list access by others.*/
- buf_block_t* root = btr_root_block_get(index, RW_SX_LATCH, mtr);
- return(root ? buf_block_get_frame(root) : NULL);
+ /* Intended to be used for accessing file segment lists.
+ Concurrent read of other data is allowed. */
+ if (buf_block_t *root= btr_root_block_get(index, RW_SX_LATCH, mtr, err))
+ return root->page.frame;
+ return nullptr;
}
/**************************************************************//**
@@ -439,28 +467,27 @@ buf_block_t*
btr_page_alloc_for_ibuf(
/*====================*/
dict_index_t* index, /*!< in: index tree */
- mtr_t* mtr) /*!< in: mtr */
+ mtr_t* mtr, /*!< in: mtr */
+ dberr_t* err) /*!< out: error code */
{
- buf_block_t* new_block;
+ buf_block_t *root= btr_root_block_get(index, RW_SX_LATCH, mtr, err);
+ if (UNIV_UNLIKELY(!root))
+ return root;
- buf_block_t* root = btr_root_block_get(index, RW_SX_LATCH, mtr);
-
- fil_addr_t node_addr = flst_get_first(PAGE_HEADER
- + PAGE_BTR_IBUF_FREE_LIST
- + root->page.frame);
- ut_a(node_addr.page != FIL_NULL);
-
- new_block = buf_page_get(
- page_id_t(index->table->space_id, node_addr.page),
- index->table->space->zip_size(),
- RW_X_LATCH, mtr);
-
- flst_remove(root, PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST,
- new_block, PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST_NODE,
- mtr);
- ut_d(flst_validate(root, PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST, mtr));
-
- return(new_block);
+ buf_block_t *new_block=
+ buf_page_get_gen(page_id_t(index->table->space_id,
+ mach_read_from_4(PAGE_HEADER +
+ PAGE_BTR_IBUF_FREE_LIST +
+ FLST_FIRST + FIL_ADDR_PAGE +
+ root->page.frame)),
+ index->table->space->zip_size(), RW_X_LATCH, nullptr,
+ BUF_GET, mtr, err);
+ if (new_block)
+ *err= flst_remove(root, PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST, new_block,
+ PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST_NODE, mtr);
+ ut_d(if (*err == DB_SUCCESS)
+ flst_validate(root, PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST, mtr));
+ return new_block;
}
/**************************************************************//**
@@ -479,26 +506,18 @@ btr_page_alloc_low(
in the tree */
mtr_t* mtr, /*!< in/out: mini-transaction
for the allocation */
- mtr_t* init_mtr) /*!< in/out: mtr or another
+ mtr_t* init_mtr, /*!< in/out: mtr or another
mini-transaction in which the
page should be initialized. */
+ dberr_t* err) /*!< out: error code */
{
- page_t* root = btr_root_get(index, mtr);
-
- fseg_header_t* seg_header = (level
- ? PAGE_HEADER + PAGE_BTR_SEG_TOP
- : PAGE_HEADER + PAGE_BTR_SEG_LEAF)
- + root;
-
- /* Parameter TRUE below states that the caller has made the
- reservation for free extents, and thus we know that a page can
- be allocated: */
-
- buf_block_t* block = fseg_alloc_free_page_general(
- seg_header, hint_page_no, file_direction,
- true, mtr, init_mtr);
-
- return block;
+ buf_block_t *root= btr_root_block_get(index, RW_SX_LATCH, mtr, err);
+ if (UNIV_UNLIKELY(!root))
+ return root;
+ fseg_header_t *seg_header= root->page.frame +
+ (level ? PAGE_HEADER + PAGE_BTR_SEG_TOP : PAGE_HEADER + PAGE_BTR_SEG_LEAF);
+ return fseg_alloc_free_page_general(seg_header, hint_page_no, file_direction,
+ true, mtr, init_mtr, err);
}
/**************************************************************//**
@@ -516,38 +535,40 @@ btr_page_alloc(
in the tree */
mtr_t* mtr, /*!< in/out: mini-transaction
for the allocation */
- mtr_t* init_mtr) /*!< in/out: mini-transaction
+ mtr_t* init_mtr, /*!< in/out: mini-transaction
for x-latching and initializing
the page */
+ dberr_t* err) /*!< out: error code */
{
- if (dict_index_is_ibuf(index)) {
-
- return(btr_page_alloc_for_ibuf(index, mtr));
- }
-
- return btr_page_alloc_low(
- index, hint_page_no, file_direction, level, mtr, init_mtr);
+ ut_ad(level < BTR_MAX_NODE_LEVEL);
+ return index->is_ibuf()
+ ? btr_page_alloc_for_ibuf(index, mtr, err)
+ : btr_page_alloc_low(index, hint_page_no, file_direction, level,
+ mtr, init_mtr, err);
}
/**************************************************************//**
Frees a page used in an ibuf tree. Puts the page to the free list of the
ibuf tree. */
static
-void
+dberr_t
btr_page_free_for_ibuf(
/*===================*/
dict_index_t* index, /*!< in: index tree */
buf_block_t* block, /*!< in: block to be freed, x-latched */
mtr_t* mtr) /*!< in: mtr */
{
- ut_ad(mtr->memo_contains_flagged(block, MTR_MEMO_PAGE_X_FIX));
+ ut_ad(mtr->memo_contains_flagged(block, MTR_MEMO_PAGE_X_FIX));
- buf_block_t* root = btr_root_block_get(index, RW_SX_LATCH, mtr);
-
- flst_add_first(root, PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST,
- block, PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST_NODE, mtr);
-
- ut_d(flst_validate(root, PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST, mtr));
+ dberr_t err;
+ if (buf_block_t *root= btr_root_block_get(index, RW_SX_LATCH, mtr, &err))
+ {
+ err= flst_add_first(root, PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST,
+ block, PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST_NODE, mtr);
+ ut_d(if (err == DB_SUCCESS)
+ flst_validate(root, PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST, mtr));
+ }
+ return err;
}
/** Free an index page.
@@ -555,51 +576,53 @@ btr_page_free_for_ibuf(
@param[in,out] block block to be freed
@param[in,out] mtr mini-transaction
@param[in] blob whether this is freeing a BLOB page
-@param[in] latched whether index->table->space->x_lock() was called */
-void btr_page_free(dict_index_t* index, buf_block_t* block, mtr_t* mtr,
- bool blob, bool space_latched)
+@param[in] latched whether index->table->space->x_lock() was called
+@return error code */
+dberr_t btr_page_free(dict_index_t* index, buf_block_t* block, mtr_t* mtr,
+ bool blob, bool space_latched)
{
- ut_ad(mtr->memo_contains_flagged(block, MTR_MEMO_PAGE_X_FIX));
+ ut_ad(mtr->memo_contains_flagged(block, MTR_MEMO_PAGE_X_FIX));
#ifdef BTR_CUR_HASH_ADAPT
- if (block->index && !block->index->freed()) {
- ut_ad(!blob);
- ut_ad(page_is_leaf(block->page.frame));
- }
+ if (block->index && !block->index->freed())
+ {
+ ut_ad(!blob);
+ ut_ad(page_is_leaf(block->page.frame));
+ }
#endif
- const page_id_t id(block->page.id());
- ut_ad(index->table->space_id == id.space());
- /* The root page is freed by btr_free_root(). */
- ut_ad(id.page_no() != index->page);
- ut_ad(mtr->is_named_space(index->table->space));
+ const uint32_t page{block->page.id().page_no()};
+ ut_ad(index->table->space_id == block->page.id().space());
+ /* The root page is freed by btr_free_root(). */
+ ut_ad(page != index->page);
+ ut_ad(mtr->is_named_space(index->table->space));
- /* The page gets invalid for optimistic searches: increment the frame
- modify clock */
+ /* The page gets invalid for optimistic searches: increment the frame
+ modify clock */
+ buf_block_modify_clock_inc(block);
- buf_block_modify_clock_inc(block);
+ /* TODO: Discard any operations for block from mtr->m_log.
+ The page will be freed, so previous changes to it by this
+ mini-transaction should not matter. */
- if (dict_index_is_ibuf(index)) {
- btr_page_free_for_ibuf(index, block, mtr);
- return;
- }
+ if (index->is_ibuf())
+ return btr_page_free_for_ibuf(index, block, mtr);
- /* TODO: Discard any operations for block from mtr->log.
- The page will be freed, so previous changes to it by this
- mini-transaction should not matter. */
- page_t* root = btr_root_get(index, mtr);
- fseg_header_t* seg_header = &root[blob
- || page_is_leaf(block->page.frame)
- ? PAGE_HEADER + PAGE_BTR_SEG_LEAF
- : PAGE_HEADER + PAGE_BTR_SEG_TOP];
- fil_space_t* space= index->table->space;
- const uint32_t page= id.page_no();
+ fil_space_t *space= index->table->space;
+ dberr_t err;
+ if (page_t* root = btr_root_get(index, mtr, &err))
+ {
+ err= fseg_free_page(&root[blob || page_is_leaf(block->page.frame)
+ ? PAGE_HEADER + PAGE_BTR_SEG_LEAF
+ : PAGE_HEADER + PAGE_BTR_SEG_TOP],
+ space, page, mtr, space_latched);
+ }
+ if (err == DB_SUCCESS)
+ buf_page_free(space, page, mtr);
- fseg_free_page(seg_header, space, page, mtr, space_latched);
- buf_page_free(space, page, mtr);
-
- /* The page was marked free in the allocation bitmap, but it
- should remain exclusively latched until mtr_t::commit() or until it
- is explicitly freed from the mini-transaction. */
- ut_ad(mtr->memo_contains_flagged(block, MTR_MEMO_PAGE_X_FIX));
+ /* The page was marked free in the allocation bitmap, but it
+ should remain exclusively latched until mtr_t::commit() or until it
+ is explicitly freed from the mini-transaction. */
+ ut_ad(mtr->memo_contains_flagged(block, MTR_MEMO_PAGE_X_FIX));
+ return err;
}
/** Set the child page number in a node pointer record.
@@ -627,6 +650,7 @@ inline void btr_node_ptr_set_child_page_no(buf_block_t *block,
mtr->write<4>(*block, rec + offs - REC_NODE_PTR_SIZE, page_no);
}
+MY_ATTRIBUTE((nonnull(1,2,3,4),warn_unused_result))
/************************************************************//**
Returns the child page of a node pointer and sx-latches it.
@return child page, sx-latched */
@@ -637,7 +661,8 @@ btr_node_ptr_get_child(
const rec_t* node_ptr,/*!< in: node pointer */
dict_index_t* index, /*!< in: index */
const rec_offs* offsets,/*!< in: array returned by rec_get_offsets() */
- mtr_t* mtr) /*!< in: mtr */
+ mtr_t* mtr, /*!< in: mtr */
+ dberr_t* err = nullptr) /*!< out: error code */
{
ut_ad(rec_offs_validate(node_ptr, index, offsets));
ut_ad(index->table->space_id
@@ -646,9 +671,10 @@ btr_node_ptr_get_child(
return btr_block_get(
*index, btr_node_ptr_get_child_page_no(node_ptr, offsets),
RW_SX_LATCH, btr_page_get_level(page_align(node_ptr)) == 1,
- mtr);
+ mtr, err);
}
+MY_ATTRIBUTE((nonnull(2,3,5), warn_unused_result))
/************************************************************//**
Returns the upper level node pointer to a page. It is assumed that mtr holds
an sx-latch on the tree.
@@ -666,18 +692,11 @@ btr_page_get_father_node_ptr_func(
or BTR_CONT_SEARCH_TREE */
mtr_t* mtr) /*!< in: mtr */
{
- dtuple_t* tuple;
- rec_t* user_rec;
- rec_t* node_ptr;
- ulint level;
- ulint page_no;
- dict_index_t* index;
-
ut_ad(latch_mode == BTR_CONT_MODIFY_TREE
|| latch_mode == BTR_CONT_SEARCH_TREE);
- page_no = btr_cur_get_block(cursor)->page.id().page_no();
- index = btr_cur_get_index(cursor);
+ const uint32_t page_no = btr_cur_get_block(cursor)->page.id().page_no();
+ dict_index_t* index = btr_cur_get_index(cursor);
ut_ad(!dict_index_is_spatial(index));
ut_ad(srv_read_only_mode
@@ -686,58 +705,27 @@ btr_page_get_father_node_ptr_func(
ut_ad(dict_index_get_page(index) != page_no);
- level = btr_page_get_level(btr_cur_get_page(cursor));
+ const auto level = btr_page_get_level(btr_cur_get_page(cursor));
- user_rec = btr_cur_get_rec(cursor);
+ const rec_t* user_rec = btr_cur_get_rec(cursor);
ut_a(page_rec_is_user_rec(user_rec));
- tuple = dict_index_build_node_ptr(index, user_rec, 0, heap, level);
- dberr_t err = DB_SUCCESS;
-
- err = btr_cur_search_to_nth_level(
- index, level + 1, tuple,
- PAGE_CUR_LE, latch_mode, cursor, 0, mtr);
-
- if (err != DB_SUCCESS) {
- ib::warn() << " Error code: " << err
- << " btr_page_get_father_node_ptr_func "
- << " level: " << level + 1
- << " table: " << index->table->name
- << " index: " << index->name();
+ if (btr_cur_search_to_nth_level(index, level + 1,
+ dict_index_build_node_ptr(index,
+ user_rec, 0,
+ heap, level),
+ PAGE_CUR_LE, latch_mode,
+ cursor, 0, mtr) != DB_SUCCESS) {
+ return nullptr;
}
- node_ptr = btr_cur_get_rec(cursor);
+ const rec_t* node_ptr = btr_cur_get_rec(cursor);
offsets = rec_get_offsets(node_ptr, index, offsets, 0,
ULINT_UNDEFINED, &heap);
if (btr_node_ptr_get_child_page_no(node_ptr, offsets) != page_no) {
- rec_t* print_rec;
-
- ib::error()
- << "Corruption of an index tree: table "
- << index->table->name
- << " index " << index->name
- << ", father ptr page no "
- << btr_node_ptr_get_child_page_no(node_ptr, offsets)
- << ", child page no " << page_no;
-
- print_rec = page_rec_get_next(
- page_get_infimum_rec(page_align(user_rec)));
- offsets = rec_get_offsets(print_rec, index, offsets,
- page_rec_is_leaf(user_rec)
- ? index->n_core_fields : 0,
- ULINT_UNDEFINED, &heap);
- page_rec_print(print_rec, offsets);
- offsets = rec_get_offsets(node_ptr, index, offsets, 0,
- ULINT_UNDEFINED, &heap);
- page_rec_print(node_ptr, offsets);
-
- ib::fatal()
- << "You should dump + drop + reimport the table to"
- << " fix the corruption. If the crash happens at"
- << " database startup. " << FORCE_RECOVERY_MSG
- << " Then dump + drop + reimport.";
+ offsets = nullptr;
}
return(offsets);
@@ -778,8 +766,9 @@ btr_page_get_father_block(
@param[in,out] index b-tree
@param[in] block child page
@param[in,out] mtr mini-transaction
-@param[out] cursor cursor pointing to the x-latched parent page */
-void btr_page_get_father(dict_index_t* index, buf_block_t* block, mtr_t* mtr,
+@param[out] cursor cursor pointing to the x-latched parent page
+@return whether the cursor was successfully positioned */
+bool btr_page_get_father(dict_index_t* index, buf_block_t* block, mtr_t* mtr,
btr_cur_t* cursor)
{
mem_heap_t* heap;
@@ -789,8 +778,9 @@ void btr_page_get_father(dict_index_t* index, buf_block_t* block, mtr_t* mtr,
btr_cur_position(index, rec, block, cursor);
heap = mem_heap_create(100);
- btr_page_get_father_node_ptr(NULL, heap, cursor, mtr);
+ const bool got = btr_page_get_father_node_ptr(NULL, heap, cursor, mtr);
mem_heap_free(heap);
+ return got;
}
#ifdef UNIV_DEBUG
@@ -800,28 +790,25 @@ constexpr index_id_t BTR_FREED_INDEX_ID = 0;
/** Free a B-tree root page. btr_free_but_not_root() must already
have been called.
-In a persistent tablespace, the caller must invoke fsp_init_file_page()
-before mtr.commit().
-@param[in,out] block index root page
-@param[in,out] mtr mini-transaction */
-static void btr_free_root(buf_block_t *block, mtr_t *mtr)
+@param block index root page
+@param space tablespace
+@param mtr mini-transaction */
+static void btr_free_root(buf_block_t *block, const fil_space_t &space,
+ mtr_t *mtr)
{
ut_ad(mtr->memo_contains_flagged(block, MTR_MEMO_PAGE_X_FIX |
MTR_MEMO_PAGE_SX_FIX));
- ut_ad(mtr->is_named_space(block->page.id().space()));
+ ut_ad(mtr->is_named_space(&space));
btr_search_drop_page_hash_index(block);
-#ifdef UNIV_BTR_DEBUG
- ut_a(btr_root_fseg_validate(PAGE_HEADER + PAGE_BTR_SEG_TOP +
- block->page.frame,
- block->page.id().space()));
-#endif /* UNIV_BTR_DEBUG */
-
- /* Free the entire segment in small steps. */
- ut_d(mtr->freeing_tree());
- while (!fseg_free_step(PAGE_HEADER + PAGE_BTR_SEG_TOP +
- block->page.frame, mtr));
+ if (btr_root_fseg_validate(PAGE_HEADER + PAGE_BTR_SEG_TOP, *block, space))
+ {
+ /* Free the entire segment in small steps. */
+ ut_d(mtr->freeing_tree());
+ while (!fseg_free_step(PAGE_HEADER + PAGE_BTR_SEG_TOP +
+ block->page.frame, mtr));
+ }
}
MY_ATTRIBUTE((warn_unused_result))
@@ -843,8 +830,6 @@ buf_block_t *btr_free_root_check(const page_id_t page_id, ulint zip_size,
nullptr, BUF_GET_POSSIBLY_FREED, mtr);
if (!block);
- else if (block->page.is_freed())
- block= nullptr;
else if (fil_page_index_page_check(block->page.frame) &&
index_id == btr_page_get_index_id(block->page.frame))
/* This should be a root page. It should not be possible to
@@ -900,6 +885,7 @@ static void btr_root_page_init(buf_block_t *block, index_id_t index_id,
@param[in,out] space tablespace where created
@param[in] index index, or NULL to create a system table
@param[in,out] mtr mini-transaction
+@param[out] err error code
@return page number of the created root
@retval FIL_NULL if did not succeed */
uint32_t
@@ -908,12 +894,14 @@ btr_create(
fil_space_t* space,
index_id_t index_id,
dict_index_t* index,
- mtr_t* mtr)
+ mtr_t* mtr,
+ dberr_t* err)
{
buf_block_t* block;
ut_ad(mtr->is_named_space(space));
ut_ad(index_id != BTR_FREED_INDEX_ID);
+ ut_ad(index || space == fil_system.sys_space);
/* Create the two new segments (one, in the case of an ibuf tree) for
the index tree; the segment headers are put on the allocated root page
@@ -923,7 +911,7 @@ btr_create(
if (UNIV_UNLIKELY(type & DICT_IBUF)) {
/* Allocate first the ibuf header page */
buf_block_t* ibuf_hdr_block = fseg_create(
- space, IBUF_HEADER + IBUF_TREE_SEG_HEADER, mtr);
+ space, IBUF_HEADER + IBUF_TREE_SEG_HEADER, mtr, err);
if (ibuf_hdr_block == NULL) {
return(FIL_NULL);
@@ -934,11 +922,11 @@ btr_create(
/* Allocate then the next page to the segment: it will be the
tree root page */
- block = fseg_alloc_free_page(
+ block = fseg_alloc_free_page_general(
buf_block_get_frame(ibuf_hdr_block)
+ IBUF_HEADER + IBUF_TREE_SEG_HEADER,
IBUF_TREE_ROOT_PAGE_NO,
- FSP_UP, mtr);
+ FSP_UP, false, mtr, mtr, err);
if (block == NULL) {
return(FIL_NULL);
@@ -949,17 +937,17 @@ btr_create(
flst_init(block, PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST, mtr);
} else {
block = fseg_create(space, PAGE_HEADER + PAGE_BTR_SEG_TOP,
- mtr);
+ mtr, err);
if (block == NULL) {
return(FIL_NULL);
}
if (!fseg_create(space, PAGE_HEADER + PAGE_BTR_SEG_LEAF, mtr,
- false, block)) {
+ err, false, block)) {
/* Not enough space for new segment, free root
segment before return. */
- btr_free_root(block, mtr);
+ btr_free_root(block, *space, mtr);
return(FIL_NULL);
}
}
@@ -1012,27 +1000,21 @@ leaf_loop:
mtr_start(&mtr);
ut_d(mtr.freeing_tree());
mtr_set_log_mode(&mtr, log_mode);
- mtr.set_named_space_id(block->page.id().space());
+ fil_space_t *space = mtr.set_named_space_id(block->page.id().space());
- page_t* root = block->page.frame;
-
- if (!root) {
+ if (!btr_root_fseg_validate(FIL_PAGE_DATA + PAGE_BTR_SEG_LEAF,
+ *block, *space)
+ || !btr_root_fseg_validate(FIL_PAGE_DATA + PAGE_BTR_SEG_TOP,
+ *block, *space)) {
mtr_commit(&mtr);
return;
}
-#ifdef UNIV_BTR_DEBUG
- ut_a(btr_root_fseg_validate(FIL_PAGE_DATA + PAGE_BTR_SEG_LEAF
- + root, block->page.id().space()));
- ut_a(btr_root_fseg_validate(FIL_PAGE_DATA + PAGE_BTR_SEG_TOP
- + root, block->page.id().space()));
-#endif /* UNIV_BTR_DEBUG */
-
/* NOTE: page hash indexes are dropped when a page is freed inside
fsp0fsp. */
- bool finished = fseg_free_step(root + PAGE_HEADER + PAGE_BTR_SEG_LEAF,
- &mtr
+ bool finished = fseg_free_step(PAGE_HEADER + PAGE_BTR_SEG_LEAF
+ + block->page.frame, &mtr
#ifdef BTR_CUR_HASH_ADAPT
, ahi
#endif /* BTR_CUR_HASH_ADAPT */
@@ -1046,21 +1028,16 @@ leaf_loop:
top_loop:
mtr_start(&mtr);
mtr_set_log_mode(&mtr, log_mode);
- mtr.set_named_space_id(block->page.id().space());
+ space = mtr.set_named_space_id(block->page.id().space());
- root = block->page.frame;
-
-#ifdef UNIV_BTR_DEBUG
- ut_a(btr_root_fseg_validate(FIL_PAGE_DATA + PAGE_BTR_SEG_TOP
- + root, block->page.id().space()));
-#endif /* UNIV_BTR_DEBUG */
-
- finished = fseg_free_step_not_header(
- root + PAGE_HEADER + PAGE_BTR_SEG_TOP, &mtr
+ finished = !btr_root_fseg_validate(FIL_PAGE_DATA + PAGE_BTR_SEG_TOP,
+ *block, *space)
+ || fseg_free_step_not_header(PAGE_HEADER + PAGE_BTR_SEG_TOP
+ + block->page.frame, &mtr
#ifdef BTR_CUR_HASH_ADAPT
- ,ahi
+ ,ahi
#endif /* BTR_CUR_HASH_ADAPT */
- );
+ );
mtr_commit(&mtr);
if (!finished) {
@@ -1070,9 +1047,10 @@ top_loop:
/** Clear the index tree and reinitialize the root page, in the
rollback of TRX_UNDO_EMPTY. The BTR_SEG_LEAF is freed and reinitialized.
-@param thr query thread */
+@param thr query thread
+@return error code */
TRANSACTIONAL_TARGET
-void dict_index_t::clear(que_thr_t *thr)
+dberr_t dict_index_t::clear(que_thr_t *thr)
{
mtr_t mtr;
mtr.start();
@@ -1081,9 +1059,11 @@ void dict_index_t::clear(que_thr_t *thr)
else
set_modified(mtr);
- if (buf_block_t *root_block= buf_page_get(page_id_t(table->space->id, page),
- table->space->zip_size(),
- RW_X_LATCH, &mtr))
+ dberr_t err;
+ if (buf_block_t *root_block=
+ buf_page_get_gen(page_id_t(table->space->id, page),
+ table->space->zip_size(),
+ RW_X_LATCH, nullptr, BUF_GET, &mtr, &err))
{
btr_free_but_not_root(root_block, mtr.get_log_mode()
#ifdef BTR_CUR_HASH_ADAPT
@@ -1098,12 +1078,13 @@ void dict_index_t::clear(que_thr_t *thr)
#endif
mtr.memset(root_block, PAGE_HEADER + PAGE_BTR_SEG_LEAF,
FSEG_HEADER_SIZE, 0);
- if (fseg_create(table->space, PAGE_HEADER + PAGE_BTR_SEG_LEAF, &mtr, false,
- root_block))
+ if (fseg_create(table->space, PAGE_HEADER + PAGE_BTR_SEG_LEAF, &mtr,
+ &err, false, root_block))
btr_root_page_init(root_block, id, this, &mtr);
}
mtr.commit();
+ return err;
}
/** Free a persistent index tree if it exists.
@@ -1120,7 +1101,7 @@ void btr_free_if_exists(fil_space_t *space, uint32_t page,
{
btr_free_but_not_root(root, mtr->get_log_mode());
mtr->set_named_space(space);
- btr_free_root(root, mtr);
+ btr_free_root(root, *space, mtr);
}
}
@@ -1141,7 +1122,7 @@ void btr_drop_temporary_table(const dict_table_t &table)
{
btr_free_but_not_root(block, MTR_LOG_NO_REDO);
mtr.set_log_mode(MTR_LOG_NO_REDO);
- btr_free_root(block, &mtr);
+ btr_free_root(block, *fil_system.temp_space, &mtr);
mtr.commit();
mtr.start();
}
@@ -1233,27 +1214,29 @@ btr_read_autoinc_with_fallback(const dict_table_t* table, unsigned col_no)
void
btr_write_autoinc(dict_index_t* index, ib_uint64_t autoinc, bool reset)
{
- ut_ad(index->is_primary());
- ut_ad(index->table->persistent_autoinc);
- ut_ad(!index->table->is_temporary());
+ ut_ad(index->is_primary());
+ ut_ad(index->table->persistent_autoinc);
+ ut_ad(!index->table->is_temporary());
- mtr_t mtr;
- mtr.start();
- fil_space_t* space = index->table->space;
- mtr.set_named_space(space);
- page_set_autoinc(buf_page_get(page_id_t(space->id, index->page),
- space->zip_size(),
- RW_SX_LATCH, &mtr),
- autoinc, &mtr, reset);
- mtr.commit();
+ mtr_t mtr;
+ mtr.start();
+ fil_space_t *space= index->table->space;
+ if (buf_block_t *root= buf_page_get(page_id_t(space->id, index->page),
+ space->zip_size(), RW_SX_LATCH, &mtr))
+ {
+ mtr.set_named_space(space);
+ page_set_autoinc(root, autoinc, &mtr, reset);
+ }
+
+ mtr.commit();
}
/** Reorganize an index page.
@param cursor index page cursor
@param index the index that the cursor belongs to
@param mtr mini-transaction */
-static void btr_page_reorganize_low(page_cur_t *cursor, dict_index_t *index,
- mtr_t *mtr)
+static dberr_t btr_page_reorganize_low(page_cur_t *cursor, dict_index_t *index,
+ mtr_t *mtr)
{
const mtr_log_t log_mode= mtr->set_log_mode(MTR_LOG_NO_REDO);
@@ -1261,7 +1244,6 @@ static void btr_page_reorganize_low(page_cur_t *cursor, dict_index_t *index,
ut_ad(mtr->memo_contains_flagged(block, MTR_MEMO_PAGE_X_FIX));
ut_ad(!is_buf_block_get_page_zip(block));
- btr_assert_not_corrupted(block, index);
ut_ad(fil_page_index_page_check(block->page.frame));
ut_ad(index->is_dummy ||
block->page.id().space() == index->table->space->id);
@@ -1288,9 +1270,11 @@ static void btr_page_reorganize_low(page_cur_t *cursor, dict_index_t *index,
/* Copy the records from the temporary space to the recreated page;
do not copy the lock bits yet */
- page_copy_rec_list_end_no_locks(block, old,
- page_get_infimum_rec(old->page.frame),
- index, mtr);
+ if (dberr_t err=
+ page_copy_rec_list_end_no_locks(block, old,
+ page_get_infimum_rec(old->page.frame),
+ index, mtr))
+ return err;
/* Copy the PAGE_MAX_TRX_ID or PAGE_ROOT_AUTO_INC. */
ut_ad(!page_get_max_trx_id(block->page.frame));
@@ -1504,6 +1488,7 @@ static void btr_page_reorganize_low(page_cur_t *cursor, dict_index_t *index,
MONITOR_INC(MONITOR_INDEX_REORG_ATTEMPTS);
MONITOR_INC(MONITOR_INDEX_REORG_SUCCESSFUL);
+ return DB_SUCCESS;
}
/*************************************************************//**
@@ -1515,9 +1500,9 @@ be done either within the same mini-transaction, or by invoking
ibuf_reset_free_bits() before mtr_commit(). On uncompressed pages,
IBUF_BITMAP_FREE is unaffected by reorganization.
-@retval true if the operation was successful
-@retval false if it is a compressed page, and recompression failed */
-bool
+@return error code
+@retval DB_FAIL if reorganizing a ROW_FORMAT=COMPRESSED page failed */
+dberr_t
btr_page_reorganize_block(
ulint z_level,/*!< in: compression level to be used
if dealing with compressed page */
@@ -1525,15 +1510,11 @@ btr_page_reorganize_block(
dict_index_t* index, /*!< in: the index tree of the page */
mtr_t* mtr) /*!< in/out: mini-transaction */
{
- if (buf_block_get_page_zip(block)) {
- return page_zip_reorganize(block, index, z_level, mtr, true);
- }
-
- page_cur_t cur;
- page_cur_set_before_first(block, &cur);
-
- btr_page_reorganize_low(&cur, index, mtr);
- return true;
+ if (buf_block_get_page_zip(block))
+ return page_zip_reorganize(block, index, z_level, mtr, true);
+ page_cur_t cur;
+ page_cur_set_before_first(block, &cur);
+ return btr_page_reorganize_low(&cur, index, mtr);
}
/*************************************************************//**
@@ -1545,33 +1526,28 @@ be done either within the same mini-transaction, or by invoking
ibuf_reset_free_bits() before mtr_commit(). On uncompressed pages,
IBUF_BITMAP_FREE is unaffected by reorganization.
-@retval true if the operation was successful
-@retval false if it is a compressed page, and recompression failed */
-bool
+@return error code
+@retval DB_FAIL if reorganizing a ROW_FORMAT=COMPRESSED page failed */
+dberr_t
btr_page_reorganize(
/*================*/
page_cur_t* cursor, /*!< in/out: page cursor */
dict_index_t* index, /*!< in: the index tree of the page */
mtr_t* mtr) /*!< in/out: mini-transaction */
{
- if (!buf_block_get_page_zip(cursor->block)) {
- btr_page_reorganize_low(cursor, index, mtr);
- return true;
- }
+ if (!buf_block_get_page_zip(cursor->block))
+ return btr_page_reorganize_low(cursor, index, mtr);
- ulint pos = page_rec_get_n_recs_before(cursor->rec);
- if (!page_zip_reorganize(cursor->block, index, page_zip_level, mtr,
- true)) {
- return false;
- }
- if (pos) {
- cursor->rec = page_rec_get_nth(cursor->block->page.frame, pos);
- } else {
- ut_ad(cursor->rec == page_get_infimum_rec(
- cursor->block->page.frame));
- }
+ ulint pos= page_rec_get_n_recs_before(cursor->rec);
+ dberr_t err= page_zip_reorganize(cursor->block, index, page_zip_level, mtr,
+ true);
+ if (err == DB_FAIL);
+ else if (pos)
+ cursor->rec= page_rec_get_nth(cursor->block->page.frame, pos);
+ else
+ ut_ad(cursor->rec == page_get_infimum_rec(cursor->block->page.frame));
- return true;
+ return err;
}
/** Empty an index page (possibly the root page). @see btr_page_create().
@@ -1698,13 +1674,15 @@ void btr_set_instant(buf_block_t* root, const dict_index_t& index, mtr_t* mtr)
/** Reset the table to the canonical format on ROLLBACK of instant ALTER TABLE.
@param[in] index clustered index with instant ALTER TABLE
@param[in] all whether to reset FIL_PAGE_TYPE as well
-@param[in,out] mtr mini-transaction */
+@param[in,out] mtr mini-transaction
+@return error code */
ATTRIBUTE_COLD
-void btr_reset_instant(const dict_index_t &index, bool all, mtr_t *mtr)
+dberr_t btr_reset_instant(const dict_index_t &index, bool all, mtr_t *mtr)
{
ut_ad(!index.table->is_temporary());
ut_ad(index.is_primary());
- if (buf_block_t *root = btr_root_block_get(&index, RW_SX_LATCH, mtr))
+ dberr_t err;
+ if (buf_block_t *root= btr_root_block_get(&index, RW_SX_LATCH, mtr, &err))
{
byte *page_type= root->page.frame + FIL_PAGE_TYPE;
if (all)
@@ -1737,6 +1715,7 @@ void btr_reset_instant(const dict_index_t &index, bool all, mtr_t *mtr)
mtr->memcpy(*root, &root->page.frame[supremum],
supremuminfimum, 8);
}
+ return err;
}
/*************************************************************//**
@@ -1758,7 +1737,8 @@ btr_root_raise_and_insert(
mem_heap_t** heap, /*!< in/out: pointer to memory heap, or NULL */
const dtuple_t* tuple, /*!< in: tuple to insert */
ulint n_ext, /*!< in: number of externally stored columns */
- mtr_t* mtr) /*!< in: mtr */
+ mtr_t* mtr, /*!< in: mtr */
+ dberr_t* err) /*!< out: error code */
{
dict_index_t* index;
ulint new_page_no;
@@ -1783,32 +1763,33 @@ btr_root_raise_and_insert(
#endif /* UNIV_ZIP_DEBUG */
const page_id_t root_id{root->page.id()};
-#ifdef UNIV_BTR_DEBUG
- if (!dict_index_is_ibuf(index)) {
- ulint space = index->table->space_id;
-
- ut_a(btr_root_fseg_validate(FIL_PAGE_DATA + PAGE_BTR_SEG_LEAF
- + root->page.frame, space));
- ut_a(btr_root_fseg_validate(FIL_PAGE_DATA + PAGE_BTR_SEG_TOP
- + root->page.frame, space));
- }
-
- ut_a(dict_index_get_page(index) == root_id.page_no());
-#endif /* UNIV_BTR_DEBUG */
ut_ad(mtr->memo_contains_flagged(&index->lock, MTR_MEMO_X_LOCK
| MTR_MEMO_SX_LOCK));
ut_ad(mtr->memo_contains_flagged(root, MTR_MEMO_PAGE_X_FIX));
+ if (index->page != root_id.page_no()) {
+ ut_ad("corrupted root page number" == 0);
+ return nullptr;
+ }
+
+ if (index->is_ibuf()) {
+ } else if (!btr_root_fseg_validate(FIL_PAGE_DATA + PAGE_BTR_SEG_LEAF,
+ *root, *index->table->space)
+ || !btr_root_fseg_validate(FIL_PAGE_DATA + PAGE_BTR_SEG_TOP,
+ *root, *index->table->space)) {
+ return nullptr;
+ }
+
/* Allocate a new page to the tree. Root splitting is done by first
moving the root records to the new page, emptying the root, putting
a node pointer to the new page, and then splitting the new page. */
level = btr_page_get_level(root->page.frame);
- new_block = btr_page_alloc(index, 0, FSP_NO_DIR, level, mtr, mtr);
+ new_block = btr_page_alloc(index, 0, FSP_NO_DIR, level, mtr, mtr, err);
- if (new_block == NULL && os_has_said_disk_full) {
- return(NULL);
+ if (!new_block) {
+ return nullptr;
}
new_page_zip = buf_block_get_page_zip(new_block);
@@ -1832,6 +1813,10 @@ btr_root_raise_and_insert(
}
/* Copy the records from root to the new page one by one. */
+ dberr_t e;
+ if (!err) {
+ err = &e;
+ }
if (0
#ifdef UNIV_ZIP_COPY
@@ -1839,7 +1824,11 @@ btr_root_raise_and_insert(
#endif /* UNIV_ZIP_COPY */
|| !page_copy_rec_list_end(new_block, root,
page_get_infimum_rec(root->page.frame),
- index, mtr)) {
+ index, mtr, err)) {
+ if (*err != DB_SUCCESS && *err != DB_FAIL) {
+ return nullptr;
+ }
+
ut_a(new_page_zip);
/* Copy the page byte for byte. */
@@ -1974,10 +1963,10 @@ btr_root_raise_and_insert(
if (dict_index_is_spatial(index)) {
/* Split rtree page and insert tuple */
return(rtr_page_split_and_insert(flags, cursor, offsets, heap,
- tuple, n_ext, mtr));
+ tuple, n_ext, mtr, err));
} else {
return(btr_page_split_and_insert(flags, cursor, offsets, heap,
- tuple, n_ext, mtr));
+ tuple, n_ext, mtr, err));
}
}
@@ -2290,7 +2279,7 @@ btr_page_insert_fits(
/*******************************************************//**
Inserts a data tuple to a tree on a non-leaf level. It is assumed
that mtr holds an x-latch on the tree. */
-void
+dberr_t
btr_insert_on_non_leaf_level(
ulint flags, /*!< in: undo logging and locking flags */
dict_index_t* index, /*!< in: index */
@@ -2300,7 +2289,6 @@ btr_insert_on_non_leaf_level(
{
big_rec_t* dummy_big_rec;
btr_cur_t cursor;
- dberr_t err;
rec_t* rec;
mem_heap_t* heap = NULL;
rec_offs offsets_[REC_OFFS_NORMAL_SIZE];
@@ -2309,70 +2297,62 @@ btr_insert_on_non_leaf_level(
rtr_info_t rtr_info;
ut_ad(level > 0);
+ auto mode = PAGE_CUR_LE;
- if (!dict_index_is_spatial(index)) {
- dberr_t err = btr_cur_search_to_nth_level(
- index, level, tuple, PAGE_CUR_LE,
- BTR_CONT_MODIFY_TREE,
- &cursor, 0, mtr);
-
- if (err != DB_SUCCESS) {
- ib::warn() << " Error code: " << err
- << " btr_page_get_father_node_ptr_func "
- << " level: " << level
- << " table: " << index->table->name
- << " index: " << index->name;
- }
- } else {
+ if (index->is_spatial()) {
+ mode = PAGE_CUR_RTREE_INSERT;
/* For spatial index, initialize structures to track
its parents etc. */
rtr_init_rtr_info(&rtr_info, false, &cursor, index, false);
rtr_info_update_btr(&cursor, &rtr_info);
-
- btr_cur_search_to_nth_level(index, level, tuple,
- PAGE_CUR_RTREE_INSERT,
- BTR_CONT_MODIFY_TREE,
- &cursor, 0, mtr);
}
+ flags |= BTR_NO_LOCKING_FLAG | BTR_KEEP_SYS_FLAG
+ | BTR_NO_UNDO_LOG_FLAG;
+
+ dberr_t err = btr_cur_search_to_nth_level(index, level, tuple, mode,
+ BTR_CONT_MODIFY_TREE,
+ &cursor, 0, mtr);
ut_ad(cursor.flag == BTR_CUR_BINARY);
- err = btr_cur_optimistic_insert(
- flags
- | BTR_NO_LOCKING_FLAG
- | BTR_KEEP_SYS_FLAG
- | BTR_NO_UNDO_LOG_FLAG,
- &cursor, &offsets, &heap,
- tuple, &rec, &dummy_big_rec, 0, NULL, mtr);
+ if (UNIV_LIKELY(err == DB_SUCCESS)) {
+ err = btr_cur_optimistic_insert(flags,
+ &cursor, &offsets, &heap,
+ tuple, &rec,
+ &dummy_big_rec, 0, NULL, mtr);
+ }
if (err == DB_FAIL) {
- err = btr_cur_pessimistic_insert(flags
- | BTR_NO_LOCKING_FLAG
- | BTR_KEEP_SYS_FLAG
- | BTR_NO_UNDO_LOG_FLAG,
+ err = btr_cur_pessimistic_insert(flags,
&cursor, &offsets, &heap,
tuple, &rec,
&dummy_big_rec, 0, NULL, mtr);
- ut_a(err == DB_SUCCESS);
}
- if (heap != NULL) {
+ if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
- if (dict_index_is_spatial(index)) {
+ if (index->is_spatial()) {
ut_ad(cursor.rtr_info);
rtr_clean_rtr_info(&rtr_info, true);
}
+
+ return err;
}
+static_assert(FIL_PAGE_OFFSET % 4 == 0, "alignment");
+static_assert(FIL_PAGE_PREV % 4 == 0, "alignment");
+static_assert(FIL_PAGE_NEXT % 4 == 0, "alignment");
+
+MY_ATTRIBUTE((nonnull,warn_unused_result))
/**************************************************************//**
Attaches the halves of an index page on the appropriate level in an
index tree. */
-static MY_ATTRIBUTE((nonnull))
-void
+static
+dberr_t
btr_attach_half_pages(
/*==================*/
ulint flags, /*!< in: undo logging and
@@ -2452,32 +2432,38 @@ btr_attach_half_pages(
/* Insert it next to the pointer to the lower half. Note that this
may generate recursion leading to a split on the higher level. */
- btr_insert_on_non_leaf_level(flags, index, level + 1,
- node_ptr_upper, mtr);
+ dberr_t err = btr_insert_on_non_leaf_level(
+ flags, index, level + 1, node_ptr_upper, mtr);
/* Free the memory heap */
mem_heap_free(heap);
+ if (UNIV_UNLIKELY(err != DB_SUCCESS)) {
+ return err;
+ }
+
/* Update page links of the level */
if (prev_block) {
-#ifdef UNIV_BTR_DEBUG
- ut_a(page_is_comp(prev_block->page.frame)
- == page_is_comp(block->page.frame));
- ut_a(btr_page_get_next(prev_block->page.frame)
- == block->page.id().page_no());
-#endif /* UNIV_BTR_DEBUG */
+ if (UNIV_UNLIKELY(memcmp_aligned<4>(prev_block->page.frame
+ + FIL_PAGE_NEXT,
+ block->page.frame
+ + FIL_PAGE_OFFSET,
+ 4))) {
+ return DB_CORRUPTION;
+ }
btr_page_set_next(prev_block, lower_block->page.id().page_no(),
mtr);
}
if (next_block) {
-#ifdef UNIV_BTR_DEBUG
- ut_a(page_is_comp(next_block->page.frame)
- == page_is_comp(block->page.frame));
- ut_a(btr_page_get_prev(next_block->page.frame)
- == block->page.id().page_no());
-#endif /* UNIV_BTR_DEBUG */
+ if (UNIV_UNLIKELY(memcmp_aligned<4>(next_block->page.frame
+ + FIL_PAGE_PREV,
+ block->page.frame
+ + FIL_PAGE_OFFSET,
+ 4))) {
+ return DB_CORRUPTION;
+ }
btr_page_set_prev(next_block, upper_block->page.id().page_no(),
mtr);
}
@@ -2496,6 +2482,8 @@ btr_attach_half_pages(
btr_page_set_prev(upper_block, lower_block->page.id().page_no(), mtr);
btr_page_set_next(lower_block, upper_block->page.id().page_no(), mtr);
+
+ return DB_SUCCESS;
}
/*************************************************************//**
@@ -2566,27 +2554,28 @@ btr_insert_into_right_sibling(
if (next_page_no == FIL_NULL || !page_rec_is_supremum(
page_rec_get_next(btr_cur_get_rec(cursor)))) {
- return(NULL);
+ return nullptr;
}
page_cur_t next_page_cursor;
buf_block_t* next_block;
page_t* next_page;
btr_cur_t next_father_cursor;
- rec_t* rec = NULL;
+ rec_t* rec = nullptr;
ulint max_size;
next_block = btr_block_get(*cursor->index, next_page_no, RW_X_LATCH,
page_is_leaf(page), mtr);
if (UNIV_UNLIKELY(!next_block)) {
- return NULL;
+ return nullptr;
}
next_page = buf_block_get_frame(next_block);
+ const bool is_leaf = page_is_leaf(next_page);
- bool is_leaf = page_is_leaf(next_page);
-
- btr_page_get_father(
- cursor->index, next_block, mtr, &next_father_cursor);
+ if (!btr_page_get_father(cursor->index, next_block, mtr,
+ &next_father_cursor)) {
+ return nullptr;
+ }
page_cur_search(
next_block, cursor->index, tuple, PAGE_CUR_LE,
@@ -2603,7 +2592,7 @@ btr_insert_into_right_sibling(
&next_page_cursor, tuple, cursor->index, offsets, &heap,
n_ext, mtr);
- if (rec == NULL) {
+ if (!rec) {
if (is_leaf
&& next_block->page.zip.ssize
&& !dict_index_is_clust(cursor->index)
@@ -2613,7 +2602,7 @@ btr_insert_into_right_sibling(
reorganize before failing. */
ibuf_reset_free_bits(next_block);
}
- return(NULL);
+ return nullptr;
}
ibool compressed;
@@ -2632,18 +2621,22 @@ btr_insert_into_right_sibling(
&err, TRUE, &next_father_cursor,
BTR_CREATE_FLAG, false, mtr);
- ut_a(err == DB_SUCCESS);
+ if (err != DB_SUCCESS) {
+ return nullptr;
+ }
if (!compressed) {
- btr_cur_compress_if_useful(&next_father_cursor, FALSE, mtr);
+ btr_cur_compress_if_useful(&next_father_cursor, false, mtr);
}
dtuple_t* node_ptr = dict_index_build_node_ptr(
cursor->index, rec, next_block->page.id().page_no(),
heap, level);
- btr_insert_on_non_leaf_level(
- flags, cursor->index, level + 1, node_ptr, mtr);
+ if (btr_insert_on_non_leaf_level(flags, cursor->index, level + 1,
+ node_ptr, mtr) != DB_SUCCESS) {
+ return nullptr;
+ }
ut_ad(rec_offs_validate(rec, cursor->index, *offsets));
@@ -2665,6 +2658,95 @@ btr_insert_into_right_sibling(
return(rec);
}
+/*************************************************************//**
+Moves record list end to another page. Moved records include
+split_rec.
+
+IMPORTANT: The caller will have to update IBUF_BITMAP_FREE
+if new_block is a compressed leaf page in a secondary index.
+This has to be done either within the same mini-transaction,
+or by invoking ibuf_reset_free_bits() before mtr_commit().
+
+@return error code */
+static
+dberr_t
+page_move_rec_list_end(
+/*===================*/
+ buf_block_t* new_block, /*!< in/out: index page where to move */
+ buf_block_t* block, /*!< in: index page from where to move */
+ rec_t* split_rec, /*!< in: first record to move */
+ dict_index_t* index, /*!< in: record descriptor */
+ mtr_t* mtr) /*!< in: mtr */
+{
+ page_t* new_page = buf_block_get_frame(new_block);
+ ulint old_data_size;
+ ulint new_data_size;
+ ulint old_n_recs;
+ ulint new_n_recs;
+
+ ut_ad(!dict_index_is_spatial(index));
+
+ old_data_size = page_get_data_size(new_page);
+ old_n_recs = page_get_n_recs(new_page);
+#ifdef UNIV_ZIP_DEBUG
+ {
+ page_zip_des_t* new_page_zip
+ = buf_block_get_page_zip(new_block);
+ page_zip_des_t* page_zip
+ = buf_block_get_page_zip(block);
+ ut_a(!new_page_zip == !page_zip);
+ ut_a(!new_page_zip
+ || page_zip_validate(new_page_zip, new_page, index));
+ ut_a(!page_zip
+ || page_zip_validate(page_zip, page_align(split_rec),
+ index));
+ }
+#endif /* UNIV_ZIP_DEBUG */
+
+ dberr_t err;
+ if (!page_copy_rec_list_end(new_block, block,
+ split_rec, index, mtr, &err)) {
+ return err;
+ }
+
+ new_data_size = page_get_data_size(new_page);
+ new_n_recs = page_get_n_recs(new_page);
+
+ ut_ad(new_data_size >= old_data_size);
+
+ page_delete_rec_list_end(split_rec, block, index,
+ new_n_recs - old_n_recs,
+ new_data_size - old_data_size, mtr);
+
+ return DB_SUCCESS;
+}
+
+/*************************************************************//**
+Moves record list start to another page. Moved records do not include
+split_rec.
+
+IMPORTANT: The caller will have to update IBUF_BITMAP_FREE
+if new_block is a compressed leaf page in a secondary index.
+This has to be done either within the same mini-transaction,
+or by invoking ibuf_reset_free_bits() before mtr_commit().
+
+@return error code */
+static
+dberr_t
+page_move_rec_list_start(
+/*=====================*/
+ buf_block_t* new_block, /*!< in/out: index page where to move */
+ buf_block_t* block, /*!< in/out: page containing split_rec */
+ rec_t* split_rec, /*!< in: first record not to move */
+ dict_index_t* index, /*!< in: record descriptor */
+ mtr_t* mtr) /*!< in: mtr */
+{
+ dberr_t err;
+ if (page_copy_rec_list_start(new_block, block, split_rec, index, mtr, &err))
+ page_delete_rec_list_start(split_rec, block, index, mtr);
+ return err;
+}
+
/*************************************************************//**
Splits an index page to halves and inserts the tuple. It is assumed
that mtr holds an x-latch to the index tree. NOTE: the tree x-latch is
@@ -2672,9 +2754,6 @@ released within this function! NOTE that the operation of this
function must always succeed, we cannot reverse it: therefore enough
free disk space (2 pages) must be guaranteed to be available before
this function is called.
-NOTE: jonaso added support for calling function with tuple == NULL
-which cause it to only split a page.
-
@return inserted record or NULL if run out of space */
rec_t*
btr_page_split_and_insert(
@@ -2687,7 +2766,8 @@ btr_page_split_and_insert(
mem_heap_t** heap, /*!< in/out: pointer to memory heap, or NULL */
const dtuple_t* tuple, /*!< in: tuple to insert */
ulint n_ext, /*!< in: number of externally stored columns */
- mtr_t* mtr) /*!< in: mtr */
+ mtr_t* mtr, /*!< in: mtr */
+ dberr_t* err) /*!< out: error code */
{
buf_block_t* block;
page_t* page;
@@ -2705,10 +2785,12 @@ btr_page_split_and_insert(
ulint n_iterations = 0;
ulint n_uniq;
+ ut_ad(*err == DB_SUCCESS);
+
if (cursor->index->is_spatial()) {
/* Split rtree page and update parent */
- return(rtr_page_split_and_insert(flags, cursor, offsets, heap,
- tuple, n_ext, mtr));
+ return rtr_page_split_and_insert(flags, cursor, offsets, heap,
+ tuple, n_ext, mtr, err);
}
if (!*heap) {
@@ -2746,7 +2828,7 @@ func_start:
uint32_t hint_page_no = block->page.id().page_no() + 1;
byte direction = FSP_UP;
- if (tuple && n_iterations > 0) {
+ if (n_iterations > 0) {
split_rec = btr_page_get_split_rec(cursor, tuple, n_ext);
if (split_rec == NULL) {
@@ -2774,17 +2856,13 @@ func_start:
}
}
- DBUG_EXECUTE_IF("disk_is_full",
- os_has_said_disk_full = true;
- return(NULL););
-
/* 2. Allocate a new page to the index */
const uint16_t page_level = btr_page_get_level(page);
new_block = btr_page_alloc(cursor->index, hint_page_no, direction,
- page_level, mtr, mtr);
+ page_level, mtr, mtr, err);
if (!new_block) {
- return(NULL);
+ return nullptr;
}
new_page = buf_block_get_frame(new_block);
@@ -2816,8 +2894,7 @@ func_start:
? cursor->index->n_core_fields : 0,
n_uniq, heap);
- insert_left = !tuple
- || cmp_dtuple_rec(tuple, split_rec, *offsets) < 0;
+ insert_left = cmp_dtuple_rec(tuple, split_rec, *offsets) < 0;
if (!insert_left && new_page_zip && n_iterations > 0) {
/* If a compressed page has already been split,
@@ -2846,29 +2923,23 @@ insert_empty:
/* 4. Do first the modifications in the tree structure */
/* FIXME: write FIL_PAGE_PREV,FIL_PAGE_NEXT in new_block earlier! */
- btr_attach_half_pages(flags, cursor->index, block,
- first_rec, new_block, direction, mtr);
+ *err = btr_attach_half_pages(flags, cursor->index, block,
+ first_rec, new_block, direction, mtr);
+
+ if (UNIV_UNLIKELY(*err != DB_SUCCESS)) {
+ return nullptr;
+ }
/* If the split is made on the leaf level and the insert will fit
on the appropriate half-page, we may release the tree x-latch.
We can then move the records after releasing the tree latch,
thus reducing the tree latch contention. */
- bool insert_will_fit;
- if (tuple == NULL) {
- insert_will_fit = true;
- } else if (split_rec) {
- insert_will_fit = !new_page_zip
- && btr_page_insert_fits(cursor, split_rec,
- offsets, tuple, n_ext, heap);
- } else {
- if (!insert_left) {
- UT_DELETE_ARRAY(buf);
- buf = NULL;
- }
-
- insert_will_fit = !new_page_zip
- && btr_page_insert_fits(cursor, NULL,
- offsets, tuple, n_ext, heap);
+ const bool insert_will_fit = !new_page_zip
+ && btr_page_insert_fits(cursor, split_rec, offsets, tuple,
+ n_ext, heap);
+ if (!split_rec && !insert_left) {
+ UT_DELETE_ARRAY(buf);
+ buf = NULL;
}
if (!srv_read_only_mode
@@ -2891,9 +2962,14 @@ insert_empty:
#ifdef UNIV_ZIP_COPY
|| page_zip
#endif /* UNIV_ZIP_COPY */
- || !page_move_rec_list_start(new_block, block, move_limit,
- cursor->index, mtr)) {
- /* For some reason, compressing new_page failed,
+ || (*err = page_move_rec_list_start(new_block, block,
+ move_limit,
+ cursor->index, mtr))) {
+ if (*err != DB_FAIL) {
+ return nullptr;
+ }
+
+ /* For some reason, compressing new_block failed,
even though it should contain fewer records than
the original page. Copy the page byte for byte
and then delete the records from both pages
@@ -2936,8 +3012,13 @@ insert_empty:
#ifdef UNIV_ZIP_COPY
|| page_zip
#endif /* UNIV_ZIP_COPY */
- || !page_move_rec_list_end(new_block, block, move_limit,
- cursor->index, mtr)) {
+ || (*err = page_move_rec_list_end(new_block, block,
+ move_limit,
+ cursor->index, mtr))) {
+ if (*err != DB_FAIL) {
+ return nullptr;
+ }
+
/* For some reason, compressing new_page failed,
even though it should contain fewer records than
the original page. Copy the page byte for byte
@@ -2992,11 +3073,6 @@ insert_empty:
buf_block_t* const insert_block = insert_left
? left_block : right_block;
- if (UNIV_UNLIKELY(!tuple)) {
- rec = NULL;
- goto func_exit;
- }
-
/* 7. Reposition the cursor for insert and try insertion */
page_cursor = btr_cur_get_page_cur(cursor);
@@ -3028,12 +3104,16 @@ insert_empty:
For compressed pages, page_cur_tuple_insert() will have
attempted this already. */
- if (page_cur_get_page_zip(page_cursor)
- || !btr_page_reorganize(page_cursor, cursor->index, mtr)) {
-
+ if (page_cur_get_page_zip(page_cursor)) {
goto insert_failed;
}
+ *err = btr_page_reorganize(page_cursor, cursor->index, mtr);
+
+ if (*err != DB_SUCCESS) {
+ return nullptr;
+ }
+
rec = page_cur_tuple_insert(page_cursor, tuple, cursor->index,
offsets, heap, n_ext, mtr);
@@ -3073,7 +3153,6 @@ func_exit:
ut_ad(page_validate(buf_block_get_frame(left_block), cursor->index));
ut_ad(page_validate(buf_block_get_frame(right_block), cursor->index));
- ut_ad(tuple || !rec);
ut_ad(!rec || rec_offs_validate(rec, cursor->index, *offsets));
return(rec);
}
@@ -3095,40 +3174,38 @@ dberr_t btr_level_list_remove(const buf_block_t& block,
const uint32_t next_page_no = btr_page_get_next(page);
/* Update page links of the level */
+ dberr_t err;
if (prev_page_no != FIL_NULL) {
buf_block_t* prev_block = btr_block_get(
index, prev_page_no, RW_X_LATCH, page_is_leaf(page),
- mtr);
-#ifdef UNIV_BTR_DEBUG
- ut_a(page_is_comp(prev_block->page.frame)
- == page_is_comp(page));
- static_assert(FIL_PAGE_NEXT % 4 == 0, "alignment");
- static_assert(FIL_PAGE_OFFSET % 4 == 0, "alignment");
- ut_a(!memcmp_aligned<4>(prev_block->page.frame + FIL_PAGE_NEXT,
- page + FIL_PAGE_OFFSET, 4));
-#endif /* UNIV_BTR_DEBUG */
-
+ mtr, &err);
+ if (UNIV_UNLIKELY(!prev_block)) {
+ return err;
+ }
+ if (UNIV_UNLIKELY(memcmp_aligned<4>(prev_block->page.frame
+ + FIL_PAGE_NEXT,
+ page + FIL_PAGE_OFFSET,
+ 4))) {
+ return DB_CORRUPTION;
+ }
btr_page_set_next(prev_block, next_page_no, mtr);
}
if (next_page_no != FIL_NULL) {
buf_block_t* next_block = btr_block_get(
index, next_page_no, RW_X_LATCH, page_is_leaf(page),
- mtr);
+ mtr, &err);
- if (!next_block) {
- return DB_ERROR;
+ if (UNIV_UNLIKELY(!next_block)) {
+ return err;
+ }
+ if (UNIV_UNLIKELY(memcmp_aligned<4>(next_block->page.frame
+ + FIL_PAGE_PREV,
+ page + FIL_PAGE_OFFSET,
+ 4))) {
+ return DB_CORRUPTION;
}
-#ifdef UNIV_BTR_DEBUG
- ut_a(page_is_comp(next_block->page.frame)
- == page_is_comp(page));
- static_assert(FIL_PAGE_PREV % 4 == 0, "alignment");
- static_assert(FIL_PAGE_OFFSET % 4 == 0, "alignment");
- ut_a(!memcmp_aligned<4>(next_block->page.frame + FIL_PAGE_PREV,
- page + FIL_PAGE_OFFSET, 4));
-#endif /* UNIV_BTR_DEBUG */
-
btr_page_set_prev(next_block, prev_page_no, mtr);
}
@@ -3146,7 +3223,8 @@ btr_lift_page_up(
must not be empty: use
btr_discard_only_page_on_level if the last
record from the page should be removed */
- mtr_t* mtr) /*!< in: mtr */
+ mtr_t* mtr, /*!< in/out: mini-transaction */
+ dberr_t* err) /*!< out: error code */
{
buf_block_t* father_block;
ulint page_level;
@@ -3259,7 +3337,11 @@ btr_lift_page_up(
#endif /* UNIV_ZIP_COPY */
|| !page_copy_rec_list_end(father_block, block,
page_get_infimum_rec(page),
- index, mtr)) {
+ index, mtr, err)) {
+ if (*err != DB_SUCCESS && *err != DB_FAIL) {
+ return nullptr;
+ }
+
const page_zip_des_t* page_zip
= buf_block_get_page_zip(block);
ut_a(father_page_zip);
@@ -3329,16 +3411,16 @@ level lifts the records of the page to the father page, thus reducing the
tree height. It is assumed that mtr holds an x-latch on the tree and on the
page. If cursor is on the leaf level, mtr must also hold x-latches to the
brothers, if they exist.
-@return TRUE on success */
-ibool
+@return error code */
+dberr_t
btr_compress(
/*=========*/
btr_cur_t* cursor, /*!< in/out: cursor on the page to merge
or lift; the page must not be empty:
when deleting records, use btr_discard_page()
if the page would become empty */
- ibool adjust, /*!< in: TRUE if should adjust the
- cursor position even if compression occurs */
+ bool adjust, /*!< in: whether the cursor position should be
+ adjusted even when compression occurs */
mtr_t* mtr) /*!< in/out: mini-transaction */
{
dict_index_t* index;
@@ -3362,8 +3444,6 @@ btr_compress(
page = btr_cur_get_page(cursor);
index = btr_cur_get_index(cursor);
- btr_assert_not_corrupted(block, index);
-
ut_ad(mtr->memo_contains_flagged(&index->lock, MTR_MEMO_X_LOCK
| MTR_MEMO_SX_LOCK));
ut_ad(mtr->memo_contains_flagged(block, MTR_MEMO_PAGE_X_FIX));
@@ -3372,14 +3452,12 @@ btr_compress(
const uint32_t left_page_no = btr_page_get_prev(page);
const uint32_t right_page_no = btr_page_get_next(page);
+ dberr_t err = DB_SUCCESS;
-#ifdef UNIV_DEBUG
- if (!page_is_leaf(page) && left_page_no == FIL_NULL) {
- ut_a(REC_INFO_MIN_REC_FLAG & rec_get_info_bits(
- page_rec_get_next(page_get_infimum_rec(page)),
- page_is_comp(page)));
- }
-#endif /* UNIV_DEBUG */
+ ut_ad(page_is_leaf(page) || left_page_no != FIL_NULL
+ || (REC_INFO_MIN_REC_FLAG & rec_get_info_bits(
+ page_rec_get_next(page_get_infimum_rec(page)),
+ page_is_comp(page))));
heap = mem_heap_create(100);
@@ -3412,7 +3490,7 @@ btr_compress(
/* The page is the only one on the level, lift the records
to the father */
- merge_block = btr_lift_page_up(index, block, mtr);
+ merge_block = btr_lift_page_up(index, block, mtr, &err);
goto func_exit;
}
@@ -3437,20 +3515,21 @@ retry:
if (!merge_block) {
merge_page = NULL;
}
+cannot_merge:
+ err = DB_FAIL;
goto err_exit;
}
merge_page = buf_block_get_frame(merge_block);
-#ifdef UNIV_BTR_DEBUG
- if (is_left) {
- ut_a(btr_page_get_next(merge_page)
- == block->page.id().page_no());
- } else {
- ut_a(btr_page_get_prev(merge_page)
- == block->page.id().page_no());
+ if (UNIV_UNLIKELY(memcmp_aligned<4>(merge_page + (is_left
+ ? FIL_PAGE_NEXT
+ : FIL_PAGE_PREV),
+ block->page.frame
+ + FIL_PAGE_OFFSET, 4))) {
+ err = DB_CORRUPTION;
+ goto err_exit;
}
-#endif /* UNIV_BTR_DEBUG */
ut_ad(page_validate(merge_page, index));
@@ -3502,7 +3581,7 @@ retry:
rec_t* orig_pred = page_copy_rec_list_start(
merge_block, block, page_get_supremum_rec(page),
- index, mtr);
+ index, mtr, &err);
if (!orig_pred) {
goto err_exit;
@@ -3511,7 +3590,9 @@ retry:
btr_search_drop_page_hash_index(block);
/* Remove the page from the level list */
- if (DB_SUCCESS != btr_level_list_remove(*block, *index, mtr)) {
+ err = btr_level_list_remove(*block, *index, mtr);
+
+ if (UNIV_UNLIKELY(err != DB_SUCCESS)) {
goto err_exit;
}
@@ -3540,7 +3621,10 @@ retry:
/* No GAP lock needs to be worrying about */
lock_sys.prdt_page_free_from_discard(id);
} else {
- btr_cur_node_ptr_delete(&father_cursor, mtr);
+ err = btr_cur_node_ptr_delete(&father_cursor, mtr);
+ if (UNIV_UNLIKELY(err != DB_SUCCESS)) {
+ goto err_exit;
+ }
if (index->has_locking()) {
lock_update_merge_left(
*merge_block, orig_pred, id);
@@ -3557,9 +3641,7 @@ retry:
btr_cur_t cursor2;
/* father cursor pointing to node ptr
of the right sibling */
-#ifdef UNIV_BTR_DEBUG
byte fil_page_prev[4];
-#endif /* UNIV_BTR_DEBUG */
if (dict_index_is_spatial(index)) {
cursor2.rtr_info = NULL;
@@ -3572,15 +3654,16 @@ retry:
index, &cursor2,
btr_cur_get_block(&father_cursor),
merge_block, heap)) {
- goto err_exit;
+ goto cannot_merge;
}
/* Set rtr_info for cursor2, since it is
necessary in recursive page merge. */
cursor2.rtr_info = cursor->rtr_info;
cursor2.tree_height = cursor->tree_height;
- } else {
- btr_page_get_father(index, merge_block, mtr, &cursor2);
+ } else if (!btr_page_get_father(index, merge_block, mtr,
+ &cursor2)) {
+ goto cannot_merge;
}
if (merge_page_zip && left_page_no == FIL_NULL) {
@@ -3590,33 +3673,28 @@ retry:
requires that FIL_PAGE_PREV be FIL_NULL.
Clear the field, but prepare to restore it. */
static_assert(FIL_PAGE_PREV % 8 == 0, "alignment");
-#ifdef UNIV_BTR_DEBUG
memcpy(fil_page_prev, merge_page + FIL_PAGE_PREV, 4);
-#endif /* UNIV_BTR_DEBUG */
compile_time_assert(FIL_NULL == 0xffffffffU);
memset_aligned<4>(merge_page + FIL_PAGE_PREV, 0xff, 4);
}
orig_succ = page_copy_rec_list_end(merge_block, block,
page_get_infimum_rec(page),
- cursor->index, mtr);
+ cursor->index, mtr, &err);
if (!orig_succ) {
ut_a(merge_page_zip);
-#ifdef UNIV_BTR_DEBUG
if (left_page_no == FIL_NULL) {
/* FIL_PAGE_PREV was restored from
merge_page_zip. */
- ut_a(!memcmp(fil_page_prev,
- merge_page + FIL_PAGE_PREV, 4));
+ ut_ad(!memcmp(fil_page_prev,
+ merge_page + FIL_PAGE_PREV, 4));
}
-#endif /* UNIV_BTR_DEBUG */
goto err_exit;
}
btr_search_drop_page_hash_index(block);
-#ifdef UNIV_BTR_DEBUG
if (merge_page_zip && left_page_no == FIL_NULL) {
/* Restore FIL_PAGE_PREV in order to avoid an assertion
@@ -3627,10 +3705,11 @@ retry:
are X-latched. */
memcpy(merge_page + FIL_PAGE_PREV, fil_page_prev, 4);
}
-#endif /* UNIV_BTR_DEBUG */
/* Remove the page from the level list */
- if (DB_SUCCESS != btr_level_list_remove(*block, *index, mtr)) {
+ err = btr_level_list_remove(*block, *index, mtr);
+
+ if (UNIV_UNLIKELY(err != DB_SUCCESS)) {
goto err_exit;
}
@@ -3701,8 +3780,7 @@ retry:
ut_a(err == DB_SUCCESS);
if (!compressed) {
- btr_cur_compress_if_useful(&cursor2,
- FALSE,
+ btr_cur_compress_if_useful(&cursor2, false,
mtr);
}
@@ -3767,39 +3845,33 @@ retry:
}
/* Free the file page */
- btr_page_free(index, block, mtr);
-
- /* btr_check_node_ptr() needs parent block latched.
- If the merge_block's parent block is not same,
- we cannot use btr_check_node_ptr() */
- ut_ad(leftmost_child
- || btr_check_node_ptr(index, merge_block, mtr));
+ err = btr_page_free(index, block, mtr);
+ if (err == DB_SUCCESS) {
+ ut_ad(leftmost_child
+ || btr_check_node_ptr(index, merge_block, mtr));
func_exit:
- mem_heap_free(heap);
-
- if (adjust) {
- ut_ad(nth_rec > 0);
- btr_cur_position(
- index,
- page_rec_get_nth(merge_block->page.frame, nth_rec),
- merge_block, cursor);
- }
-
- MONITOR_INC(MONITOR_INDEX_MERGE_SUCCESSFUL);
-
- DBUG_RETURN(TRUE);
+ MONITOR_INC(MONITOR_INDEX_MERGE_SUCCESSFUL);
+ if (adjust) {
+ ut_ad(nth_rec > 0);
+ btr_cur_position(
+ index,
+ page_rec_get_nth(merge_block->page.frame,
+ nth_rec),
+ merge_block, cursor);
+ }
+ } else {
err_exit:
- /* We play it safe and reset the free bits. */
- if (merge_block && merge_block->zip_size()
- && page_is_leaf(merge_block->page.frame)
- && !dict_index_is_clust(index)) {
-
- ibuf_reset_free_bits(merge_block);
- }
+ /* We play it safe and reset the free bits. */
+ if (merge_block && merge_block->zip_size()
+ && page_is_leaf(merge_block->page.frame)
+ && !index->is_clust()) {
+ ibuf_reset_free_bits(merge_block);
+ }
+ }
mem_heap_free(heap);
- DBUG_RETURN(FALSE);
+ DBUG_RETURN(err);
}
/*************************************************************//**
@@ -3839,12 +3911,17 @@ btr_discard_only_page_on_level(
ut_ad(mtr->memo_contains_flagged(block, MTR_MEMO_PAGE_X_FIX));
btr_search_drop_page_hash_index(block);
- if (dict_index_is_spatial(index)) {
+ if (index->is_spatial()) {
/* Check any concurrent search having this page */
rtr_check_discard_page(index, NULL, block);
- rtr_page_get_father(index, block, mtr, NULL, &cursor);
+ if (!rtr_page_get_father(index, block, mtr, nullptr,
+ &cursor)) {
+ return;
+ }
} else {
- btr_page_get_father(index, block, mtr, &cursor);
+ if (!btr_page_get_father(index, block, mtr, &cursor)) {
+ return;
+ }
}
father = btr_cur_get_block(&cursor);
@@ -3854,7 +3931,9 @@ btr_discard_only_page_on_level(
}
/* Free the file page */
- btr_page_free(index, block, mtr);
+ if (btr_page_free(index, block, mtr) != DB_SUCCESS) {
+ return;
+ }
block = father;
page_level++;
@@ -3864,17 +3943,6 @@ btr_discard_only_page_on_level(
for the node pointer to the (now discarded) block(s). */
ut_ad(!page_has_siblings(block->page.frame));
-#ifdef UNIV_BTR_DEBUG
- if (!dict_index_is_ibuf(index)) {
- const page_t* root = buf_block_get_frame(block);
- const ulint space = index->table->space_id;
- ut_a(btr_root_fseg_validate(FIL_PAGE_DATA + PAGE_BTR_SEG_LEAF
- + root, space));
- ut_a(btr_root_fseg_validate(FIL_PAGE_DATA + PAGE_BTR_SEG_TOP
- + root, space));
- }
-#endif /* UNIV_BTR_DEBUG */
-
mem_heap_t* heap = nullptr;
const rec_t* rec = nullptr;
rec_offs* offsets = nullptr;
@@ -3927,7 +3995,7 @@ btr_discard_only_page_on_level(
Discards a page from a B-tree. This is used to remove the last record from
a B-tree page: the whole page must be removed at the same time. This cannot
be used for the root page, which is allowed to be empty. */
-void
+dberr_t
btr_discard_page(
/*=============*/
btr_cur_t* cursor, /*!< in: cursor on the page to discard: not on
@@ -3950,10 +4018,10 @@ btr_discard_page(
MONITOR_INC(MONITOR_INDEX_DISCARD);
- if (dict_index_is_spatial(index)) {
- rtr_page_get_father(index, block, mtr, cursor, &parent_cursor);
- } else {
- btr_page_get_father(index, block, mtr, &parent_cursor);
+ if (index->is_spatial()
+ ? !rtr_page_get_father(index, block, mtr, cursor, &parent_cursor)
+ : !btr_page_get_father(index, block, mtr, &parent_cursor)) {
+ return DB_CORRUPTION;
}
/* Decide the page which will inherit the locks */
@@ -3963,12 +4031,20 @@ btr_discard_page(
ut_d(bool parent_is_different = false);
if (left_page_no != FIL_NULL) {
+ dberr_t err;
merge_block = btr_block_get(*index, left_page_no, RW_X_LATCH,
- true, mtr);
-#ifdef UNIV_BTR_DEBUG
- ut_a(btr_page_get_next(merge_block->page.frame)
- == block->page.id().page_no());
-#endif /* UNIV_BTR_DEBUG */
+ true, mtr, &err);
+ if (UNIV_UNLIKELY(!merge_block)) {
+ return err;
+ }
+
+ if (UNIV_UNLIKELY(memcmp_aligned<4>(merge_block->page.frame
+ + FIL_PAGE_NEXT,
+ block->page.frame
+ + FIL_PAGE_OFFSET, 4))) {
+ return DB_CORRUPTION;
+ }
+
ut_d(parent_is_different =
(page_rec_get_next(
page_get_infimum_rec(
@@ -3976,12 +4052,19 @@ btr_discard_page(
&parent_cursor)))
== btr_cur_get_rec(&parent_cursor)));
} else if (right_page_no != FIL_NULL) {
+ dberr_t err;
merge_block = btr_block_get(*index, right_page_no, RW_X_LATCH,
- true, mtr);
-#ifdef UNIV_BTR_DEBUG
- ut_a(btr_page_get_prev(merge_block->page.frame)
- == block->page.id().page_no());
-#endif /* UNIV_BTR_DEBUG */
+ true, mtr, &err);
+ if (UNIV_UNLIKELY(!merge_block)) {
+ return err;
+ }
+ if (UNIV_UNLIKELY(memcmp_aligned<4>(merge_block->page.frame
+ + FIL_PAGE_PREV,
+ block->page.frame
+ + FIL_PAGE_OFFSET, 4))) {
+ return DB_CORRUPTION;
+ }
+
ut_d(parent_is_different = page_rec_is_supremum(
page_rec_get_next(btr_cur_get_rec(&parent_cursor))));
if (!page_is_leaf(merge_block->page.frame)) {
@@ -3995,26 +4078,29 @@ btr_discard_page(
}
} else {
btr_discard_only_page_on_level(index, block, mtr);
-
- return;
+ return DB_SUCCESS;
+ }
+
+ if (UNIV_UNLIKELY(memcmp_aligned<2>(&merge_block->page.frame
+ [PAGE_HEADER + PAGE_LEVEL],
+ &block->page.frame
+ [PAGE_HEADER + PAGE_LEVEL], 2))) {
+ return DB_CORRUPTION;
}
- ut_a(page_is_comp(merge_block->page.frame)
- == page_is_comp(block->page.frame));
- ut_ad(!memcmp_aligned<2>(&merge_block->page.frame
- [PAGE_HEADER + PAGE_LEVEL],
- &block->page.frame
- [PAGE_HEADER + PAGE_LEVEL], 2));
btr_search_drop_page_hash_index(block);
if (dict_index_is_spatial(index)) {
rtr_node_ptr_delete(&parent_cursor, mtr);
- } else {
- btr_cur_node_ptr_delete(&parent_cursor, mtr);
+ } else if (dberr_t err =
+ btr_cur_node_ptr_delete(&parent_cursor, mtr)) {
+ return err;
}
/* Remove the page from the level list */
- ut_a(DB_SUCCESS == btr_level_list_remove(*block, *index, mtr));
+ if (dberr_t err = btr_level_list_remove(*block, *index, mtr)) {
+ return err;
+ }
#ifdef UNIV_ZIP_DEBUG
{
@@ -4042,20 +4128,25 @@ btr_discard_page(
}
/* Free the file page */
- btr_page_free(index, block, mtr);
+ dberr_t err = btr_page_free(index, block, mtr);
- /* btr_check_node_ptr() needs parent block latched.
- If the merge_block's parent block is not same,
- we cannot use btr_check_node_ptr() */
- ut_ad(parent_is_different
- || btr_check_node_ptr(index, merge_block, mtr));
+ if (err == DB_SUCCESS) {
+ /* btr_check_node_ptr() needs parent block latched.
+ If the merge_block's parent block is not same,
+ we cannot use btr_check_node_ptr() */
+ ut_ad(parent_is_different
+ || btr_check_node_ptr(index, merge_block, mtr));
- if (btr_cur_get_block(&parent_cursor)->page.id().page_no()
- == index->page
- && !page_has_siblings(btr_cur_get_page(&parent_cursor))
- && page_get_n_recs(btr_cur_get_page(&parent_cursor)) == 1) {
- btr_lift_page_up(index, merge_block, mtr);
+ if (btr_cur_get_block(&parent_cursor)->page.id().page_no()
+ == index->page
+ && !page_has_siblings(btr_cur_get_page(&parent_cursor))
+ && page_get_n_recs(btr_cur_get_page(&parent_cursor))
+ == 1) {
+ btr_lift_page_up(index, merge_block, mtr, &err);
+ }
}
+
+ return err;
}
#ifdef UNIV_BTR_PRINT
@@ -4146,12 +4237,12 @@ btr_print_recursive(
*offsets = rec_get_offsets(
node_ptr, index, *offsets, 0,
ULINT_UNDEFINED, heap);
- btr_print_recursive(index,
- btr_node_ptr_get_child(node_ptr,
- index,
- *offsets,
- &mtr2),
- width, heap, offsets, &mtr2);
+ if (buf_block_t *child =
+ btr_node_ptr_get_child(node_ptr, index, *offsets,
+ &mtr2)) {
+ btr_print_recursive(index, child, width, heap,
+ offsets, &mtr2);
+ }
mtr_commit(&mtr2);
}
@@ -4538,11 +4629,9 @@ btr_validate_report2(
error << ", index tree level " << level;
}
-/************************************************************//**
-Validates index tree level.
-@return TRUE if ok */
+/** Validate an index tree level. */
static
-bool
+dberr_t
btr_validate_level(
/*===============*/
dict_index_t* index, /*!< in: index tree */
@@ -4560,7 +4649,6 @@ btr_validate_level(
rec_t* rec;
page_cur_t cursor;
dtuple_t* node_ptr_tuple;
- bool ret = true;
mtr_t mtr;
mem_heap_t* heap = mem_heap_create(256);
rec_offs* offsets = NULL;
@@ -4584,23 +4672,31 @@ btr_validate_level(
}
}
- block = btr_root_block_get(index, RW_SX_LATCH, &mtr);
+ dberr_t err;
+ block = btr_root_block_get(index, RW_SX_LATCH, &mtr, &err);
+ if (!block) {
+ mtr.commit();
+ return err;
+ }
page = buf_block_get_frame(block);
fil_space_t* space = index->table->space;
while (level != btr_page_get_level(page)) {
const rec_t* node_ptr;
-
- if (fseg_page_is_free(space, block->page.id().page_no())) {
-
+ switch (dberr_t e =
+ fseg_page_is_allocated(space,
+ block->page.id().page_no())) {
+ case DB_SUCCESS_LOCKED_REC:
+ break;
+ case DB_SUCCESS:
btr_validate_report1(index, level, block);
-
ib::warn() << "Page is free";
-
- ret = false;
+ e = DB_CORRUPTION;
+ /* fall through */
+ default:
+ err = e;
}
-
ut_a(index->table->space_id == block->page.id().space());
ut_a(block->page.id().space() == page_get_space_id(page));
#ifdef UNIV_ZIP_DEBUG
@@ -4617,7 +4713,11 @@ btr_validate_level(
ULINT_UNDEFINED, &heap);
savepoint2 = mtr_set_savepoint(&mtr);
- block = btr_node_ptr_get_child(node_ptr, index, offsets, &mtr);
+ block = btr_node_ptr_get_child(node_ptr, index, offsets, &mtr,
+ &err);
+ if (!block) {
+ break;
+ }
page = buf_block_get_frame(block);
/* For R-Tree, since record order might not be the same as
@@ -4639,7 +4739,10 @@ btr_validate_level(
savepoint2 = mtr_set_savepoint(&mtr);
block = btr_block_get(*index, left_page_no,
RW_SX_LATCH, false,
- &mtr);
+ &mtr, &err);
+ if (!block) {
+ goto invalid_page;
+ }
page = buf_block_get_frame(block);
left_page_no = btr_page_get_prev(page);
}
@@ -4650,8 +4753,16 @@ btr_validate_level(
level. */
loop:
+ if (!block) {
+invalid_page:
+func_exit:
+ mem_heap_free(heap);
+ return err;
+ }
+
mem_heap_empty(heap);
offsets = offsets2 = NULL;
+
if (!srv_read_only_mode) {
if (lockout) {
mtr_x_lock_index(index, &mtr);
@@ -4660,72 +4771,64 @@ loop:
}
}
+ page = block->page.frame;
+
#ifdef UNIV_ZIP_DEBUG
page_zip = buf_block_get_page_zip(block);
ut_a(!page_zip || page_zip_validate(page_zip, page, index));
#endif /* UNIV_ZIP_DEBUG */
- ut_a(block->page.id().space() == index->table->space_id);
-
- if (fseg_page_is_free(space, block->page.id().page_no())) {
-
+ if (DB_SUCCESS_LOCKED_REC
+ != fseg_page_is_allocated(space, block->page.id().page_no())) {
btr_validate_report1(index, level, block);
ib::warn() << "Page is marked as free";
- ret = false;
-
+ err = DB_CORRUPTION;
} else if (btr_page_get_index_id(page) != index->id) {
-
ib::error() << "Page index id " << btr_page_get_index_id(page)
<< " != data dictionary index id " << index->id;
-
- ret = false;
-
+ err = DB_CORRUPTION;
} else if (!page_validate(page, index)) {
-
btr_validate_report1(index, level, block);
- ret = false;
-
+ err = DB_CORRUPTION;
+ } else if (btr_page_get_level(page) != level) {
+ btr_validate_report1(index, level, block);
+ ib::error() << "Page level is not " << level;
+ err = DB_CORRUPTION;
} else if (level == 0 && !btr_index_page_validate(block, index)) {
-
/* We are on level 0. Check that the records have the right
number of fields, and field lengths are right. */
-
- ret = false;
+ err = DB_CORRUPTION;
+ } else if (!page_is_empty(page)) {
+ } else if (level) {
+ btr_validate_report1(index, level, block);
+ ib::error() << "Non-leaf page is empty";
+ } else if (block->page.id().page_no() != index->page) {
+ btr_validate_report1(index, level, block);
+ ib::error() << "Empty leaf page is not index root";
}
- ut_a(btr_page_get_level(page) == level);
-
uint32_t right_page_no = btr_page_get_next(page);
uint32_t left_page_no = btr_page_get_prev(page);
- ut_a(!page_is_empty(page)
- || (level == 0
- && page_get_page_no(page) == dict_index_get_page(index)));
-
if (right_page_no != FIL_NULL) {
const rec_t* right_rec;
savepoint = mtr_set_savepoint(&mtr);
right_block = btr_block_get(*index, right_page_no, RW_SX_LATCH,
- !level, &mtr);
+ !level, &mtr, &err);
+ if (!right_block) {
+ btr_validate_report1(index, level, block);
+ fputs("InnoDB: broken FIL_PAGE_NEXT link\n", stderr);
+ goto invalid_page;
+ }
right_page = buf_block_get_frame(right_block);
if (btr_page_get_prev(right_page) != page_get_page_no(page)) {
btr_validate_report2(index, level, block, right_block);
fputs("InnoDB: broken FIL_PAGE_NEXT"
" or FIL_PAGE_PREV links\n", stderr);
-
- ret = false;
- }
-
- if (page_is_comp(right_page) != page_is_comp(page)) {
- btr_validate_report2(index, level, block, right_block);
- fputs("InnoDB: 'compact' flag mismatch\n", stderr);
-
- ret = false;
-
- goto node_ptr_fails;
+ err = DB_CORRUPTION;
}
rec = page_rec_get_prev(page_get_supremum_rec(page));
@@ -4761,15 +4864,17 @@ loop:
page_get_infimum_rec(right_page));
rec_print(stderr, rec, index);
putc('\n', stderr);
-
- ret = false;
+ err = DB_CORRUPTION;
}
}
- if (level > 0 && left_page_no == FIL_NULL) {
- ut_a(REC_INFO_MIN_REC_FLAG & rec_get_info_bits(
- page_rec_get_next(page_get_infimum_rec(page)),
- page_is_comp(page)));
+ if (level > 0 && left_page_no == FIL_NULL
+ && !(REC_INFO_MIN_REC_FLAG & rec_get_info_bits(
+ page_rec_get_next(page_get_infimum_rec(page)),
+ page_is_comp(page)))) {
+ btr_validate_report1(index, level, block);
+ ib::error() << "Missing REC_INFO_MIN_REC_FLAG";
+ err = DB_CORRUPTION;
}
/* Similarly skip the father node check for spatial index for now,
@@ -4826,8 +4931,7 @@ loop:
fputs("InnoDB: record on page ", stderr);
rec_print_new(stderr, rec, offsets);
putc('\n', stderr);
- ret = false;
-
+ err = DB_CORRUPTION;
goto node_ptr_fails;
}
@@ -4851,8 +4955,7 @@ loop:
fputs("InnoDB: first rec ", stderr);
rec_print(stderr, first_rec, index);
putc('\n', stderr);
- ret = false;
-
+ err = DB_CORRUPTION;
goto node_ptr_fails;
}
}
@@ -4890,7 +4993,15 @@ loop:
right_block = btr_block_get(*index,
right_page_no,
RW_SX_LATCH,
- !level, &mtr);
+ !level, &mtr,
+ &err);
+ if (!right_block) {
+ btr_validate_report1(index, level,
+ block);
+ fputs("InnoDB: broken FIL_PAGE_NEXT"
+ " link\n", stderr);
+ goto invalid_page;
+ }
}
btr_cur_position(
@@ -4908,7 +5019,7 @@ loop:
if (btr_cur_get_rec(&right_node_cur)
!= right_node_ptr) {
- ret = false;
+ err = DB_CORRUPTION;
fputs("InnoDB: node pointer to"
" the right page is wrong\n",
stderr);
@@ -4924,7 +5035,7 @@ loop:
!= page_rec_get_next(
page_get_infimum_rec(
right_father_page))) {
- ret = false;
+ err = DB_CORRUPTION;
fputs("InnoDB: node pointer 2 to"
" the right page is wrong\n",
stderr);
@@ -4936,7 +5047,7 @@ loop:
if (page_get_page_no(right_father_page)
!= btr_page_get_next(father_page)) {
- ret = false;
+ err = DB_CORRUPTION;
fputs("InnoDB: node pointer 3 to"
" the right page is wrong\n",
stderr);
@@ -4975,15 +5086,11 @@ node_ptr_fails:
}
block = btr_block_get(*index, right_page_no, RW_SX_LATCH,
- !level, &mtr);
- page = buf_block_get_frame(block);
-
+ !level, &mtr, &err);
goto loop;
}
- mem_heap_free(heap);
-
- return(ret);
+ goto func_exit;
}
/**************************************************************//**
@@ -4995,45 +5102,33 @@ btr_validate_index(
dict_index_t* index, /*!< in: index */
const trx_t* trx) /*!< in: transaction or NULL */
{
- dberr_t err = DB_SUCCESS;
- bool lockout = dict_index_is_spatial(index);
+ /* Full Text index are implemented by auxiliary tables, not the B-tree */
+ if (index->online_status != ONLINE_INDEX_COMPLETE ||
+ (index->type & (DICT_FTS | DICT_CORRUPT)))
+ return DB_SUCCESS;
- /* Full Text index are implemented by auxiliary tables,
- not the B-tree */
- if (dict_index_is_online_ddl(index) || (index->type & DICT_FTS)) {
- return(err);
- }
+ const bool lockout= index->is_spatial();
- mtr_t mtr;
+ mtr_t mtr;
+ mtr.start();
- mtr_start(&mtr);
+ if (lockout)
+ mtr_x_lock_index(index, &mtr);
+ else
+ mtr_sx_lock_index(index, &mtr);
- if (!srv_read_only_mode) {
- if (lockout) {
- mtr_x_lock_index(index, &mtr);
- } else {
- mtr_sx_lock_index(index, &mtr);
- }
- }
+ dberr_t err;
+ if (page_t *root= btr_root_get(index, &mtr, &err))
+ for (auto level= btr_page_get_level(root);; level--)
+ {
+ if (dberr_t err_level= btr_validate_level(index, trx, level, lockout))
+ err= err_level;
+ if (!level)
+ break;
+ }
- page_t* root = btr_root_get(index, &mtr);
-
- if (!root) {
- mtr_commit(&mtr);
- return DB_CORRUPTION;
- }
-
- ulint n = btr_page_get_level(root);
-
- for (ulint i = 0; i <= n; ++i) {
-
- if (!btr_validate_level(index, trx, n - i, lockout)) {
- err = DB_CORRUPTION;
- }
- }
-
- mtr_commit(&mtr);
- return(err);
+ mtr.commit();
+ return err;
}
/**************************************************************//**
@@ -5060,6 +5155,7 @@ btr_can_merge_with_page(
DBUG_ENTER("btr_can_merge_with_page");
if (page_no == FIL_NULL) {
+error:
*merge_block = NULL;
DBUG_RETURN(false);
}
@@ -5069,6 +5165,9 @@ btr_can_merge_with_page(
mblock = btr_block_get(*index, page_no, RW_X_LATCH, page_is_leaf(page),
mtr);
+ if (!mblock) {
+ goto error;
+ }
mpage = buf_block_get_frame(mblock);
n_recs = page_get_n_recs(page);
@@ -5095,8 +5194,8 @@ btr_can_merge_with_page(
if (data_size > max_ins_size) {
/* We have to reorganize mpage */
- if (!btr_page_reorganize_block(page_zip_level, mblock, index,
- mtr)) {
+ if (btr_page_reorganize_block(page_zip_level, mblock, index,
+ mtr) != DB_SUCCESS) {
goto error;
}
@@ -5116,8 +5215,4 @@ btr_can_merge_with_page(
*merge_block = mblock;
DBUG_RETURN(true);
-
-error:
- *merge_block = NULL;
- DBUG_RETURN(false);
}
diff --git a/storage/innobase/btr/btr0bulk.cc b/storage/innobase/btr/btr0bulk.cc
index 263a2f92003..538cb06e654 100644
--- a/storage/innobase/btr/btr0bulk.cc
+++ b/storage/innobase/btr/btr0bulk.cc
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 2014, 2019, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2017, 2021, MariaDB Corporation.
+Copyright (c) 2017, 2022, 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
@@ -61,17 +61,22 @@ PageBulk::init()
m_index->set_modified(alloc_mtr);
uint32_t n_reserved;
- if (!fsp_reserve_free_extents(&n_reserved,
- m_index->table->space,
- 1, FSP_NORMAL, &alloc_mtr)) {
+ dberr_t err = fsp_reserve_free_extents(
+ &n_reserved, m_index->table->space, 1, FSP_NORMAL,
+ &alloc_mtr);
+ if (UNIV_UNLIKELY(err != DB_SUCCESS)) {
+oom:
alloc_mtr.commit();
m_mtr.commit();
- return(DB_OUT_OF_FILE_SPACE);
+ return err;
}
/* Allocate a new page. */
new_block = btr_page_alloc(m_index, 0, FSP_UP, m_level,
- &alloc_mtr, &m_mtr);
+ &alloc_mtr, &m_mtr, &err);
+ if (!new_block) {
+ goto oom;
+ }
m_index->table->space->release_free_extents(n_reserved);
@@ -103,9 +108,12 @@ PageBulk::init()
} else {
new_block = btr_block_get(*m_index, m_page_no, RW_X_LATCH,
false, &m_mtr);
+ if (!new_block) {
+ m_mtr.commit();
+ return(DB_CORRUPTION);
+ }
new_page = buf_block_get_frame(new_block);
- ut_ad(new_block->page.id().page_no() == m_page_no);
ut_ad(page_dir_get_n_heap(new_page) == PAGE_HEAP_NO_USER_LOW);
@@ -820,14 +828,6 @@ PageBulk::storeExt(
dberr_t err = btr_store_big_rec_extern_fields(
&btr_pcur, offsets, big_rec, &m_mtr, BTR_STORE_INSERT_BULK);
- /* Reset m_block and m_cur_rec from page cursor, because
- block may be changed during blob insert. (FIXME: Can it really?) */
- ut_ad(m_block == btr_pcur.btr_cur.page_cur.block);
-
- m_block = btr_pcur.btr_cur.page_cur.block;
- m_cur_rec = btr_pcur.btr_cur.page_cur.rec;
- m_page = buf_block_get_frame(m_block);
-
return(err);
}
@@ -848,38 +848,19 @@ PageBulk::release()
}
/** Start mtr and latch the block */
-dberr_t
-PageBulk::latch()
+void PageBulk::latch()
{
- m_mtr.start();
- m_index->set_modified(m_mtr);
+ m_mtr.start();
+ m_index->set_modified(m_mtr);
+#ifdef BTR_CUR_HASH_ADAPT
+ ut_ad(!m_block->index);
+#endif
+ m_block->page.lock.x_lock();
+ ut_ad(m_block->page.buf_fix_count());
+ m_mtr.memo_push(m_block, MTR_MEMO_PAGE_X_FIX);
- ut_ad(m_block->page.buf_fix_count());
-
- /* In case the block is U-latched by page_cleaner. */
- if (!buf_page_optimistic_get(RW_X_LATCH, m_block, m_modify_clock,
- &m_mtr)) {
- /* FIXME: avoid another lookup */
- m_block = buf_page_get_gen(page_id_t(m_index->table->space_id,
- m_page_no),
- 0, RW_X_LATCH,
- m_block, BUF_GET_IF_IN_POOL,
- &m_mtr, &m_err);
-
- if (m_err != DB_SUCCESS) {
- return (m_err);
- }
-
- ut_ad(m_block != NULL);
- }
-
- ut_d(const auto buf_fix_count =) m_block->page.unfix();
-
- ut_ad(buf_fix_count);
- ut_ad(m_cur_rec > m_page);
- ut_ad(m_cur_rec < m_heap_top);
-
- return (m_err);
+ ut_ad(m_cur_rec > m_page);
+ ut_ad(m_cur_rec < m_heap_top);
}
/** Split a page
@@ -1207,6 +1188,13 @@ BtrBulk::finish(dberr_t err)
ut_ad(last_page_no != FIL_NULL);
last_block = btr_block_get(*m_index, last_page_no, RW_X_LATCH,
false, &mtr);
+ if (!last_block) {
+ err = DB_CORRUPTION;
+err_exit:
+ mtr.commit();
+ return err;
+ }
+
first_rec = page_rec_get_next(
page_get_infimum_rec(last_block->page.frame));
ut_ad(page_rec_is_user_rec(first_rec));
@@ -1214,18 +1202,18 @@ BtrBulk::finish(dberr_t err)
/* Copy last page to root page. */
err = root_page_bulk.init();
if (err != DB_SUCCESS) {
- mtr.commit();
- return(err);
+ goto err_exit;
}
root_page_bulk.copyIn(first_rec);
root_page_bulk.finish();
/* Remove last page. */
- btr_page_free(m_index, last_block, &mtr);
-
+ err = btr_page_free(m_index, last_block, &mtr);
mtr.commit();
- err = pageCommit(&root_page_bulk, NULL, false);
+ if (dberr_t e = pageCommit(&root_page_bulk, NULL, false)) {
+ err = e;
+ }
ut_ad(err == DB_SUCCESS);
}
diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc
index c55e50ca32a..3dfeb4aa060 100644
--- a/storage/innobase/btr/btr0cur.cc
+++ b/storage/innobase/btr/btr0cur.cc
@@ -202,177 +202,157 @@ btr_rec_free_externally_stored_fields(
@param[in] latch_mode BTR_SEARCH_LEAF, ...
@param[in] cursor cursor
@param[in] mtr mini-transaction
-@return blocks and savepoints which actually latched. */
-btr_latch_leaves_t
+@param[out] latch_leaves latched blocks and savepoints */
+void
btr_cur_latch_leaves(
buf_block_t* block,
ulint latch_mode,
btr_cur_t* cursor,
- mtr_t* mtr)
+ mtr_t* mtr,
+ btr_latch_leaves_t* latch_leaves)
{
- rw_lock_type_t mode;
- uint32_t left_page_no;
- uint32_t right_page_no;
- buf_block_t* get_block;
- bool spatial;
- btr_latch_leaves_t latch_leaves = {{NULL, NULL, NULL}, {0, 0, 0}};
-
compile_time_assert(int(MTR_MEMO_PAGE_S_FIX) == int(RW_S_LATCH));
compile_time_assert(int(MTR_MEMO_PAGE_X_FIX) == int(RW_X_LATCH));
compile_time_assert(int(MTR_MEMO_PAGE_SX_FIX) == int(RW_SX_LATCH));
ut_ad(block->page.id().space() == cursor->index->table->space->id);
-
- spatial = dict_index_is_spatial(cursor->index) && cursor->rtr_info;
ut_ad(block->page.in_file());
ut_ad(srv_read_only_mode
|| mtr->memo_contains_flagged(&cursor->index->lock,
MTR_MEMO_S_LOCK
| MTR_MEMO_X_LOCK
| MTR_MEMO_SX_LOCK));
+ auto rtr_info = cursor->rtr_info;
+ if (UNIV_LIKELY_NULL(rtr_info) && !cursor->index->is_spatial()) {
+ rtr_info = nullptr;
+ }
+
+ const rw_lock_type_t mode = rw_lock_type_t(
+ latch_mode & (RW_X_LATCH | RW_S_LATCH));
+ static_assert(ulint{RW_S_LATCH} == ulint{BTR_SEARCH_LEAF}, "");
+ static_assert(ulint{RW_X_LATCH} == ulint{BTR_MODIFY_LEAF}, "");
+ static_assert(BTR_SEARCH_LEAF & BTR_SEARCH_TREE, "");
switch (latch_mode) {
+ uint32_t left_page_no;
+ uint32_t right_page_no;
+ ulint save;
case BTR_SEARCH_LEAF:
case BTR_MODIFY_LEAF:
case BTR_SEARCH_TREE:
- if (spatial) {
- cursor->rtr_info->tree_savepoints[RTR_MAX_LEVELS]
- = mtr_set_savepoint(mtr);
+ if (UNIV_LIKELY_NULL(rtr_info)) {
+ rtr_info->tree_savepoints[RTR_MAX_LEVELS]
+ = mtr->get_savepoint();
}
-
- mode = latch_mode == BTR_MODIFY_LEAF ? RW_X_LATCH : RW_S_LATCH;
- latch_leaves.savepoints[1] = mtr_set_savepoint(mtr);
- get_block = btr_block_get(*cursor->index,
- block->page.id().page_no(), mode,
- true, mtr);
- latch_leaves.blocks[1] = get_block;
-#ifdef UNIV_BTR_DEBUG
- ut_a(page_is_comp(get_block->page.frame)
- == page_is_comp(block->page.frame));
-#endif /* UNIV_BTR_DEBUG */
- if (spatial) {
- cursor->rtr_info->tree_blocks[RTR_MAX_LEVELS]
- = get_block;
+latch_block:
+ if (latch_leaves) {
+ latch_leaves->savepoints[1] = mtr->get_savepoint();
+ latch_leaves->blocks[1] = block;
}
-
- return(latch_leaves);
+ block->page.fix();
+ mtr->page_lock(block, mode);
+ if (UNIV_LIKELY_NULL(rtr_info)) {
+ rtr_info->tree_blocks[RTR_MAX_LEVELS] = block;
+ }
+ return;
case BTR_MODIFY_TREE:
/* It is exclusive for other operations which calls
btr_page_set_prev() */
ut_ad(mtr->memo_contains_flagged(&cursor->index->lock,
MTR_MEMO_X_LOCK
| MTR_MEMO_SX_LOCK));
+ save = mtr->get_savepoint();
/* x-latch also siblings from left to right */
left_page_no = btr_page_get_prev(block->page.frame);
if (left_page_no != FIL_NULL) {
-
- if (spatial) {
- cursor->rtr_info->tree_savepoints[
- RTR_MAX_LEVELS] = mtr_set_savepoint(mtr);
- }
-
- latch_leaves.savepoints[0] = mtr_set_savepoint(mtr);
- get_block = btr_block_get(
+ buf_block_t *b = btr_block_get(
*cursor->index, left_page_no, RW_X_LATCH,
true, mtr);
- latch_leaves.blocks[0] = get_block;
- if (spatial) {
- cursor->rtr_info->tree_blocks[RTR_MAX_LEVELS]
- = get_block;
+ if (latch_leaves) {
+ latch_leaves->savepoints[0] = save;
+ latch_leaves->blocks[0] = b;
}
+
+ if (UNIV_LIKELY_NULL(rtr_info)) {
+ rtr_info->tree_savepoints[RTR_MAX_LEVELS]
+ = save;
+ rtr_info->tree_blocks[RTR_MAX_LEVELS] = b;
+ }
+
+ save = mtr->get_savepoint();
}
- if (spatial) {
- cursor->rtr_info->tree_savepoints[RTR_MAX_LEVELS + 1]
- = mtr_set_savepoint(mtr);
+ if (latch_leaves) {
+ latch_leaves->savepoints[1] = mtr->get_savepoint();
+ latch_leaves->blocks[1] = block;
}
- latch_leaves.savepoints[1] = mtr_set_savepoint(mtr);
- get_block = btr_block_get(
- *cursor->index, block->page.id().page_no(),
- RW_X_LATCH, true, mtr);
- latch_leaves.blocks[1] = get_block;
+ mtr->memo_push(block, MTR_MEMO_PAGE_X_FIX);
-#ifdef UNIV_BTR_DEBUG
- ut_a(page_is_comp(get_block->page.frame)
- == page_is_comp(block->page.frame));
-#endif /* UNIV_BTR_DEBUG */
+ block->page.fix();
+ block->page.lock.x_lock();
+#ifdef BTR_CUR_HASH_ADAPT
+ ut_ad(!block->index || !block->index->freed());
+#endif
- if (spatial) {
- cursor->rtr_info->tree_blocks[RTR_MAX_LEVELS + 1]
- = get_block;
+ if (UNIV_LIKELY_NULL(rtr_info)) {
+ rtr_info->tree_savepoints[RTR_MAX_LEVELS + 1] = save;
+ rtr_info->tree_blocks[RTR_MAX_LEVELS + 1] = block;
}
right_page_no = btr_page_get_next(block->page.frame);
if (right_page_no != FIL_NULL) {
- if (spatial) {
- cursor->rtr_info->tree_savepoints[
- RTR_MAX_LEVELS + 2] = mtr_set_savepoint(
- mtr);
+ save = mtr->get_savepoint();
+
+ buf_block_t* b = btr_block_get(
+ *cursor->index, right_page_no, RW_X_LATCH,
+ true, mtr);
+ if (latch_leaves) {
+ latch_leaves->savepoints[2] = save;
+ latch_leaves->blocks[2] = b;
}
- latch_leaves.savepoints[2] = mtr_set_savepoint(mtr);
- get_block = btr_block_get(*cursor->index,
- right_page_no, RW_X_LATCH,
- true, mtr);
- latch_leaves.blocks[2] = get_block;
-#ifdef UNIV_BTR_DEBUG
- if (get_block) {
- ut_a(page_is_comp(get_block->page.frame)
- == page_is_comp(block->page.frame));
- ut_a(btr_page_get_prev(get_block->page.frame)
- == block->page.id().page_no());
- }
-#endif /* UNIV_BTR_DEBUG */
- if (spatial) {
- cursor->rtr_info->tree_blocks[
- RTR_MAX_LEVELS + 2] = get_block;
+
+ if (UNIV_LIKELY_NULL(rtr_info)) {
+ rtr_info->tree_savepoints[RTR_MAX_LEVELS + 2]
+ = save;
+ rtr_info->tree_blocks[RTR_MAX_LEVELS + 2] = b;
}
}
- return(latch_leaves);
+ return;
case BTR_SEARCH_PREV:
case BTR_MODIFY_PREV:
- mode = latch_mode == BTR_SEARCH_PREV ? RW_S_LATCH : RW_X_LATCH;
+ ut_ad(!rtr_info);
+ static_assert(BTR_SEARCH_PREV & BTR_SEARCH_LEAF, "");
+ static_assert(BTR_MODIFY_PREV & BTR_MODIFY_LEAF, "");
+ static_assert((BTR_SEARCH_PREV ^ BTR_MODIFY_PREV)
+ == (RW_S_LATCH ^ RW_X_LATCH), "");
+
/* Because we are holding index->lock, no page splits
or merges may run concurrently, and we may read
FIL_PAGE_PREV from a buffer-fixed, unlatched page. */
left_page_no = btr_page_get_prev(block->page.frame);
if (left_page_no != FIL_NULL) {
- latch_leaves.savepoints[0] = mtr_set_savepoint(mtr);
- get_block = btr_block_get(
- *cursor->index, left_page_no, mode,
- true, mtr);
- latch_leaves.blocks[0] = get_block;
- cursor->left_block = get_block;
-#ifdef UNIV_BTR_DEBUG
- ut_a(page_is_comp(get_block->page.frame)
- == page_is_comp(block->page.frame));
- ut_a(btr_page_get_next(get_block->page.frame)
- == block->page.id().page_no());
-#endif /* UNIV_BTR_DEBUG */
+ save = mtr->get_savepoint();
+ cursor->left_block = btr_block_get(
+ *cursor->index, left_page_no, mode, true, mtr);
+ if (latch_leaves) {
+ latch_leaves->savepoints[0] = save;
+ latch_leaves->blocks[0] = cursor->left_block;
+ }
}
- latch_leaves.savepoints[1] = mtr_set_savepoint(mtr);
- get_block = btr_block_get(*cursor->index,
- block->page.id().page_no(), mode,
- true, mtr);
- latch_leaves.blocks[1] = get_block;
-#ifdef UNIV_BTR_DEBUG
- ut_a(page_is_comp(get_block->page.frame)
- == page_is_comp(block->page.frame));
-#endif /* UNIV_BTR_DEBUG */
- return(latch_leaves);
+ goto latch_block;
case BTR_CONT_MODIFY_TREE:
- ut_ad(dict_index_is_spatial(cursor->index));
- return(latch_leaves);
+ ut_ad(cursor->index->is_spatial());
+ return;
}
- ut_error;
- return(latch_leaves);
+ MY_ASSERT_UNREACHABLE();
}
/** Load the instant ALTER TABLE metadata from the clustered index
@@ -389,21 +369,28 @@ static dberr_t btr_cur_instant_init_low(dict_index_t* index, mtr_t* mtr)
ut_ad(index->table->supports_instant());
ut_ad(index->table->is_readable());
+ dberr_t err;
const fil_space_t* space = index->table->space;
if (!space) {
+corrupted:
+ err = DB_CORRUPTION;
unreadable:
ib::error() << "Table " << index->table->name
<< " has an unreadable root page";
index->table->corrupted = true;
- return DB_CORRUPTION;
+ index->table->file_unreadable = true;
+ return err;
}
- buf_block_t* root = btr_root_block_get(index, RW_SX_LATCH, mtr);
-
- if (!root || btr_cur_instant_root_init(index, root->page.frame)) {
+ buf_block_t* root = btr_root_block_get(index, RW_SX_LATCH, mtr, &err);
+ if (!root) {
goto unreadable;
}
+ if (btr_cur_instant_root_init(index, root->page.frame)) {
+ goto corrupted;
+ }
+
ut_ad(index->n_core_null_bytes != dict_index_t::NO_CORE_NULL_BYTES);
if (fil_page_get_type(root->page.frame) == FIL_PAGE_INDEX) {
@@ -415,8 +402,8 @@ unreadable:
/* Relax the assertion in rec_init_offsets(). */
ut_ad(!index->in_instant_init);
ut_d(index->in_instant_init = true);
- dberr_t err = btr_cur_open_at_index_side(true, index, BTR_SEARCH_LEAF,
- &cur, 0, mtr);
+ err = btr_cur_open_at_index_side(true, index, BTR_SEARCH_LEAF,
+ &cur, 0, mtr);
ut_d(index->in_instant_init = false);
if (err != DB_SUCCESS) {
index->table->corrupted = true;
@@ -549,6 +536,10 @@ incompatible:
page_id_t(space->id,
mach_read_from_4(ptr + BTR_EXTERN_PAGE_NO)),
0, RW_S_LATCH, mtr);
+ if (!block) {
+ goto incompatible;
+ }
+
if (fil_page_get_type(block->page.frame) != FIL_PAGE_TYPE_BLOB
|| mach_read_from_4(&block->page.frame
[FIL_PAGE_DATA
@@ -667,14 +658,14 @@ index root page.
bool btr_cur_instant_root_init(dict_index_t* index, const page_t* page)
{
ut_ad(!index->is_dummy);
- ut_ad(fil_page_index_page_check(page));
- ut_ad(!page_has_siblings(page));
- ut_ad(page_get_space_id(page) == index->table->space_id);
- ut_ad(page_get_page_no(page) == index->page);
- ut_ad(!page_is_comp(page) == !dict_table_is_comp(index->table));
ut_ad(index->is_primary());
ut_ad(!index->is_instant());
ut_ad(index->table->supports_instant());
+
+ if (page_has_siblings(page)) {
+ return true;
+ }
+
/* This is normally executed as part of btr_cur_instant_init()
when dict_load_table_one() is loading a table definition.
Other threads should not access or modify the n_core_null_bytes,
@@ -685,13 +676,14 @@ bool btr_cur_instant_root_init(dict_index_t* index, const page_t* page)
switch (fil_page_get_type(page)) {
default:
- ut_ad("wrong page type" == 0);
return true;
case FIL_PAGE_INDEX:
/* The field PAGE_INSTANT is guaranteed 0 on clustered
index root pages of ROW_FORMAT=COMPACT or
ROW_FORMAT=DYNAMIC when instant ADD COLUMN is not used. */
- ut_ad(!page_is_comp(page) || !page_get_instant(page));
+ if (page_is_comp(page) && page_get_instant(page)) {
+ return true;
+ }
index->n_core_null_bytes = static_cast(
UT_BITS_IN_BYTES(unsigned(index->n_nullable)));
return false;
@@ -768,7 +760,7 @@ btr_cur_optimistic_latch_leaves(
switch (*latch_mode) {
default:
- ut_error;
+ MY_ASSERT_UNREACHABLE();
return(false);
case BTR_SEARCH_LEAF:
case BTR_MODIFY_LEAF:
@@ -787,31 +779,32 @@ btr_cur_optimistic_latch_leaves(
left_page_no = btr_page_get_prev(block->page.frame);
}
- const rw_lock_type_t mode = *latch_mode == BTR_SEARCH_PREV
- ? RW_S_LATCH : RW_X_LATCH;
+ static_assert(BTR_SEARCH_PREV & BTR_SEARCH_LEAF, "");
+ static_assert(BTR_MODIFY_PREV & BTR_MODIFY_LEAF, "");
+ static_assert((BTR_SEARCH_PREV ^ BTR_MODIFY_PREV)
+ == (RW_S_LATCH ^ RW_X_LATCH), "");
+
+ const rw_lock_type_t mode = rw_lock_type_t(
+ *latch_mode & (RW_X_LATCH | RW_S_LATCH));
if (left_page_no != FIL_NULL) {
- dberr_t err = DB_SUCCESS;
cursor->left_block = buf_page_get_gen(
page_id_t(cursor->index->table->space_id,
left_page_no),
cursor->index->table->space->zip_size(),
- mode, nullptr, BUF_GET_POSSIBLY_FREED,
- mtr, &err);
+ mode, nullptr, BUF_GET_POSSIBLY_FREED, mtr);
- if (!cursor->left_block) {
- cursor->index->table->file_unreadable = true;
- } else if (cursor->left_block->page.is_freed()
- || btr_page_get_next(
- cursor->left_block->page.frame)
- != curr_page_no) {
+ if (cursor->left_block
+ && btr_page_get_next(
+ cursor->left_block->page.frame)
+ != curr_page_no) {
/* release the left block */
btr_leaf_page_release(
cursor->left_block, mode, mtr);
return false;
}
} else {
- cursor->left_block = NULL;
+ cursor->left_block = nullptr;
}
if (buf_page_optimistic_get(mode, block, modify_clock, mtr)) {
@@ -833,10 +826,8 @@ btr_cur_optimistic_latch_leaves(
}
ut_ad(block->page.buf_fix_count());
- /* release the left block */
- if (cursor->left_block != NULL) {
- btr_leaf_page_release(cursor->left_block,
- mode, mtr);
+ if (cursor->left_block) {
+ btr_leaf_page_release(cursor->left_block, mode, mtr);
}
}
@@ -899,7 +890,7 @@ btr_cur_latch_for_root_leaf(
return(RW_NO_LATCH);
}
- ut_error;
+ MY_ASSERT_UNREACHABLE();
return(RW_NO_LATCH); /* avoid compiler warnings */
}
@@ -1062,7 +1053,7 @@ btr_cur_need_opposite_intention(
return(false);
}
- ut_error;
+ MY_ASSERT_UNREACHABLE();
return(false);
}
@@ -1264,7 +1255,6 @@ btr_cur_search_to_nth_level_func(
page_cur_t* page_cursor;
btr_op_t btr_op;
ulint root_height = 0; /* remove warning */
- dberr_t err = DB_SUCCESS;
btr_intention_t lock_intention;
bool modify_external;
@@ -1328,10 +1318,8 @@ btr_cur_search_to_nth_level_func(
/* These flags are mutually exclusive, they are lumped together
with the latch mode for historical reasons. It's possible for
none of the flags to be set. */
- switch (UNIV_EXPECT(latch_mode
- & (BTR_INSERT | BTR_DELETE | BTR_DELETE_MARK),
- 0)) {
- case 0:
+ switch (UNIV_EXPECT(latch_mode & BTR_DELETE, 0)) {
+ default:
btr_op = BTR_NO_OP;
break;
case BTR_INSERT:
@@ -1346,10 +1334,6 @@ btr_cur_search_to_nth_level_func(
case BTR_DELETE_MARK:
btr_op = BTR_DELMARK_OP;
break;
- default:
- /* only one of BTR_INSERT, BTR_DELETE, BTR_DELETE_MARK
- should be specified at a time */
- ut_error;
}
/* Operations on the insert buffer tree cannot be buffered. */
@@ -1426,7 +1410,7 @@ btr_cur_search_to_nth_level_func(
|| mode != PAGE_CUR_LE);
++btr_cur_n_sea;
- DBUG_RETURN(err);
+ DBUG_RETURN(DB_SUCCESS);
} else {
++btr_cur_n_non_sea;
}
@@ -1599,30 +1583,24 @@ search_loop:
retry_page_get:
ut_ad(n_blocks < BTR_MAX_LEVELS);
tree_savepoints[n_blocks] = mtr_set_savepoint(mtr);
+ dberr_t err;
block = buf_page_get_gen(page_id, zip_size, rw_latch, guess,
buf_mode, mtr, &err,
height == 0 && !index->is_clust());
tree_blocks[n_blocks] = block;
- /* Note that block==NULL signifies either an error or change
- buffering. */
-
- if (err != DB_SUCCESS) {
- ut_ad(block == NULL);
- if (err == DB_DECRYPTION_FAILED) {
- ib_push_warning((void *)NULL,
- DB_DECRYPTION_FAILED,
- "Table %s is encrypted but encryption service or"
- " used key_id is not available. "
- " Can't continue reading table.",
- index->table->name.m_name);
- index->table->file_unreadable = true;
+ if (!block) {
+ switch (err) {
+ case DB_SUCCESS:
+ /* change buffering */
+ break;
+ case DB_DECRYPTION_FAILED:
+ btr_decryption_failed(*index);
+ /* fall through */
+ default:
+ goto func_exit;
}
- goto func_exit;
- }
-
- if (block == NULL) {
/* This must be a search to perform an insert/delete
mark/ delete; try using the insert/delete buffer */
@@ -1631,7 +1609,7 @@ retry_page_get:
switch (btr_op) {
default:
- ut_error;
+ MY_ASSERT_UNREACHABLE();
break;
case BTR_INSERT_OP:
case BTR_INSERT_IGNORE_UNIQUE_OP:
@@ -1722,15 +1700,9 @@ retry_page_get:
prev_tree_blocks[prev_n_blocks] = get_block;
prev_n_blocks++;
- if (err != DB_SUCCESS) {
+ if (!get_block) {
if (err == DB_DECRYPTION_FAILED) {
- ib_push_warning((void *)NULL,
- DB_DECRYPTION_FAILED,
- "Table %s is encrypted but encryption service or"
- " used key_id is not available. "
- " Can't continue reading table.",
- index->table->name.m_name);
- index->table->file_unreadable = true;
+ btr_decryption_failed(*index);
}
goto func_exit;
@@ -1751,15 +1723,9 @@ retry_page_get:
rw_latch, NULL, buf_mode, mtr, &err);
tree_blocks[n_blocks] = block;
- if (err != DB_SUCCESS) {
+ if (!block) {
if (err == DB_DECRYPTION_FAILED) {
- ib_push_warning((void *)NULL,
- DB_DECRYPTION_FAILED,
- "Table %s is encrypted but encryption service or"
- " used key_id is not available. "
- " Can't continue reading table.",
- index->table->name.m_name);
- index->table->file_unreadable = true;
+ btr_decryption_failed(*index);
}
goto func_exit;
@@ -1829,8 +1795,8 @@ retry_page_get:
if (height == 0) {
if (rw_latch == RW_NO_LATCH) {
- latch_leaves = btr_cur_latch_leaves(
- block, latch_mode, cursor, mtr);
+ btr_cur_latch_leaves(block, latch_mode, cursor, mtr,
+ &latch_leaves);
}
switch (latch_mode) {
@@ -1941,17 +1907,18 @@ retry_page_get:
/* Need to use BTR_MODIFY_TREE to do the MBR adjustment */
if (search_mode == PAGE_CUR_RTREE_INSERT
&& cursor->rtr_info->mbr_adj) {
- if (latch_mode & BTR_MODIFY_LEAF) {
+ static_assert(BTR_MODIFY_TREE
+ == (8 | BTR_MODIFY_LEAF), "");
+
+ if (!(latch_mode & 8)) {
/* Parent MBR needs updated, should retry
with BTR_MODIFY_TREE */
goto func_exit;
- } else if (latch_mode & BTR_MODIFY_TREE) {
- rtree_parent_modified = true;
- cursor->rtr_info->mbr_adj = false;
- mbr_adj = true;
- } else {
- ut_ad(0);
}
+
+ rtree_parent_modified = true;
+ cursor->rtr_info->mbr_adj = false;
+ mbr_adj = true;
}
if (found && page_mode == PAGE_CUR_RTREE_GET_FATHER) {
@@ -2386,15 +2353,13 @@ need_opposite_intention:
if (upper_rw_latch == RW_NO_LATCH) {
ut_ad(latch_mode == BTR_CONT_MODIFY_TREE
|| latch_mode == BTR_CONT_SEARCH_TREE);
- buf_block_t* child_block = btr_block_get(
+ btr_block_get(
*index, page_id.page_no(),
latch_mode == BTR_CONT_MODIFY_TREE
- ? RW_X_LATCH : RW_SX_LATCH, false, mtr);
- btr_assert_not_corrupted(child_block, index);
+ ? RW_X_LATCH : RW_SX_LATCH, false, mtr, &err);
} else {
ut_ad(mtr->memo_contains_flagged(block,
upper_rw_latch));
- btr_assert_not_corrupted(block, index);
if (s_latch_by_caller) {
ut_ad(latch_mode == BTR_SEARCH_TREE);
@@ -2522,7 +2487,7 @@ btr_cur_open_at_index_side(
mem_heap_t* heap = NULL;
rec_offs offsets_[REC_OFFS_NORMAL_SIZE];
rec_offs* offsets = offsets_;
- dberr_t err = DB_SUCCESS;
+ dberr_t err;
rec_offs_init(offsets_);
@@ -2622,15 +2587,9 @@ btr_cur_open_at_index_side(
ut_ad((block != NULL) == (err == DB_SUCCESS));
tree_blocks[n_blocks] = block;
- if (err != DB_SUCCESS) {
+ if (!block) {
if (err == DB_DECRYPTION_FAILED) {
- ib_push_warning((void *)NULL,
- DB_DECRYPTION_FAILED,
- "Table %s is encrypted but encryption service or"
- " used key_id is not available. "
- " Can't continue reading table.",
- index->table->name.m_name);
- index->table->file_unreadable = true;
+ btr_decryption_failed(*index);
}
goto exit_loop;
@@ -2936,7 +2895,7 @@ btr_cur_open_at_rnd_pos(
page_id_t page_id(index->table->space_id, index->page);
const ulint zip_size = index->table->space->zip_size();
- dberr_t err = DB_SUCCESS;
+ dberr_t err;
if (root_leaf_rw_latch == RW_X_LATCH) {
node_ptr_max_size = btr_node_ptr_max_size(index);
@@ -2962,15 +2921,9 @@ btr_cur_open_at_rnd_pos(
ut_ad((block != NULL) == (err == DB_SUCCESS));
- if (err != DB_SUCCESS) {
+ if (!block) {
if (err == DB_DECRYPTION_FAILED) {
- ib_push_warning((void *)NULL,
- DB_DECRYPTION_FAILED,
- "Table %s is encrypted but encryption service or"
- " used key_id is not available. "
- " Can't continue reading table.",
- index->table->name.m_name);
- index->table->file_unreadable = true;
+ btr_decryption_failed(*index);
}
break;
@@ -3012,7 +2965,7 @@ btr_cur_open_at_rnd_pos(
mtr);
}
- /* btr_cur_open_at_index_side_func() and
+ /* btr_cur_open_at_index_side() and
btr_cur_search_to_nth_level() release
tree s-latch here.*/
switch (latch_mode) {
@@ -3180,7 +3133,8 @@ btr_cur_insert_if_possible(
For compressed pages, page_cur_tuple_insert()
attempted this already. */
if (!rec && !page_cur_get_page_zip(page_cursor)
- && btr_page_reorganize(page_cursor, cursor->index, mtr)) {
+ && btr_page_reorganize(page_cursor, cursor->index, mtr)
+ == DB_SUCCESS) {
rec = page_cur_tuple_insert(
page_cursor, tuple, cursor->index,
offsets, heap, n_ext, mtr);
@@ -3505,7 +3459,8 @@ fail_err:
<< ' ' << rec_printer(entry).str());
DBUG_EXECUTE_IF("do_page_reorganize",
if (n_recs)
- btr_page_reorganize(page_cursor, index, mtr););
+ ut_a(btr_page_reorganize(page_cursor, index, mtr)
+ == DB_SUCCESS););
/* Now, try the insert */
{
@@ -3568,25 +3523,17 @@ fail_err:
goto fail;
} else {
ut_ad(!reorg);
+ reorg = true;
/* If the record did not fit, reorganize */
- if (!btr_page_reorganize(page_cursor, index, mtr)) {
- ut_ad(0);
- goto fail;
- }
-
- ut_ad(page_get_max_insert_size(page, 1) == max_size);
-
- reorg = TRUE;
-
- *rec = page_cur_tuple_insert(page_cursor, entry, index,
- offsets, heap, n_ext, mtr);
-
- if (UNIV_UNLIKELY(!*rec)) {
- ib::fatal() << "Cannot insert tuple " << *entry
- << "into index " << index->name
- << " of table " << index->table->name
- << ". Max size: " << max_size;
+ err = btr_page_reorganize(page_cursor, index, mtr);
+ if (err != DB_SUCCESS
+ || page_get_max_insert_size(page, 1) != max_size
+ || !(*rec = page_cur_tuple_insert(page_cursor, entry, index,
+ offsets, heap, n_ext,
+ mtr))) {
+ err = DB_CORRUPTION;
+ goto fail_err;
}
}
@@ -3680,9 +3627,7 @@ btr_cur_pessimistic_insert(
{
dict_index_t* index = cursor->index;
big_rec_t* big_rec_vec = NULL;
- dberr_t err;
bool inherit = false;
- bool success;
uint32_t n_reserved = 0;
ut_ad(dtuple_check_typed(entry));
@@ -3702,27 +3647,24 @@ btr_cur_pessimistic_insert(
/* Check locks and write to undo log, if specified */
- err = btr_cur_ins_lock_and_undo(flags, cursor, entry,
- thr, mtr, &inherit);
+ dberr_t err = btr_cur_ins_lock_and_undo(flags, cursor, entry,
+ thr, mtr, &inherit);
if (err != DB_SUCCESS) {
-
return(err);
}
- if (!(flags & BTR_NO_UNDO_LOG_FLAG)) {
- /* First reserve enough free space for the file segments
- of the index tree, so that the insert will not fail because
- of lack of space */
+ /* First reserve enough free space for the file segments of
+ the index tree, so that the insert will not fail because of
+ lack of space */
- uint32_t n_extents = uint32_t(cursor->tree_height / 16 + 3);
-
- success = fsp_reserve_free_extents(&n_reserved,
- index->table->space,
- n_extents, FSP_NORMAL, mtr);
- if (!success) {
- return(DB_OUT_OF_FILE_SPACE);
- }
+ if (!index->is_ibuf()
+ && (err = fsp_reserve_free_extents(&n_reserved, index->table->space,
+ uint32_t(cursor->tree_height / 16
+ + 3),
+ FSP_NORMAL, mtr))
+ != DB_SUCCESS) {
+ return err;
}
if (page_zip_rec_needs_ext(rec_get_converted_size(index, entry, n_ext),
@@ -3753,19 +3695,14 @@ btr_cur_pessimistic_insert(
}
}
- if (dict_index_get_page(index)
- == btr_cur_get_block(cursor)->page.id().page_no()) {
+ *rec = index->page == btr_cur_get_block(cursor)->page.id().page_no()
+ ? btr_root_raise_and_insert(flags, cursor, offsets, heap,
+ entry, n_ext, mtr, &err)
+ : btr_page_split_and_insert(flags, cursor, offsets, heap,
+ entry, n_ext, mtr, &err);
- /* The page is the root page */
- *rec = btr_root_raise_and_insert(
- flags, cursor, offsets, heap, entry, n_ext, mtr);
- } else {
- *rec = btr_page_split_and_insert(
- flags, cursor, offsets, heap, entry, n_ext, mtr);
- }
-
- if (*rec == NULL && os_has_said_disk_full) {
- return(DB_OUT_OF_FILE_SPACE);
+ if (!*rec) {
+ goto func_exit;
}
ut_ad(page_rec_get_next(btr_cur_get_rec(cursor)) == *rec
@@ -3816,10 +3753,12 @@ btr_cur_pessimistic_insert(
}
}
+ err = DB_SUCCESS;
+func_exit:
index->table->space->release_free_extents(n_reserved);
*big_rec = big_rec_vec;
- return(DB_SUCCESS);
+ return err;
}
/*==================== B-TREE UPDATE =========================*/
@@ -4048,32 +3987,26 @@ btr_cur_update_alloc_zip_func(
return(false);
}
- if (!btr_page_reorganize(cursor, index, mtr)) {
- goto out_of_space;
+ if (btr_page_reorganize(cursor, index, mtr) == DB_SUCCESS) {
+ rec_offs_make_valid(page_cur_get_rec(cursor), index,
+ page_is_leaf(page), offsets);
+
+ /* After recompressing a page, we must make sure that the free
+ bits in the insert buffer bitmap will not exceed the free
+ space on the page. Because this function will not attempt
+ recompression unless page_zip_available() fails above, it is
+ safe to reset the free bits if page_zip_available() fails
+ again, below. The free bits can safely be reset in a separate
+ mini-transaction. If page_zip_available() succeeds below, we
+ can be sure that the btr_page_reorganize() above did not reduce
+ the free space available on the page. */
+
+ if (page_zip_available(page_zip, dict_index_is_clust(index),
+ length, create)) {
+ return true;
+ }
}
- rec_offs_make_valid(page_cur_get_rec(cursor), index,
- page_is_leaf(page), offsets);
-
- /* After recompressing a page, we must make sure that the free
- bits in the insert buffer bitmap will not exceed the free
- space on the page. Because this function will not attempt
- recompression unless page_zip_available() fails above, it is
- safe to reset the free bits if page_zip_available() fails
- again, below. The free bits can safely be reset in a separate
- mini-transaction. If page_zip_available() succeeds below, we
- can be sure that the btr_page_reorganize() above did not reduce
- the free space available on the page. */
-
- if (page_zip_available(page_zip, dict_index_is_clust(index),
- length, create)) {
- return(true);
- }
-
-out_of_space:
- ut_ad(rec_offs_validate(page_cur_get_rec(cursor), index, offsets));
-
- /* Out of space: reset the free bits. */
if (!dict_index_is_clust(index)
&& !index->table->is_temporary()
&& page_is_leaf(page)) {
@@ -4422,6 +4355,11 @@ static void btr_cur_trim_alter_metadata(dtuple_t* entry,
page_id_t(index->table->space->id,
mach_read_from_4(ptr + BTR_EXTERN_PAGE_NO)),
0, RW_S_LATCH, &mtr);
+ if (!block) {
+ ut_ad("corruption" == 0);
+ mtr.commit();
+ return;
+ }
ut_ad(fil_page_get_type(block->page.frame) == FIL_PAGE_TYPE_BLOB);
ut_ad(mach_read_from_4(&block->page.frame
[FIL_PAGE_DATA + BTR_BLOB_HDR_NEXT_PAGE_NO])
@@ -4671,7 +4609,6 @@ any_extern:
(!dict_table_is_comp(index->table)
&& new_rec_size >= REDUNDANT_REC_MAX_DATA_SIZE)) {
err = DB_OVERFLOW;
-
goto func_exit;
}
@@ -4762,17 +4699,22 @@ any_extern:
btr_cur_write_sys(new_entry, index, trx_id, roll_ptr);
}
- /* There are no externally stored columns in new_entry */
- rec = btr_cur_insert_if_possible(
- cursor, new_entry, offsets, heap, 0/*n_ext*/, mtr);
- ut_a(rec); /* <- We calculated above the insert would fit */
+ rec = btr_cur_insert_if_possible(cursor, new_entry, offsets, heap,
+ 0/*n_ext*/, mtr);
+ if (UNIV_UNLIKELY(!rec)) {
+ err = DB_CORRUPTION;
+ goto func_exit;
+ }
if (UNIV_UNLIKELY(update->is_metadata())) {
/* We must empty the PAGE_FREE list, because if this
was a rollback, the shortened metadata record
would have too many fields, and we would be unable to
know the size of the freed record. */
- btr_page_reorganize(page_cursor, index, mtr);
+ err = btr_page_reorganize(page_cursor, index, mtr);
+ if (err != DB_SUCCESS) {
+ goto func_exit;
+ }
} else {
/* Restore the old explicit lock state on the record */
lock_rec_restore_from_page_infimum(*block, rec,
@@ -4810,7 +4752,7 @@ updated record. In the split it may have inherited locks from the successor
of the updated record, which is not correct. This function restores the
right locks for the new supremum. */
static
-void
+dberr_t
btr_cur_pess_upd_restore_supremum(
/*==============================*/
buf_block_t* block, /*!< in: buffer block of rec */
@@ -4818,28 +4760,30 @@ btr_cur_pess_upd_restore_supremum(
mtr_t* mtr) /*!< in: mtr */
{
page_t* page;
- buf_block_t* prev_block;
page = buf_block_get_frame(block);
if (page_rec_get_next(page_get_infimum_rec(page)) != rec) {
/* Updated record is not the first user record on its page */
-
- return;
+ return DB_SUCCESS;
}
const uint32_t prev_page_no = btr_page_get_prev(page);
const page_id_t block_id{block->page.id()};
const page_id_t prev_id(block_id.space(), prev_page_no);
-
- ut_ad(prev_page_no != FIL_NULL);
- prev_block = buf_page_get_with_no_latch(prev_id, block->zip_size(),
- mtr);
-#ifdef UNIV_BTR_DEBUG
- ut_a(btr_page_get_next(prev_block->page.frame)
- == block->page.id().page_no());
-#endif /* UNIV_BTR_DEBUG */
+ dberr_t err;
+ buf_block_t* prev_block
+ = buf_page_get_gen(prev_id, 0, RW_NO_LATCH, nullptr,
+ BUF_PEEK_IF_IN_POOL, mtr, &err);
+ /* Since we already held an x-latch on prev_block, it must
+ be available and not be corrupted unless the buffer pool got
+ corrupted somehow. */
+ if (UNIV_UNLIKELY(!prev_block)) {
+ return err;
+ }
+ ut_ad(!memcmp_aligned<4>(prev_block->page.frame + FIL_PAGE_NEXT,
+ block->page.frame + FIL_PAGE_OFFSET, 4));
/* We must already have an x-latch on prev_block! */
ut_ad(mtr->memo_contains_flagged(prev_block, MTR_MEMO_PAGE_X_FIX));
@@ -4847,6 +4791,7 @@ btr_cur_pess_upd_restore_supremum(
lock_rec_reset_and_inherit_gap_locks(*prev_block, block_id,
PAGE_HEAP_NO_SUPREMUM,
page_rec_get_heap_no(rec));
+ return DB_SUCCESS;
}
/*************************************************************//**
@@ -5054,18 +4999,17 @@ btr_cur_pessimistic_update(
}
if (optim_err == DB_OVERFLOW) {
-
/* First reserve enough free space for the file segments
of the index tree, so that the update will not fail because
of lack of space */
- uint32_t n_extents = uint32_t(cursor->tree_height / 16 + 3);
-
- if (!fsp_reserve_free_extents(
- &n_reserved, index->table->space, n_extents,
- flags & BTR_NO_UNDO_LOG_FLAG
- ? FSP_CLEANING : FSP_NORMAL,
- mtr)) {
+ err = fsp_reserve_free_extents(
+ &n_reserved, index->table->space,
+ uint32_t(cursor->tree_height / 16 + 3),
+ flags & BTR_NO_UNDO_LOG_FLAG
+ ? FSP_CLEANING : FSP_NORMAL,
+ mtr);
+ if (UNIV_UNLIKELY(err != DB_SUCCESS)) {
err = DB_OUT_OF_FILE_SPACE;
goto err_exit;
}
@@ -5124,7 +5068,10 @@ btr_cur_pessimistic_update(
was a rollback, the shortened metadata record
would have too many fields, and we would be unable to
know the size of the freed record. */
- btr_page_reorganize(page_cursor, index, mtr);
+ err = btr_page_reorganize(page_cursor, index, mtr);
+ if (err != DB_SUCCESS) {
+ goto return_after_reservations;
+ }
rec = page_cursor->rec;
rec_offs_make_valid(rec, index, true, *offsets);
if (page_cursor->block->page.id().page_no()
@@ -5236,8 +5183,8 @@ btr_cur_pessimistic_update(
cursor, offsets, offsets_heap,
new_entry, &rec,
&dummy_big_rec, n_ext, NULL, mtr);
- ut_a(rec);
ut_a(err == DB_SUCCESS);
+ ut_a(rec);
ut_a(dummy_big_rec == NULL);
ut_ad(rec_offs_validate(rec, cursor->index, *offsets));
page_cursor->rec = rec;
@@ -5276,7 +5223,10 @@ btr_cur_pessimistic_update(
was a rollback, the shortened metadata record
would have too many fields, and we would be unable to
know the size of the freed record. */
- btr_page_reorganize(page_cursor, index, mtr);
+ err = btr_page_reorganize(page_cursor, index, mtr);
+ if (err != DB_SUCCESS) {
+ goto return_after_reservations;
+ }
rec = page_cursor->rec;
} else {
lock_rec_restore_from_page_infimum(
@@ -5289,13 +5239,14 @@ btr_cur_pessimistic_update(
from a wrong record. */
if (!was_first) {
- btr_cur_pess_upd_restore_supremum(btr_cur_get_block(cursor),
- rec, mtr);
+ err = btr_cur_pess_upd_restore_supremum(
+ btr_cur_get_block(cursor), rec, mtr);
}
return_after_reservations:
#ifdef UNIV_ZIP_DEBUG
- ut_a(!page_zip || page_zip_validate(btr_cur_get_page_zip(cursor),
+ ut_a(err ||
+ !page_zip || page_zip_validate(btr_cur_get_page_zip(cursor),
btr_cur_get_page(cursor), index));
#endif /* UNIV_ZIP_DEBUG */
@@ -5414,15 +5365,15 @@ that mtr holds an x-latch on the tree and on the cursor page. To avoid
deadlocks, mtr must also own x-latches to brothers of page, if those
brothers exist. NOTE: it is assumed that the caller has reserved enough
free extents so that the compression will always succeed if done!
-@return TRUE if compression occurred */
-ibool
+@return whether compression occurred */
+bool
btr_cur_compress_if_useful(
/*=======================*/
btr_cur_t* cursor, /*!< in/out: cursor on the page to compress;
cursor does not stay valid if !adjust and
compression occurs */
- ibool adjust, /*!< in: TRUE if should adjust the
- cursor position even if compression occurs */
+ bool adjust, /*!< in: whether the cursor position should be
+ adjusted even when compression occurs */
mtr_t* mtr) /*!< in/out: mini-transaction */
{
ut_ad(mtr->memo_contains_flagged(&cursor->index->lock,
@@ -5442,16 +5393,17 @@ btr_cur_compress_if_useful(
}
}
- return(btr_cur_compress_recommendation(cursor, mtr)
- && btr_compress(cursor, adjust, mtr));
+ return btr_cur_compress_recommendation(cursor, mtr)
+ && btr_compress(cursor, adjust, mtr) == DB_SUCCESS;
}
/*******************************************************//**
Removes the record on which the tree cursor is positioned on a leaf page.
It is assumed that the mtr has an x-latch on the page where the cursor is
positioned, but no latch on the whole tree.
-@return TRUE if success, i.e., the page did not become too empty */
-ibool
+@return error code
+@retval DB_FAIL if the page would become too empty */
+dberr_t
btr_cur_optimistic_delete(
/*======================*/
btr_cur_t* cursor, /*!< in: cursor on leaf page, on the record to
@@ -5493,14 +5445,15 @@ btr_cur_optimistic_delete(
cursor->index->n_core_fields,
ULINT_UNDEFINED, &heap);
- const ibool no_compress_needed = !rec_offs_any_extern(offsets)
- && btr_cur_can_delete_without_compress(
- cursor, rec_offs_size(offsets), mtr);
-
- if (!no_compress_needed) {
+ dberr_t err = DB_SUCCESS;
+ if (rec_offs_any_extern(offsets)
+ || !btr_cur_can_delete_without_compress(cursor,
+ rec_offs_size(offsets),
+ mtr)) {
/* prefetch siblings of the leaf for the pessimistic
operation. */
btr_cur_prefetch_siblings(block, cursor->index);
+ err = DB_FAIL;
goto func_exit;
}
@@ -5565,8 +5518,8 @@ btr_cur_optimistic_delete(
after rollback, this deleted metadata record
would have too many fields, and we would be
unable to know the size of the freed record. */
- btr_page_reorganize(btr_cur_get_page_cur(cursor),
- cursor->index, mtr);
+ err = btr_page_reorganize(btr_cur_get_page_cur(cursor),
+ cursor->index, mtr);
goto func_exit;
} else {
if (!flags) {
@@ -5615,7 +5568,7 @@ func_exit:
mem_heap_free(heap);
}
- return(no_compress_needed);
+ return err;
}
/*************************************************************//**
@@ -5653,7 +5606,6 @@ btr_cur_pessimistic_delete(
dict_index_t* index;
rec_t* rec;
uint32_t n_reserved = 0;
- bool success;
ibool ret = FALSE;
mem_heap_t* heap;
rec_offs* offsets;
@@ -5683,13 +5635,11 @@ btr_cur_pessimistic_delete(
uint32_t n_extents = uint32_t(cursor->tree_height / 32 + 1);
- success = fsp_reserve_free_extents(&n_reserved,
- index->table->space,
- n_extents,
- FSP_CLEANING, mtr);
- if (!success) {
- *err = DB_OUT_OF_FILE_SPACE;
-
+ *err = fsp_reserve_free_extents(&n_reserved,
+ index->table->space,
+ n_extents,
+ FSP_CLEANING, mtr);
+ if (UNIV_UNLIKELY(*err != DB_SUCCESS)) {
return(FALSE);
}
}
@@ -5778,10 +5728,10 @@ btr_cur_pessimistic_delete(
after rollback, this deleted metadata record
would carry too many fields, and we would be
unable to know the size of the freed record. */
- btr_page_reorganize(btr_cur_get_page_cur(cursor),
- index, mtr);
+ *err = btr_page_reorganize(btr_cur_get_page_cur(cursor),
+ index, mtr);
ut_ad(!ret);
- goto return_after_reservations;
+ goto err_exit;
}
} else if (UNIV_UNLIKELY(page_rec_is_first(rec, page))) {
if (page_rec_is_last(rec, page)) {
@@ -5833,22 +5783,36 @@ discard_page:
so that it is equal to the new leftmost node pointer
on the page */
btr_cur_t cursor;
- btr_page_get_father(index, block, mtr, &cursor);
- btr_cur_node_ptr_delete(&cursor, mtr);
+ ret = btr_page_get_father(index, block, mtr, &cursor);
+ if (!ret) {
+ *err = DB_CORRUPTION;
+ goto err_exit;
+ }
+ *err = btr_cur_node_ptr_delete(&cursor, mtr);
+ if (*err != DB_SUCCESS) {
+got_err:
+ ret = FALSE;
+ goto err_exit;
+ }
+
const ulint level = btr_page_get_level(page);
// FIXME: reuse the node_ptr from above
dtuple_t* node_ptr = dict_index_build_node_ptr(
index, next_rec, block->page.id().page_no(),
heap, level);
- btr_insert_on_non_leaf_level(
+ *err = btr_insert_on_non_leaf_level(
flags, index, level + 1, node_ptr, mtr);
+ if (*err != DB_SUCCESS) {
+ ret = FALSE;
+ goto got_err;
+ }
ut_d(parent_latched = true);
}
}
- /* SPATIAL INDEX never use SX locks; we can allow page merges
+ /* SPATIAL INDEX never use U locks; we can allow page merges
while holding X lock on the spatial index tree.
Do not allow merges of non-leaf B-tree pages unless it is
safe to do so. */
@@ -5889,7 +5853,7 @@ discard_page:
return_after_reservations:
*err = DB_SUCCESS;
-
+err_exit:
mem_heap_free(heap);
if (!srv_read_only_mode
@@ -5910,7 +5874,7 @@ return_after_reservations:
/** Delete the node pointer in a parent page.
@param[in,out] parent cursor pointing to parent record
@param[in,out] mtr mini-transaction */
-void btr_cur_node_ptr_delete(btr_cur_t* parent, mtr_t* mtr)
+dberr_t btr_cur_node_ptr_delete(btr_cur_t* parent, mtr_t* mtr)
{
ut_ad(mtr->memo_contains_flagged(btr_cur_get_block(parent),
MTR_MEMO_PAGE_X_FIX));
@@ -5918,10 +5882,11 @@ void btr_cur_node_ptr_delete(btr_cur_t* parent, mtr_t* mtr)
ibool compressed = btr_cur_pessimistic_delete(&err, TRUE, parent,
BTR_CREATE_FLAG, false,
mtr);
- ut_a(err == DB_SUCCESS);
- if (!compressed) {
+ if (err == DB_SUCCESS && !compressed) {
btr_cur_compress_if_useful(parent, FALSE, mtr);
}
+
+ return err;
}
/*******************************************************************//**
@@ -6034,7 +5999,7 @@ btr_estimate_n_rows_in_range_on_level(
mtr_t mtr;
page_t* page;
buf_block_t* block;
- dberr_t err=DB_SUCCESS;
+ dberr_t err;
mtr_start(&mtr);
@@ -6051,13 +6016,7 @@ btr_estimate_n_rows_in_range_on_level(
if (!block) {
if (err == DB_DECRYPTION_FAILED) {
- ib_push_warning((void *)NULL,
- DB_DECRYPTION_FAILED,
- "Table %s is encrypted but encryption service or"
- " used key_id is not available. "
- " Can't continue reading table.",
- index->table->name.m_name);
- index->table->file_unreadable = true;
+ btr_decryption_failed(*index);
}
mtr_commit(&mtr);
@@ -6190,18 +6149,23 @@ btr_estimate_n_rows_in_range_low(
example if "5 < x AND x <= 10" then we should not include the left
boundary, but should include the right one. */
- mtr_start(&mtr);
+ mtr.start();
cursor.path_arr = path1;
- bool should_count_the_left_border;
+ bool should_count_the_left_border =
+ dtuple_get_n_fields(tuple1->tuple) > 0;
- if (dtuple_get_n_fields(tuple1->tuple) > 0) {
-
- btr_cur_search_to_nth_level(index, 0, tuple1->tuple,
- tuple1->mode,
- BTR_SEARCH_LEAF | BTR_ESTIMATE,
- &cursor, 0, &mtr);
+ if (should_count_the_left_border) {
+ if (btr_cur_search_to_nth_level(index, 0, tuple1->tuple,
+ tuple1->mode,
+ BTR_SEARCH_LEAF | BTR_ESTIMATE,
+ &cursor, 0, &mtr)
+ != DB_SUCCESS) {
+corrupted:
+ mtr.commit();
+ return 0;
+ }
ut_ad(!page_rec_is_infimum(btr_cur_get_rec(&cursor)));
@@ -6214,19 +6178,11 @@ btr_estimate_n_rows_in_range_low(
should_count_the_left_border
= !page_rec_is_supremum(btr_cur_get_rec(&cursor));
} else {
- dberr_t err = DB_SUCCESS;
-
- err = btr_cur_open_at_index_side(true, index,
- BTR_SEARCH_LEAF | BTR_ESTIMATE,
- &cursor, 0, &mtr);
-
- if (err != DB_SUCCESS) {
- ib::warn() << " Error code: " << err
- << " btr_estimate_n_rows_in_range_low "
- << " called from file: "
- << __FILE__ << " line: " << __LINE__
- << " table: " << index->table->name
- << " index: " << index->name;
+ if (btr_cur_open_at_index_side(true, index,
+ BTR_SEARCH_LEAF | BTR_ESTIMATE,
+ &cursor, 0, &mtr)
+ != DB_SUCCESS) {
+ goto corrupted;
}
ut_ad(page_rec_is_infimum(btr_cur_get_rec(&cursor)));
@@ -6235,29 +6191,27 @@ btr_estimate_n_rows_in_range_low(
'x < 123' or 'x <= 123' and btr_cur_open_at_index_side()
positioned the cursor on the infimum record on the leftmost
page, which must not be counted. */
- should_count_the_left_border = false;
}
tuple1->page_id= cursor.page_cur.block->page.id();
- mtr_commit(&mtr);
+ mtr.commit();
- if (!index->is_readable()) {
- return 0;
- }
-
- mtr_start(&mtr);
+ mtr.start();
cursor.path_arr = path2;
- bool should_count_the_right_border;
+ bool should_count_the_right_border =
+ dtuple_get_n_fields(tuple2->tuple) > 0;
- if (dtuple_get_n_fields(tuple2->tuple) > 0) {
-
- btr_cur_search_to_nth_level(index, 0, tuple2->tuple,
- mode2,
- BTR_SEARCH_LEAF | BTR_ESTIMATE,
- &cursor, 0, &mtr);
+ if (should_count_the_right_border) {
+ if (btr_cur_search_to_nth_level(index, 0, tuple2->tuple,
+ mode2,
+ BTR_SEARCH_LEAF | BTR_ESTIMATE,
+ &cursor, 0, &mtr)
+ != DB_SUCCESS) {
+ goto corrupted;
+ }
const rec_t* rec = btr_cur_get_rec(&cursor);
@@ -6286,19 +6240,11 @@ btr_estimate_n_rows_in_range_low(
the requested one (can also be positioned on the 'sup') and
we should not count the right border. */
} else {
- dberr_t err = DB_SUCCESS;
-
- err = btr_cur_open_at_index_side(false, index,
- BTR_SEARCH_LEAF | BTR_ESTIMATE,
- &cursor, 0, &mtr);
-
- if (err != DB_SUCCESS) {
- ib::warn() << " Error code: " << err
- << " btr_estimate_n_rows_in_range_low "
- << " called from file: "
- << __FILE__ << " line: " << __LINE__
- << " table: " << index->table->name
- << " index: " << index->name;
+ if (btr_cur_open_at_index_side(false, index,
+ BTR_SEARCH_LEAF | BTR_ESTIMATE,
+ &cursor, 0, &mtr)
+ != DB_SUCCESS) {
+ goto corrupted;
}
ut_ad(page_rec_is_supremum(btr_cur_get_rec(&cursor)));
@@ -6307,12 +6253,11 @@ btr_estimate_n_rows_in_range_low(
'x > 123' or 'x >= 123' and btr_cur_open_at_index_side()
positioned the cursor on the supremum record on the rightmost
page, which must not be counted. */
- should_count_the_right_border = false;
}
tuple2->page_id= cursor.page_cur.block->page.id();
- mtr_commit(&mtr);
+ mtr.commit();
/* We have the path information for the range in path1 and path2 */
@@ -6818,11 +6763,12 @@ struct btr_blob_log_check_t {
if (UNIV_UNLIKELY(page_no != FIL_NULL)) {
m_pcur->btr_cur.page_cur.block = btr_block_get(
*index, page_no, RW_X_LATCH, false, m_mtr);
+ /* The page should not be evicted or corrupted while
+ we are holding a buffer-fix on it. */
+ m_pcur->btr_cur.page_cur.block->page.unfix();
m_pcur->btr_cur.page_cur.rec
= m_pcur->btr_cur.page_cur.block->page.frame
+ offs;
-
- m_pcur->btr_cur.page_cur.block->page.unfix();
} else {
ut_ad(m_pcur->rel_pos == BTR_PCUR_ON);
ut_a(m_pcur->restore_position(
@@ -6862,9 +6808,7 @@ the file, in case the file was somehow truncated in the crash.
dberr_t
btr_store_big_rec_extern_fields(
/*============================*/
- btr_pcur_t* pcur, /*!< in/out: a persistent cursor. if
- btr_mtr is restarted, then this can
- be repositioned. */
+ btr_pcur_t* pcur, /*!< in: a persistent cursor */
rec_offs* offsets, /*!< in/out: rec_get_offsets() on
pcur. the "external storage" flags
in offsets will correctly correspond
@@ -6898,11 +6842,15 @@ btr_store_big_rec_extern_fields(
ut_ad(buf_block_get_frame(rec_block) == page_align(rec));
ut_a(dict_index_is_clust(index));
+ if (!fil_page_index_page_check(page_align(rec))) {
+ if (op != BTR_STORE_INSERT_BULK) {
+ return DB_PAGE_CORRUPTED;
+ }
+ }
+
btr_blob_log_check_t redo_log(pcur, btr_mtr, offsets, &rec_block,
&rec, op);
page_zip = buf_block_get_page_zip(rec_block);
- ut_a(fil_page_index_page_check(page_align(rec))
- || op == BTR_STORE_INSERT_BULK);
if (page_zip) {
int err;
@@ -6993,42 +6941,48 @@ btr_store_big_rec_extern_fields(
mtr.start();
index->set_modified(mtr);
- mtr.set_log_mode(btr_mtr->get_log_mode());
+ mtr.set_log_mode_sub(*btr_mtr);
+ mtr.memo_push(rec_block, MTR_MEMO_PAGE_X_FIX);
- buf_page_get(rec_block->page.id(),
- rec_block->zip_size(), RW_X_LATCH, &mtr);
+ rec_block->page.fix();
+ rec_block->page.lock.x_lock();
+#ifdef BTR_CUR_HASH_ADAPT
+ ut_ad(!rec_block->index || !rec_block->index->freed());
+#endif
uint32_t hint_prev = prev_page_no;
if (hint_prev == FIL_NULL) {
hint_prev = rec_block->page.id().page_no();
}
- if (!fsp_reserve_free_extents(&r_extents,
- index->table->space, 1,
- FSP_BLOB, &mtr, 1)) {
+ error = fsp_reserve_free_extents(
+ &r_extents, index->table->space, 1,
+ FSP_BLOB, &mtr, 1);
+ if (UNIV_UNLIKELY(error != DB_SUCCESS)) {
+alloc_fail:
mtr.commit();
- error = DB_OUT_OF_FILE_SPACE;
goto func_exit;
}
block = btr_page_alloc(index, hint_prev + 1,
- FSP_NO_DIR, 0, &mtr, &mtr);
+ FSP_NO_DIR, 0, &mtr, &mtr,
+ &error);
index->table->space->release_free_extents(r_extents);
-
- ut_a(block != NULL);
+ if (!block) {
+ goto alloc_fail;
+ }
const uint32_t space_id = block->page.id().space();
const uint32_t page_no = block->page.id().page_no();
- if (prev_page_no != FIL_NULL) {
- buf_block_t* prev_block;
-
- prev_block = buf_page_get(
- page_id_t(space_id, prev_page_no),
- rec_block->zip_size(),
- RW_X_LATCH, &mtr);
-
+ if (prev_page_no == FIL_NULL) {
+ } else if (buf_block_t* prev_block =
+ buf_page_get_gen(page_id_t(space_id,
+ prev_page_no),
+ rec_block->zip_size(),
+ RW_X_LATCH, nullptr,
+ BUF_GET, &mtr, &error)) {
if (page_zip) {
mtr.write<4>(*prev_block,
prev_block->page.frame
@@ -7047,6 +7001,8 @@ btr_store_big_rec_extern_fields(
+ prev_block->page.frame,
page_no);
}
+ } else {
+ goto alloc_fail;
}
ut_ad(!page_has_siblings(block->page.frame));
@@ -7293,14 +7249,11 @@ btr_free_externally_stored_field(
containing the latch to data an an
X-latch to the index tree */
{
- page_t* page;
const uint32_t space_id = mach_read_from_4(
field_ref + BTR_EXTERN_SPACE_ID);
- uint32_t page_no;
- uint32_t next_page_no;
- mtr_t mtr;
ut_ad(index->is_primary());
+ ut_ad(block->page.lock.have_x());
ut_ad(local_mtr->memo_contains_flagged(&index->lock, MTR_MEMO_X_LOCK
| MTR_MEMO_SX_LOCK));
ut_ad(local_mtr->memo_contains_page_flagged(field_ref,
@@ -7325,29 +7278,22 @@ btr_free_externally_stored_field(
ut_ad(space_id == index->table->space_id);
const ulint ext_zip_size = index->table->space->zip_size();
- const ulint rec_zip_size = rec ? ext_zip_size : 0;
-
/* !rec holds in a call from purge when field_ref is in an undo page */
ut_ad(rec || !block->page.zip.data);
for (;;) {
- buf_block_t* ext_block;
+ mtr_t mtr;
- mtr_start(&mtr);
+ mtr.start();
mtr.set_spaces(*local_mtr);
- mtr.set_log_mode(local_mtr->get_log_mode());
+ mtr.set_log_mode_sub(*local_mtr);
ut_ad(!index->table->is_temporary()
|| local_mtr->get_log_mode() == MTR_LOG_NO_REDO);
- const page_t* p = page_align(field_ref);
-
- const page_id_t page_id(page_get_space_id(p),
- page_get_page_no(p));
-
- buf_page_get(page_id, rec_zip_size, RW_X_LATCH, &mtr);
-
- page_no = mach_read_from_4(field_ref + BTR_EXTERN_PAGE_NO);
+ const uint32_t page_no = mach_read_from_4(
+ field_ref + BTR_EXTERN_PAGE_NO);
+ buf_block_t* ext_block;
if (/* There is no external storage data */
page_no == FIL_NULL
@@ -7358,18 +7304,31 @@ btr_free_externally_stored_field(
|| (rollback
&& (mach_read_from_1(field_ref + BTR_EXTERN_LEN)
& BTR_EXTERN_INHERITED_FLAG))) {
-
+skip_free:
/* Do not free */
- mtr_commit(&mtr);
+ mtr.commit();
return;
}
- ext_block = buf_page_get(
- page_id_t(space_id, page_no), ext_zip_size,
- RW_X_LATCH, &mtr);
+ ext_block = buf_page_get(page_id_t(space_id, page_no),
+ ext_zip_size, RW_X_LATCH, &mtr);
- page = buf_block_get_frame(ext_block);
+ if (!ext_block) {
+ goto skip_free;
+ }
+
+ /* The buffer pool block containing the BLOB pointer is
+ exclusively latched by local_mtr. To satisfy some design
+ constraints, we must recursively latch it in mtr as well. */
+ mtr.memo_push(block, MTR_MEMO_PAGE_X_FIX);
+ block->fix();
+ block->page.lock.x_lock();
+#ifdef BTR_CUR_HASH_ADAPT
+ ut_ad(!block->index || !block->index->freed());
+#endif
+
+ const page_t* page = buf_block_get_frame(ext_block);
if (ext_zip_size) {
/* Note that page_zip will be NULL
@@ -7379,9 +7338,10 @@ btr_free_externally_stored_field(
case FIL_PAGE_TYPE_ZBLOB2:
break;
default:
- ut_error;
+ MY_ASSERT_UNREACHABLE();
}
- next_page_no = mach_read_from_4(page + FIL_PAGE_NEXT);
+ const uint32_t next_page_no = mach_read_from_4(
+ page + FIL_PAGE_NEXT);
btr_page_free(index, ext_block, &mtr, true,
local_mtr->memo_contains(
@@ -7406,7 +7366,7 @@ btr_free_externally_stored_field(
ut_ad(!block->page.zip.data);
btr_check_blob_fil_page_type(*ext_block, false);
- next_page_no = mach_read_from_4(
+ const uint32_t next_page_no = mach_read_from_4(
page + FIL_PAGE_DATA
+ BTR_BLOB_HDR_NEXT_PAGE_NO);
btr_page_free(index, ext_block, &mtr, true,
@@ -7538,6 +7498,10 @@ btr_copy_blob_prefix(
mtr_start(&mtr);
block = buf_page_get(id, 0, RW_S_LATCH, &mtr);
+ if (!block) {
+ mtr.commit();
+ return copied_len;
+ }
page = buf_block_get_frame(block);
btr_check_blob_fil_page_type(*block, true);
diff --git a/storage/innobase/btr/btr0defragment.cc b/storage/innobase/btr/btr0defragment.cc
index 8823bab572d..23d93caecf5 100644
--- a/storage/innobase/btr/btr0defragment.cc
+++ b/storage/innobase/btr/btr0defragment.cc
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (C) 2012, 2014 Facebook, Inc. All Rights Reserved.
-Copyright (C) 2014, 2021, MariaDB Corporation.
+Copyright (C) 2014, 2022, 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
@@ -283,7 +283,8 @@ btr_defragment_calc_n_recs_for_size(
/*************************************************************//**
Merge as many records from the from_block to the to_block. Delete
the from_block if all records are successfully merged to to_block.
-@return the to_block to target for next merge operation. */
+@return the to_block to target for next merge operation.
+@retval nullptr if corruption was noticed */
static
buf_block_t*
btr_defragment_merge_pages(
@@ -330,9 +331,9 @@ btr_defragment_merge_pages(
// reorganizing the page, otherwise we need to reorganize the page
// first to release more space.
if (move_size > max_ins_size) {
- if (!btr_page_reorganize_block(page_zip_level,
- to_block, index,
- mtr)) {
+ dberr_t err = btr_page_reorganize_block(page_zip_level,
+ to_block, index, mtr);
+ if (err != DB_SUCCESS) {
if (!dict_index_is_clust(index)
&& page_is_leaf(to_page)) {
ibuf_reset_free_bits(to_block);
@@ -341,23 +342,30 @@ btr_defragment_merge_pages(
// not compressable. There's no point to try
// merging into this page. Continue to the
// next page.
- return from_block;
+ return err == DB_FAIL ? from_block : nullptr;
}
ut_ad(page_validate(to_page, index));
max_ins_size = page_get_max_insert_size(to_page, n_recs);
- ut_a(max_ins_size >= move_size);
+ if (max_ins_size < move_size) {
+ return nullptr;
+ }
}
// Move records to pack to_page more full.
orig_pred = NULL;
target_n_recs = n_recs_to_move;
+ dberr_t err;
while (n_recs_to_move > 0) {
rec = page_rec_get_nth(from_page,
n_recs_to_move + 1);
orig_pred = page_copy_rec_list_start(
- to_block, from_block, rec, index, mtr);
+ to_block, from_block, rec, index, mtr, &err);
if (orig_pred)
break;
+ if (err != DB_FAIL) {
+ return nullptr;
+ }
+
// If we reach here, that means compression failed after packing
// n_recs_to_move number of records to to_page. We try to reduce
// the targeted data size on the to_page by
@@ -396,19 +404,20 @@ btr_defragment_merge_pages(
}
}
btr_cur_t parent;
- if (n_recs_to_move == n_recs) {
+ if (!btr_page_get_father(index, from_block, mtr, &parent)) {
+ to_block = nullptr;
+ } else if (n_recs_to_move == n_recs) {
/* The whole page is merged with the previous page,
free it. */
- const page_id_t from{from_block->page.id()};
- lock_update_merge_left(*to_block, orig_pred, from);
+ lock_update_merge_left(*to_block, orig_pred,
+ from_block->page.id());
btr_search_drop_page_hash_index(from_block);
- ut_a(DB_SUCCESS == btr_level_list_remove(*from_block, *index,
- mtr));
- btr_page_get_father(index, from_block, mtr, &parent);
- btr_cur_node_ptr_delete(&parent, mtr);
- /* btr_blob_dbg_remove(from_page, index,
- "btr_defragment_n_pages"); */
- btr_page_free(index, from_block, mtr);
+ if (btr_level_list_remove(*from_block, *index, mtr)
+ != DB_SUCCESS
+ || btr_cur_node_ptr_delete(&parent, mtr) != DB_SUCCESS
+ || btr_page_free(index, from_block, mtr) != DB_SUCCESS) {
+ return nullptr;
+ }
} else {
// There are still records left on the page, so
// increment n_defragmented. Node pointer will be changed
@@ -424,15 +433,20 @@ btr_defragment_merge_pages(
orig_pred,
from_block);
// FIXME: reuse the node_ptr!
- btr_page_get_father(index, from_block, mtr, &parent);
- btr_cur_node_ptr_delete(&parent, mtr);
+ if (btr_cur_node_ptr_delete(&parent, mtr)
+ != DB_SUCCESS) {
+ return nullptr;
+ }
rec = page_rec_get_next(
page_get_infimum_rec(from_page));
node_ptr = dict_index_build_node_ptr(
index, rec, page_get_page_no(from_page),
heap, level);
- btr_insert_on_non_leaf_level(0, index, level+1,
- node_ptr, mtr);
+ if (btr_insert_on_non_leaf_level(0, index, level+1,
+ node_ptr, mtr)
+ != DB_SUCCESS) {
+ return nullptr;
+ }
}
to_block = from_block;
}
@@ -507,6 +521,9 @@ btr_defragment_n_pages(
blocks[i] = btr_block_get(*index, page_no, RW_X_LATCH, true,
mtr);
+ if (!blocks[i]) {
+ return nullptr;
+ }
}
if (n_pages == 1) {
@@ -517,7 +534,8 @@ btr_defragment_n_pages(
return NULL;
/* given page is the last page.
Lift the records to father. */
- btr_lift_page_up(index, block, mtr);
+ dberr_t err;
+ btr_lift_page_up(index, block, mtr, &err);
}
return NULL;
}
@@ -580,6 +598,9 @@ btr_defragment_n_pages(
if (new_block != current_block) {
n_defragmented ++;
current_block = new_block;
+ if (!new_block) {
+ break;
+ }
}
}
mem_heap_free(heap);
@@ -667,17 +688,19 @@ processed:
mtr_start(&mtr);
dict_index_t *index = item->pcur->btr_cur.index;
index->set_modified(mtr);
- /* To follow the latching order defined in WL#6326, acquire index->lock X-latch.
- This entitles us to acquire page latches in any order for the index. */
+ /* To follow the latching order defined in WL#6326,
+ acquire index->lock X-latch. This entitles us to
+ acquire page latches in any order for the index. */
mtr_x_lock_index(index, &mtr);
- /* This will acquire index->lock SX-latch, which per WL#6363 is allowed
+ /* This will acquire index->lock U latch, which is allowed
when we are already holding the X-latch. */
- item->pcur->restore_position(BTR_MODIFY_TREE, &mtr);
- buf_block_t* first_block = btr_pcur_get_block(item->pcur);
if (buf_block_t *last_block =
- btr_defragment_n_pages(first_block, index,
- srv_defragment_n_pages,
- &mtr)) {
+ item->pcur->restore_position(BTR_MODIFY_TREE, &mtr)
+ == btr_pcur_t::CORRUPTED
+ ? nullptr
+ : btr_defragment_n_pages(btr_pcur_get_block(item->pcur),
+ index, srv_defragment_n_pages,
+ &mtr)) {
/* If we haven't reached the end of the index,
place the cursor on the last record of last page,
store the cursor position, and put back in queue. */
diff --git a/storage/innobase/btr/btr0pcur.cc b/storage/innobase/btr/btr0pcur.cc
index 9c63cfbd568..8c33fee9e61 100644
--- a/storage/innobase/btr/btr0pcur.cc
+++ b/storage/innobase/btr/btr0pcur.cc
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2016, 2021, MariaDB Corporation.
+Copyright (c) 2016, 2022, 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
@@ -299,21 +299,14 @@ btr_pcur_t::restore_position(ulint restore_latch_mode, mtr_t *mtr)
if (UNIV_UNLIKELY
(rel_pos == BTR_PCUR_AFTER_LAST_IN_TREE
|| rel_pos == BTR_PCUR_BEFORE_FIRST_IN_TREE)) {
- dberr_t err = DB_SUCCESS;
-
/* In these cases we do not try an optimistic restoration,
but always do a search */
- err = btr_cur_open_at_index_side(
+ if (btr_cur_open_at_index_side(
rel_pos == BTR_PCUR_BEFORE_FIRST_IN_TREE,
index, restore_latch_mode,
- &btr_cur, 0, mtr);
-
- if (err != DB_SUCCESS) {
- ib::warn() << " Error code: " << err
- << " btr_pcur_t::restore_position "
- << " table: " << index->table->name
- << " index: " << index->name;
+ &btr_cur, 0, mtr) != DB_SUCCESS) {
+ return restore_status::CORRUPTED;
}
latch_mode =
@@ -412,16 +405,20 @@ btr_pcur_t::restore_position(ulint restore_latch_mode, mtr_t *mtr)
mode = PAGE_CUR_L;
break;
default:
- ut_error;
+ MY_ASSERT_UNREACHABLE();
mode = PAGE_CUR_UNSUPP;
}
- btr_pcur_open_with_no_init_func(index, tuple, mode, restore_latch_mode,
- this,
+ if (btr_pcur_open_with_no_init_func(
+ index, tuple, mode, restore_latch_mode,
+ this,
#ifdef BTR_CUR_HASH_ADAPT
- NULL,
+ nullptr,
#endif /* BTR_CUR_HASH_ADAPT */
- mtr);
+ mtr) != DB_SUCCESS) {
+ mem_heap_free(heap);
+ return restore_status::CORRUPTED;
+ }
/* Restore the old search mode */
search_mode = old_mode;
@@ -473,7 +470,7 @@ Moves the persistent cursor to the first record on the next page. Releases the
latch on the current page, and bufferunfixes it. Note that there must not be
modifications on the current page, as then the x-latch can be released only in
mtr_commit. */
-void
+dberr_t
btr_pcur_move_to_next_page(
/*=======================*/
btr_pcur_t* cursor, /*!< in: persistent cursor; must be on the
@@ -487,11 +484,6 @@ btr_pcur_move_to_next_page(
cursor->old_stored = false;
const page_t* page = btr_pcur_get_page(cursor);
-
- if (UNIV_UNLIKELY(!page)) {
- return;
- }
-
const uint32_t next_page_no = btr_page_get_next(page);
ut_ad(next_page_no != FIL_NULL);
@@ -505,28 +497,31 @@ btr_pcur_move_to_next_page(
mode = BTR_MODIFY_LEAF;
}
+ dberr_t err;
buf_block_t* next_block = btr_block_get(
*btr_pcur_get_btr_cur(cursor)->index, next_page_no, mode,
- page_is_leaf(page), mtr);
+ page_is_leaf(page), mtr, &err);
if (UNIV_UNLIKELY(!next_block)) {
- return;
+ return err;
}
const page_t* next_page = buf_block_get_frame(next_block);
-#ifdef UNIV_BTR_DEBUG
- ut_a(page_is_comp(next_page) == page_is_comp(page));
- ut_a(btr_page_get_prev(next_page)
- == btr_pcur_get_block(cursor)->page.id().page_no());
-#endif /* UNIV_BTR_DEBUG */
+
+ if (UNIV_UNLIKELY(memcmp_aligned<4>(next_page + FIL_PAGE_PREV,
+ page + FIL_PAGE_OFFSET, 4))) {
+ return DB_CORRUPTION;
+ }
btr_leaf_page_release(btr_pcur_get_block(cursor), mode, mtr);
page_cur_set_before_first(next_block, btr_pcur_get_page_cur(cursor));
ut_d(page_check_dir(next_page));
+ return err;
}
+MY_ATTRIBUTE((nonnull,warn_unused_result))
/*********************************************************//**
Moves the persistent cursor backward if it is on the first record of the page.
Commits mtr. Note that to prevent a possible deadlock, the operation
@@ -537,36 +532,18 @@ return, but it may happen that the cursor is not positioned on the last
record of any page, because the structure of the tree may have changed
during the time when the cursor had no latches. */
static
-void
+bool
btr_pcur_move_backward_from_page(
/*=============================*/
btr_pcur_t* cursor, /*!< in: persistent cursor, must be on the first
record of the current page */
mtr_t* mtr) /*!< in: mtr */
{
- ulint prev_page_no;
- page_t* page;
- buf_block_t* prev_block;
- ulint latch_mode;
- ulint latch_mode2;
-
- ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
ut_ad(btr_pcur_is_before_first_on_page(cursor));
ut_ad(!btr_pcur_is_before_first_in_tree(cursor));
- latch_mode = cursor->latch_mode;
-
- if (latch_mode == BTR_SEARCH_LEAF) {
-
- latch_mode2 = BTR_SEARCH_PREV;
-
- } else if (latch_mode == BTR_MODIFY_LEAF) {
-
- latch_mode2 = BTR_MODIFY_PREV;
- } else {
- latch_mode2 = 0; /* To eliminate compiler warning */
- ut_error;
- }
+ const ulint latch_mode = cursor->latch_mode;
+ ut_ad(latch_mode == BTR_SEARCH_LEAF || latch_mode == BTR_MODIFY_LEAF);
btr_pcur_store_position(cursor, mtr);
@@ -574,43 +551,42 @@ btr_pcur_move_backward_from_page(
mtr_start(mtr);
- cursor->restore_position(latch_mode2, mtr);
+ static_assert(BTR_SEARCH_PREV == (4 | BTR_SEARCH_LEAF), "");
+ static_assert(BTR_MODIFY_PREV == (4 | BTR_MODIFY_LEAF), "");
- page = btr_pcur_get_page(cursor);
+ if (UNIV_UNLIKELY(cursor->restore_position(4 | latch_mode, mtr)
+ == btr_pcur_t::CORRUPTED)) {
+ return true;
+ }
- prev_page_no = btr_page_get_prev(page);
+ buf_block_t* prev_block = btr_pcur_get_btr_cur(cursor)->left_block;
- if (prev_page_no == FIL_NULL) {
+ if (!page_has_prev(btr_pcur_get_page(cursor))) {
} else if (btr_pcur_is_before_first_on_page(cursor)) {
-
- prev_block = btr_pcur_get_btr_cur(cursor)->left_block;
-
btr_leaf_page_release(btr_pcur_get_block(cursor),
latch_mode, mtr);
page_cur_set_after_last(prev_block,
btr_pcur_get_page_cur(cursor));
} else {
-
/* The repositioned cursor did not end on an infimum
record on a page. Cursor repositioning acquired a latch
also on the previous page, but we do not need the latch:
release it. */
-
prev_block = btr_pcur_get_btr_cur(cursor)->left_block;
-
btr_leaf_page_release(prev_block, latch_mode, mtr);
}
cursor->latch_mode = latch_mode;
cursor->old_stored = false;
+ return false;
}
/*********************************************************//**
Moves the persistent cursor to the previous record in the tree. If no records
are left, the cursor stays 'before first in tree'.
@return TRUE if the cursor was not before first in tree */
-ibool
+bool
btr_pcur_move_to_prev(
/*==================*/
btr_pcur_t* cursor, /*!< in: persistent cursor; NOTE that the
@@ -623,53 +599,13 @@ btr_pcur_move_to_prev(
cursor->old_stored = false;
if (btr_pcur_is_before_first_on_page(cursor)) {
-
- if (btr_pcur_is_before_first_in_tree(cursor)) {
-
- return(FALSE);
- }
-
- btr_pcur_move_backward_from_page(cursor, mtr);
-
- return(TRUE);
- }
-
- btr_pcur_move_to_prev_on_page(cursor);
-
- return(TRUE);
-}
-
-/**************************************************************//**
-If mode is PAGE_CUR_G or PAGE_CUR_GE, opens a persistent cursor on the first
-user record satisfying the search condition, in the case PAGE_CUR_L or
-PAGE_CUR_LE, on the last user record. If no such user record exists, then
-in the first case sets the cursor after last in tree, and in the latter case
-before first in tree. The latching mode must be BTR_SEARCH_LEAF or
-BTR_MODIFY_LEAF. */
-void
-btr_pcur_open_on_user_rec(
- dict_index_t* index, /*!< in: index */
- const dtuple_t* tuple, /*!< in: tuple on which search done */
- page_cur_mode_t mode, /*!< in: PAGE_CUR_L, ... */
- ulint latch_mode, /*!< in: BTR_SEARCH_LEAF or
- BTR_MODIFY_LEAF */
- btr_pcur_t* cursor, /*!< in: memory buffer for persistent
- cursor */
- mtr_t* mtr) /*!< in: mtr */
-{
- btr_pcur_open_low(index, 0, tuple, mode, latch_mode, cursor, 0, mtr);
-
- if ((mode == PAGE_CUR_GE) || (mode == PAGE_CUR_G)) {
-
- if (btr_pcur_is_after_last_on_page(cursor)) {
-
- btr_pcur_move_to_next_user_rec(cursor, mtr);
+ if (btr_pcur_is_before_first_in_tree(cursor)
+ || btr_pcur_move_backward_from_page(cursor, mtr)) {
+ return false;
}
} else {
- ut_ad((mode == PAGE_CUR_LE) || (mode == PAGE_CUR_L));
-
- /* Not implemented yet */
-
- ut_error;
+ btr_pcur_move_to_prev_on_page(cursor);
}
+
+ return true;
}
diff --git a/storage/innobase/btr/btr0sea.cc b/storage/innobase/btr/btr0sea.cc
index 96bbd8af3c1..a9b4e9ff0d0 100644
--- a/storage/innobase/btr/btr0sea.cc
+++ b/storage/innobase/btr/btr0sea.cc
@@ -1124,15 +1124,14 @@ fail:
block->page.fix();
block->page.set_accessed();
buf_page_make_young_if_needed(&block->page);
- mtr_memo_type_t fix_type;
- if (latch_mode == BTR_SEARCH_LEAF) {
- fix_type = MTR_MEMO_PAGE_S_FIX;
- ut_ad(!block->page.is_read_fixed());
- } else {
- fix_type = MTR_MEMO_PAGE_X_FIX;
- ut_ad(!block->page.is_io_fixed());
- }
- mtr->memo_push(block, fix_type);
+ ut_ad(!block->page.is_read_fixed());
+ ut_ad(latch_mode == BTR_SEARCH_LEAF
+ || !block->page.is_io_fixed());
+ static_assert(ulint{MTR_MEMO_PAGE_S_FIX} ==
+ ulint{BTR_SEARCH_LEAF}, "");
+ static_assert(ulint{MTR_MEMO_PAGE_X_FIX} ==
+ ulint{BTR_MODIFY_LEAF}, "");
+ mtr->memo_push(block, mtr_memo_type_t(latch_mode));
++buf_pool.stat.n_page_gets;
@@ -1437,19 +1436,13 @@ void btr_search_drop_page_hash_when_freed(const page_id_t page_id)
block = buf_page_get_gen(page_id, 0, RW_X_LATCH, NULL,
BUF_PEEK_IF_IN_POOL, &mtr);
- if (block) {
- /* If AHI is still valid, page can't be in free state.
- AHI is dropped when page is freed. */
- DBUG_ASSERT(!block->page.is_freed());
-
- if (block->index) {
- /* In all our callers, the table handle should
- be open, or we should be in the process of
- dropping the table (preventing eviction). */
- DBUG_ASSERT(block->index->table->get_ref_count()
- || dict_sys.locked());
- btr_search_drop_page_hash_index(block);
- }
+ if (block && block->index) {
+ /* In all our callers, the table handle should
+ be open, or we should be in the process of
+ dropping the table (preventing eviction). */
+ DBUG_ASSERT(block->index->table->get_ref_count()
+ || dict_sys.locked());
+ btr_search_drop_page_hash_index(block);
}
mtr_commit(&mtr);
diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc
index 03c15ecebf7..2e901aab854 100644
--- a/storage/innobase/buf/buf0buf.cc
+++ b/storage/innobase/buf/buf0buf.cc
@@ -66,6 +66,7 @@ Created 11/5/1995 Heikki Tuuri
#include "buf0dump.h"
#include