summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmake/plugin.cmake14
-rwxr-xr-xdebian/autobake-deb.sh20
-rwxr-xr-xdebian/rules28
-rw-r--r--extra/mariabackup/xtrabackup.cc2
-rw-r--r--mysql-test/suite/binlog/r/show_concurrent_rotate.result3
-rw-r--r--mysql-test/suite/binlog/t/show_concurrent_rotate.test7
-rw-r--r--mysql-test/suite/encryption/r/innodb_import.result21
-rw-r--r--mysql-test/suite/encryption/t/innodb_import.combinations7
-rw-r--r--mysql-test/suite/encryption/t/innodb_import.opt1
-rw-r--r--mysql-test/suite/encryption/t/innodb_import.test23
-rw-r--r--mysql-test/suite/federated/federated_partition.result36
-rw-r--r--mysql-test/suite/federated/federated_partition.test25
-rw-r--r--mysql-test/suite/galera/r/galera_as_slave_replay.result18
-rw-r--r--mysql-test/suite/galera/t/galera_as_slave_replay.test12
-rw-r--r--mysql-test/suite/galera_sr/r/MDEV-25717.result47
-rw-r--r--mysql-test/suite/galera_sr/t/MDEV-25717.test113
-rw-r--r--mysql-test/suite/innodb/r/full_crc32_import.result17
-rw-r--r--mysql-test/suite/innodb/r/implicit_gap_lock_convertion.result17
-rw-r--r--mysql-test/suite/innodb/r/import_corrupted.result30
-rw-r--r--mysql-test/suite/innodb/r/innodb-fk-warnings.result2
-rw-r--r--mysql-test/suite/innodb/r/innodb_information_schema.result2
-rw-r--r--mysql-test/suite/innodb/t/full_crc32_import.opt1
-rw-r--r--mysql-test/suite/innodb/t/full_crc32_import.test9
-rw-r--r--mysql-test/suite/innodb/t/implicit_gap_lock_convertion.test21
-rw-r--r--mysql-test/suite/innodb/t/import_corrupted.test68
-rw-r--r--mysql-test/suite/innodb_fts/r/sync.result10
-rw-r--r--mysql-test/suite/innodb_fts/t/sync.test14
-rw-r--r--mysql-test/suite/innodb_gis/r/alter_spatial_index.result39
-rw-r--r--mysql-test/suite/innodb_gis/t/alter_spatial_index.test10
-rw-r--r--mysql-test/suite/vcol/r/partition.result73
-rw-r--r--mysql-test/suite/vcol/t/partition.test48
-rw-r--r--mysql-test/suite/versioning/r/foreign.result13
-rw-r--r--mysql-test/suite/versioning/t/foreign.test18
-rw-r--r--scripts/wsrep_sst_common.sh8
-rw-r--r--scripts/wsrep_sst_mariabackup.sh48
-rw-r--r--scripts/wsrep_sst_rsync.sh12
-rw-r--r--sql/field.cc3
-rw-r--r--sql/field.h35
-rw-r--r--sql/filesort.cc9
-rw-r--r--sql/ha_partition.cc217
-rw-r--r--sql/ha_partition.h14
-rw-r--r--sql/item_jsonfunc.h4
-rw-r--r--sql/log.cc3
-rw-r--r--sql/log.h6
-rw-r--r--sql/sql_audit.h2
-rw-r--r--sql/sql_class.cc17
-rw-r--r--sql/sql_class.h1
-rw-r--r--sql/sql_connect.h5
-rw-r--r--sql/sql_lex.cc5
-rw-r--r--sql/sql_prepare.cc5
-rw-r--r--sql/sql_repl.cc12
-rw-r--r--sql/sql_view.cc2
-rw-r--r--sql/table.cc4
-rw-r--r--sql/table.h2
-rw-r--r--sql/wsrep_mysqld.cc15
-rw-r--r--storage/innobase/btr/btr0btr.cc20
-rw-r--r--storage/innobase/btr/btr0cur.cc10
-rw-r--r--storage/innobase/btr/btr0defragment.cc3
-rw-r--r--storage/innobase/buf/buf0buf.cc7
-rw-r--r--storage/innobase/buf/buf0rea.cc3
-rw-r--r--storage/innobase/fil/fil0fil.cc42
-rw-r--r--storage/innobase/fil/fil0pagecompress.cc3
-rw-r--r--storage/innobase/fts/fts0config.cc8
-rw-r--r--storage/innobase/fts/fts0fts.cc18
-rw-r--r--storage/innobase/fts/fts0opt.cc28
-rw-r--r--storage/innobase/fts/fts0que.cc8
-rw-r--r--storage/innobase/fts/fts0sql.cc2
-rw-r--r--storage/innobase/handler/ha_innodb.cc2
-rw-r--r--storage/innobase/handler/i_s.cc2
-rw-r--r--storage/innobase/include/btr0btr.h5
-rw-r--r--storage/innobase/include/fil0pagecompress.h4
-rw-r--r--storage/innobase/include/pars0pars.h10
-rw-r--r--storage/innobase/lock/lock0lock.cc25
-rw-r--r--storage/innobase/pars/pars0pars.cc4
-rw-r--r--storage/innobase/row/row0import.cc289
-rw-r--r--storage/innobase/row/row0ins.cc34
-rw-r--r--storage/innobase/row/row0mysql.cc50
-rw-r--r--storage/innobase/srv/srv0srv.cc4
-rw-r--r--storage/perfschema/CMakeLists.txt3
-rw-r--r--storage/spider/mysql-test/spider/bugfix/include/mdev_24523_deinit.inc9
-rw-r--r--storage/spider/mysql-test/spider/bugfix/include/mdev_24523_init.inc31
-rw-r--r--storage/spider/mysql-test/spider/bugfix/r/mdev_24523.result58
-rw-r--r--storage/spider/mysql-test/spider/bugfix/t/mdev_24523.cnf3
-rw-r--r--storage/spider/mysql-test/spider/bugfix/t/mdev_24523.test66
-rw-r--r--tests/mysql_client_test.c12
85 files changed, 1512 insertions, 449 deletions
diff --git a/cmake/plugin.cmake b/cmake/plugin.cmake
index 95729e29fce..813d8ef6e42 100644
--- a/cmake/plugin.cmake
+++ b/cmake/plugin.cmake
@@ -30,13 +30,13 @@ INCLUDE(CMakeParseArguments)
# [CONFIG cnf_file_name]
# [VERSION version_string]
# [LINK_LIBRARIES lib1...libN]
-# [DEPENDENCIES target1...targetN]
+# [DEPENDS target1...targetN]
MACRO(MYSQL_ADD_PLUGIN)
CMAKE_PARSE_ARGUMENTS(ARG
"STORAGE_ENGINE;STATIC_ONLY;MODULE_ONLY;MANDATORY;DEFAULT;DISABLED;NOT_EMBEDDED;RECOMPILE_FOR_EMBEDDED;CLIENT"
"MODULE_OUTPUT_NAME;STATIC_OUTPUT_NAME;COMPONENT;CONFIG;VERSION"
- "LINK_LIBRARIES;DEPENDENCIES"
+ "LINK_LIBRARIES;DEPENDS"
${ARGN}
)
IF(NOT WITHOUT_SERVER OR ARG_CLIENT)
@@ -115,8 +115,8 @@ MACRO(MYSQL_ADD_PLUGIN)
ENDIF()
UNSET(${with_var} CACHE)
- IF(NOT ARG_DEPENDENCIES)
- SET(ARG_DEPENDENCIES)
+ IF(NOT ARG_DEPENDS)
+ SET(ARG_DEPENDS)
ENDIF()
IF(ARG_VERSION)
@@ -146,7 +146,7 @@ MACRO(MYSQL_ADD_PLUGIN)
ADD_LIBRARY(${target} STATIC ${SOURCES})
DTRACE_INSTRUMENT(${target})
- ADD_DEPENDENCIES(${target} GenError ${ARG_DEPENDENCIES})
+ ADD_DEPENDENCIES(${target} GenError ${ARG_DEPENDS})
RESTRICT_SYMBOL_EXPORTS(${target})
IF(WITH_EMBEDDED_SERVER AND (NOT ARG_NOT_EMBEDDED))
# Embedded library should contain PIC code and be linkable
@@ -160,7 +160,7 @@ MACRO(MYSQL_ADD_PLUGIN)
SET_TARGET_PROPERTIES(${target}_embedded
PROPERTIES COMPILE_DEFINITIONS "EMBEDDED_LIBRARY${version_string}")
ENDIF()
- ADD_DEPENDENCIES(${target}_embedded GenError)
+ ADD_DEPENDENCIES(${target}_embedded GenError ${ARG_DEPENDS})
ENDIF()
ENDIF()
@@ -235,7 +235,7 @@ MACRO(MYSQL_ADD_PLUGIN)
TARGET_LINK_LIBRARIES (${target} "-Wl,--no-undefined")
ENDIF()
- ADD_DEPENDENCIES(${target} GenError ${ARG_DEPENDENCIES})
+ ADD_DEPENDENCIES(${target} GenError ${ARG_DEPENDS})
SET_TARGET_PROPERTIES(${target} PROPERTIES
OUTPUT_NAME "${ARG_MODULE_OUTPUT_NAME}")
diff --git a/debian/autobake-deb.sh b/debian/autobake-deb.sh
index 5e4beb1aa41..5a78c527e3c 100755
--- a/debian/autobake-deb.sh
+++ b/debian/autobake-deb.sh
@@ -17,29 +17,17 @@ set -e
# building the deb packages here.
export DEB_BUILD_OPTIONS="nocheck $DEB_BUILD_OPTIONS"
-# Take the files and part of control from MCS directory
-if [[ -d storage/columnstore/columnstore/debian ]]
-then
- cp -v storage/columnstore/columnstore/debian/mariadb-plugin-columnstore.* debian/
- echo >> debian/control
- cat storage/columnstore/columnstore/debian/control >> debian/control
-
- # ColumnStore is explicitly disabled in the native build, so allow it now
- # when build it when triggered by autobake-deb.sh
- sed '/-DPLUGIN_COLUMNSTORE=NO/d' -i debian/rules
-fi
-
# General CI optimizations to keep build output smaller
if [[ $TRAVIS ]] || [[ $GITLAB_CI ]]
then
# On both Travis and Gitlab the output log must stay under 4MB so make the
# build less verbose
- sed '/Add support for verbose builds/,/^$/d' -i debian/rules
-
# MCOL-4149: ColumnStore builds are so slow and big that they must be skipped on
# both Travis-CI and Gitlab-CI
- sed 's|$(CMAKEFLAGS)|$(CMAKEFLAGS) -DPLUGIN_COLUMNSTORE=NO|' -i debian/rules
- sed "/Package: mariadb-plugin-columnstore/,/^$/d" -i debian/control
+ sed -e '/Add support for verbose builds/,/^$/d' \
+ -e '/ColumnStore is part of the build/,/^$/d' \
+ -e 's|$(CMAKEFLAGS)|$(CMAKEFLAGS) -DPLUGIN_COLUMNSTORE=NO|' \
+ -i debian/rules
fi
# Don't build or try to put files in a package for selected plugins and components on Travis-CI
diff --git a/debian/rules b/debian/rules
index 123a0b9305e..03e8f280a63 100755
--- a/debian/rules
+++ b/debian/rules
@@ -38,11 +38,6 @@ else
NUMJOBS = 1
endif
-# RocksDB cannot build on 32-bit platforms
-ifeq (32,$(DEB_HOST_ARCH_BITS))
- CMAKEFLAGS += -DPLUGIN_ROCKSDB=NO
-endif
-
# Cross building requires stack direction instruction
ifneq ($(DEB_BUILD_ARCH),$(DEB_HOST_ARCH))
ifneq (,$(filter $(DEB_HOST_ARCH_CPU),alpha amd64 arm arm64 i386 ia64 m68k mips64el mipsel powerpc ppc64 ppc64el riscv64 s390x sh4 sparc64))
@@ -59,14 +54,6 @@ ifneq (,$(filter $(DEB_HOST_ARCH_CPU),amd64 arm64 ppc64el))
CMAKEFLAGS += -DWITH_PMEM=yes
endif
-# Add extra flag to avoid WolfSSL code crashing the entire mariadbd on s390x. This
-# can be removed once upstream has made the code s390x compatible, see
-# https://jira.mariadb.org/browse/MDEV-21705 and
-# https://github.com/wolfSSL/wolfssl/issues/2828
-ifeq ($(DEB_HOST_ARCH),s390x)
- CFLAGS += -DWC_NO_CACHE_RESISTANT
-endif
-
# Add support for verbose builds
MAKEFLAGS += VERBOSE=1
@@ -85,15 +72,25 @@ ifneq ($(DEB_BUILD_ARCH),$(DEB_HOST_ARCH))
dpkg-architecture -a$(DEB_BUILD_ARCH) -f -c dh_auto_configure --builddirectory=builddir-native
dh_auto_build --builddirectory=builddir-native -- import_executables
endif
+
+ # ColumnStore is part of the build
+ifneq (32,$(DEB_HOST_ARCH_BITS))
+ # Take the files and part of control from MCS directory
+ cp -v storage/columnstore/columnstore/debian/mariadb-plugin-columnstore.* debian/
+ # Don't include twice
+ grep -q '^Package: mariadb-plugin-columnstore$$' debian/control || \
+ ( echo && cat storage/columnstore/columnstore/debian/control ) >> debian/control
+endif
+
echo "server:Version=$(DEB_VERSION)" >> debian/substvars
- # Don't build ColumnStore as part of the native build, only build it when
- # triggered by autobake-deb.sh. Saves build time and disk space.
+ # RocksDB and Column Store cannot build on 32-bit platforms
PATH=$${MYSQL_BUILD_PATH:-"/usr/lib/ccache:/usr/local/bin:/usr/bin:/bin"} \
NO_UPDATE_BUILD_VERSION=1 \
dh_auto_configure --builddirectory=$(BUILDDIR) -- \
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
$(CMAKEFLAGS) \
+ $(if $(findstring $(DEB_HOST_ARCH_BITS),32),-DPLUGIN_ROCKSDB=NO -DPLUGIN_COLUMNSTORE=NO) \
$(if $(filter $(DEB_BUILD_ARCH),$(DEB_HOST_ARCH)),,-DIMPORT_EXECUTABLES=$(CURDIR)/builddir-native/import_executables.cmake) \
-DCOMPILATION_COMMENT="mariadb.org binary distribution" \
-DMYSQL_SERVER_SUFFIX="-$(DEB_VERSION_REVISION)" \
@@ -102,7 +99,6 @@ endif
-DBUILD_CONFIG=mysql_release \
-DCONC_DEFAULT_CHARSET=utf8mb4 \
-DPLUGIN_AWS_KEY_MANAGEMENT=NO \
- -DPLUGIN_COLUMNSTORE=NO \
-DIGNORE_AIO_CHECK=YES \
-DWITH_URING=yes \
-DDEB=$(DEB_VENDOR)
diff --git a/extra/mariabackup/xtrabackup.cc b/extra/mariabackup/xtrabackup.cc
index ff6fc6100e9..e1875e5a265 100644
--- a/extra/mariabackup/xtrabackup.cc
+++ b/extra/mariabackup/xtrabackup.cc
@@ -3450,7 +3450,7 @@ next_file:
if (err == ERROR_NO_MORE_FILES) {
status = 1;
} else {
- msg("readdir_next_file in %s returned %lu", dir, err);
+ msg("FindNextFile in %s returned %lu", dirname, err);
status = -1;
}
}
diff --git a/mysql-test/suite/binlog/r/show_concurrent_rotate.result b/mysql-test/suite/binlog/r/show_concurrent_rotate.result
index cee5de33973..b830b75eeef 100644
--- a/mysql-test/suite/binlog/r/show_concurrent_rotate.result
+++ b/mysql-test/suite/binlog/r/show_concurrent_rotate.result
@@ -2,9 +2,10 @@ connect con1,localhost,root,,;
FLUSH LOGS;
FLUSH LOGS;
FLUSH LOGS;
-SET DEBUG_SYNC= "at_after_lock_index WAIT_FOR con1_go";
+SET DEBUG_SYNC= "at_after_lock_index SIGNAL con1_ready WAIT_FOR con1_go";
SHOW BINARY LOGS;
connect con2,localhost,root,,;
+SET DEBUG_SYNC= "now WAIT_FOR con1_ready";
RESET MASTER;
FLUSH LOGS;
SET DEBUG_SYNC= "now SIGNAL con1_go";
diff --git a/mysql-test/suite/binlog/t/show_concurrent_rotate.test b/mysql-test/suite/binlog/t/show_concurrent_rotate.test
index 79d36c30a86..b5758e3a883 100644
--- a/mysql-test/suite/binlog/t/show_concurrent_rotate.test
+++ b/mysql-test/suite/binlog/t/show_concurrent_rotate.test
@@ -8,10 +8,15 @@ FLUSH LOGS;
FLUSH LOGS;
FLUSH LOGS;
-SET DEBUG_SYNC= "at_after_lock_index WAIT_FOR con1_go";
+# This forced synchronization pattern ensures con1 will execute its retry
+# path. More specifically, con1 should see that the cache of log files it
+# creates during SHOW BINARY LOGS becomes invalidated after con2 completes
+# RESET MASTER.
+SET DEBUG_SYNC= "at_after_lock_index SIGNAL con1_ready WAIT_FOR con1_go";
--send SHOW BINARY LOGS
connect(con2,localhost,root,,);
+SET DEBUG_SYNC= "now WAIT_FOR con1_ready";
RESET MASTER;
FLUSH LOGS;
SET DEBUG_SYNC= "now SIGNAL con1_go";
diff --git a/mysql-test/suite/encryption/r/innodb_import.result b/mysql-test/suite/encryption/r/innodb_import.result
new file mode 100644
index 00000000000..169af37f404
--- /dev/null
+++ b/mysql-test/suite/encryption/r/innodb_import.result
@@ -0,0 +1,21 @@
+#
+# MDEV-26131 SEGV in ha_innobase::discard_or_import_tablespace
+#
+CREATE TABLE t1(f1 int,f2 text)ENGINE=InnoDB;
+INSERT INTO t1 VALUES(1, "InnoDB");
+CREATE TABLE t2 LIKE t1;
+ALTER TABLE t2 ADD KEY idx (f2(13));
+ALTER TABLE t2 DISCARD TABLESPACE;
+FLUSH TABLES t1 FOR EXPORT;
+UNLOCK TABLES;
+ALTER TABLE t2 IMPORT TABLESPACE;
+ERROR HY000: Internal error: Drop all secondary indexes before importing table test/t2 when .cfg file is missing.
+ALTER TABLE t2 DROP KEY idx;
+ALTER TABLE t2 IMPORT TABLESPACE;
+Warnings:
+Warning 1814 Tablespace has been discarded for table `t2`
+Warning 1810 IO Read error: (2, No such file or directory) Error opening './test/t2.cfg', will attempt to import without schema verification
+SELECT * FROM t2;
+f1 f2
+1 InnoDB
+DROP TABLE t1, t2;
diff --git a/mysql-test/suite/encryption/t/innodb_import.combinations b/mysql-test/suite/encryption/t/innodb_import.combinations
new file mode 100644
index 00000000000..75458949582
--- /dev/null
+++ b/mysql-test/suite/encryption/t/innodb_import.combinations
@@ -0,0 +1,7 @@
+[page_compressed]
+innodb-compression-default=1
+[encryption]
+innodb-encrypt-tables=1
+[page_compressed_encryption]
+innodb-compression-default=1
+innodb-encrypt-tables=1
diff --git a/mysql-test/suite/encryption/t/innodb_import.opt b/mysql-test/suite/encryption/t/innodb_import.opt
new file mode 100644
index 00000000000..c44c611ed60
--- /dev/null
+++ b/mysql-test/suite/encryption/t/innodb_import.opt
@@ -0,0 +1 @@
+--innodb-checksum-algorithm=crc32
diff --git a/mysql-test/suite/encryption/t/innodb_import.test b/mysql-test/suite/encryption/t/innodb_import.test
new file mode 100644
index 00000000000..2e5470c5568
--- /dev/null
+++ b/mysql-test/suite/encryption/t/innodb_import.test
@@ -0,0 +1,23 @@
+--source include/have_innodb.inc
+--source include/have_example_key_management_plugin.inc
+--source include/innodb_checksum_algorithm.inc
+--echo #
+--echo # MDEV-26131 SEGV in ha_innobase::discard_or_import_tablespace
+--echo #
+let $MYSQLD_DATADIR = `SELECT @@datadir`;
+CREATE TABLE t1(f1 int,f2 text)ENGINE=InnoDB;
+INSERT INTO t1 VALUES(1, "InnoDB");
+CREATE TABLE t2 LIKE t1;
+ALTER TABLE t2 ADD KEY idx (f2(13));
+ALTER TABLE t2 DISCARD TABLESPACE;
+FLUSH TABLES t1 FOR EXPORT;
+--copy_file $MYSQLD_DATADIR/test/t1.ibd $MYSQLD_DATADIR/test/t2.ibd
+UNLOCK TABLES;
+--error ER_INTERNAL_ERROR
+ALTER TABLE t2 IMPORT TABLESPACE;
+
+ALTER TABLE t2 DROP KEY idx;
+--replace_regex /opening '.*\/test\//opening '.\/test\//
+ALTER TABLE t2 IMPORT TABLESPACE;
+SELECT * FROM t2;
+DROP TABLE t1, t2;
diff --git a/mysql-test/suite/federated/federated_partition.result b/mysql-test/suite/federated/federated_partition.result
index c8a61d825b6..374dba515c7 100644
--- a/mysql-test/suite/federated/federated_partition.result
+++ b/mysql-test/suite/federated/federated_partition.result
@@ -47,6 +47,42 @@ connection slave;
drop table federated.t1_1;
drop table federated.t1_2;
End of 5.1 tests
+#
+# MDEV-18734 ASAN heap-use-after-free upon sorting by blob column from partitioned table
+#
+connection slave;
+use federated;
+create table t1_1 (x int, b text, key(x));
+create table t1_2 (x int, b text, key(x));
+connection master;
+create table t1 (x int, b text, key(x)) engine=federated
+partition by range columns (x) (
+partition p1 values less than (40) connection='mysql://root@127.0.0.1:SLAVE_PORT/federated/t1_1',
+partition pn values less than (maxvalue) connection='mysql://root@127.0.0.1:SLAVE_PORT/federated/t1_2'
+);
+insert t1 values (1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6), (7, 7), (8, 8);
+insert t1 select x + 8, x + 8 from t1;
+insert t1 select x + 16, x + 16 from t1;
+insert t1 select x + 49, repeat(x + 49, 100) from t1;
+flush tables;
+# This produces wrong result before MDEV-17573
+select x, left(b, 10) from t1 where x > 30 and x < 60 order by b;
+x left(b, 10)
+31 31
+32 32
+50 5050505050
+51 5151515151
+52 5252525252
+53 5353535353
+54 5454545454
+55 5555555555
+56 5656565656
+57 5757575757
+58 5858585858
+59 5959595959
+drop table t1;
+connection slave;
+drop table t1_1, t1_2;
connection master;
DROP TABLE IF EXISTS federated.t1;
DROP DATABASE IF EXISTS federated;
diff --git a/mysql-test/suite/federated/federated_partition.test b/mysql-test/suite/federated/federated_partition.test
index 47110b5eebf..42f56134279 100644
--- a/mysql-test/suite/federated/federated_partition.test
+++ b/mysql-test/suite/federated/federated_partition.test
@@ -51,4 +51,29 @@ drop table federated.t1_2;
--echo End of 5.1 tests
+--echo #
+--echo # MDEV-18734 ASAN heap-use-after-free upon sorting by blob column from partitioned table
+--echo #
+connection slave;
+use federated;
+create table t1_1 (x int, b text, key(x));
+create table t1_2 (x int, b text, key(x));
+connection master;
+--replace_result $SLAVE_MYPORT SLAVE_PORT
+eval create table t1 (x int, b text, key(x)) engine=federated
+ partition by range columns (x) (
+ partition p1 values less than (40) connection='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t1_1',
+ partition pn values less than (maxvalue) connection='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t1_2'
+);
+insert t1 values (1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6), (7, 7), (8, 8);
+insert t1 select x + 8, x + 8 from t1;
+insert t1 select x + 16, x + 16 from t1;
+insert t1 select x + 49, repeat(x + 49, 100) from t1;
+flush tables;
+--echo # This produces wrong result before MDEV-17573
+select x, left(b, 10) from t1 where x > 30 and x < 60 order by b;
+drop table t1;
+connection slave;
+drop table t1_1, t1_2;
+
source include/federated_cleanup.inc;
diff --git a/mysql-test/suite/galera/r/galera_as_slave_replay.result b/mysql-test/suite/galera/r/galera_as_slave_replay.result
index 3c2cea19179..d81795eeed9 100644
--- a/mysql-test/suite/galera/r/galera_as_slave_replay.result
+++ b/mysql-test/suite/galera/r/galera_as_slave_replay.result
@@ -84,11 +84,21 @@ SET GLOBAL wsrep_provider_options = 'dbug=';
SET GLOBAL wsrep_provider_options = 'signal=commit_monitor_enter_sync';
SET DEBUG_SYNC = "RESET";
connection node_2a;
-set session wsrep_sync_wait=15;
-SELECT COUNT(*) = 1 FROM test.t1 WHERE f2 = 'e';
-COUNT(*) = 1
-1
set session wsrep_sync_wait=0;
+SELECT * from test.t1;
+f1 f2
+1 a
+2 b
+3 e
+4 d
+connection node_1;
+SELECT * from test.t1;
+f1 f2
+1 a
+2 b
+3 e
+4 d
+connection node_2a;
STOP SLAVE;
RESET SLAVE;
DROP TABLE t1;
diff --git a/mysql-test/suite/galera/t/galera_as_slave_replay.test b/mysql-test/suite/galera/t/galera_as_slave_replay.test
index 47f70bda721..2e8f45a047b 100644
--- a/mysql-test/suite/galera/t/galera_as_slave_replay.test
+++ b/mysql-test/suite/galera/t/galera_as_slave_replay.test
@@ -185,11 +185,17 @@ SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_cb";
SET DEBUG_SYNC = "RESET";
--connection node_2a
-
-set session wsrep_sync_wait=15;
-SELECT COUNT(*) = 1 FROM test.t1 WHERE f2 = 'e';
set session wsrep_sync_wait=0;
+--let $wait_condition = SELECT COUNT(*) = 1 FROM test.t1 where f2 = 'e'
+--source include/wait_condition.inc
+SELECT * from test.t1;
+--connection node_1
+--let $wait_condition = SELECT COUNT(*) = 1 FROM test.t1 where f2 = 'e'
+--source include/wait_condition.inc
+SELECT * from test.t1;
+
+--connection node_2a
STOP SLAVE;
RESET SLAVE;
diff --git a/mysql-test/suite/galera_sr/r/MDEV-25717.result b/mysql-test/suite/galera_sr/r/MDEV-25717.result
new file mode 100644
index 00000000000..22f8d5eb5db
--- /dev/null
+++ b/mysql-test/suite/galera_sr/r/MDEV-25717.result
@@ -0,0 +1,47 @@
+connection node_2;
+connection node_1;
+connection node_1;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) Engine=InnoDB;
+INSERT INTO t1 VALUES (1), (2), (3);
+connection node_2;
+SET SESSION wsrep_trx_fragment_size = 1;
+START TRANSACTION;
+INSERT INTO t1 VALUES (4);
+connection node_1;
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+3
+connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2;
+connection node_2a;
+SET GLOBAL DEBUG_DBUG = "d,sync.wsrep_apply_toi";
+connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1;
+connection node_1a;
+SET GLOBAL DEBUG_DBUG = "d,sync.wsrep_bf_abort";
+connection node_1;
+TRUNCATE TABLE t1;
+connection node_1a;
+SET DEBUG_SYNC = "now WAIT_FOR sync.wsrep_bf_abort_reached";
+connection node_2a;
+SET DEBUG_SYNC = "now WAIT_FOR sync.wsrep_apply_toi_reached";
+connection node_2;
+INSERT INTO t1 VALUES (5);
+connection node_2a;
+SET SESSION wsrep_sync_wait = 0;
+SET SESSION wsrep_sync_wait = DEFAULT;
+SET GLOBAL DEBUG_DBUG = "";
+SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_toi";
+connection node_2;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+connection node_1a;
+SET SESSION wsrep_sync_wait=0;
+SET GLOBAL DEBUG_DBUG = "+d,sync.wsrep_log_dummy_write_set";
+SET DEBUG_SYNC = "now SIGNAL signal.wsrep_bf_abort";
+SET DEBUG_SYNC = "now WAIT_FOR sync.wsrep_log_dummy_write_set_reached";
+connection node_1;
+connection node_2;
+SET GLOBAL DEBUG_DBUG = "";
+SET DEBUG_SYNC = "RESET";
+connection node_1;
+SET GLOBAL DEBUG_DBUG = "";
+SET DEBUG_SYNC = "RESET";
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera_sr/t/MDEV-25717.test b/mysql-test/suite/galera_sr/t/MDEV-25717.test
new file mode 100644
index 00000000000..7188f8bb172
--- /dev/null
+++ b/mysql-test/suite/galera_sr/t/MDEV-25717.test
@@ -0,0 +1,113 @@
+#
+# MDEV-25717 Assertion `owning_thread_id_ == wsrep::this_thread::get_id()'
+#
+# This test exposes a race condition between rollbacker thread and rollback
+# fragment processing.
+#
+
+--source include/galera_cluster.inc
+--source include/have_debug_sync.inc
+
+--connection node_1
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) Engine=InnoDB;
+INSERT INTO t1 VALUES (1), (2), (3);
+
+#
+# On node_2 we start a SR transaction, it going to
+# be BF aborted later on
+#
+--connection node_2
+SET SESSION wsrep_trx_fragment_size = 1;
+START TRANSACTION;
+INSERT INTO t1 VALUES (4);
+
+--connection node_1
+SELECT COUNT(*) FROM t1; # Sync wait
+
+#
+# Issue a conflicting TRUNCATE statement on node_1:
+# - on node_2, block it before it is going to apply
+# - on node_1, block before the before it BF aborts the INSERT
+#
+--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
+--connection node_2a
+SET GLOBAL DEBUG_DBUG = "d,sync.wsrep_apply_toi";
+
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+--connection node_1a
+SET GLOBAL DEBUG_DBUG = "d,sync.wsrep_bf_abort";
+
+--connection node_1
+--send TRUNCATE TABLE t1
+
+--connection node_1a
+SET DEBUG_SYNC = "now WAIT_FOR sync.wsrep_bf_abort_reached";
+
+--connection node_2a
+SET DEBUG_SYNC = "now WAIT_FOR sync.wsrep_apply_toi_reached";
+
+#
+# Generate one more fragment on the SR transaction.
+# This is going to fail certification and results
+# in a rollback fragment.
+#
+--connection node_2
+--let $expected_cert_failures = `SELECT VARIABLE_VALUE + 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_cert_failures'`
+
+--send INSERT INTO t1 VALUES (5)
+
+#
+# Wait until after certify and observe the certification
+# failure. Let both continue and we are done on node_2.
+#
+--connection node_2a
+SET SESSION wsrep_sync_wait = 0;
+--let $wait_condition = SELECT VARIABLE_VALUE = $expected_cert_failures FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_cert_failures'
+--source include/wait_condition.inc
+SET SESSION wsrep_sync_wait = DEFAULT;
+
+SET GLOBAL DEBUG_DBUG = "";
+SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_toi";
+
+--connection node_2
+--error ER_LOCK_DEADLOCK
+--reap
+
+#
+# On node_1 we expect the following things:
+# - the TRUNCATE should successfully bf abort the transaction
+# - A rollback fragment should be delivered as a result of
+# certification failure. We expect the rollback fragment to
+# be delivered after TRUNCATE has bf aborted, therefore rollback
+# fragment logs a dummy writeset.
+#
+--connection node_1a
+SET SESSION wsrep_sync_wait=0;
+SET GLOBAL DEBUG_DBUG = "+d,sync.wsrep_log_dummy_write_set";
+
+# Signal the TRUNCATE to continue and observe the BF abort
+--let $expected_bf_aborts = `SELECT VARIABLE_VALUE + 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_bf_aborts'`
+SET DEBUG_SYNC = "now SIGNAL signal.wsrep_bf_abort";
+
+# Expect a timeout if bug is present
+--let $wait_condition = SELECT VARIABLE_VALUE = $expected_bf_aborts FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_bf_aborts'
+--source include/wait_condition.inc
+
+# Observe logging of dummy writeset
+SET DEBUG_SYNC = "now WAIT_FOR sync.wsrep_log_dummy_write_set_reached";
+
+# TRUNCATE succeeds
+--connection node_1
+--reap
+
+#
+# Cleanup
+#
+--connection node_2
+SET GLOBAL DEBUG_DBUG = "";
+SET DEBUG_SYNC = "RESET";
+
+--connection node_1
+SET GLOBAL DEBUG_DBUG = "";
+SET DEBUG_SYNC = "RESET";
+DROP TABLE t1;
diff --git a/mysql-test/suite/innodb/r/full_crc32_import.result b/mysql-test/suite/innodb/r/full_crc32_import.result
index 06da5716aae..6fec6107f2c 100644
--- a/mysql-test/suite/innodb/r/full_crc32_import.result
+++ b/mysql-test/suite/innodb/r/full_crc32_import.result
@@ -36,19 +36,21 @@ db.opt
t1.frm
restore: t1 .ibd and .cfg files
ALTER TABLE t1 IMPORT TABLESPACE;
+ERROR HY000: Internal error: Drop all secondary indexes before importing table test/t1 when .cfg file is missing.
+ALTER TABLE t1 DROP INDEX b;
+ALTER TABLE t1 IMPORT TABLESPACE;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL AUTO_INCREMENT,
`b` blob DEFAULT NULL,
`c` blob DEFAULT NULL,
- PRIMARY KEY (`a`),
- KEY `b` (`b`(200))
+ PRIMARY KEY (`a`)
) ENGINE=InnoDB AUTO_INCREMENT=46 DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC
UPDATE t1 set b = repeat("de", 100) where b = repeat("cd", 200);
explain SELECT a FROM t1 where b = repeat("de", 100);
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref b b 203 const # Using where
+1 SIMPLE t1 ALL NULL NULL NULL NULL # Using where
SELECT a FROM t1 where b = repeat("de", 100);
a
3
@@ -112,14 +114,19 @@ ALTER TABLE t1 ROW_FORMAT=DYNAMIC;
ALTER TABLE t1 DISCARD TABLESPACE;
restore: t1 .ibd and .cfg files
ALTER TABLE t1 IMPORT TABLESPACE;
+ERROR HY000: Internal error: Drop all secondary indexes before importing table test/t1 when .cfg file is missing.
+ALTER TABLE t1 DROP INDEX idx1;
+ALTER TABLE t1 IMPORT TABLESPACE;
+Warnings:
+Warning 1814 Tablespace has been discarded for table `t1`
+Warning 1810 IO Read error: (2, No such file or directory) Error opening './test/t1.cfg', will attempt to import without schema verification
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` int(11) NOT NULL AUTO_INCREMENT,
`c2` point NOT NULL,
`c3` linestring NOT NULL,
- PRIMARY KEY (`c1`),
- SPATIAL KEY `idx1` (`c2`)
+ PRIMARY KEY (`c1`)
) ENGINE=InnoDB AUTO_INCREMENT=14325 DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC
UPDATE t1 SET C2 = ST_GeomFromText('POINT(0 0)');
SELECT COUNT(*) FROM t1;
diff --git a/mysql-test/suite/innodb/r/implicit_gap_lock_convertion.result b/mysql-test/suite/innodb/r/implicit_gap_lock_convertion.result
new file mode 100644
index 00000000000..fd197324c3e
--- /dev/null
+++ b/mysql-test/suite/innodb/r/implicit_gap_lock_convertion.result
@@ -0,0 +1,17 @@
+CREATE TABLE t(a INT UNSIGNED PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t VALUES (10), (30);
+connect con1,localhost,root,,;
+SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
+BEGIN;
+INSERT INTO t VALUES (20);
+SELECT * FROM t WHERE a BETWEEN 10 AND 30;
+a
+10
+20
+30
+connection default;
+SET session innodb_lock_wait_timeout=1;
+INSERT INTO t VALUES (15);
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+disconnect con1;
+DROP TABLE t;
diff --git a/mysql-test/suite/innodb/r/import_corrupted.result b/mysql-test/suite/innodb/r/import_corrupted.result
new file mode 100644
index 00000000000..149a48dccfe
--- /dev/null
+++ b/mysql-test/suite/innodb/r/import_corrupted.result
@@ -0,0 +1,30 @@
+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");
+CREATE TABLE t1 (
+id INT AUTO_INCREMENT PRIMARY KEY,
+not_id INT,
+data CHAR(255),
+data2 BLOB
+) ENGINE=INNODB;
+ALTER TABLE t1 MODIFY not_id INT UNIQUE KEY;
+connect purge_control,localhost,root,,;
+START TRANSACTION WITH CONSISTENT SNAPSHOT;
+connection default;
+DELETE FROM t1 WHERE id % 2 = 1;
+FLUSH TABLES t1 FOR EXPORT;
+UNLOCK TABLES;
+connection purge_control;
+COMMIT;
+connection default;
+DROP TABLE t1;
+CREATE TABLE t2 (
+id INT AUTO_INCREMENT PRIMARY KEY,
+not_id INT UNIQUE KEY,
+data CHAR(255),
+data2 BLOB
+) ENGINE=INNODB;
+ALTER TABLE t2 DISCARD TABLESPACE;
+ALTER TABLE t2 IMPORT TABLESPACE;
+ERROR HY000: Index for table 't2' is corrupt; try to repair it
+DROP TABLE t2;
diff --git a/mysql-test/suite/innodb/r/innodb-fk-warnings.result b/mysql-test/suite/innodb/r/innodb-fk-warnings.result
index 99b16dc1e9c..c85dcf22c06 100644
--- a/mysql-test/suite/innodb/r/innodb-fk-warnings.result
+++ b/mysql-test/suite/innodb/r/innodb-fk-warnings.result
@@ -129,7 +129,7 @@ create table t2(a char(20), key(a), foreign key(a) references t1(f1)) engine=inn
ERROR HY000: Can't create table `test`.`t2` (errno: 150 "Foreign key constraint is incorrectly formed")
show warnings;
Level Code Message
-Warning 150 Create table `test`.`t2` with foreign key (a) constraint failed. Field type or character set for column 'a' does not mach referenced column 'f1'.
+Warning 150 Create table `test`.`t2` with foreign key (a) constraint failed. Field type or character set for column 'a' does not match referenced column 'f1'.
Error 1005 Can't create table `test`.`t2` (errno: 150 "Foreign key constraint is incorrectly formed")
Warning 1215 Cannot add foreign key constraint for `t2`
drop table t1;
diff --git a/mysql-test/suite/innodb/r/innodb_information_schema.result b/mysql-test/suite/innodb/r/innodb_information_schema.result
index 70458758437..6325917c236 100644
--- a/mysql-test/suite/innodb/r/innodb_information_schema.result
+++ b/mysql-test/suite/innodb/r/innodb_information_schema.result
@@ -45,7 +45,7 @@ trx_last_foreign_key_error varchar(256) YES NULL
trx_is_read_only int(1) NO 0
trx_autocommit_non_locking int(1) NO 0
trx_state trx_weight trx_tables_in_use trx_tables_locked trx_rows_locked trx_rows_modified trx_concurrency_tickets trx_isolation_level trx_unique_checks trx_foreign_key_checks
-RUNNING 3 0 1 5 1 0 REPEATABLE READ 1 1
+RUNNING 3 0 1 6 1 0 REPEATABLE READ 1 1
trx_isolation_level trx_unique_checks trx_foreign_key_checks
SERIALIZABLE 0 0
trx_state trx_isolation_level trx_last_foreign_key_error
diff --git a/mysql-test/suite/innodb/t/full_crc32_import.opt b/mysql-test/suite/innodb/t/full_crc32_import.opt
deleted file mode 100644
index ac859973988..00000000000
--- a/mysql-test/suite/innodb/t/full_crc32_import.opt
+++ /dev/null
@@ -1 +0,0 @@
---innodb_checksum_algorithm=full_crc32
diff --git a/mysql-test/suite/innodb/t/full_crc32_import.test b/mysql-test/suite/innodb/t/full_crc32_import.test
index aa4db3f9bf7..c50e3899fc8 100644
--- a/mysql-test/suite/innodb/t/full_crc32_import.test
+++ b/mysql-test/suite/innodb/t/full_crc32_import.test
@@ -53,6 +53,9 @@ ib_restore_tablespaces("test", "t1");
EOF
--remove_file $MYSQLD_DATADIR/test/t1.cfg
+--error ER_INTERNAL_ERROR
+ALTER TABLE t1 IMPORT TABLESPACE;
+ALTER TABLE t1 DROP INDEX b;
--disable_warnings
ALTER TABLE t1 IMPORT TABLESPACE;
--enable_warnings
@@ -131,9 +134,13 @@ ib_restore_tablespaces("test", "t1");
EOF
--remove_file $MYSQLD_DATADIR/test/t1.cfg
---disable_warnings
+--error ER_INTERNAL_ERROR
ALTER TABLE t1 IMPORT TABLESPACE;
--enable_warnings
+ALTER TABLE t1 DROP INDEX idx1;
+--replace_regex /opening '.*\/test\//opening '.\/test\//
+ALTER TABLE t1 IMPORT TABLESPACE;
+--disable_warnings
SHOW CREATE TABLE t1;
UPDATE t1 SET C2 = ST_GeomFromText('POINT(0 0)');
SELECT COUNT(*) FROM t1;
diff --git a/mysql-test/suite/innodb/t/implicit_gap_lock_convertion.test b/mysql-test/suite/innodb/t/implicit_gap_lock_convertion.test
new file mode 100644
index 00000000000..bf2d09ffb2e
--- /dev/null
+++ b/mysql-test/suite/innodb/t/implicit_gap_lock_convertion.test
@@ -0,0 +1,21 @@
+--source include/have_innodb.inc
+--source include/count_sessions.inc
+
+CREATE TABLE t(a INT UNSIGNED PRIMARY KEY) ENGINE=InnoDB;
+
+INSERT INTO t VALUES (10), (30);
+
+--connect (con1,localhost,root,,)
+SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
+BEGIN;
+INSERT INTO t VALUES (20);
+SELECT * FROM t WHERE a BETWEEN 10 AND 30;
+
+--connection default
+SET session innodb_lock_wait_timeout=1;
+--error ER_LOCK_WAIT_TIMEOUT
+INSERT INTO t VALUES (15);
+
+--disconnect con1
+DROP TABLE t;
+--source include/wait_until_count_sessions.inc
diff --git a/mysql-test/suite/innodb/t/import_corrupted.test b/mysql-test/suite/innodb/t/import_corrupted.test
new file mode 100644
index 00000000000..976cbe03dbb
--- /dev/null
+++ b/mysql-test/suite/innodb/t/import_corrupted.test
@@ -0,0 +1,68 @@
+--source include/have_innodb.inc
+
+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");
+
+let MYSQLD_DATADIR = `SELECT @@datadir`;
+
+CREATE TABLE t1 (
+ id INT AUTO_INCREMENT PRIMARY KEY,
+ not_id INT,
+ data CHAR(255),
+ data2 BLOB
+) ENGINE=INNODB;
+
+--disable_query_log
+--let i = 0
+while ($i != 1000) {
+ eval INSERT INTO t1 VALUES (DEFAULT, $i, REPEAT('b', 255), REPEAT('a', 5000));
+ --inc $i
+}
+--enable_query_log
+
+ALTER TABLE t1 MODIFY not_id INT UNIQUE KEY;
+
+connect (purge_control,localhost,root,,);
+START TRANSACTION WITH CONSISTENT SNAPSHOT;
+connection default;
+
+DELETE FROM t1 WHERE id % 2 = 1;
+
+FLUSH TABLES t1 FOR EXPORT;
+
+--copy_file $MYSQLD_DATADIR/test/t1.ibd $MYSQLD_DATADIR/test/tmp.ibd
+--copy_file $MYSQLD_DATADIR/test/t1.cfg $MYSQLD_DATADIR/test/tmp.cfg
+
+perl;
+use strict;
+die unless open(FILE, "+<$ENV{MYSQLD_DATADIR}/test/tmp.ibd");
+die unless truncate(FILE, 16384*23);
+close(FILE);
+EOF
+
+UNLOCK TABLES;
+connection purge_control;
+COMMIT;
+connection default;
+DROP TABLE t1;
+
+CREATE TABLE t2 (
+ id INT AUTO_INCREMENT PRIMARY KEY,
+ not_id INT UNIQUE KEY,
+ data CHAR(255),
+ data2 BLOB
+) ENGINE=INNODB;
+
+ALTER TABLE t2 DISCARD TABLESPACE;
+
+--copy_file $MYSQLD_DATADIR/test/tmp.ibd $MYSQLD_DATADIR/test/t2.ibd
+--copy_file $MYSQLD_DATADIR/test/tmp.cfg $MYSQLD_DATADIR/test/t2.cfg
+
+--error ER_NOT_KEYFILE
+ALTER TABLE t2 IMPORT TABLESPACE;
+
+DROP TABLE t2;
+
+--remove_file $MYSQLD_DATADIR/test/tmp.ibd
+--remove_file $MYSQLD_DATADIR/test/tmp.cfg
diff --git a/mysql-test/suite/innodb_fts/r/sync.result b/mysql-test/suite/innodb_fts/r/sync.result
index 92cb3a748e4..928efffdb21 100644
--- a/mysql-test/suite/innodb_fts/r/sync.result
+++ b/mysql-test/suite/innodb_fts/r/sync.result
@@ -145,3 +145,13 @@ id title
2 database
3 good
DROP TABLE t1;
+#
+# MDEV-26273 InnoDB fts DDL fails when
+# innodb_force_recovery is set to 2
+#
+# restart: --innodb_force_recovery=2
+CREATE TABLE t1 (FTS_DOC_ID BIGINT UNSIGNED KEY,
+f1 CHAR(200)) ENGINE=InnoDB;
+ALTER TABLE t1 ADD FULLTEXT INDEX(f1);
+DROP TABLE t1;
+# restart
diff --git a/mysql-test/suite/innodb_fts/t/sync.test b/mysql-test/suite/innodb_fts/t/sync.test
index 6929dce31b8..f16953ba09f 100644
--- a/mysql-test/suite/innodb_fts/t/sync.test
+++ b/mysql-test/suite/innodb_fts/t/sync.test
@@ -170,3 +170,17 @@ SET GLOBAL innodb_ft_aux_table=default;
SELECT * FROM t1 WHERE MATCH(title) AGAINST ('mysql database good');
DROP TABLE t1;
+
+--echo #
+--echo # MDEV-26273 InnoDB fts DDL fails when
+--echo # innodb_force_recovery is set to 2
+--echo #
+
+let $restart_parameters=--innodb_force_recovery=2;
+--source include/restart_mysqld.inc
+CREATE TABLE t1 (FTS_DOC_ID BIGINT UNSIGNED KEY,
+ f1 CHAR(200)) ENGINE=InnoDB;
+ALTER TABLE t1 ADD FULLTEXT INDEX(f1);
+DROP TABLE t1;
+let $restart_parameters=;
+--source include/restart_mysqld.inc
diff --git a/mysql-test/suite/innodb_gis/r/alter_spatial_index.result b/mysql-test/suite/innodb_gis/r/alter_spatial_index.result
index ada44f2062b..2f016327858 100644
--- a/mysql-test/suite/innodb_gis/r/alter_spatial_index.result
+++ b/mysql-test/suite/innodb_gis/r/alter_spatial_index.result
@@ -252,6 +252,16 @@ UNLOCK TABLES;
ALTER TABLE tab DISCARD TABLESPACE;
SELECT c1,ST_Astext(c2),ST_Astext(c4) FROM tab;
ERROR HY000: Tablespace has been discarded for table `tab`
+ERROR HY000: Internal error: Drop all secondary indexes before importing table test/tab when .cfg file is missing.
+Table Create Table
+tab CREATE TABLE `tab` (
+ `c1` int(11) NOT NULL,
+ `c2` point NOT NULL,
+ `c3` linestring NOT NULL,
+ `c4` polygon NOT NULL,
+ `c5` geometry NOT NULL,
+ PRIMARY KEY (`c2`(25))
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
CHECK TABLE tab;
Table Op Msg_type Msg_text
test.tab check status OK
@@ -282,9 +292,6 @@ INSERT INTO tab SELECT * FROM tab1;
ALTER TABLE tab DROP PRIMARY KEY;
affected rows: 1
info: Records: 1 Duplicates: 0 Warnings: 0
-ALTER TABLE tab DROP INDEX idx2;
-affected rows: 0
-info: Records: 0 Duplicates: 0 Warnings: 0
SET STATEMENT sql_mode = 'NO_ENGINE_SUBSTITUTION' FOR
CREATE TEMPORARY TABLE temp_tab AS SELECT * FROM tab where c1 = c2;
ERROR HY000: Illegal parameter data types int and point for operation '='
@@ -325,18 +332,10 @@ tab CREATE TABLE `tab` (
`c2` point NOT NULL,
`c3` linestring NOT NULL,
`c4` polygon NOT NULL,
- `c5` geometry NOT NULL,
- SPATIAL KEY `idx3` (`c3`),
- SPATIAL KEY `idx4` (`c4`) COMMENT 'testing spatial index on Polygon',
- SPATIAL KEY `idx5` (`c5`) COMMENT 'testing spatial index on Geometry',
- KEY `idx6` (`c4`(10)) USING BTREE
+ `c5` geometry NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1
SHOW INDEX FROM tab;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment Ignored
-tab 1 idx3 1 c3 A # 32 NULL SPATIAL NO
-tab 1 idx4 1 c4 A # 32 NULL SPATIAL testing spatial index on Polygon NO
-tab 1 idx5 1 c5 A # 32 NULL SPATIAL testing spatial index on Geometry NO
-tab 1 idx6 1 c4 A # 10 NULL BTREE NO
DELETE FROM tab;
ALTER TABLE tab ADD PRIMARY KEY(c2);
affected rows: 0
@@ -357,20 +356,12 @@ tab CREATE TABLE `tab` (
`c5` geometry NOT NULL,
PRIMARY KEY (`c2`(25)),
UNIQUE KEY `const_1` (`c2`(25)),
- SPATIAL KEY `idx3` (`c3`),
- SPATIAL KEY `idx4` (`c4`) COMMENT 'testing spatial index on Polygon',
- SPATIAL KEY `idx5` (`c5`) COMMENT 'testing spatial index on Geometry',
- KEY `idx6` (`c4`(10)) USING BTREE,
SPATIAL KEY `idx2` (`c2`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
SHOW INDEX FROM tab;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment Ignored
tab 0 PRIMARY 1 c2 A # 25 NULL BTREE NO
tab 0 const_1 1 c2 A # 25 NULL BTREE NO
-tab 1 idx3 1 c3 A # 32 NULL SPATIAL NO
-tab 1 idx4 1 c4 A # 32 NULL SPATIAL testing spatial index on Polygon NO
-tab 1 idx5 1 c5 A # 32 NULL SPATIAL testing spatial index on Geometry NO
-tab 1 idx6 1 c4 A # 10 NULL BTREE NO
tab 1 idx2 1 c2 A # 32 NULL SPATIAL NO
INSERT INTO tab(c1,c2,c3,c4,c5)
VALUES(1,ST_GeomFromText('POINT(10 10)'),ST_GeomFromText('LINESTRING(5 5,20 20,30 30)'),
@@ -399,20 +390,12 @@ tab CREATE TABLE `tab` (
`c5` geometry NOT NULL,
PRIMARY KEY (`c5`(10)),
UNIQUE KEY `const_1` (`c5`(10)),
- SPATIAL KEY `idx3` (`c3`),
- SPATIAL KEY `idx4` (`c4`) COMMENT 'testing spatial index on Polygon',
- SPATIAL KEY `idx5` (`c5`) COMMENT 'testing spatial index on Geometry',
- KEY `idx6` (`c4`(10)) USING BTREE,
SPATIAL KEY `idx2` (`c2`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
SHOW INDEX FROM tab;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment Ignored
tab 0 PRIMARY 1 c5 A # 10 NULL BTREE NO
tab 0 const_1 1 c5 A # 10 NULL BTREE NO
-tab 1 idx3 1 c3 A # 32 NULL SPATIAL NO
-tab 1 idx4 1 c4 A # 32 NULL SPATIAL testing spatial index on Polygon NO
-tab 1 idx5 1 c5 A # 32 NULL SPATIAL testing spatial index on Geometry NO
-tab 1 idx6 1 c4 A # 10 NULL BTREE NO
tab 1 idx2 1 c2 A # 32 NULL SPATIAL NO
INSERT INTO tab(c1,c2,c3,c4,c5)
VALUES(1,ST_GeomFromText('POINT(10 10)'),ST_GeomFromText('LINESTRING(5 5,20 20,30 30)'),
diff --git a/mysql-test/suite/innodb_gis/t/alter_spatial_index.test b/mysql-test/suite/innodb_gis/t/alter_spatial_index.test
index 9c3835a4a75..6d1607656d3 100644
--- a/mysql-test/suite/innodb_gis/t/alter_spatial_index.test
+++ b/mysql-test/suite/innodb_gis/t/alter_spatial_index.test
@@ -277,8 +277,17 @@ SELECT c1,ST_Astext(c2),ST_Astext(c4) FROM tab;
--disable_query_log
+--error ER_INTERNAL_ERROR
ALTER TABLE tab IMPORT TABLESPACE;
+ALTER TABLE tab DROP INDEX idx2;
+ALTER TABLE tab DROP INDEX idx3;
+ALTER TABLE tab DROP INDEX idx4;
+ALTER TABLE tab DROP INDEX idx5;
+ALTER TABLE tab DROP INDEX idx6;
+
+SHOW CREATE TABLE tab;
+ALTER TABLE tab IMPORT TABLESPACE;
--enable_query_log
CHECK TABLE tab;
@@ -308,7 +317,6 @@ INSERT INTO tab SELECT * FROM tab1;
--enable_info
ALTER TABLE tab DROP PRIMARY KEY;
-ALTER TABLE tab DROP INDEX idx2;
--disable_info
# Check spatial index on temp tables
diff --git a/mysql-test/suite/vcol/r/partition.result b/mysql-test/suite/vcol/r/partition.result
index bd1353fa145..d7c5052b72a 100644
--- a/mysql-test/suite/vcol/r/partition.result
+++ b/mysql-test/suite/vcol/r/partition.result
@@ -28,3 +28,76 @@ set statement sql_mode= '' for update t1 set i= 1, v= 2;
Warnings:
Warning 1906 The value specified for generated column 'v' in table 't1' has been ignored
drop table t1;
+#
+# MDEV-18734 ASAN heap-use-after-free in my_strnxfrm_simple_internal upon update on versioned partitioned table
+#
+# Cover queue_fix() in ha_partition::handle_ordered_index_scan()
+create or replace table t1 (
+x int auto_increment primary key,
+b text, v mediumtext as (b) virtual,
+index (v(10))
+) partition by range columns (x) (
+partition p1 values less than (3),
+partition p2 values less than (6),
+partition p3 values less than (9),
+partition p4 values less than (12),
+partition p5 values less than (15),
+partition p6 values less than (17),
+partition p7 values less than (19),
+partition p8 values less than (21),
+partition p9 values less than (23),
+partition p10 values less than (25),
+partition p11 values less than (27),
+partition p12 values less than (29),
+partition p13 values less than (31),
+partition p14 values less than (33),
+partition p15 values less than (35),
+partition pn values less than (maxvalue));
+insert into t1 (b) values
+(repeat('q', 8192)), (repeat('z', 8192)), (repeat('a', 8192)), (repeat('b', 8192)),
+(repeat('x', 8192)), (repeat('y', 8192));
+insert t1 (b) select b from t1;
+insert t1 (b) select b from t1;
+insert t1 (b) select b from t1;
+insert t1 (b) select b from t1;
+select x, left(b, 10), left(v, 10) from t1 where x > 30 and x < 60 order by v;
+x left(b, 10) left(v, 10)
+33 aaaaaaaaaa aaaaaaaaaa
+39 aaaaaaaaaa aaaaaaaaaa
+45 aaaaaaaaaa aaaaaaaaaa
+51 aaaaaaaaaa aaaaaaaaaa
+57 aaaaaaaaaa aaaaaaaaaa
+34 bbbbbbbbbb bbbbbbbbbb
+40 bbbbbbbbbb bbbbbbbbbb
+46 bbbbbbbbbb bbbbbbbbbb
+52 bbbbbbbbbb bbbbbbbbbb
+58 bbbbbbbbbb bbbbbbbbbb
+31 qqqqqqqqqq qqqqqqqqqq
+37 qqqqqqqqqq qqqqqqqqqq
+43 qqqqqqqqqq qqqqqqqqqq
+49 qqqqqqqqqq qqqqqqqqqq
+55 qqqqqqqqqq qqqqqqqqqq
+35 xxxxxxxxxx xxxxxxxxxx
+41 xxxxxxxxxx xxxxxxxxxx
+47 xxxxxxxxxx xxxxxxxxxx
+53 xxxxxxxxxx xxxxxxxxxx
+59 xxxxxxxxxx xxxxxxxxxx
+36 yyyyyyyyyy yyyyyyyyyy
+42 yyyyyyyyyy yyyyyyyyyy
+48 yyyyyyyyyy yyyyyyyyyy
+54 yyyyyyyyyy yyyyyyyyyy
+32 zzzzzzzzzz zzzzzzzzzz
+38 zzzzzzzzzz zzzzzzzzzz
+44 zzzzzzzzzz zzzzzzzzzz
+50 zzzzzzzzzz zzzzzzzzzz
+56 zzzzzzzzzz zzzzzzzzzz
+update t1 set b= 'bar' where v > 'a' limit 20;
+drop table t1;
+# Cover return_top_record() in ha_partition::handle_ordered_index_scan()
+create table t1 (x int primary key, b tinytext, v text as (b) virtual)
+partition by range columns (x) (
+partition p1 values less than (4),
+partition pn values less than (maxvalue));
+insert into t1 (x, b) values (1, ''), (2, ''), (3, 'a'), (4, 'b');
+update t1 set b= 'bar' where x > 0 order by v limit 2;
+drop table t1;
diff --git a/mysql-test/suite/vcol/t/partition.test b/mysql-test/suite/vcol/t/partition.test
index 889724fb1c5..408990b20a6 100644
--- a/mysql-test/suite/vcol/t/partition.test
+++ b/mysql-test/suite/vcol/t/partition.test
@@ -30,3 +30,51 @@ subpartition by hash(v) subpartitions 3 (
insert t1 set i= 0;
set statement sql_mode= '' for update t1 set i= 1, v= 2;
drop table t1;
+
+--echo #
+--echo # MDEV-18734 ASAN heap-use-after-free in my_strnxfrm_simple_internal upon update on versioned partitioned table
+--echo #
+--echo # Cover queue_fix() in ha_partition::handle_ordered_index_scan()
+create or replace table t1 (
+ x int auto_increment primary key,
+ b text, v mediumtext as (b) virtual,
+ index (v(10))
+) partition by range columns (x) (
+ partition p1 values less than (3),
+ partition p2 values less than (6),
+ partition p3 values less than (9),
+ partition p4 values less than (12),
+ partition p5 values less than (15),
+ partition p6 values less than (17),
+ partition p7 values less than (19),
+ partition p8 values less than (21),
+ partition p9 values less than (23),
+ partition p10 values less than (25),
+ partition p11 values less than (27),
+ partition p12 values less than (29),
+ partition p13 values less than (31),
+ partition p14 values less than (33),
+ partition p15 values less than (35),
+ partition pn values less than (maxvalue));
+insert into t1 (b) values
+(repeat('q', 8192)), (repeat('z', 8192)), (repeat('a', 8192)), (repeat('b', 8192)),
+(repeat('x', 8192)), (repeat('y', 8192));
+
+insert t1 (b) select b from t1;
+insert t1 (b) select b from t1;
+insert t1 (b) select b from t1;
+insert t1 (b) select b from t1;
+
+select x, left(b, 10), left(v, 10) from t1 where x > 30 and x < 60 order by v;
+update t1 set b= 'bar' where v > 'a' limit 20;
+
+drop table t1;
+
+--echo # Cover return_top_record() in ha_partition::handle_ordered_index_scan()
+create table t1 (x int primary key, b tinytext, v text as (b) virtual)
+partition by range columns (x) (
+ partition p1 values less than (4),
+ partition pn values less than (maxvalue));
+insert into t1 (x, b) values (1, ''), (2, ''), (3, 'a'), (4, 'b');
+update t1 set b= 'bar' where x > 0 order by v limit 2;
+drop table t1;
diff --git a/mysql-test/suite/versioning/r/foreign.result b/mysql-test/suite/versioning/r/foreign.result
index 07e133e1eeb..3c8508507fd 100644
--- a/mysql-test/suite/versioning/r/foreign.result
+++ b/mysql-test/suite/versioning/r/foreign.result
@@ -446,6 +446,19 @@ pk f1 f2 left(f3, 4) check_row_ts(row_start, row_end)
2 8 8 LONG HISTORICAL ROW
drop table t1;
#
+# MDEV-21555 Assertion secondary index is out of sync on delete from versioned table
+#
+create table t1 (a int, b int as (a + 1) virtual, key(a)) engine=innodb with system versioning;
+set foreign_key_checks= off;
+insert into t1 (a) values (1), (2);
+alter table t1 add foreign key (b) references t1 (a), algorithm=copy;
+update t1 set a= null where a = 1;
+delete from t1 where a is null;
+set foreign_key_checks= on;
+delete history from t1;
+delete from t1;
+drop table t1;
+#
# MDEV-20729 Fix REFERENCES constraint in column definition
#
create or replace table t1(
diff --git a/mysql-test/suite/versioning/t/foreign.test b/mysql-test/suite/versioning/t/foreign.test
index 138698b6306..934053f83ba 100644
--- a/mysql-test/suite/versioning/t/foreign.test
+++ b/mysql-test/suite/versioning/t/foreign.test
@@ -479,6 +479,24 @@ select pk, f1, f2, left(f3, 4), check_row_ts(row_start, row_end) from t1 for sys
drop table t1;
--echo #
+--echo # MDEV-21555 Assertion secondary index is out of sync on delete from versioned table
+--echo #
+create table t1 (a int, b int as (a + 1) virtual, key(a)) engine=innodb with system versioning;
+
+set foreign_key_checks= off;
+insert into t1 (a) values (1), (2);
+alter table t1 add foreign key (b) references t1 (a), algorithm=copy;
+update t1 set a= null where a = 1;
+delete from t1 where a is null;
+set foreign_key_checks= on;
+
+delete history from t1;
+delete from t1;
+
+# cleanup
+drop table t1;
+
+--echo #
--echo # MDEV-20729 Fix REFERENCES constraint in column definition
--echo #
create or replace table t1(
diff --git a/scripts/wsrep_sst_common.sh b/scripts/wsrep_sst_common.sh
index c30ee229b5f..816121dcf5c 100644
--- a/scripts/wsrep_sst_common.sh
+++ b/scripts/wsrep_sst_common.sh
@@ -1010,7 +1010,13 @@ check_port()
lsof -Pnl -i ":$port" 2>/dev/null | \
grep -q -E "^($utils)[^[:space:]]*[[:space:]]+$pid[[:space:]].*\\(LISTEN\\)" && rc=0
elif [ $sockstat_available -ne 0 ]; then
- sockstat -p "$port" 2>/dev/null | \
+ local opts='-p'
+ if [ "$OS" = 'FreeBSD' ]; then
+ # sockstat on FreeBSD requires the "-s" option
+ # to display the connection state:
+ opts='-sp'
+ fi
+ sockstat "$opts" "$port" 2>/dev/null | \
grep -q -E "[[:space:]]+($utils)[^[:space:]]*[[:space:]]+$pid[[:space:]].*[[:space:]]LISTEN" && rc=0
elif [ $ss_available -ne 0 ]; then
ss -nlpH "( sport = :$port )" 2>/dev/null | \
diff --git a/scripts/wsrep_sst_mariabackup.sh b/scripts/wsrep_sst_mariabackup.sh
index 46804c9dce4..562b9b929f2 100644
--- a/scripts/wsrep_sst_mariabackup.sh
+++ b/scripts/wsrep_sst_mariabackup.sh
@@ -166,7 +166,8 @@ get_keys()
fi
if [ -z "$ekey" -a ! -r "$ekeyfile" ]; then
- wsrep_log_error "FATAL: Either key or keyfile must be readable"
+ wsrep_log_error "FATAL: Either key must be specified " \
+ "or keyfile must be readable"
exit 3
fi
@@ -448,9 +449,30 @@ encgroups='--mysqld|sst|xtrabackup'
check_server_ssl_config()
{
- tcert=$(parse_cnf "$encgroups" 'ssl-ca')
- tpem=$(parse_cnf "$encgroups" 'ssl-cert')
- tkey=$(parse_cnf "$encgroups" 'ssl-key')
+ # backward-compatible behavior:
+ tcert=$(parse_cnf 'sst' 'tca')
+ tpem=$(parse_cnf 'sst' 'tcert')
+ tkey=$(parse_cnf 'sst' 'tkey')
+ # reading new ssl configuration options:
+ local tcert2=$(parse_cnf "$encgroups" 'ssl-ca')
+ local tpem2=$(parse_cnf "$encgroups" 'ssl-cert')
+ local tkey2=$(parse_cnf "$encgroups" 'ssl-key')
+ # if there are no old options, then we take new ones:
+ if [ -z "$tcert" -a -z "$tpem" -a -z "$tkey" ]; then
+ tcert="$tcert2"
+ tpem="$tpem2"
+ tkey="$tkey2"
+ # checking for presence of the new-style SSL configuration:
+ elif [ -n "$tcert2" -o -n "$tpem2" -o -n "$tkey2" ]; then
+ if [ "$tcert" != "$tcert2" -o \
+ "$tpem" != "$tpem2" -o \
+ "$tkey" != "$tkey2" ]
+ then
+ wsrep_log_info "new ssl configuration options (ssl-ca, ssl-cert " \
+ "and ssl-key) are ignored by SST due to presence " \
+ "of the tca, tcert and/or tkey in the [sst] section"
+ fi
+ fi
}
read_cnf()
@@ -463,18 +485,10 @@ read_cnf()
if [ $encrypt -eq 0 -o $encrypt -ge 2 ]
then
- if [ "$tmode" != 'DISABLED' -o $encrypt -ge 2 ]
- then
- tcert=$(parse_cnf 'sst' 'tca')
- tpem=$(parse_cnf 'sst' 'tcert')
- tkey=$(parse_cnf 'sst' 'tkey')
+ if [ "$tmode" != 'DISABLED' -o $encrypt -ge 2 ]; then
+ check_server_ssl_config
fi
if [ "$tmode" != 'DISABLED' ]; then
- # backward-incompatible behavior
- if [ -z "$tpem" -a -z "$tkey" -a -z "$tcert" ]; then
- # no old-style SSL config in [sst]
- check_server_ssl_config
- fi
if [ 0 -eq $encrypt -a -n "$tpem" -a -n "$tkey" ]
then
encrypt=3 # enable cert/key SSL encyption
@@ -489,7 +503,11 @@ read_cnf()
ealgo=$(parse_cnf "$encgroups" 'encrypt-algo')
eformat=$(parse_cnf "$encgroups" 'encrypt-format' 'openssl')
ekey=$(parse_cnf "$encgroups" 'encrypt-key')
- ekeyfile=$(parse_cnf "$encgroups" 'encrypt-key-file')
+ # The keyfile should be read only when the key
+ # is not specified or empty:
+ if [ -z "$ekey" ]; then
+ ekeyfile=$(parse_cnf "$encgroups" 'encrypt-key-file')
+ fi
fi
wsrep_log_info "SSL configuration: CA='$tcert', CERT='$tpem'," \
diff --git a/scripts/wsrep_sst_rsync.sh b/scripts/wsrep_sst_rsync.sh
index fc9f5017937..d90e87b68f2 100644
--- a/scripts/wsrep_sst_rsync.sh
+++ b/scripts/wsrep_sst_rsync.sh
@@ -93,7 +93,15 @@ check_pid_and_port()
else
local filter='([^[:space:]]+[[:space:]]+){4}[^[:space:]]+'
if [ $sockstat_available -eq 1 ]; then
- port_info=$(sockstat -p "$port" 2>/dev/null | \
+ local opts='-p'
+ if [ "$OS" = 'FreeBSD' ]; then
+ # sockstat on FreeBSD requires the "-s" option
+ # to display the connection state:
+ opts='-sp'
+ # in addition, sockstat produces an additional column:
+ filter='([^[:space:]]+[[:space:]]+){5}[^[:space:]]+'
+ fi
+ port_info=$(sockstat "$opts" "$port" 2>/dev/null | \
grep -E '[[:space:]]LISTEN' | grep -o -E "$filter")
else
port_info=$(ss -nlpH "( sport = :$port )" 2>/dev/null | \
@@ -388,7 +396,7 @@ EOF
# Use deltaxfer only for WAN
inv=$(basename "$0")
WHOLE_FILE_OPT=""
- if [ "${inv%wsrep_sst_rsync_wan*}" != "$inv" ]; then
+ if [ "${inv%wsrep_sst_rsync_wan*}" = "$inv" ]; then
WHOLE_FILE_OPT="--whole-file"
fi
diff --git a/sql/field.cc b/sql/field.cc
index b500cffc4d2..46a3a1deea3 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -1,6 +1,6 @@
/*
Copyright (c) 2000, 2017, Oracle and/or its affiliates.
- Copyright (c) 2008, 2020, MariaDB
+ Copyright (c) 2008, 2021, MariaDB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -8637,6 +8637,7 @@ int Field_blob::store(const char *from,size_t length,CHARSET_INFO *cs)
rc= well_formed_copy_with_check((char*) value.ptr(), (uint) new_length,
cs, from, length,
length, true, &copy_len);
+ value.length(copy_len);
Field_blob::store_length(copy_len);
bmove(ptr+packlength,(uchar*) &tmp,sizeof(char*));
diff --git a/sql/field.h b/sql/field.h
index 4b64742b7b3..94a45d23802 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -4561,7 +4561,13 @@ public:
uchar *new_ptr, uint32 length,
uchar *new_null_ptr, uint new_null_bit) override;
void sql_type(String &str) const override;
- inline bool copy()
+ /**
+ Copy blob buffer into internal storage "value" and update record pointer.
+
+ @retval true Memory allocation error
+ @retval false Success
+ */
+ bool copy()
{
uchar *tmp= get_ptr();
if (value.copy((char*) tmp, get_length(), charset()))
@@ -4573,6 +4579,33 @@ public:
memcpy(ptr+packlength, &tmp, sizeof(char*));
return 0;
}
+ void swap(String &inout, bool set_read_value)
+ {
+ if (set_read_value)
+ read_value.swap(inout);
+ else
+ value.swap(inout);
+ }
+ /**
+ Return pointer to blob cache or NULL if not cached.
+ */
+ String * cached(bool *set_read_value)
+ {
+ char *tmp= (char *) get_ptr();
+ if (!value.is_empty() && tmp == value.ptr())
+ {
+ *set_read_value= false;
+ return &value;
+ }
+
+ if (!read_value.is_empty() && tmp == read_value.ptr())
+ {
+ *set_read_value= true;
+ return &read_value;
+ }
+
+ return NULL;
+ }
/* store value for the duration of the current read record */
inline void swap_value_and_read_value()
{
diff --git a/sql/filesort.cc b/sql/filesort.cc
index c9e60aa6434..07194cb2e4f 100644
--- a/sql/filesort.cc
+++ b/sql/filesort.cc
@@ -720,6 +720,15 @@ const char* dbug_print_table_row(TABLE *table)
}
+const char* dbug_print_row(TABLE *table, uchar *rec)
+{
+ table->move_fields(table->field, rec, table->record[0]);
+ const char* ret= dbug_print_table_row(table);
+ table->move_fields(table->field, table->record[0], rec);
+ return ret;
+}
+
+
/*
Print a text, SQL-like record representation into dbug trace.
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc
index 484e3ebc281..4cb9ca9179a 100644
--- a/sql/ha_partition.cc
+++ b/sql/ha_partition.cc
@@ -5433,59 +5433,69 @@ bool ha_partition::init_record_priority_queue()
/*
Initialize the ordered record buffer.
*/
- if (!m_ordered_rec_buffer)
- {
- size_t alloc_len;
- uint used_parts= bitmap_bits_set(&m_part_info->read_partitions);
-
- if (used_parts == 0) /* Do nothing since no records expected. */
- DBUG_RETURN(false);
+ size_t alloc_len;
+ uint used_parts= bitmap_bits_set(&m_part_info->read_partitions);
- /* Allocate record buffer for each used partition. */
- m_priority_queue_rec_len= m_rec_length + PARTITION_BYTES_IN_POS;
- if (!m_using_extended_keys)
- m_priority_queue_rec_len += get_open_file_sample()->ref_length;
- alloc_len= used_parts * m_priority_queue_rec_len;
- /* Allocate a key for temporary use when setting up the scan. */
- alloc_len+= table_share->max_key_length;
+ if (used_parts == 0) /* Do nothing since no records expected. */
+ DBUG_RETURN(false);
- if (!(m_ordered_rec_buffer= (uchar*)my_malloc(key_memory_partition_sort_buffer,
- alloc_len, MYF(MY_WME))))
- DBUG_RETURN(true);
+ /* Allocate record buffer for each used partition. */
+ m_priority_queue_rec_len= m_rec_length + ORDERED_REC_OFFSET;
+ if (!m_using_extended_keys)
+ m_priority_queue_rec_len+= get_open_file_sample()->ref_length;
+ alloc_len= used_parts * m_priority_queue_rec_len;
+ /* Allocate a key for temporary use when setting up the scan. */
+ alloc_len+= table_share->max_key_length;
+ Ordered_blob_storage **blob_storage;
+ Ordered_blob_storage *objs;
+ const size_t n_all= used_parts * table->s->blob_fields;
+
+ if (!my_multi_malloc(key_memory_partition_sort_buffer, MYF(MY_WME),
+ &m_ordered_rec_buffer, alloc_len,
+ &blob_storage, n_all * sizeof *blob_storage,
+ &objs, n_all * sizeof *objs, NULL))
+ DBUG_RETURN(true);
- /*
- We set-up one record per partition and each record has 2 bytes in
- front where the partition id is written. This is used by ordered
- index_read.
- We also set-up a reference to the first record for temporary use in
- setting up the scan.
- */
- char *ptr= (char*) m_ordered_rec_buffer;
- uint i;
- for (i= bitmap_get_first_set(&m_part_info->read_partitions);
- i < m_tot_parts;
- i= bitmap_get_next_set(&m_part_info->read_partitions, i))
+ /*
+ We set-up one record per partition and each record has 2 bytes in
+ front where the partition id is written. This is used by ordered
+ index_read.
+ We also set-up a reference to the first record for temporary use in
+ setting up the scan.
+ */
+ char *ptr= (char*) m_ordered_rec_buffer;
+ uint i;
+ for (i= bitmap_get_first_set(&m_part_info->read_partitions);
+ i < m_tot_parts;
+ i= bitmap_get_next_set(&m_part_info->read_partitions, i))
+ {
+ DBUG_PRINT("info", ("init rec-buf for part %u", i));
+ if (table->s->blob_fields)
{
- DBUG_PRINT("info", ("init rec-buf for part %u", i));
- int2store(ptr, i);
- ptr+= m_priority_queue_rec_len;
+ for (uint j= 0; j < table->s->blob_fields; ++j, ++objs)
+ blob_storage[j]= new (objs) Ordered_blob_storage;
+ *((Ordered_blob_storage ***) ptr)= blob_storage;
+ blob_storage+= table->s->blob_fields;
}
- m_start_key.key= (const uchar*)ptr;
+ int2store(ptr + sizeof(String **), i);
+ ptr+= m_priority_queue_rec_len;
+ }
+ m_start_key.key= (const uchar*)ptr;
- /* Initialize priority queue, initialized to reading forward. */
- int (*cmp_func)(void *, uchar *, uchar *);
- void *cmp_arg= (void*) this;
- if (!m_using_extended_keys && !(table_flags() & HA_SLOW_CMP_REF))
- cmp_func= cmp_key_rowid_part_id;
- else
- cmp_func= cmp_key_part_id;
- DBUG_PRINT("info", ("partition queue_init(1) used_parts: %u", used_parts));
- if (init_queue(&m_queue, used_parts, 0, 0, cmp_func, cmp_arg, 0, 0))
- {
- my_free(m_ordered_rec_buffer);
- m_ordered_rec_buffer= NULL;
- DBUG_RETURN(true);
- }
+ /* Initialize priority queue, initialized to reading forward. */
+ int (*cmp_func)(void *, uchar *, uchar *);
+ void *cmp_arg= (void*) this;
+ if (!m_using_extended_keys && !(table_flags() & HA_SLOW_CMP_REF))
+ cmp_func= cmp_key_rowid_part_id;
+ else
+ cmp_func= cmp_key_part_id;
+ DBUG_PRINT("info", ("partition queue_init(1) used_parts: %u", used_parts));
+ if (init_queue(&m_queue, used_parts, ORDERED_PART_NUM_OFFSET,
+ 0, cmp_func, cmp_arg, 0, 0))
+ {
+ my_free(m_ordered_rec_buffer);
+ m_ordered_rec_buffer= NULL;
+ DBUG_RETURN(true);
}
DBUG_RETURN(false);
}
@@ -5500,6 +5510,20 @@ void ha_partition::destroy_record_priority_queue()
DBUG_ENTER("ha_partition::destroy_record_priority_queue");
if (m_ordered_rec_buffer)
{
+ if (table->s->blob_fields)
+ {
+ char *ptr= (char *) m_ordered_rec_buffer;
+ for (uint i= bitmap_get_first_set(&m_part_info->read_partitions);
+ i < m_tot_parts;
+ i= bitmap_get_next_set(&m_part_info->read_partitions, i))
+ {
+ Ordered_blob_storage **blob_storage= *((Ordered_blob_storage ***) ptr);
+ for (uint b= 0; b < table->s->blob_fields; ++b)
+ blob_storage[b]->blob.free();
+ ptr+= m_priority_queue_rec_len;
+ }
+ }
+
delete_queue(&m_queue);
my_free(m_ordered_rec_buffer);
m_ordered_rec_buffer= NULL;
@@ -5727,12 +5751,10 @@ static int cmp_part_ids(uchar *ref1, uchar *ref2)
extern "C" int cmp_key_part_id(void *ptr, uchar *ref1, uchar *ref2)
{
ha_partition *file= (ha_partition*)ptr;
- int res;
- if ((res= key_rec_cmp(file->m_curr_key_info, ref1 + PARTITION_BYTES_IN_POS,
- ref2 + PARTITION_BYTES_IN_POS)))
- {
+ if (int res= key_rec_cmp(file->m_curr_key_info,
+ ref1 + PARTITION_BYTES_IN_POS,
+ ref2 + PARTITION_BYTES_IN_POS))
return res;
- }
return cmp_part_ids(ref1, ref2);
}
@@ -6980,6 +7002,48 @@ int ha_partition::pre_ft_end()
}
+void ha_partition::swap_blobs(uchar * rec_buf, Ordered_blob_storage ** storage, bool restore)
+{
+ uint *ptr, *end;
+ uint blob_n= 0;
+ table->move_fields(table->field, rec_buf, table->record[0]);
+ for (ptr= table->s->blob_field, end= ptr + table->s->blob_fields;
+ ptr != end; ++ptr, ++blob_n)
+ {
+ DBUG_ASSERT(*ptr < table->s->fields);
+ Field_blob *blob= (Field_blob*) table->field[*ptr];
+ DBUG_ASSERT(blob->flags & BLOB_FLAG);
+ DBUG_ASSERT(blob->field_index == *ptr);
+ if (!bitmap_is_set(table->read_set, *ptr) || blob->is_null())
+ continue;
+
+ Ordered_blob_storage &s= *storage[blob_n];
+
+ if (restore)
+ {
+ /*
+ We protect only blob cache (value or read_value). If the cache was
+ empty that doesn't mean the blob was empty. Blobs allocated by a
+ storage engine should work just fine.
+ */
+ if (!s.blob.is_empty())
+ blob->swap(s.blob, s.set_read_value);
+ }
+ else
+ {
+ bool set_read_value;
+ String *cached= blob->cached(&set_read_value);
+ if (cached)
+ {
+ cached->swap(s.blob);
+ s.set_read_value= set_read_value;
+ }
+ }
+ }
+ table->move_fields(table->field, table->record[0], rec_buf);
+}
+
+
/**
Initialize a full text search using the extended API.
@@ -7687,8 +7751,8 @@ int ha_partition::handle_ordered_index_scan(uchar *buf, bool reverse_order)
{
DBUG_PRINT("info", ("reading from part %u (scan_type: %u)",
i, m_index_scan_type));
- DBUG_ASSERT(i == uint2korr(part_rec_buf_ptr));
- uchar *rec_buf_ptr= part_rec_buf_ptr + PARTITION_BYTES_IN_POS;
+ DBUG_ASSERT(i == uint2korr(part_rec_buf_ptr + ORDERED_PART_NUM_OFFSET));
+ uchar *rec_buf_ptr= part_rec_buf_ptr + ORDERED_REC_OFFSET;
handler *file= m_file[i];
switch (m_index_scan_type) {
@@ -7768,6 +7832,12 @@ int ha_partition::handle_ordered_index_scan(uchar *buf, bool reverse_order)
Initialize queue without order first, simply insert
*/
queue_element(&m_queue, j++)= part_rec_buf_ptr;
+ if (table->s->blob_fields)
+ {
+ Ordered_blob_storage **storage=
+ *((Ordered_blob_storage ***) part_rec_buf_ptr);
+ swap_blobs(rec_buf_ptr, storage, false);
+ }
}
else if (error == HA_ERR_KEY_NOT_FOUND)
{
@@ -7810,7 +7880,7 @@ int ha_partition::handle_ordered_index_scan(uchar *buf, bool reverse_order)
DBUG_PRINT("info", ("partition !bitmap_is_set(&m_mrr_used_partitions, i)"));
continue;
}
- DBUG_ASSERT(i == uint2korr(part_rec_buf_ptr));
+ DBUG_ASSERT(i == uint2korr(part_rec_buf_ptr + ORDERED_PART_NUM_OFFSET));
if (smallest_range_seq == m_stock_range_seq[i])
{
m_stock_range_seq[i]= 0;
@@ -7857,12 +7927,17 @@ void ha_partition::return_top_record(uchar *buf)
{
uint part_id;
uchar *key_buffer= queue_top(&m_queue);
- uchar *rec_buffer= key_buffer + PARTITION_BYTES_IN_POS;
+ uchar *rec_buffer= key_buffer + ORDERED_REC_OFFSET;
DBUG_ENTER("ha_partition::return_top_record");
DBUG_PRINT("enter", ("partition this: %p", this));
- part_id= uint2korr(key_buffer);
+ part_id= uint2korr(key_buffer + ORDERED_PART_NUM_OFFSET);
memcpy(buf, rec_buffer, m_rec_length);
+ if (table->s->blob_fields)
+ {
+ Ordered_blob_storage **storage= *((Ordered_blob_storage ***) key_buffer);
+ swap_blobs(buf, storage, true);
+ }
m_last_part= part_id;
DBUG_PRINT("info", ("partition m_last_part: %u", m_last_part));
m_top_entry= part_id;
@@ -7914,7 +7989,7 @@ int ha_partition::handle_ordered_index_scan_key_not_found()
This partition is used and did return HA_ERR_KEY_NOT_FOUND
in index_read_map.
*/
- curr_rec_buf= part_buf + PARTITION_BYTES_IN_POS;
+ curr_rec_buf= part_buf + ORDERED_REC_OFFSET;
error= m_file[i]->ha_index_next(curr_rec_buf);
/* HA_ERR_KEY_NOT_FOUND is not allowed from index_next! */
DBUG_ASSERT(error != HA_ERR_KEY_NOT_FOUND);
@@ -7965,7 +8040,8 @@ int ha_partition::handle_ordered_next(uchar *buf, bool is_next_same)
DBUG_RETURN(HA_ERR_END_OF_FILE);
uint part_id= m_top_entry;
- uchar *rec_buf= queue_top(&m_queue) + PARTITION_BYTES_IN_POS;
+ uchar *part_rec_buf_ptr= queue_top(&m_queue);
+ uchar *rec_buf= part_rec_buf_ptr + ORDERED_REC_OFFSET;
handler *file;
if (m_key_not_found)
@@ -8007,7 +8083,16 @@ int ha_partition::handle_ordered_next(uchar *buf, bool is_next_same)
if (m_index_scan_type == partition_read_range)
{
error= file->read_range_next();
- memcpy(rec_buf, table->record[0], m_rec_length);
+ if (likely(!error))
+ {
+ memcpy(rec_buf, table->record[0], m_rec_length);
+ if (table->s->blob_fields)
+ {
+ Ordered_blob_storage **storage=
+ *((Ordered_blob_storage ***) part_rec_buf_ptr);
+ swap_blobs(rec_buf, storage, false);
+ }
+ }
}
else if (m_index_scan_type == partition_read_multi_range)
{
@@ -8044,6 +8129,11 @@ int ha_partition::handle_ordered_next(uchar *buf, bool is_next_same)
DBUG_PRINT("info", ("m_mrr_range_current->id: %u",
m_mrr_range_current->id));
memcpy(rec_buf, table->record[0], m_rec_length);
+ if (table->s->blob_fields)
+ {
+ Ordered_blob_storage **storage= *((Ordered_blob_storage ***) part_rec_buf_ptr);
+ swap_blobs(rec_buf, storage, false);
+ }
if (((PARTITION_KEY_MULTI_RANGE *) m_range_info[part_id])->id !=
m_mrr_range_current->id)
{
@@ -8094,9 +8184,8 @@ int ha_partition::handle_ordered_next(uchar *buf, bool is_next_same)
DBUG_PRINT("info",("partition !bitmap_is_set(&m_mrr_used_partitions, i)"));
continue;
}
- DBUG_PRINT("info",("partition uint2korr: %u",
- uint2korr(part_rec_buf_ptr)));
- DBUG_ASSERT(i == uint2korr(part_rec_buf_ptr));
+ DBUG_ASSERT(i == uint2korr(part_rec_buf_ptr +
+ ORDERED_PART_NUM_OFFSET));
DBUG_PRINT("info", ("partition m_stock_range_seq[%u]: %u",
i, m_stock_range_seq[i]));
if (smallest_range_seq == m_stock_range_seq[i])
@@ -8185,7 +8274,7 @@ int ha_partition::handle_ordered_prev(uchar *buf)
DBUG_RETURN(HA_ERR_END_OF_FILE);
uint part_id= m_top_entry;
- uchar *rec_buf= queue_top(&m_queue) + PARTITION_BYTES_IN_POS;
+ uchar *rec_buf= queue_top(&m_queue) + ORDERED_REC_OFFSET;
handler *file= m_file[part_id];
if (unlikely((error= file->ha_index_prev(rec_buf))))
diff --git a/sql/ha_partition.h b/sql/ha_partition.h
index 90993cf694c..14f68b36c0b 100644
--- a/sql/ha_partition.h
+++ b/sql/ha_partition.h
@@ -21,8 +21,19 @@
#include "sql_partition.h" /* part_id_range, partition_element */
#include "queues.h" /* QUEUE */
-#define PARTITION_BYTES_IN_POS 2
+struct Ordered_blob_storage
+{
+ String blob;
+ bool set_read_value;
+ Ordered_blob_storage() : set_read_value(false)
+ {}
+};
+
#define PAR_EXT ".par"
+#define PARTITION_BYTES_IN_POS 2
+#define ORDERED_PART_NUM_OFFSET sizeof(Ordered_blob_storage **)
+#define ORDERED_REC_OFFSET (ORDERED_PART_NUM_OFFSET + PARTITION_BYTES_IN_POS)
+
/** Struct used for partition_name_hash */
typedef struct st_part_name_def
@@ -935,6 +946,7 @@ private:
int handle_ordered_next(uchar * buf, bool next_same);
int handle_ordered_prev(uchar * buf);
void return_top_record(uchar * buf);
+ void swap_blobs(uchar* rec_buf, Ordered_blob_storage ** storage, bool restore);
public:
/*
-------------------------------------------------------------------------
diff --git a/sql/item_jsonfunc.h b/sql/item_jsonfunc.h
index a249349c8f8..60600108320 100644
--- a/sql/item_jsonfunc.h
+++ b/sql/item_jsonfunc.h
@@ -525,9 +525,9 @@ public:
{
static LEX_CSTRING json_set= {STRING_WITH_LEN("json_set") };
static LEX_CSTRING json_insert= {STRING_WITH_LEN("json_insert") };
- static LEX_CSTRING json_update= {STRING_WITH_LEN("json_update") };
+ static LEX_CSTRING json_replace= {STRING_WITH_LEN("json_replace") };
return (mode_insert ?
- (mode_replace ? json_set : json_insert) : json_update);
+ (mode_replace ? json_set : json_insert) : json_replace);
}
Item *get_copy(THD *thd) override
{ return get_item_copy<Item_func_json_insert>(thd, this); }
diff --git a/sql/log.cc b/sql/log.cc
index d228cf697dd..b372af823d6 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -3396,7 +3396,7 @@ MYSQL_BIN_LOG::MYSQL_BIN_LOG(uint *sync_period)
checksum_alg_reset(BINLOG_CHECKSUM_ALG_UNDEF),
relay_log_checksum_alg(BINLOG_CHECKSUM_ALG_UNDEF),
description_event_for_exec(0), description_event_for_queue(0),
- current_binlog_id(0)
+ current_binlog_id(0), reset_master_count(0)
{
/*
We don't want to initialize locks here as such initialization depends on
@@ -4489,6 +4489,7 @@ err:
}
mysql_cond_broadcast(&COND_xid_list);
reset_master_pending--;
+ reset_master_count++;
mysql_mutex_unlock(&LOCK_xid_list);
}
diff --git a/sql/log.h b/sql/log.h
index 6227e579757..000d22854e9 100644
--- a/sql/log.h
+++ b/sql/log.h
@@ -676,6 +676,11 @@ public:
my_off_t last_commit_pos_offset;
ulong current_binlog_id;
+ /*
+ Tracks the number of times that the master has been reset
+ */
+ Atomic_counter<uint64> reset_master_count;
+
MYSQL_BIN_LOG(uint *sync_period);
/*
note that there's no destructor ~MYSQL_BIN_LOG() !
@@ -893,6 +898,7 @@ public:
inline mysql_mutex_t* get_log_lock() { return &LOCK_log; }
inline mysql_cond_t* get_bin_log_cond() { return &COND_bin_log_updated; }
inline IO_CACHE* get_log_file() { return &log_file; }
+ inline uint64 get_reset_master_count() { return reset_master_count; }
inline void lock_index() { mysql_mutex_lock(&LOCK_index);}
inline void unlock_index() { mysql_mutex_unlock(&LOCK_index);}
diff --git a/sql/sql_audit.h b/sql/sql_audit.h
index 40276c86a78..64500067699 100644
--- a/sql/sql_audit.h
+++ b/sql/sql_audit.h
@@ -155,7 +155,7 @@ void mysql_audit_general(THD *thd, uint event_subtype,
DBUG_ENTER("mysql_audit_general");
if (mysql_audit_general_enabled())
{
- char user_buff[MAX_USER_HOST_SIZE];
+ char user_buff[MAX_USER_HOST_SIZE+1];
mysql_event_general event;
event.event_subclass= event_subtype;
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 99383ba1d71..c26d8906cbd 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -4787,6 +4787,19 @@ extern "C" const char *thd_priv_host(MYSQL_THD thd, size_t *length)
}
+extern "C" const char *thd_priv_user(MYSQL_THD thd, size_t *length)
+{
+ const Security_context *sctx= thd->security_ctx;
+ if (!sctx)
+ {
+ *length= 0;
+ return NULL;
+ }
+ *length= strlen(sctx->priv_user);
+ return sctx->priv_user;
+}
+
+
#ifdef INNODB_COMPATIBILITY_HOOKS
/** open a table and add it to thd->open_tables
@@ -5446,8 +5459,8 @@ extern "C" bool thd_is_strict_mode(const MYSQL_THD thd)
*/
void thd_get_query_start_data(THD *thd, char *buf)
{
- LEX_CSTRING field_name;
- Field_timestampf f((uchar *)buf, NULL, 0, Field::NONE, &field_name, NULL, 6);
+ Field_timestampf f((uchar *)buf, nullptr, 0, Field::NONE, &empty_clex_str,
+ nullptr, 6);
f.store_TIME(thd->query_start(), thd->query_start_sec_part());
}
diff --git a/sql/sql_class.h b/sql/sql_class.h
index b112023dc7c..01fdc819f4d 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -199,6 +199,7 @@ extern MYSQL_PLUGIN_IMPORT const char **errmesg;
extern "C" LEX_STRING * thd_query_string (MYSQL_THD thd);
extern "C" unsigned long long thd_query_id(const MYSQL_THD thd);
extern "C" size_t thd_query_safe(MYSQL_THD thd, char *buf, size_t buflen);
+extern "C" const char *thd_priv_user(MYSQL_THD thd, size_t *length);
extern "C" const char *thd_priv_host(MYSQL_THD thd, size_t *length);
extern "C" const char *thd_user_name(MYSQL_THD thd);
extern "C" const char *thd_client_host(MYSQL_THD thd);
diff --git a/sql/sql_connect.h b/sql/sql_connect.h
index 1a84cb56e5c..8be6c1aecc0 100644
--- a/sql/sql_connect.h
+++ b/sql/sql_connect.h
@@ -35,7 +35,10 @@ public:
#ifdef _WIN32
HANDLE pipe;
CONNECT(HANDLE pipe_arg): pipe(pipe_arg), vio_type(VIO_TYPE_NAMEDPIPE),
- scheduler(thread_scheduler), thread_id(0), prior_thr_create_utime(0) {}
+ scheduler(thread_scheduler), thread_id(0), prior_thr_create_utime(0)
+ {
+ count++;
+ }
#endif
enum enum_vio_type vio_type;
scheduler_functions *scheduler;
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index cc2c43d3e71..41ba2a4a31e 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -3562,7 +3562,7 @@ bool st_select_lex::setup_ref_array(THD *thd, uint order_group_num)
prepared statement
*/
Query_arena *arena= thd->stmt_arena;
- const uint n_elems= (n_sum_items +
+ const size_t n_elems= (n_sum_items +
n_child_sum_items +
item_list.elements +
select_n_reserved +
@@ -3570,7 +3570,8 @@ bool st_select_lex::setup_ref_array(THD *thd, uint order_group_num)
select_n_where_fields +
order_group_num +
hidden_bit_fields +
- fields_in_window_functions) * 5;
+ fields_in_window_functions) * (size_t) 5;
+ DBUG_ASSERT(n_elems % 5 == 0);
if (!ref_pointer_array.is_null())
{
/*
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 4d7389e72bb..09ad632dd98 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -3542,6 +3542,11 @@ static void mysql_stmt_execute_common(THD *thd,
stmt_id == LAST_STMT_ID, read_types))
{
my_error(ER_MALFORMED_PACKET, MYF(0));
+ /*
+ Let's set the thd->query_string so the audit plugin
+ can report the executed query that failed.
+ */
+ thd->set_query_inner(stmt->query_string);
DBUG_VOID_RETURN;
}
diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc
index b187c26eee7..7bcff12a735 100644
--- a/sql/sql_repl.cc
+++ b/sql/sql_repl.cc
@@ -4387,6 +4387,7 @@ bool show_binlogs(THD* thd)
Protocol *protocol= thd->protocol;
uint retry_count= 0;
size_t cur_dir_len;
+ uint64 expected_reset_masters;
DBUG_ENTER("show_binlogs");
if (!mysql_bin_log.is_open())
@@ -4411,6 +4412,7 @@ retry:
mysql_mutex_lock(mysql_bin_log.get_log_lock());
mysql_bin_log.lock_index();
mysql_bin_log.raw_get_current_log(&cur);
+ expected_reset_masters= mysql_bin_log.get_reset_master_count();
mysql_mutex_unlock(mysql_bin_log.get_log_lock());
/* The following call unlocks lock_index */
@@ -4431,6 +4433,16 @@ retry:
cur_link->name.str+= dir_len;
cur_link->name.length-= dir_len;
+ if (mysql_bin_log.get_reset_master_count() > expected_reset_masters)
+ {
+ /*
+ Reset master was called after we cached filenames.
+ Reinitialize the cache.
+ */
+ free_root(&mem_root, MYF(MY_MARK_BLOCKS_FREE));
+ goto retry;
+ }
+
if (!(strncmp(fname+dir_len, cur.log_file_name+cur_dir_len, length)))
cur_link->size= cur.pos; /* The active log, use the active position */
else
diff --git a/sql/sql_view.cc b/sql/sql_view.cc
index eb5c1bff200..20ac4b086bb 100644
--- a/sql/sql_view.cc
+++ b/sql/sql_view.cc
@@ -887,7 +887,7 @@ int mariadb_fix_view(THD *thd, TABLE_LIST *view, bool wrong_checksum,
if ((view->md5.str= (char *)thd->alloc(32 + 1)) == NULL)
DBUG_RETURN(HA_ADMIN_FAILED);
}
- view->calc_md5(view->md5.str);
+ view->calc_md5(const_cast<char*>(view->md5.str));
view->md5.length= 32;
}
view->mariadb_version= MYSQL_VERSION_ID;
diff --git a/sql/table.cc b/sql/table.cc
index ec950c582c3..3fa1337ba0b 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -5627,12 +5627,12 @@ void TABLE::reset_item_list(List<Item> *item_list, uint skip) const
buffer buffer for md5 writing
*/
-void TABLE_LIST::calc_md5(const char *buffer)
+void TABLE_LIST::calc_md5(char *buffer)
{
uchar digest[16];
compute_md5_hash(digest, select_stmt.str,
select_stmt.length);
- sprintf((char *) buffer,
+ sprintf(buffer,
"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
digest[0], digest[1], digest[2], digest[3],
digest[4], digest[5], digest[6], digest[7],
diff --git a/sql/table.h b/sql/table.h
index a8c0358b7c4..69bde681b14 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -2636,7 +2636,7 @@ struct TABLE_LIST
List<String> *partition_names;
#endif /* WITH_PARTITION_STORAGE_ENGINE */
- void calc_md5(const char *buffer);
+ void calc_md5(char *buffer);
int view_check_option(THD *thd, bool ignore_failure);
bool create_field_translation(THD *thd);
bool setup_underlying(THD *thd);
diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc
index 0f2fa131f0a..0f150851e4f 100644
--- a/sql/wsrep_mysqld.cc
+++ b/sql/wsrep_mysqld.cc
@@ -806,17 +806,20 @@ void wsrep_init_globals()
{
wsrep_gtid_server.domain_id= wsrep_gtid_domain_id;
wsrep_init_sidno(Wsrep_server_state::instance().connected_gtid().id());
- wsrep_init_gtid();
/* Recover last written wsrep gtid */
+ wsrep_init_gtid();
if (wsrep_new_cluster)
{
- wsrep_server_gtid_t gtid= {wsrep_gtid_server.domain_id,
- wsrep_gtid_server.server_id, 0};
- wsrep_get_binlog_gtid_seqno(gtid);
- wsrep_gtid_server.seqno(gtid.seqno);
+ /* Start with provided domain_id & server_id found in configuration */
+ wsrep_server_gtid_t new_gtid;
+ new_gtid.domain_id= wsrep_gtid_domain_id;
+ new_gtid.server_id= global_system_variables.server_id;
+ new_gtid.seqno= 0;
+ /* Try to search for domain_id and server_id combination in binlog if found continue from last seqno */
+ wsrep_get_binlog_gtid_seqno(new_gtid);
+ wsrep_gtid_server.gtid(new_gtid);
}
wsrep_init_schema();
-
if (WSREP_ON)
{
Wsrep_server_state::instance().initialized();
diff --git a/storage/innobase/btr/btr0btr.cc b/storage/innobase/btr/btr0btr.cc
index 07f2ee974c0..f786da84b17 100644
--- a/storage/innobase/btr/btr0btr.cc
+++ b/storage/innobase/btr/btr0btr.cc
@@ -3119,8 +3119,8 @@ func_exit:
@param[in] block page to remove
@param[in] index index tree
@param[in,out] mtr mini-transaction */
-void btr_level_list_remove(const buf_block_t& block, const dict_index_t& index,
- mtr_t* mtr)
+dberr_t btr_level_list_remove(const buf_block_t& block,
+ const dict_index_t& index, mtr_t* mtr)
{
ut_ad(mtr->memo_contains_flagged(&block, MTR_MEMO_PAGE_X_FIX));
ut_ad(block.zip_size() == index.table->space->zip_size());
@@ -3152,6 +3152,10 @@ void btr_level_list_remove(const buf_block_t& block, const dict_index_t& index,
buf_block_t* next_block = btr_block_get(
index, next_page_no, RW_X_LATCH, page_is_leaf(page),
mtr);
+
+ if (!next_block) {
+ return DB_ERROR;
+ }
#ifdef UNIV_BTR_DEBUG
ut_a(page_is_comp(next_block->frame) == page_is_comp(page));
static_assert(FIL_PAGE_PREV % 4 == 0, "alignment");
@@ -3162,6 +3166,8 @@ void btr_level_list_remove(const buf_block_t& block, const dict_index_t& index,
btr_page_set_prev(next_block, prev_page_no, mtr);
}
+
+ return DB_SUCCESS;
}
/*************************************************************//**
@@ -3537,7 +3543,9 @@ retry:
btr_search_drop_page_hash_index(block);
/* Remove the page from the level list */
- btr_level_list_remove(*block, *index, mtr);
+ if (DB_SUCCESS != btr_level_list_remove(*block, *index, mtr)) {
+ goto err_exit;
+ }
const page_id_t id{block->page.id()};
@@ -3662,7 +3670,9 @@ retry:
#endif /* UNIV_BTR_DEBUG */
/* Remove the page from the level list */
- btr_level_list_remove(*block, *index, mtr);
+ if (DB_SUCCESS != btr_level_list_remove(*block, *index, mtr)) {
+ goto err_exit;
+ }
ut_ad(btr_node_ptr_get_child_page_no(
btr_cur_get_rec(&father_cursor), offsets)
@@ -4040,7 +4050,7 @@ btr_discard_page(
}
/* Remove the page from the level list */
- btr_level_list_remove(*block, *index, mtr);
+ ut_a(DB_SUCCESS == btr_level_list_remove(*block, *index, mtr));
#ifdef UNIV_ZIP_DEBUG
{
diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc
index a88fceac6e6..60912ac7777 100644
--- a/storage/innobase/btr/btr0cur.cc
+++ b/storage/innobase/btr/btr0cur.cc
@@ -331,10 +331,12 @@ btr_cur_latch_leaves(
true, mtr);
latch_leaves.blocks[2] = get_block;
#ifdef UNIV_BTR_DEBUG
- ut_a(page_is_comp(get_block->frame)
- == page_is_comp(block->frame));
- ut_a(btr_page_get_prev(get_block->frame)
- == block->page.id().page_no());
+ if (get_block) {
+ ut_a(page_is_comp(get_block->frame)
+ == page_is_comp(block->frame));
+ ut_a(btr_page_get_prev(get_block->frame)
+ == block->page.id().page_no());
+ }
#endif /* UNIV_BTR_DEBUG */
if (spatial) {
cursor->rtr_info->tree_blocks[
diff --git a/storage/innobase/btr/btr0defragment.cc b/storage/innobase/btr/btr0defragment.cc
index 2125b39d5b6..fa0ad06d7ab 100644
--- a/storage/innobase/btr/btr0defragment.cc
+++ b/storage/innobase/btr/btr0defragment.cc
@@ -400,7 +400,8 @@ btr_defragment_merge_pages(
const page_id_t from{from_block->page.id()};
lock_update_merge_left(*to_block, orig_pred, from);
btr_search_drop_page_hash_index(from_block);
- btr_level_list_remove(*from_block, *index, mtr);
+ 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,
diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc
index a85af2c0072..58820c7b906 100644
--- a/storage/innobase/buf/buf0buf.cc
+++ b/storage/innobase/buf/buf0buf.cc
@@ -584,8 +584,7 @@ bool buf_is_zeroes(span<const byte> buf)
/** Check if a page is corrupt.
@param[in] check_lsn whether the LSN should be checked
@param[in] read_buf database page
-@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
-@param[in] space tablespace
+@param[in] fsp_flags tablespace flags
@return whether the page is corrupted */
bool
buf_page_is_corrupted(
@@ -2656,6 +2655,10 @@ lookup:
}
}
+ if (local_err == DB_IO_ERROR) {
+ return NULL;
+ }
+
ib::fatal() << "Unable to read page " << page_id
<< " into the buffer pool after "
<< BUF_PAGE_READ_MAX_RETRIES
diff --git a/storage/innobase/buf/buf0rea.cc b/storage/innobase/buf/buf0rea.cc
index 45379bccb8c..52f10cf7582 100644
--- a/storage/innobase/buf/buf0rea.cc
+++ b/storage/innobase/buf/buf0rea.cc
@@ -339,7 +339,8 @@ nothing_read:
*err= fio.err;
if (UNIV_UNLIKELY(fio.err != DB_SUCCESS)) {
- if (!sync || fio.err == DB_TABLESPACE_DELETED) {
+ if (!sync || fio.err == DB_TABLESPACE_DELETED
+ || fio.err == DB_IO_ERROR) {
buf_pool.corrupted_evict(bpage);
return false;
}
diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc
index dea9cf740c9..0d4aa4901f8 100644
--- a/storage/innobase/fil/fil0fil.cc
+++ b/storage/innobase/fil/fil0fil.cc
@@ -2730,17 +2730,20 @@ func_exit:
/*============================ FILE I/O ================================*/
/** Report information about an invalid page access. */
-ATTRIBUTE_COLD __attribute__((noreturn))
-static void
-fil_report_invalid_page_access(const char *name,
- os_offset_t offset, ulint len, bool is_read)
+ATTRIBUTE_COLD
+static void fil_invalid_page_access_msg(bool fatal, const char *name,
+ os_offset_t offset, ulint len,
+ bool is_read)
{
- ib::fatal() << "Trying to " << (is_read ? "read " : "write ") << len
- << " bytes at " << offset
- << " outside the bounds of the file: " << name;
+ sql_print_error("%s%s %zu bytes at " UINT64PF
+ " outside the bounds of the file: %s",
+ fatal ? "[FATAL] InnoDB: " : "InnoDB: ",
+ is_read ? "Trying to read" : "Trying to write",
+ len, offset, name);
+ if (fatal)
+ abort();
}
-
/** Update the data structures on write completion */
inline void fil_node_t::complete_write()
{
@@ -2793,6 +2796,7 @@ fil_io_t fil_space_t::io(const IORequest &type, os_offset_t offset, size_t len,
}
ulint p = static_cast<ulint>(offset >> srv_page_size_shift);
+ bool fatal;
if (UNIV_LIKELY_NULL(UT_LIST_GET_NEXT(chain, node))) {
ut_ad(this == fil_system.sys_space
@@ -2803,13 +2807,16 @@ fil_io_t fil_space_t::io(const IORequest &type, os_offset_t offset, size_t len,
p -= node->size;
node = UT_LIST_GET_NEXT(chain, node);
if (!node) {
- if (type.type == IORequest::READ_ASYNC) {
- release();
- return {DB_ERROR, nullptr};
+ release();
+ if (type.type != IORequest::READ_ASYNC) {
+ fatal = true;
+fail:
+ fil_invalid_page_access_msg(
+ fatal, node->name,
+ offset, len,
+ type.is_read());
}
- fil_report_invalid_page_access(node->name,
- offset, len,
- type.is_read());
+ return {DB_IO_ERROR, nullptr};
}
}
@@ -2817,16 +2824,17 @@ fil_io_t fil_space_t::io(const IORequest &type, os_offset_t offset, size_t len,
}
if (UNIV_UNLIKELY(node->size <= p)) {
+ release();
+
if (type.type == IORequest::READ_ASYNC) {
- release();
/* If we can tolerate the non-existent pages, we
should return with DB_ERROR and let caller decide
what to do. */
return {DB_ERROR, nullptr};
}
- fil_report_invalid_page_access(
- node->name, offset, len, type.is_read());
+ fatal = node->space->purpose != FIL_TYPE_IMPORT;
+ goto fail;
}
dberr_t err;
diff --git a/storage/innobase/fil/fil0pagecompress.cc b/storage/innobase/fil/fil0pagecompress.cc
index ffa2563d338..9961bdf056c 100644
--- a/storage/innobase/fil/fil0pagecompress.cc
+++ b/storage/innobase/fil/fil0pagecompress.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (C) 2013, 2020, MariaDB Corporation.
+Copyright (C) 2013, 2021, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -596,6 +596,7 @@ ulint fil_page_decompress_for_non_full_crc32(
/** Decompress a page that may be subject to page_compressed compression.
@param[in,out] tmp_buf temporary buffer (of innodb_page_size)
@param[in,out] buf possibly compressed page buffer
+@param[in] flags tablespace flags
@return size of the compressed data
@retval 0 if decompression failed
@retval srv_page_size if the page was not compressed */
diff --git a/storage/innobase/fts/fts0config.cc b/storage/innobase/fts/fts0config.cc
index 4fa1c0c609b..09cce53f8db 100644
--- a/storage/innobase/fts/fts0config.cc
+++ b/storage/innobase/fts/fts0config.cc
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 2007, 2016, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2017, 2020, MariaDB Corporation.
+Copyright (c) 2017, 2021, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -97,7 +97,7 @@ fts_config_get_value(
fts_table->suffix = "CONFIG";
fts_get_table_name(fts_table, table_name);
- pars_info_bind_id(info, true, "table_name", table_name);
+ pars_info_bind_id(info, "table_name", table_name);
graph = fts_parse_sql(
fts_table,
@@ -213,7 +213,7 @@ fts_config_set_value(
fts_table->suffix = "CONFIG";
fts_get_table_name(fts_table, table_name, dict_locked);
- pars_info_bind_id(info, true, "table_name", table_name);
+ pars_info_bind_id(info, "table_name", table_name);
graph = fts_parse_sql(
fts_table, info,
@@ -241,7 +241,7 @@ fts_config_set_value(
info, "value", value->f_str, value->f_len);
fts_get_table_name(fts_table, table_name, dict_locked);
- pars_info_bind_id(info, true, "table_name", table_name);
+ pars_info_bind_id(info, "table_name", table_name);
graph = fts_parse_sql(
fts_table, info,
diff --git a/storage/innobase/fts/fts0fts.cc b/storage/innobase/fts/fts0fts.cc
index be05e4fb521..7b6ca048271 100644
--- a/storage/innobase/fts/fts0fts.cc
+++ b/storage/innobase/fts/fts0fts.cc
@@ -484,7 +484,7 @@ cleanup:
pars_info_t* info = pars_info_create();
- pars_info_bind_id(info, TRUE, "table_stopword", stopword_table_name);
+ pars_info_bind_id(info, "table_stopword", stopword_table_name);
pars_info_bind_function(info, "my_func", fts_read_stopword,
stopword_info);
@@ -1903,7 +1903,7 @@ fts_create_common_tables(
fts_table.suffix = "CONFIG";
fts_get_table_name(&fts_table, fts_name, true);
- pars_info_bind_id(info, true, "config_table", fts_name);
+ pars_info_bind_id(info, "config_table", fts_name);
graph = fts_parse_sql_no_dict_lock(
info, fts_config_table_insert_values_sql);
@@ -2583,7 +2583,7 @@ retry:
info, "my_func", fts_fetch_store_doc_id, doc_id);
fts_get_table_name(&fts_table, table_name);
- pars_info_bind_id(info, true, "config_table", table_name);
+ pars_info_bind_id(info, "config_table", table_name);
graph = fts_parse_sql(
&fts_table, info,
@@ -2711,7 +2711,7 @@ fts_update_sync_doc_id(
fts_get_table_name(&fts_table, fts_name,
table->fts->dict_locked);
- pars_info_bind_id(info, true, "table_name", fts_name);
+ pars_info_bind_id(info, "table_name", fts_name);
graph = fts_parse_sql(
&fts_table, info,
@@ -2854,7 +2854,7 @@ fts_delete(
fts_table.suffix = "DELETED";
fts_get_table_name(&fts_table, table_name);
- pars_info_bind_id(info, true, "deleted", table_name);
+ pars_info_bind_id(info, "deleted", table_name);
graph = fts_parse_sql(
&fts_table,
@@ -3665,7 +3665,7 @@ fts_doc_fetch_by_doc_id(
pars_info_bind_function(info, "my_func", callback, arg);
select_str = fts_get_select_columns_str(index, info, info->heap);
- pars_info_bind_id(info, TRUE, "table_name", index->table->name.m_name);
+ pars_info_bind_id(info, "table_name", index->table->name.m_name);
if (!get_doc || !get_doc->get_document_graph) {
if (option == FTS_FETCH_DOC_BY_ID_EQUAL) {
@@ -3772,7 +3772,7 @@ fts_write_node(
info = pars_info_create();
fts_get_table_name(fts_table, table_name);
- pars_info_bind_id(info, true, "index_table_name", table_name);
+ pars_info_bind_id(info, "index_table_name", table_name);
}
pars_info_bind_varchar_literal(info, "token", word->f_str, word->f_len);
@@ -3847,7 +3847,7 @@ fts_sync_add_deleted_cache(
&fts_table, "DELETED_CACHE", FTS_COMMON_TABLE, sync->table);
fts_get_table_name(&fts_table, table_name);
- pars_info_bind_id(info, true, "table_name", table_name);
+ pars_info_bind_id(info, "table_name", table_name);
graph = fts_parse_sql(
&fts_table,
@@ -4844,7 +4844,7 @@ fts_get_rows_count(
pars_info_bind_function(info, "my_func", fts_read_ulint, &count);
fts_get_table_name(fts_table, table_name);
- pars_info_bind_id(info, true, "table_name", table_name);
+ pars_info_bind_id(info, "table_name", table_name);
graph = fts_parse_sql(
fts_table,
diff --git a/storage/innobase/fts/fts0opt.cc b/storage/innobase/fts/fts0opt.cc
index 7a83930fb1a..64179947832 100644
--- a/storage/innobase/fts/fts0opt.cc
+++ b/storage/innobase/fts/fts0opt.cc
@@ -499,7 +499,7 @@ fts_index_fetch_nodes(
fts_get_table_name(fts_table, table_name);
- pars_info_bind_id(info, true, "table_name", table_name);
+ pars_info_bind_id(info, "table_name", table_name);
}
pars_info_bind_function(info, "my_func", fetch->read_record, fetch);
@@ -828,7 +828,7 @@ fts_index_fetch_words(
info, "word", word->f_str, word->f_len);
fts_get_table_name(&optim->fts_index_table, table_name);
- pars_info_bind_id(info, true, "table_name", table_name);
+ pars_info_bind_id(info, "table_name", table_name);
graph = fts_parse_sql(
&optim->fts_index_table,
@@ -984,7 +984,7 @@ fts_table_fetch_doc_ids(
pars_info_bind_function(info, "my_func", fts_fetch_doc_ids, doc_ids);
fts_get_table_name(fts_table, table_name);
- pars_info_bind_id(info, true, "table_name", table_name);
+ pars_info_bind_id(info, "table_name", table_name);
graph = fts_parse_sql(
fts_table,
@@ -1445,7 +1445,7 @@ fts_optimize_write_word(
fts_table->suffix = fts_get_suffix(selected);
fts_get_table_name(fts_table, table_name);
- pars_info_bind_id(info, true, "table_name", table_name);
+ pars_info_bind_id(info, "table_name", table_name);
graph = fts_parse_sql(
fts_table,
@@ -2037,11 +2037,11 @@ fts_optimize_purge_deleted_doc_ids(
used in the fts_delete_doc_ids_sql */
optim->fts_common_table.suffix = fts_common_tables[3];
fts_get_table_name(&optim->fts_common_table, deleted);
- pars_info_bind_id(info, true, fts_common_tables[3], deleted);
+ pars_info_bind_id(info, fts_common_tables[3], deleted);
optim->fts_common_table.suffix = fts_common_tables[4];
fts_get_table_name(&optim->fts_common_table, deleted_cache);
- pars_info_bind_id(info, true, fts_common_tables[4], deleted_cache);
+ pars_info_bind_id(info, fts_common_tables[4], deleted_cache);
graph = fts_parse_sql(NULL, info, fts_delete_doc_ids_sql);
@@ -2094,12 +2094,11 @@ fts_optimize_purge_deleted_doc_id_snapshot(
used in the fts_end_delete_sql */
optim->fts_common_table.suffix = fts_common_tables[0];
fts_get_table_name(&optim->fts_common_table, being_deleted);
- pars_info_bind_id(info, true, fts_common_tables[0], being_deleted);
+ pars_info_bind_id(info, fts_common_tables[0], being_deleted);
optim->fts_common_table.suffix = fts_common_tables[1];
fts_get_table_name(&optim->fts_common_table, being_deleted_cache);
- pars_info_bind_id(info, true, fts_common_tables[1],
- being_deleted_cache);
+ pars_info_bind_id(info, fts_common_tables[1], being_deleted_cache);
/* Delete the doc ids that were copied to delete pending state at
the start of optimize. */
@@ -2155,20 +2154,19 @@ fts_optimize_create_deleted_doc_id_snapshot(
used in the fts_init_delete_sql */
optim->fts_common_table.suffix = fts_common_tables[0];
fts_get_table_name(&optim->fts_common_table, being_deleted);
- pars_info_bind_id(info, true, fts_common_tables[0], being_deleted);
+ pars_info_bind_id(info, fts_common_tables[0], being_deleted);
optim->fts_common_table.suffix = fts_common_tables[3];
fts_get_table_name(&optim->fts_common_table, deleted);
- pars_info_bind_id(info, true, fts_common_tables[3], deleted);
+ pars_info_bind_id(info, fts_common_tables[3], deleted);
optim->fts_common_table.suffix = fts_common_tables[1];
fts_get_table_name(&optim->fts_common_table, being_deleted_cache);
- pars_info_bind_id(info, true, fts_common_tables[1],
- being_deleted_cache);
+ pars_info_bind_id(info, fts_common_tables[1], being_deleted_cache);
optim->fts_common_table.suffix = fts_common_tables[4];
fts_get_table_name(&optim->fts_common_table, deleted_cache);
- pars_info_bind_id(info, true, fts_common_tables[4], deleted_cache);
+ pars_info_bind_id(info, fts_common_tables[4], deleted_cache);
/* Move doc_ids that are to be deleted to state being deleted. */
graph = fts_parse_sql(NULL, info, fts_init_delete_sql);
@@ -3005,6 +3003,8 @@ fts_optimize_shutdown()
@param[in] table table to be synced */
void fts_sync_during_ddl(dict_table_t* table)
{
+ if (!fts_optimize_wq)
+ return;
mysql_mutex_lock(&fts_optimize_wq->mutex);
const auto sync_message= table->fts->sync_message;
mysql_mutex_unlock(&fts_optimize_wq->mutex);
diff --git a/storage/innobase/fts/fts0que.cc b/storage/innobase/fts/fts0que.cc
index d8b5ab6b904..594faf971ad 100644
--- a/storage/innobase/fts/fts0que.cc
+++ b/storage/innobase/fts/fts0que.cc
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 2007, 2020, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2017, 2020, MariaDB Corporation.
+Copyright (c) 2017, 2021, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -2147,7 +2147,7 @@ fts_query_find_term(
query->fts_index_table.suffix = fts_get_suffix(selected);
fts_get_table_name(&query->fts_index_table, table_name);
- pars_info_bind_id(info, true, "index_table_name", table_name);
+ pars_info_bind_id(info, "index_table_name", table_name);
}
select.found = FALSE;
@@ -2287,7 +2287,7 @@ fts_query_total_docs_containing_term(
fts_get_table_name(&query->fts_index_table, table_name);
- pars_info_bind_id(info, true, "index_table_name", table_name);
+ pars_info_bind_id(info, "index_table_name", table_name);
graph = fts_parse_sql(
&query->fts_index_table,
@@ -2370,7 +2370,7 @@ fts_query_terms_in_document(
fts_get_table_name(&query->fts_index_table, table_name);
- pars_info_bind_id(info, true, "index_table_name", table_name);
+ pars_info_bind_id(info, "index_table_name", table_name);
graph = fts_parse_sql(
&query->fts_index_table,
diff --git a/storage/innobase/fts/fts0sql.cc b/storage/innobase/fts/fts0sql.cc
index c451cb5e3c7..2d41776eb12 100644
--- a/storage/innobase/fts/fts0sql.cc
+++ b/storage/innobase/fts/fts0sql.cc
@@ -245,7 +245,7 @@ fts_get_select_columns_str(
sel_str = mem_heap_printf(heap, "sel%lu", (ulong) i);
/* Set copy_name to TRUE since it's dynamic. */
- pars_info_bind_id(info, TRUE, sel_str, field->name);
+ pars_info_bind_id(info, sel_str, field->name);
str = mem_heap_printf(
heap, "%s%s$%s", str, (*str) ? ", " : "", sel_str);
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index a01ba8ed11c..1485e8aa0df 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -12039,7 +12039,7 @@ foreign_push_index_error(trx_t* trx, const char* operation,
trx, DB_CANNOT_ADD_CONSTRAINT, create_name,
"%s table %s with foreign key %s constraint"
" failed. Field type or character set for column '%s' "
- "does not mach referenced column '%s'.",
+ "does not match referenced column '%s'.",
operation, create_name, fk_text, columns[err_col],
col_name);
return;
diff --git a/storage/innobase/handler/i_s.cc b/storage/innobase/handler/i_s.cc
index 8d8ab582f05..2f37675c8fc 100644
--- a/storage/innobase/handler/i_s.cc
+++ b/storage/innobase/handler/i_s.cc
@@ -2921,7 +2921,7 @@ i_s_fts_index_table_fill_selected(
FTS_INIT_INDEX_TABLE(&fts_table, fts_get_suffix(selected),
FTS_INDEX_TABLE, index);
fts_get_table_name(&fts_table, table_name);
- pars_info_bind_id(info, true, "table_name", table_name);
+ pars_info_bind_id(info, "table_name", table_name);
graph = fts_parse_sql(
&fts_table, info,
diff --git a/storage/innobase/include/btr0btr.h b/storage/innobase/include/btr0btr.h
index 1c5533ecd59..65608552986 100644
--- a/storage/innobase/include/btr0btr.h
+++ b/storage/innobase/include/btr0btr.h
@@ -689,8 +689,9 @@ btr_validate_index(
@param[in] block page to remove
@param[in] index index tree
@param[in,out] mtr mini-transaction */
-void btr_level_list_remove(const buf_block_t& block, const dict_index_t& index,
- mtr_t* mtr);
+dberr_t btr_level_list_remove(const buf_block_t& block,
+ const dict_index_t& index, mtr_t* mtr)
+ MY_ATTRIBUTE((warn_unused_result));
/*************************************************************//**
If page is the only on its level, this function moves its records to the
diff --git a/storage/innobase/include/fil0pagecompress.h b/storage/innobase/include/fil0pagecompress.h
index c6ba24faaad..a22867ad56a 100644
--- a/storage/innobase/include/fil0pagecompress.h
+++ b/storage/innobase/include/fil0pagecompress.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (C) 2013, 2019 MariaDB Corporation.
+Copyright (C) 2013, 2021, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -48,7 +48,7 @@ ulint fil_page_compress(
/** Decompress a page that may be subject to page_compressed compression.
@param[in,out] tmp_buf temporary buffer (of innodb_page_size)
@param[in,out] buf compressed page buffer
-@param[in] flags talespace flags
+@param[in] flags tablespace flags
@return size of the compressed data
@retval 0 if decompression failed
@retval srv_page_size if the page was not compressed */
diff --git a/storage/innobase/include/pars0pars.h b/storage/innobase/include/pars0pars.h
index c3cb23e44ca..bef446184a1 100644
--- a/storage/innobase/include/pars0pars.h
+++ b/storage/innobase/include/pars0pars.h
@@ -480,7 +480,6 @@ void
pars_info_bind_id(
/*=============*/
pars_info_t* info, /*!< in: info struct */
- ibool copy_name,/* in: make a copy of name if TRUE */
const char* name, /*!< in: name */
const char* id); /*!< in: id */
/****************************************************************//**
@@ -527,15 +526,6 @@ pars_info_bind_ull_literal(
MY_ATTRIBUTE((nonnull));
/****************************************************************//**
-Add bound id. */
-void
-pars_info_add_id(
-/*=============*/
- pars_info_t* info, /*!< in: info struct */
- const char* name, /*!< in: name */
- const char* id); /*!< in: id */
-
-/****************************************************************//**
Get bound literal with the given name.
@return bound literal, or NULL if not found */
pars_bound_lit_t*
diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc
index bcdf430e476..dccad0f3442 100644
--- a/storage/innobase/lock/lock0lock.cc
+++ b/storage/innobase/lock/lock0lock.cc
@@ -5205,16 +5205,18 @@ lock_sec_rec_read_check_and_lock(
if the max trx id for the page >= min trx id for the trx list or a
database recovery is running. */
- if (!page_rec_is_supremum(rec)
+ trx_t *trx = thr_get_trx(thr);
+ if (!lock_table_has(trx, index->table, LOCK_X)
+ && !page_rec_is_supremum(rec)
&& page_get_max_trx_id(block->frame) >= trx_sys.get_min_trx_id()
&& lock_rec_convert_impl_to_expl(thr_get_trx(thr), id, rec,
- index, offsets)) {
+ index, offsets)
+ && gap_mode == LOCK_REC_NOT_GAP) {
/* We already hold an implicit exclusive lock. */
return DB_SUCCESS;
}
#ifdef WITH_WSREP
- trx_t *trx= thr_get_trx(thr);
/* If transaction scanning an unique secondary key is wsrep
high priority thread (brute force) this scanning may involve
GAP-locking in the index. As this locking happens also when
@@ -5267,9 +5269,6 @@ lock_clust_rec_read_check_and_lock(
LOCK_REC_NOT_GAP */
que_thr_t* thr) /*!< in: query thread */
{
- dberr_t err;
- ulint heap_no;
-
ut_ad(dict_index_is_clust(index));
ut_ad(block->frame == page_align(rec));
ut_ad(page_rec_is_user_rec(rec) || page_rec_is_supremum(rec));
@@ -5288,17 +5287,19 @@ lock_clust_rec_read_check_and_lock(
const page_id_t id{block->page.id()};
- heap_no = page_rec_get_heap_no(rec);
+ ulint heap_no = page_rec_get_heap_no(rec);
- if (heap_no != PAGE_HEAP_NO_SUPREMUM
- && lock_rec_convert_impl_to_expl(thr_get_trx(thr), id, rec,
- index, offsets)) {
+ trx_t *trx = thr_get_trx(thr);
+ if (!lock_table_has(trx, index->table, LOCK_X)
+ && heap_no != PAGE_HEAP_NO_SUPREMUM
+ && lock_rec_convert_impl_to_expl(trx, id, rec, index, offsets)
+ && gap_mode == LOCK_REC_NOT_GAP) {
/* We already hold an implicit exclusive lock. */
return DB_SUCCESS;
}
- err = lock_rec_lock(false, gap_mode | mode,
- block, heap_no, index, thr);
+ dberr_t err = lock_rec_lock(false, gap_mode | mode,
+ block, heap_no, index, thr);
ut_ad(lock_rec_queue_validate(false, id, rec, index, offsets));
diff --git a/storage/innobase/pars/pars0pars.cc b/storage/innobase/pars/pars0pars.cc
index 1c3802f05e4..74c33b0cd9c 100644
--- a/storage/innobase/pars/pars0pars.cc
+++ b/storage/innobase/pars/pars0pars.cc
@@ -2341,7 +2341,6 @@ void
pars_info_bind_id(
/*==============*/
pars_info_t* info, /*!< in: info struct */
- ibool copy_name, /* in: copy name if TRUE */
const char* name, /*!< in: name */
const char* id) /*!< in: id */
{
@@ -2364,8 +2363,7 @@ pars_info_bind_id(
bid = static_cast<pars_bound_id_t*>(
ib_vector_push(info->bound_ids, NULL));
- bid->name = (copy_name)
- ? mem_heap_strdup(info->heap, name) : name;
+ bid->name = name;
}
bid->id = id;
diff --git a/storage/innobase/row/row0import.cc b/storage/innobase/row/row0import.cc
index ccbd00c7ff1..710e1910d1b 100644
--- a/storage/innobase/row/row0import.cc
+++ b/storage/innobase/row/row0import.cc
@@ -225,6 +225,19 @@ struct row_import {
found and was readable */
};
+struct fil_iterator_t {
+ pfs_os_file_t file; /*!< File handle */
+ const char* filepath; /*!< File path name */
+ os_offset_t start; /*!< From where to start */
+ os_offset_t end; /*!< Where to stop */
+ os_offset_t file_size; /*!< File size in bytes */
+ ulint n_io_buffers; /*!< Number of pages to use
+ for IO */
+ byte* io_buffer; /*!< Buffer to use for IO */
+ fil_space_crypt_t *crypt_data; /*!< Crypt data (if encrypted) */
+ byte* crypt_io_buffer; /*!< IO buffer when encrypted */
+};
+
/** Use the page cursor to iterate over records in a block. */
class RecIterator {
public:
@@ -468,6 +481,10 @@ public:
? block->page.zip.data : block->frame;
}
+ /** Invoke the functionality for the callback */
+ virtual dberr_t run(const fil_iterator_t& iter,
+ buf_block_t* block) UNIV_NOTHROW = 0;
+
protected:
/** Get the physical offset of the extent descriptor within the page.
@param page_no page number of the extent descriptor
@@ -628,6 +645,24 @@ AbstractCallback::init(
}
/**
+TODO: This can be made parallel trivially by chunking up the file
+and creating a callback per thread.. Main benefit will be to use
+multiple CPUs for checksums and compressed tables. We have to do
+compressed tables block by block right now. Secondly we need to
+decompress/compress and copy too much of data. These are
+CPU intensive.
+
+Iterate over all the pages in the tablespace.
+@param iter - Tablespace iterator
+@param block - block to use for IO
+@param callback - Callback to inspect and update page contents
+@retval DB_SUCCESS or error code */
+static dberr_t fil_iterate(
+ const fil_iterator_t& iter,
+ buf_block_t* block,
+ AbstractCallback& callback);
+
+/**
Try and determine the index root pages by checking if the next/prev
pointers are both FIL_NULL. We need to ensure that skip deleted pages. */
struct FetchIndexRootPages : public AbstractCallback {
@@ -644,19 +679,24 @@ struct FetchIndexRootPages : public AbstractCallback {
ulint m_page_no; /*!< Root page number */
};
- typedef std::vector<Index, ut_allocator<Index> > Indexes;
-
/** Constructor
@param trx covering (user) transaction
@param table table definition in server .*/
FetchIndexRootPages(const dict_table_t* table, trx_t* trx)
:
AbstractCallback(trx, ULINT_UNDEFINED),
- m_table(table) UNIV_NOTHROW { }
+ m_table(table), m_index(0, 0) UNIV_NOTHROW { }
/** Destructor */
~FetchIndexRootPages() UNIV_NOTHROW override { }
+ /** Fetch the clustered index root page in the tablespace
+ @param iter Tablespace iterator
+ @param block Block to use for IO
+ @retval DB_SUCCESS or error code */
+ dberr_t run(const fil_iterator_t& iter,
+ buf_block_t* block) UNIV_NOTHROW override;
+
/** Called for each block as it is read from the file.
@param block block to convert, it is not from the buffer pool.
@retval DB_SUCCESS or error code. */
@@ -670,7 +710,7 @@ struct FetchIndexRootPages : public AbstractCallback {
const dict_table_t* m_table;
/** Index information */
- Indexes m_indexes;
+ Index m_index;
};
/** Called for each block as it is read from the file. Check index pages to
@@ -685,39 +725,27 @@ dberr_t FetchIndexRootPages::operator()(buf_block_t* block) UNIV_NOTHROW
const page_t* page = get_frame(block);
- ulint page_type = fil_page_get_type(page);
-
- if (page_type == FIL_PAGE_TYPE_XDES) {
- return set_current_xdes(block->page.id().page_no(), page);
- } else if (fil_page_index_page_check(page)
- && !is_free(block->page.id().page_no())
- && !page_has_siblings(page)) {
-
- index_id_t id = btr_page_get_index_id(page);
-
- m_indexes.push_back(Index(id, block->page.id().page_no()));
+ m_index.m_id = btr_page_get_index_id(page);
+ m_index.m_page_no = block->page.id().page_no();
- if (m_indexes.size() == 1) {
- /* Check that the tablespace flags match the table flags. */
- ulint expected = dict_tf_to_fsp_flags(m_table->flags);
- if (!fsp_flags_match(expected, m_space_flags)) {
- ib_errf(m_trx->mysql_thd, IB_LOG_LEVEL_ERROR,
- ER_TABLE_SCHEMA_MISMATCH,
- "Expected FSP_SPACE_FLAGS=0x%x, .ibd "
- "file contains 0x%x.",
- unsigned(expected),
- unsigned(m_space_flags));
- return(DB_CORRUPTION);
- }
- }
+ /* Check that the tablespace flags match the table flags. */
+ ulint expected = dict_tf_to_fsp_flags(m_table->flags);
+ if (!fsp_flags_match(expected, m_space_flags)) {
+ ib_errf(m_trx->mysql_thd, IB_LOG_LEVEL_ERROR,
+ ER_TABLE_SCHEMA_MISMATCH,
+ "Expected FSP_SPACE_FLAGS=0x%x, .ibd "
+ "file contains 0x%x.",
+ unsigned(expected),
+ unsigned(m_space_flags));
+ return(DB_CORRUPTION);
+ }
- if (!page_is_comp(block->frame) !=
- !dict_table_is_comp(m_table)) {
- ib_errf(m_trx->mysql_thd, IB_LOG_LEVEL_ERROR,
- ER_TABLE_SCHEMA_MISMATCH,
- "ROW_FORMAT mismatch");
- return DB_CORRUPTION;
- }
+ if (!page_is_comp(block->frame) !=
+ !dict_table_is_comp(m_table)) {
+ ib_errf(m_trx->mysql_thd, IB_LOG_LEVEL_ERROR,
+ ER_TABLE_SCHEMA_MISMATCH,
+ "ROW_FORMAT mismatch");
+ return DB_CORRUPTION;
}
return DB_SUCCESS;
@@ -729,11 +757,9 @@ Update the import configuration that will be used to import the tablespace.
dberr_t
FetchIndexRootPages::build_row_import(row_import* cfg) const UNIV_NOTHROW
{
- Indexes::const_iterator end = m_indexes.end();
-
ut_a(cfg->m_table == m_table);
cfg->m_zip_size = m_zip_size;
- cfg->m_n_indexes = m_indexes.size();
+ cfg->m_n_indexes = 1;
if (cfg->m_n_indexes == 0) {
@@ -759,37 +785,32 @@ FetchIndexRootPages::build_row_import(row_import* cfg) const UNIV_NOTHROW
row_index_t* cfg_index = cfg->m_indexes;
- for (Indexes::const_iterator it = m_indexes.begin();
- it != end;
- ++it, ++cfg_index) {
+ char name[BUFSIZ];
- char name[BUFSIZ];
+ snprintf(name, sizeof(name), "index" IB_ID_FMT, m_index.m_id);
- snprintf(name, sizeof(name), "index" IB_ID_FMT, it->m_id);
+ ulint len = strlen(name) + 1;
- ulint len = strlen(name) + 1;
+ cfg_index->m_name = UT_NEW_ARRAY_NOKEY(byte, len);
- cfg_index->m_name = UT_NEW_ARRAY_NOKEY(byte, len);
-
- /* Trigger OOM */
- DBUG_EXECUTE_IF(
- "ib_import_OOM_12",
- UT_DELETE_ARRAY(cfg_index->m_name);
- cfg_index->m_name = NULL;
- );
+ /* Trigger OOM */
+ DBUG_EXECUTE_IF(
+ "ib_import_OOM_12",
+ UT_DELETE_ARRAY(cfg_index->m_name);
+ cfg_index->m_name = NULL;
+ );
- if (cfg_index->m_name == NULL) {
- return(DB_OUT_OF_MEMORY);
- }
+ if (cfg_index->m_name == NULL) {
+ return(DB_OUT_OF_MEMORY);
+ }
- memcpy(cfg_index->m_name, name, len);
+ memcpy(cfg_index->m_name, name, len);
- cfg_index->m_id = it->m_id;
+ cfg_index->m_id = m_index.m_id;
- cfg_index->m_space = m_space;
+ cfg_index->m_space = m_space;
- cfg_index->m_page_no = it->m_page_no;
- }
+ cfg_index->m_page_no = m_index.m_page_no;
return(DB_SUCCESS);
}
@@ -845,6 +866,12 @@ public:
}
}
+ dberr_t run(const fil_iterator_t& iter,
+ buf_block_t* block) UNIV_NOTHROW override
+ {
+ return fil_iterate(iter, block, *this);
+ }
+
/** Called for each block as it is read from the file.
@param block block to convert, it is not from the buffer pool.
@retval DB_SUCCESS or error code. */
@@ -1902,8 +1929,10 @@ PageConverter::update_index_page(
row_index_t* index = find_index(id);
if (UNIV_UNLIKELY(!index)) {
- ib::warn() << "Unknown index id " << id
- << " on page " << page_id.page_no();
+ if (!m_cfg->m_missing) {
+ ib::warn() << "Unknown index id " << id
+ << " on page " << page_id.page_no();
+ }
return DB_SUCCESS;
}
@@ -3326,20 +3355,6 @@ dberr_t row_import_update_discarded_flag(trx_t* trx, table_id_t table_id,
return(err);
}
-struct fil_iterator_t {
- pfs_os_file_t file; /*!< File handle */
- const char* filepath; /*!< File path name */
- os_offset_t start; /*!< From where to start */
- os_offset_t end; /*!< Where to stop */
- os_offset_t file_size; /*!< File size in bytes */
- ulint n_io_buffers; /*!< Number of pages to use
- for IO */
- byte* io_buffer; /*!< Buffer to use for IO */
- fil_space_crypt_t *crypt_data; /*!< Crypt data (if encrypted) */
- byte* crypt_io_buffer; /*!< IO buffer when encrypted */
-};
-
-
/** InnoDB writes page by page when there is page compressed
tablespace involved. It does help to save the disk space when
punch hole is enabled
@@ -3397,22 +3412,102 @@ dberr_t fil_import_compress_fwrite(const fil_iterator_t &iter,
return DB_SUCCESS;
}
-/********************************************************************//**
-TODO: This can be made parallel trivially by chunking up the file and creating
-a callback per thread. . Main benefit will be to use multiple CPUs for
-checksums and compressed tables. We have to do compressed tables block by
-block right now. Secondly we need to decompress/compress and copy too much
-of data. These are CPU intensive.
+dberr_t FetchIndexRootPages::run(const fil_iterator_t& iter,
+ buf_block_t* block) UNIV_NOTHROW
+{
+ const unsigned zip_size= fil_space_t::zip_size(m_space_flags);
+ const unsigned size= zip_size ? zip_size : unsigned(srv_page_size);
+ const ulint buf_size=
+#ifdef HAVE_LZO
+ LZO1X_1_15_MEM_COMPRESS+
+#elif defined HAVE_SNAPPY
+ snappy_max_compressed_length(srv_page_size) +
+#endif
+ srv_page_size;
+ byte* page_compress_buf = static_cast<byte*>(malloc(buf_size));
+ const bool full_crc32 = fil_space_t::full_crc32(m_space_flags);
+ bool skip_checksum_check = false;
+ ut_ad(!srv_read_only_mode);
-Iterate over all the pages in the tablespace.
-@param iter - Tablespace iterator
-@param block - block to use for IO
-@param callback - Callback to inspect and update page contents
-@retval DB_SUCCESS or error code */
-static
-dberr_t
-fil_iterate(
-/*========*/
+ if (!page_compress_buf)
+ return DB_OUT_OF_MEMORY;
+
+ const bool encrypted= iter.crypt_data != NULL &&
+ iter.crypt_data->should_encrypt();
+ byte* const readptr= iter.io_buffer;
+ block->frame= readptr;
+
+ if (block->page.zip.data)
+ block->page.zip.data= readptr;
+
+ bool page_compressed= false;
+
+ dberr_t err= os_file_read_no_error_handling(
+ IORequestReadPartial, iter.file, readptr, 3 * size, size, 0);
+ if (err != DB_SUCCESS)
+ {
+ ib::error() << iter.filepath << ": os_file_read() failed";
+ goto func_exit;
+ }
+
+ if (page_get_page_no(readptr) != 3)
+ {
+page_corrupted:
+ ib::warn() << filename() << ": Page 3 at offset "
+ << 3 * size << " looks corrupted.";
+ err= DB_CORRUPTION;
+ goto func_exit;
+ }
+
+ block->page.id_.set_page_no(3);
+ if (full_crc32 && fil_space_t::is_compressed(m_space_flags))
+ page_compressed= buf_page_is_compressed(readptr, m_space_flags);
+ else
+ {
+ switch (fil_page_get_type(readptr)) {
+ case FIL_PAGE_PAGE_COMPRESSED:
+ case FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED:
+ if (block->page.zip.data)
+ goto page_corrupted;
+ page_compressed= true;
+ }
+ }
+
+ if (encrypted)
+ {
+ if (!buf_page_verify_crypt_checksum(readptr, m_space_flags))
+ goto page_corrupted;
+
+ if (!fil_space_decrypt(get_space_id(), iter.crypt_data, readptr,
+ size, m_space_flags, readptr, &err) ||
+ err != DB_SUCCESS)
+ goto func_exit;
+ }
+
+ /* For full_crc32 format, skip checksum check
+ after decryption. */
+ skip_checksum_check= full_crc32 && encrypted;
+
+ if (page_compressed)
+ {
+ ulint compress_length= fil_page_decompress(page_compress_buf,
+ readptr,
+ m_space_flags);
+ ut_ad(compress_length != srv_page_size);
+ if (compress_length == 0)
+ goto page_corrupted;
+ }
+ else if (!skip_checksum_check
+ && buf_page_is_corrupted(false, readptr, m_space_flags))
+ goto page_corrupted;
+
+ err= this->operator()(block);
+func_exit:
+ free(page_compress_buf);
+ return err;
+}
+
+static dberr_t fil_iterate(
const fil_iterator_t& iter,
buf_block_t* block,
AbstractCallback& callback)
@@ -3874,7 +3969,7 @@ fil_tablespace_iterate(
block->page.zip.data = block->frame + srv_page_size;
}
- err = fil_iterate(iter, block, callback);
+ err = callback.run(iter, block);
if (iter.crypt_data) {
fil_space_destroy_crypt_data(&iter.crypt_data);
@@ -4003,6 +4098,16 @@ row_import_for_mysql(
cfg.m_zip_size = 0;
+ if (UT_LIST_GET_LEN(table->indexes) > 1) {
+ ib_errf(trx->mysql_thd, IB_LOG_LEVEL_ERROR,
+ ER_INTERNAL_ERROR,
+ "Drop all secondary indexes before importing "
+ "table %s when .cfg file is missing.",
+ table->name.m_name);
+ err = DB_ERROR;
+ return row_import_error(prebuilt, trx, err);
+ }
+
FetchIndexRootPages fetchIndexRootPages(table, trx);
err = fil_tablespace_iterate(
diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc
index 4312e95d110..3d1f07093fd 100644
--- a/storage/innobase/row/row0ins.cc
+++ b/storage/innobase/row/row0ins.cc
@@ -1657,23 +1657,6 @@ row_ins_check_foreign_constraint(
cmp = cmp_dtuple_rec(entry, rec, offsets);
if (cmp == 0) {
- if (check_table->versioned()) {
- bool history_row = false;
-
- if (check_index->is_primary()) {
- history_row = check_index->
- vers_history_row(rec, offsets);
- } else if (check_index->
- vers_history_row(rec, history_row))
- {
- break;
- }
-
- if (history_row) {
- continue;
- }
- }
-
if (rec_get_deleted_flag(rec,
rec_offs_comp(offsets))) {
/* In delete-marked records, DB_TRX_ID must
@@ -1695,6 +1678,23 @@ row_ins_check_foreign_constraint(
goto end_scan;
}
} else {
+ if (check_table->versioned()) {
+ bool history_row = false;
+
+ if (check_index->is_primary()) {
+ history_row = check_index->
+ vers_history_row(rec,
+ offsets);
+ } else if (check_index->
+ vers_history_row(rec,
+ history_row)) {
+ break;
+ }
+
+ if (history_row) {
+ continue;
+ }
+ }
/* Found a matching record. Lock only
a record because we can allow inserts
into gaps */
diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc
index f84755a5c4a..a5c8f7047b6 100644
--- a/storage/innobase/row/row0mysql.cc
+++ b/storage/innobase/row/row0mysql.cc
@@ -73,25 +73,6 @@ Created 9/17/2000 Heikki Tuuri
#endif
/*******************************************************************//**
-Determine if the given name is a name reserved for MySQL system tables.
-@return TRUE if name is a MySQL system table name */
-static
-ibool
-row_mysql_is_system_table(
-/*======================*/
- const char* name)
-{
- if (strncmp(name, "mysql/", 6) != 0) {
-
- return(FALSE);
- }
-
- return(0 == strcmp(name + 6, "host")
- || 0 == strcmp(name + 6, "user")
- || 0 == strcmp(name + 6, "db"));
-}
-
-/*******************************************************************//**
Delays an INSERT, DELETE or UPDATE operation if the purge is lagging. */
static
void
@@ -2207,29 +2188,16 @@ row_create_table_for_mysql(
DBUG_EXECUTE_IF(
"ib_create_table_fail_at_start_of_row_create_table_for_mysql",
- goto err_exit;
+ dict_mem_table_free(table); return DB_ERROR;
);
- trx->op_info = "creating table";
-
- if (row_mysql_is_system_table(table->name.m_name)) {
-
- ib::error() << "Trying to create a MariaDB system table "
- << table->name << " of type InnoDB. MariaDB system"
- " tables must be of the MyISAM type!";
-
-err_exit:
+ if (!dict_sys.sys_tables_exist()) {
+ sql_print_error("InnoDB: Some system tables are missing");
dict_mem_table_free(table);
-
- trx->op_info = "";
-
- return(DB_ERROR);
+ return DB_ERROR;
}
- if (!dict_sys.sys_tables_exist()) {
- ib::error() << "Some InnoDB system tables are missing";
- goto err_exit;
- }
+ trx->op_info = "creating table";
trx_start_if_not_started_xa(trx, true);
@@ -2770,14 +2738,6 @@ row_rename_table_for_mysql(
if (high_level_read_only) {
return(DB_READ_ONLY);
-
- } else if (row_mysql_is_system_table(new_name)) {
-
- ib::error() << "Trying to create a MariaDB system table "
- << new_name << " of type InnoDB. MariaDB system tables"
- " must be of the MyISAM type!";
-
- goto funct_exit;
}
trx->op_info = "renaming table";
diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc
index 81e0a3d2b79..fa3121b5f52 100644
--- a/storage/innobase/srv/srv0srv.cc
+++ b/storage/innobase/srv/srv0srv.cc
@@ -1798,7 +1798,7 @@ static std::mutex purge_thd_mutex;
extern void* thd_attach_thd(THD*);
extern void thd_detach_thd(void *);
-THD* acquire_thd(void **ctx)
+static THD *acquire_thd(void **ctx)
{
std::unique_lock<std::mutex> lk(purge_thd_mutex);
if (purge_thds.empty()) {
@@ -1816,7 +1816,7 @@ THD* acquire_thd(void **ctx)
return thd;
}
-void release_thd(THD *thd, void *ctx)
+static void release_thd(THD *thd, void *ctx)
{
thd_detach_thd(ctx);
std::unique_lock<std::mutex> lk(purge_thd_mutex);
diff --git a/storage/perfschema/CMakeLists.txt b/storage/perfschema/CMakeLists.txt
index dfb41a5b1c1..2a77e2a8301 100644
--- a/storage/perfschema/CMakeLists.txt
+++ b/storage/perfschema/CMakeLists.txt
@@ -341,9 +341,8 @@ FAIL_REGEX "warning: incompatible pointer to integer conversion"
CONFIGURE_FILE(pfs_config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/pfs_config.h)
MYSQL_ADD_PLUGIN(perfschema ${PERFSCHEMA_SOURCES} STORAGE_ENGINE DEFAULT
- STATIC_ONLY RECOMPILE_FOR_EMBEDDED)
+ STATIC_ONLY RECOMPILE_FOR_EMBEDDED DEPENDS GenServerSource)
IF (TARGET perfschema)
- ADD_DEPENDENCIES(perfschema GenServerSource)
IF(WITH_UNIT_TESTS)
ADD_SUBDIRECTORY(unittest)
ENDIF(WITH_UNIT_TESTS)
diff --git a/storage/spider/mysql-test/spider/bugfix/include/mdev_24523_deinit.inc b/storage/spider/mysql-test/spider/bugfix/include/mdev_24523_deinit.inc
new file mode 100644
index 00000000000..e8d30523978
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/include/mdev_24523_deinit.inc
@@ -0,0 +1,9 @@
+--let $MASTER_1_COMMENT_P_2_1= $MASTER_1_COMMENT_P_2_1_BACKUP
+--let $CHILD2_1_CREATE_TABLES= $CHILD2_1_CREATE_TABLES_BACKUP
+--disable_warnings
+--disable_query_log
+--disable_result_log
+--source ../t/test_deinit.inc
+--enable_result_log
+--enable_query_log
+--enable_warnings
diff --git a/storage/spider/mysql-test/spider/bugfix/include/mdev_24523_init.inc b/storage/spider/mysql-test/spider/bugfix/include/mdev_24523_init.inc
new file mode 100644
index 00000000000..989faa54c16
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/include/mdev_24523_init.inc
@@ -0,0 +1,31 @@
+--disable_warnings
+--disable_query_log
+--disable_result_log
+--source ../t/test_init.inc
+--enable_result_log
+--enable_query_log
+--enable_warnings
+--let $MASTER_1_COMMENT_P_2_1_BACKUP= $MASTER_1_COMMENT_P_2_1
+let $MASTER_1_COMMENT_P_2_1=
+ PARTITION BY RANGE(i) (
+ PARTITION pt1 VALUES LESS THAN (5) COMMENT='srv "s_2_1", table "ta_r2"',
+ PARTITION pt2 VALUES LESS THAN (10) COMMENT='srv "s_2_1", table "ta_r3"',
+ PARTITION pt3 VALUES LESS THAN MAXVALUE COMMENT='srv "s_2_1", table "ta_r4"'
+ );
+--let $CHILD2_1_CREATE_TABLES_BACKUP= $CHILD2_1_CREATE_TABLES
+let $CHILD2_1_CREATE_TABLES=
+ CREATE TABLE ta_r2 (
+ i INT,
+ j JSON,
+ PRIMARY KEY(i)
+ ) $CHILD2_1_ENGINE $CHILD2_1_CHARSET $STR_SEMICOLON
+ CREATE TABLE ta_r3 (
+ i INT,
+ j JSON,
+ PRIMARY KEY(i)
+ ) $CHILD2_1_ENGINE $CHILD2_1_CHARSET $STR_SEMICOLON
+ CREATE TABLE ta_r4 (
+ i INT,
+ j JSON,
+ PRIMARY KEY(i)
+ ) $CHILD2_1_ENGINE $CHILD2_1_CHARSET;
diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_24523.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_24523.result
new file mode 100644
index 00000000000..0b3d6c3142b
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_24523.result
@@ -0,0 +1,58 @@
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+
+this test is for MDEV-24523
+
+drop and create databases
+connection master_1;
+CREATE DATABASE auto_test_local;
+USE auto_test_local;
+connection child2_1;
+CREATE DATABASE auto_test_remote;
+USE auto_test_remote;
+
+create table and insert
+connection child2_1;
+CHILD2_1_CREATE_TABLES
+connection master_1;
+CREATE TABLE tbl_a (
+i INT,
+j JSON,
+PRIMARY KEY(i)
+) ENGINE=Spider PARTITION BY RANGE(i) (
+PARTITION pt1 VALUES LESS THAN (5) COMMENT='srv "s_2_1", table "ta_r2"',
+PARTITION pt2 VALUES LESS THAN (10) COMMENT='srv "s_2_1", table "ta_r3"',
+PARTITION pt3 VALUES LESS THAN MAXVALUE COMMENT='srv "s_2_1", table "ta_r4"'
+ )
+INSERT INTO tbl_a VALUES (1, '{ "a": 1, "b": [2, 3]}');
+
+test 1
+connection master_1;
+UPDATE tbl_a SET j = JSON_REPLACE(j, '$.a', 10, '$.c', '[1, 2]');
+SELECT * FROM tbl_a;
+i j
+1 {"a": 10, "b": [2, 3]}
+TRUNCATE TABLE tbl_a;
+INSERT INTO tbl_a VALUES (1, '{ "a": 1, "b": [2, 3]}');
+UPDATE tbl_a SET j = JSON_REPLACE(j, '$.a', 10, '$.b', '[1, 2]');
+SELECT * FROM tbl_a;
+i j
+1 {"a": 10, "b": "[1, 2]"}
+
+deinit
+connection master_1;
+DROP DATABASE IF EXISTS auto_test_local;
+connection child2_1;
+DROP DATABASE IF EXISTS auto_test_remote;
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+
+end of test
diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_24523.cnf b/storage/spider/mysql-test/spider/bugfix/t/mdev_24523.cnf
new file mode 100644
index 00000000000..05dfd8a0bce
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_24523.cnf
@@ -0,0 +1,3 @@
+!include include/default_mysqld.cnf
+!include ../my_1_1.cnf
+!include ../my_2_1.cnf
diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_24523.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_24523.test
new file mode 100644
index 00000000000..00c0c873f20
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_24523.test
@@ -0,0 +1,66 @@
+--source ../include/mdev_24523_init.inc
+--echo
+--echo this test is for MDEV-24523
+--echo
+--echo drop and create databases
+
+--connection master_1
+--disable_warnings
+CREATE DATABASE auto_test_local;
+USE auto_test_local;
+
+--connection child2_1
+CREATE DATABASE auto_test_remote;
+USE auto_test_remote;
+--enable_warnings
+
+--echo
+--echo create table and insert
+
+--connection child2_1
+--disable_query_log
+--disable_ps_protocol
+echo CHILD2_1_CREATE_TABLES;
+eval $CHILD2_1_CREATE_TABLES;
+--enable_ps_protocol
+--enable_query_log
+
+--connection master_1
+--disable_query_log
+echo CREATE TABLE tbl_a (
+ i INT,
+ j JSON,
+ PRIMARY KEY(i)
+) $MASTER_1_ENGINE $MASTER_1_COMMENT_P_2_1;
+eval CREATE TABLE tbl_a (
+ i INT,
+ j JSON,
+ PRIMARY KEY(i)
+) $MASTER_1_ENGINE $MASTER_1_COMMENT_P_2_1;
+--enable_query_log
+INSERT INTO tbl_a VALUES (1, '{ "a": 1, "b": [2, 3]}');
+
+--echo
+--echo test 1
+
+--connection master_1
+UPDATE tbl_a SET j = JSON_REPLACE(j, '$.a', 10, '$.c', '[1, 2]');
+SELECT * FROM tbl_a;
+TRUNCATE TABLE tbl_a;
+INSERT INTO tbl_a VALUES (1, '{ "a": 1, "b": [2, 3]}');
+UPDATE tbl_a SET j = JSON_REPLACE(j, '$.a', 10, '$.b', '[1, 2]');
+SELECT * FROM tbl_a;
+--echo
+--echo deinit
+--disable_warnings
+
+--connection master_1
+DROP DATABASE IF EXISTS auto_test_local;
+
+--connection child2_1
+DROP DATABASE IF EXISTS auto_test_remote;
+
+--enable_warnings
+--source ../include/mdev_24523_deinit.inc
+--echo
+--echo end of test
diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c
index 59ed669217d..9c18667614b 100644
--- a/tests/mysql_client_test.c
+++ b/tests/mysql_client_test.c
@@ -5256,10 +5256,10 @@ static void test_manual_sample()
{
unsigned int param_count;
MYSQL_STMT *stmt;
- short small_data;
- int int_data;
+ short small_data= 1;
+ int int_data= 2;
int rc;
- char str_data[50];
+ char str_data[50]= "std_data";
ulonglong affected_rows;
MYSQL_BIND my_bind[3];
my_bool is_null;
@@ -18209,9 +18209,9 @@ static void test_bug40365(void)
if (!opt_silent)
fprintf(stdout, "\ntime[%d]: %02d-%02d-%02d ",
i, tm[i].year, tm[i].month, tm[i].day);
- DIE_UNLESS(tm[i].year == 0);
- DIE_UNLESS(tm[i].month == 0);
- DIE_UNLESS(tm[i].day == 0);
+ DIE_UNLESS(tm[i].year == 0);
+ DIE_UNLESS(tm[i].month == 0);
+ DIE_UNLESS(tm[i].day == 0);
}
mysql_stmt_close(stmt);
rc= mysql_commit(mysql);