summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2021-09-30 11:01:07 +0300
committerMarko Mäkelä <marko.makela@mariadb.com>2021-09-30 11:01:07 +0300
commitb36d6f92a865e519271925f68802d599e62cf26c (patch)
tree27c9bd08266f17aaa712d84f14bf41f657ad9fb3
parent8dd4794c4e11b8790fadf0c203bcd118e7b755e8 (diff)
parenta49e394399859b23ba609d0058b498cfa876cac4 (diff)
downloadmariadb-git-b36d6f92a865e519271925f68802d599e62cf26c.tar.gz
Merge 10.6 into 10.7
-rw-r--r--.gitlab-ci.yml201
-rw-r--r--client/mysqltest.cc100
-rw-r--r--cmake/cpack_rpm.cmake4
-rw-r--r--include/m_ctype.h37
-rw-r--r--include/my_minidump.h25
-rw-r--r--libmysqld/CMakeLists.txt3
-rw-r--r--mysql-test/lib/My/SafeProcess/CMakeLists.txt3
-rw-r--r--mysql-test/lib/My/SafeProcess/safe_kill_win.cc109
-rw-r--r--mysql-test/lib/mtr_process.pl2
-rw-r--r--mysql-test/main/errors.result4
-rw-r--r--mysql-test/main/errors.test2
-rw-r--r--mysql-test/main/lock_sync.result3
-rw-r--r--mysql-test/main/lock_sync.test3
-rw-r--r--mysql-test/main/sp-bugs.result4
-rw-r--r--mysql-test/main/sp-lock.result8
-rw-r--r--mysql-test/main/sp-lock.test3
-rw-r--r--mysql-test/main/sp.result19
-rw-r--r--mysql-test/main/sp.test18
-rw-r--r--mysql-test/main/view.result43
-rw-r--r--mysql-test/main/view.test49
-rw-r--r--mysql-test/suite/compat/oracle/r/sp-package.result8
-rw-r--r--mysql-test/suite/galera/disabled.def1
-rw-r--r--mysql-test/suite/galera/r/galera_fulltext.result56
-rw-r--r--mysql-test/suite/galera/r/galera_partition.result2
-rw-r--r--mysql-test/suite/galera/t/galera_fulltext.test66
-rw-r--r--mysql-test/suite/galera/t/galera_partition.cnf4
-rw-r--r--mysql-test/suite/galera/t/galera_partition.test6
-rw-r--r--mysql-test/suite/galera/t/galera_var_ignore_apply_errors.cnf7
-rw-r--r--mysql-test/suite/galera/t/galera_var_ignore_apply_errors.test19
-rw-r--r--mysql-test/suite/innodb/r/doublewrite.result1
-rw-r--r--mysql-test/suite/innodb/r/innodb_defrag_stats.result214
-rw-r--r--mysql-test/suite/innodb/t/doublewrite.test2
-rw-r--r--mysql-test/suite/innodb/t/innodb_defrag_stats.test74
-rw-r--r--mysql-test/suite/innodb/t/undo_truncate.test4
-rw-r--r--mysql-test/suite/plugins/r/feedback_plugin_load.result16
-rw-r--r--mysql-test/suite/plugins/t/feedback_plugin_load.test7
-rw-r--r--mysys/CMakeLists.txt3
-rw-r--r--mysys/charset-def.c4
-rw-r--r--mysys/my_minidump.cc115
-rw-r--r--plugin/feedback/feedback.cc12
-rw-r--r--scripts/wsrep_sst_common.sh16
-rw-r--r--scripts/wsrep_sst_mariabackup.sh55
-rw-r--r--scripts/wsrep_sst_rsync.sh63
-rw-r--r--sql/item.cc96
-rw-r--r--sql/item.h1
-rw-r--r--sql/item_subselect.cc1
-rw-r--r--sql/item_sum.cc8
-rw-r--r--sql/mysql_upgrade_service.cc14
-rw-r--r--sql/sp.cc22
-rw-r--r--sql/sql_base.cc1
-rw-r--r--sql/sql_prepare.cc2
-rw-r--r--sql/wsrep_schema.cc9
-rw-r--r--storage/innobase/fil/fil0fil.cc35
-rw-r--r--storage/innobase/fsp/fsp0file.cc32
-rw-r--r--storage/innobase/handler/ha_innodb.cc69
-rw-r--r--storage/innobase/include/fil0fil.h2
-rw-r--r--storage/innobase/include/srw_lock.h107
-rw-r--r--storage/innobase/sync/srw_lock.cc172
-rw-r--r--strings/ctype-big5.c17
-rw-r--r--strings/ctype-bin.c13
-rw-r--r--strings/ctype-cp932.c17
-rw-r--r--strings/ctype-czech.c13
-rw-r--r--strings/ctype-euc_kr.c17
-rw-r--r--strings/ctype-eucjpms.c17
-rw-r--r--strings/ctype-gb2312.c17
-rw-r--r--strings/ctype-gbk.c17
-rw-r--r--strings/ctype-latin1.c5
-rw-r--r--strings/ctype-mb.c41
-rw-r--r--strings/ctype-mb.h37
-rw-r--r--strings/ctype-simple.c38
-rw-r--r--strings/ctype-simple.h37
-rw-r--r--strings/ctype-sjis.c17
-rw-r--r--strings/ctype-tis620.c9
-rw-r--r--strings/ctype-uca.ic17
-rw-r--r--strings/ctype-ucs2.c65
-rw-r--r--strings/ctype-ujis.c17
-rw-r--r--strings/ctype-utf8.c45
-rw-r--r--strings/ctype-win1250ch.c14
-rw-r--r--support-files/mysql.server.sh15
-rw-r--r--unittest/strings/strings-t.c259
80 files changed, 1876 insertions, 834 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 0a1bf5bff71..cd22fc5dd8c 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -37,8 +37,22 @@ image: fedora:33
# many components that are otherwise slow to build.
variables:
CMAKE_FLAGS: "-DWITH_SSL=system -DPLUGIN_COLUMNSTORE=NO -DPLUGIN_ROCKSDB=NO -DPLUGIN_S3=NO -DPLUGIN_MROONGA=NO -DPLUGIN_CONNECT=NO -DPLUGIN_MROONGA=NO -DPLUGIN_TOKUDB=NO -DPLUGIN_PERFSCHEMA=NO -DWITH_WSREP=OFF"
- # Major version dictates which branches share the same ccache
+ # Major version dictates which branches share the same ccache. E.g. 10.6-abc
+ # and 10.6-xyz will have the same cache.
MARIADB_MAJOR_VERSION: "10.6"
+ # NOTE! Currently ccache is only used on the Centos8 build. As each job has
+ # sufficiently different environments they are unable to benefit from each
+ # other's ccaches. As each build generates about 1 GB of ccache, having
+ # multiple caches would quickly consume all free storage on Gitlab-CI and
+ # grind all builds to a halt. Also the network overhead of download/upload
+ # decreases the benefit of ccache in Gitlab-CI, and current cache:when and
+ # cache:policy are not flexible enough to have a system where the cache is
+ # uploaded only once a week and not on every build. Having ccache on at least
+ # one build still helps ensure that ccache compatibility is at least tested
+ # and if the Centos 8 build is always significantly faster than all other
+ # builds (e.g. on self-hosted Gitlab instances) then users would at least be
+ # able to discover it.
+ #
# Most steps don't need the source code, only artifacts
GIT_STRATEGY: none
# Hack to satisfy directory name length requirement by CPackRPM in CMake 3.x
@@ -65,23 +79,21 @@ fedora:
GIT_STRATEGY: fetch
GIT_SUBMODULE_STRATEGY: normal
script:
- - yum install -y yum-utils rpm-build ccache openssl-devel
- - source /etc/profile.d/ccache.sh
- - export CCACHE_DIR="$(pwd)/.ccache"; ccache -s
+ - yum install -y yum-utils rpm-build openssl-devel graphviz
# Accelerate builds with unsafe disk access, as we can afford to loose the entire build anyway
- yum install -y https://github.com/stewartsmith/libeatmydata/releases/download/v129/libeatmydata-129-1.fc33.x86_64.rpm
# This repository does not have any .spec files, so install dependencies based on Fedora spec file
- yum-builddep -y mariadb-server
- mkdir builddir; cd builddir
- cmake -DRPM=$CI_JOB_NAME $CMAKE_FLAGS .. 2>&1 | tee -a ../build-$CI_JOB_NAME-$CI_COMMIT_REF_SLUG.log
- - eatmydata make package 2>&1 | tee -a ../build-$CI_JOB_NAME-$CI_COMMIT_REF_SLUG.log
- # @TODO: Don't use -j on Gitlab.com as builds just get stuck when running
- # multi-proc, needs more debugging
- - make test || true # Unit tests constantly fail, see https://jira.mariadb.org/browse/MDEV-25820
- # - make test-force || true # mysql-test-runner takes too long, run it in a separate job instead
+ - cmake --graphviz=../dependencies.dot .. && dot -Tpng -o ../dependencies.png ../dependencies.dot
+ - eatmydata make package -j 2 2>&1 | tee -a ../build-$CI_JOB_NAME-$CI_COMMIT_REF_SLUG.log
+ # @TODO: Don't use -j without the limit of 2 on Gitlab.com as builds just
+ # get stuck when running multi-proc and out of memory, see https://jira.mariadb.org/browse/MDEV-25968
+ - make test
+ # - make test-force # mysql-test-runner takes too long, run MTR in a separate job instead
- *rpm_listfiles
- mkdir ../rpm; mv *.rpm ../rpm
- - ccache -s
artifacts:
when: always # Must be able to see logs
paths:
@@ -89,14 +101,74 @@ fedora:
- rpmlist-$CI_JOB_NAME-$CI_COMMIT_REF_SLUG.log
- rpm
- builddir/_CPack_Packages/Linux/RPM/SPECS/
- cache:
- key: $MARIADB_MAJOR_VERSION-$CI_JOB_NAME
+ - dependencies.dot
+ - dependencies.png
+
+fedora-ninja:
+ stage: build
+ variables:
+ GIT_STRATEGY: fetch
+ GIT_SUBMODULE_STRATEGY: normal
+ script:
+ - yum install -y yum-utils rpm-build openssl-devel graphviz ninja-build
+ # Accelerate builds with unsafe disk access, as we can afford to loose the entire build anyway
+ - yum install -y https://github.com/stewartsmith/libeatmydata/releases/download/v129/libeatmydata-129-1.fc33.x86_64.rpm
+ # This repository does not have any .spec files, so install dependencies based on Fedora spec file
+ - yum-builddep -y mariadb-server
+ - mkdir builddir; cd builddir
+ - cmake -DRPM=generic $CMAKE_FLAGS -DCMAKE_BUILD_WITH_INSTALL_RPATH=ON -G Ninja .. 2>&1 | tee -a ../build-$CI_JOB_NAME-$CI_COMMIT_REF_SLUG.log
+ - ninja -t graph > ../dependencies.dot && dot -Tpng -o ../dependencies.png ../dependencies.dot
+ - eatmydata ninja package --verbose 2>&1 | tee -a ../build-$CI_JOB_NAME-$CI_COMMIT_REF_SLUG.log
+ # Ninja builds are not affected by bug https://jira.mariadb.org/browse/MDEV-25968
+ - ninja test
+ - *rpm_listfiles
+ - mkdir ../rpm; mv *.rpm ../rpm
+ artifacts:
+ when: always # Must be able to see logs
paths:
- - .ccache
- # policy: pull
- # @TODO: It would be enough to only download the cache. There is no need for
- # every job to upload a new cache every time. A monthly or weekly scheduled
- # run could update the cache for all other builds to us.
+ - build-$CI_JOB_NAME-$CI_COMMIT_REF_SLUG.log
+ - rpmlist-$CI_JOB_NAME-$CI_COMMIT_REF_SLUG.log
+ - rpm
+ - builddir/_CPack_Packages/Linux/RPM/SPECS/
+ - dependencies.dot
+ - dependencies.png
+
+fedora-clang:
+ stage: build
+ variables:
+ GIT_STRATEGY: fetch
+ GIT_SUBMODULE_STRATEGY: normal
+ script:
+ - yum install -y yum-utils rpm-build openssl-devel graphviz clang
+ # Accelerate builds with unsafe disk access, as we can afford to loose the entire build anyway
+ - yum install -y https://github.com/stewartsmith/libeatmydata/releases/download/v129/libeatmydata-129-1.fc33.x86_64.rpm
+ # This repository does not have any .spec files, so install dependencies based on Fedora spec file
+ - yum-builddep -y mariadb-server
+ - mkdir builddir; cd builddir
+ - export CXX=${CXX:-clang++}
+ - export CC=${CC:-clang}
+ - export CXX_FOR_BUILD=${CXX_FOR_BUILD:-clang++}
+ - export CC_FOR_BUILD=${CC_FOR_BUILD:-clang}
+ - export CFLAGS='-Wno-unused-command-line-argument'
+ - export CXXFLAGS='-Wno-unused-command-line-argument'
+ - cmake -DRPM=generic $CMAKE_FLAGS .. 2>&1 | tee -a ../build-$CI_JOB_NAME-$CI_COMMIT_REF_SLUG.log
+ - cmake --graphviz=../dependencies.dot .. && dot -Tpng -o ../dependencies.png ../dependencies.dot
+ - eatmydata make package -j 2 2>&1 | tee -a ../build-$CI_JOB_NAME-$CI_COMMIT_REF_SLUG.log
+ # @TODO: Don't use -j without the limit of 2 on Gitlab.com as builds just
+ # get stuck when running multi-proc and out of memory, see https://jira.mariadb.org/browse/MDEV-25968
+ - make test
+ # - make test-force # mysql-test-runner takes too long, run MTr in a separate job instead
+ - *rpm_listfiles
+ - mkdir ../rpm; mv *.rpm ../rpm
+ artifacts:
+ when: always # Must be able to see logs
+ paths:
+ - build-$CI_JOB_NAME-$CI_COMMIT_REF_SLUG.log
+ - rpmlist-$CI_JOB_NAME-$CI_COMMIT_REF_SLUG.log
+ - rpm
+ - builddir/_CPack_Packages/Linux/RPM/SPECS/
+ - dependencies.dot
+ - dependencies.png
centos8:
stage: build
@@ -119,16 +191,16 @@ centos8:
- yum install -y https://github.com/stewartsmith/libeatmydata/releases/download/v129/libeatmydata-129-1.fc33.x86_64.rpm
- yum install -y ccache # From EPEL
- source /etc/profile.d/ccache.sh
- - export CCACHE_DIR="$(pwd)/.ccache"; ccache -s
+ - export CCACHE_DIR="$(pwd)/.ccache"; ccache --zero-stats
# This repository does not have any .spec files, so install dependencies based on CentOS spec file
- yum-builddep -y mariadb-server
- mkdir builddir; cd builddir
- cmake -DRPM=$CI_JOB_NAME $CMAKE_FLAGS .. 2>&1 | tee -a ../build-$CI_JOB_NAME-$CI_COMMIT_REF_SLUG.log
- - eatmydata make package 2>&1 | tee -a ../build-$CI_JOB_NAME-$CI_COMMIT_REF_SLUG.log
- # @TODO: Don't use -j on Gitlab.com as builds just get stuck when running
- # multi-proc and out of memory, see https://jira.mariadb.org/browse/MDEV-25968
- - make test || true # Unit tests constantly fail, see https://jira.mariadb.org/browse/MDEV-25820
- # - make test-force || true # mysql-test-runner takes too long, run it in a separate job instead
+ - eatmydata make package -j 2 2>&1 | tee -a ../build-$CI_JOB_NAME-$CI_COMMIT_REF_SLUG.log
+ # @TODO: Don't use -j without the limit of 2 on Gitlab.com as builds just
+ # get stuck when running multi-proc and out of memory, see https://jira.mariadb.org/browse/MDEV-25968
+ - make test
+ # - make test-force # mysql-test-runner takes too long, run it MTR a separate job instead
- *rpm_listfiles
- mkdir ../rpm; mv *.rpm ../rpm
- ccache -s
@@ -140,7 +212,7 @@ centos8:
- rpm
- builddir/_CPack_Packages/Linux/RPM/SPECS/
cache:
- key: $MARIADB_MAJOR_VERSION-$CI_JOB_NAME
+ key: $MARIADB_MAJOR_VERSION
paths:
- .ccache
@@ -157,11 +229,11 @@ centos7:
- yum install -y yum-utils rpm-build gcc gcc-c++ bison libxml2-devel libevent-devel openssl-devel
- mkdir builddir; cd builddir
- cmake -DRPM=$CI_JOB_NAME $CMAKE_FLAGS .. 2>&1 | tee -a ../build-$CI_JOB_NAME-$CI_COMMIT_REF_SLUG.log
- - make package 2>&1 | tee -a ../build-$CI_JOB_NAME-$CI_COMMIT_REF_SLUG.log
- # @TODO: Don't use -j on Gitlab.com as builds just get stuck when running
- # multi-proc and out of memory, see https://jira.mariadb.org/browse/MDEV-25968
- - make test || true # Unit tests constantly fail, see https://jira.mariadb.org/browse/MDEV-25820
- # - make test-force || true # mysql-test-runner takes too long, run it in a separate job instead
+ - make package -j 2 2>&1 | tee -a ../build-$CI_JOB_NAME-$CI_COMMIT_REF_SLUG.log
+ # @TODO: Don't use -j without the limit of 2 on Gitlab.com as builds just
+ # get stuck when running multi-proc and out of memory, see https://jira.mariadb.org/browse/MDEV-25968
+ - make test
+ # - make test-force # mysql-test-runner takes too long, run it in a separate job instead
- *rpm_listfiles
- mkdir ../rpm; mv *.rpm ../rpm
artifacts:
@@ -178,20 +250,20 @@ mysql-test-run:
- fedora
script:
# Install packages so tests and the dependencies install
- # @TODO: RPM missing 'patch' as dependency, so installing it manually for now
- - yum install -y rpm/*.rpm patch
+ # @TODO: RPM missing 'patch' and 'diff' as dependency, so installing it manually for now
+ - yum install -y rpm/*.rpm patch diffutils
# @TODO: Fix on packaging level for /usr/share/mariadb to work and errormsg.sys be found
- rm -rf /usr/share/mariadb; ln -s /usr/share/mysql /usr/share/mariadb
# mtr expects to be launched in-place and with write access to it's own directories
- cd /usr/share/mysql-test
+ # Skip failing tests
- |
echo "
- main.mysqldump : flaky on Gitlab-CI
- main.flush_logs_not_windows : flaky in containers in general
- main.mysql_upgrade_noengine : requires diff but diffutils is not a dependency
+ main.mysqldump : Field separator argument is not what is expected; check the manual when executing 'SELECT INTO OUTFILE'
+ main.flush_logs_not_windows : query 'flush logs' succeeded - should have failed with error ER_CANT_CREATE_FILE (1004)
+ main.mysql_upgrade_noengine : upgrade output order does not match the expected
" > skiplist
- # @TODO: Flaky tests are skipped for now, but should be fixed
- - ./mtr --suite=main --force --xml-report=$CI_PROJECT_DIR/junit.xml --skip-test-list=skiplist
+ - ./mtr --suite=main --force --parallel=auto --xml-report=$CI_PROJECT_DIR/junit.xml --skip-test-list=skiplist
artifacts:
when: always # Also show results when tests fail
reports:
@@ -226,11 +298,27 @@ fedora install:
# Fedora does not support running services in Docker (like Debian packages do) so start it manually
- /usr/bin/mariadb-install-db -u mysql
- sudo -u mysql /usr/sbin/mariadbd & sleep 10
- # @TODO: Since we did a manual start, we also need to run upgrade manually
- - /usr/bin/mariadb-upgrade -u root --socket /var/lib/mysql/mysql.sock
+ # Dump database contents as is before upgrade
+ - mariadb-dump --all-databases --all-tablespaces --triggers --routines --events --skip-extended-insert > installed-database.sql
+ # Since we did a manual start, we also need to run upgrade manually
+ - /usr/bin/mariadb-upgrade -u root
+ # Dump database contents as is after upgrade
+ - mariadb-dump --all-databases --all-tablespaces --triggers --routines --events --skip-extended-insert > upgraded-database.sql
- |
- mysql --skip-column-names -e "SELECT @@version, @@version_comment" | tee /tmp/version
- grep $MARIADB_MAJOR_VERSION /tmp/version || echo "MariaDB didn't upgrade properly"
+ mariadb --skip-column-names -e "SELECT @@version, @@version_comment" | tee /tmp/version
+ grep $MARIADB_MAJOR_VERSION /tmp/version || echo "MariaDB didn't install properly"
+ - mariadb --table -e "SELECT * FROM mysql.global_priv; SHOW CREATE USER root@localhost; SHOW CREATE USER 'mariadb.sys'@localhost"
+ - mariadb --table -e "SELECT * FROM mysql.plugin; SHOW PLUGINS"
+ - mariadb -e "SHUTDOWN;"
+ - rm -rf /var/lib/mysql/* # Clear datadir before next run
+ # Start database without install-db step
+ - sudo -u mysql /usr/sbin/mariadbd --skip-network --skip-grant & sleep 10
+ # Dump database contents in initial state
+ - mariadb-dump --all-databases --all-tablespaces --triggers --routines --events --skip-extended-insert > empty-database.sql
+ artifacts:
+ paths:
+ - installed-database.sql
+ - upgraded-database.sql
fedora upgrade:
stage: test
@@ -242,24 +330,39 @@ fedora upgrade:
- /usr/libexec/mysql-check-socket
- /usr/libexec/mysql-prepare-db-dir
- sudo -u mysql /usr/libexec/mysqld --basedir=/usr & sleep 10
+ # Dump database contents in installed state
+ - mariadb-dump --all-databases --all-tablespaces --triggers --routines --events --skip-extended-insert > old-installed-database.sql
- /usr/libexec/mysql-check-upgrade
- - mysql --skip-column-names -e "SELECT @@version, @@version_comment" # Show version
+ # Dump database contents in upgraded state
+ - mariadb-dump --all-databases --all-tablespaces --triggers --routines --events --skip-extended-insert > old-upgraded-database.sql
+ - mariadb --skip-column-names -e "SELECT @@version, @@version_comment" # Show version
# @TODO: Upgrade from Fedora 33 MariaDB 10.4 to MariaDB.org latest does not work
# so do this manual step to remove conflicts until packaging is fixed
- - >
- yum remove -y mariadb-server-utils mariadb-gssapi-server mariadb-cracklib-password-check
- mariadb-backup mariadb-connector-c-config
+ - yum remove -y mariadb-server-utils mariadb-gssapi-server mariadb-cracklib-password-check mariadb-backup mariadb-connector-c-config
- rm -f rpm/*debuginfo* # Not relevant in this test
- - yum install -y rpm/*.rpm procps # procps provides pkill
+ - yum install -y rpm/*.rpm
# nothing provides galera-4 on Fedora, so this step fails if built with wsrep
- - pkill mysqld || true; sleep 5; pkill mysqld || true; sleep 5
- - /usr/bin/mariadb-install-db -u mysql
+ - mysql -e "SHUTDOWN;"
+ - /usr/bin/mariadb-install-db # This step should not do anything on upgrades, just exit
- sudo -u mysql /usr/sbin/mariadbd & sleep 10
+ # Dump database contents in installed state
+ - mariadb-dump --all-databases --all-tablespaces --triggers --routines --events --skip-extended-insert > new-installed-database.sql || true
+ # The step above fails on: mariadb-dump: Couldn't execute 'show events': Cannot proceed, because event scheduler is disabled (1577)
# @TODO: Since we did a manual start, we also need to run upgrade manually
- - /usr/bin/mariadb-upgrade -u root --socket /var/lib/mysql/mysql.sock
+ - /usr/bin/mariadb-upgrade
+ # Dump database contents in upgraded state
+ - mariadb-dump --all-databases --all-tablespaces --triggers --routines --events --skip-extended-insert > new-upgraded-database.sql
- |
- mysql --skip-column-names -e "SELECT @@version, @@version_comment" | tee /tmp/version
+ mariadb --skip-column-names -e "SELECT @@version, @@version_comment" | tee /tmp/version
grep $MARIADB_MAJOR_VERSION /tmp/version || echo "MariaDB didn't upgrade properly"
+ - mariadb --table -e "SELECT * FROM mysql.global_priv; SHOW CREATE USER root@localhost; SHOW CREATE USER 'mariadb.sys'@localhost"
+ - mariadb --table -e "SELECT * FROM mysql.plugin; SHOW PLUGINS"
+ artifacts:
+ paths:
+ - old-installed-database.sql
+ - old-upgraded-database.sql
+ - new-installed-database.sql
+ - new-upgraded-database.sql
# Once all RPM builds and tests have passed, also run the DEB builds and tests
# @NOTE: This is likely to work well only on salsa.debian.org as the Gitlab.com
diff --git a/client/mysqltest.cc b/client/mysqltest.cc
index 1979214de17..c7ec429d232 100644
--- a/client/mysqltest.cc
+++ b/client/mysqltest.cc
@@ -71,10 +71,6 @@ static my_bool non_blocking_api_enabled= 0;
#include "../tests/nonblock-wrappers.h"
#endif
-/* Use cygwin for --exec and --system before 5.0 */
-#if MYSQL_VERSION_ID < 50000
-#define USE_CYGWIN
-#endif
#define MAX_VAR_NAME_LENGTH 256
#define MAX_COLUMNS 256
@@ -619,7 +615,6 @@ const char *get_errname_from_code (uint error_code);
int multi_reg_replace(struct st_replace_regex* r,char* val);
#ifdef _WIN32
-void free_tmp_sh_file();
void free_win_path_patterns();
#endif
@@ -1457,7 +1452,6 @@ void free_used_memory()
free_re();
my_free(read_command_buf);
#ifdef _WIN32
- free_tmp_sh_file();
free_win_path_patterns();
#endif
DBUG_VOID_RETURN;
@@ -3199,33 +3193,6 @@ void do_source(struct st_command *command)
}
-#if defined _WIN32
-
-#ifdef USE_CYGWIN
-/* Variables used for temporary sh files used for emulating Unix on Windows */
-char tmp_sh_name[64], tmp_sh_cmd[70];
-#endif
-
-void init_tmp_sh_file()
-{
-#ifdef USE_CYGWIN
- /* Format a name for the tmp sh file that is unique for this process */
- my_snprintf(tmp_sh_name, sizeof(tmp_sh_name), "tmp_%d.sh", getpid());
- /* Format the command to execute in order to run the script */
- my_snprintf(tmp_sh_cmd, sizeof(tmp_sh_cmd), "sh %s", tmp_sh_name);
-#endif
-}
-
-
-void free_tmp_sh_file()
-{
-#ifdef USE_CYGWIN
- my_delete(tmp_sh_name, MYF(0));
-#endif
-}
-#endif
-
-
static void init_builtin_echo(void)
{
#ifdef _WIN32
@@ -3341,7 +3308,6 @@ void do_exec(struct st_command *command)
}
#ifdef _WIN32
-#ifndef USE_CYGWIN
/* Replace /dev/null with NUL */
while(replace(&ds_cmd, "/dev/null", 9, "NUL", 3) == 0)
;
@@ -3349,7 +3315,6 @@ void do_exec(struct st_command *command)
while(replace(&ds_cmd, ">&-", 3, ">&4", 3) == 0)
;
#endif
-#endif
if (disable_result_log)
{
@@ -3507,13 +3472,7 @@ int do_modify_var(struct st_command *command,
int my_system(DYNAMIC_STRING* ds_cmd)
{
-#if defined _WIN32 && defined USE_CYGWIN
- /* Dump the command into a sh script file and execute with system */
- str_to_file(tmp_sh_name, ds_cmd->str, ds_cmd->length);
- return system(tmp_sh_cmd);
-#else
return system(ds_cmd->str);
-#endif
}
@@ -3547,12 +3506,10 @@ void do_system(struct st_command *command)
do_eval(&ds_cmd, command->first_argument, command->end, !is_windows);
#ifdef _WIN32
-#ifndef USE_CYGWIN
/* Replace /dev/null with NUL */
while(replace(&ds_cmd, "/dev/null", 9, "NUL", 3) == 0)
;
#endif
-#endif
DBUG_PRINT("info", ("running system command '%s' as '%s'",
@@ -5022,13 +4979,34 @@ int query_get_string(MYSQL* mysql, const char* query,
}
+#ifdef _WIN32
+#define SIGKILL 9
+#include <my_minidump.h>
static int my_kill(int pid, int sig)
{
- DBUG_PRINT("info", ("Killing server, pid: %d", pid));
-#ifdef _WIN32
-#define SIGKILL 9 /* ignored anyway, see below */
HANDLE proc;
- if ((proc= OpenProcess(SYNCHRONIZE|PROCESS_TERMINATE, FALSE, pid)) == NULL)
+ if (sig == SIGABRT)
+ {
+ /*
+ Create a minidump. If process is being debugged, debug break
+ Otherwise, terminate.
+ */
+ verbose_msg("Aborting %d",pid);
+ my_create_minidump(pid,TRUE);
+ proc= OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
+ if(!proc)
+ return -1;
+ BOOL debugger_present;
+ if (CheckRemoteDebuggerPresent(proc,&debugger_present) && debugger_present)
+ {
+ if (DebugBreakProcess(proc))
+ {
+ CloseHandle(proc);
+ return 0;
+ }
+ }
+ }
+ else if ((proc= OpenProcess(SYNCHRONIZE|PROCESS_TERMINATE, FALSE, pid)) == NULL)
return -1;
if (sig == 0)
{
@@ -5039,12 +5017,30 @@ static int my_kill(int pid, int sig)
(void)TerminateProcess(proc, 201);
CloseHandle(proc);
return 1;
-#else
- return kill(pid, sig);
-#endif
}
+/* Wait until process is gone, with timeout */
+static int wait_until_dead(int pid, int timeout)
+{
+ HANDLE proc= OpenProcess(SYNCHRONIZE, FALSE, pid);
+ if (!proc)
+ return 0; /* already dead */
+ DBUG_ASSERT(timeout >= 0);
+ DBUG_ASSERT(timeout <= UINT_MAX/1000);
+ DWORD wait_result= WaitForSingleObject(proc, (DWORD)timeout*1000);
+ CloseHandle(proc);
+ return (int)wait_result;
+}
+
+#else /* !_WIN32 */
+
+
+static int my_kill(int pid, int sig)
+{
+ DBUG_PRINT("info", ("Killing server, pid: %d", pid));
+ return kill(pid, sig);
+}
/*
Shutdown the server of current connection and
@@ -5079,6 +5075,7 @@ static int wait_until_dead(int pid, int timeout)
}
DBUG_RETURN(1); // Did not die
}
+#endif /* _WIN32 */
void do_shutdown_server(struct st_command *command)
@@ -9231,10 +9228,7 @@ int main(int argc, char **argv)
init_builtin_echo();
#ifdef _WIN32
-#ifndef USE_CYGWIN
is_windows= 1;
-#endif
- init_tmp_sh_file();
init_win_path_patterns();
#endif
diff --git a/cmake/cpack_rpm.cmake b/cmake/cpack_rpm.cmake
index bba9238664b..91322b975bf 100644
--- a/cmake/cpack_rpm.cmake
+++ b/cmake/cpack_rpm.cmake
@@ -1,5 +1,7 @@
IF(RPM)
+MESSAGE(STATUS "CPackRPM building with RPM configuration: ${RPM}")
+
SET(CPACK_GENERATOR "RPM")
SET(CPACK_RPM_PACKAGE_DEBUG 1)
SET(CPACK_PACKAGING_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX})
@@ -274,7 +276,7 @@ FILE(GLOB compat101 RELATIVE ${CMAKE_SOURCE_DIR}
"${CMAKE_SOURCE_DIR}/../MariaDB-shared-10.1.*.rpm")
IF(compat53 AND compat101)
FOREACH(compat_rpm "${compat53}" "${compat101}")
- MESSAGE("Using ${compat_rpm} to build MariaDB-compat")
+ MESSAGE(STATUS "Using ${compat_rpm} to build MariaDB-compat")
INSTALL(CODE "EXECUTE_PROCESS(
COMMAND rpm2cpio ${CMAKE_SOURCE_DIR}/${compat_rpm}
COMMAND cpio --extract --make-directories */libmysqlclient*.so.* -
diff --git a/include/m_ctype.h b/include/m_ctype.h
index 279e8a74ddc..41523913c10 100644
--- a/include/m_ctype.h
+++ b/include/m_ctype.h
@@ -377,6 +377,12 @@ struct my_collation_handler_st
void (*hash_sort)(CHARSET_INFO *cs, const uchar *key, size_t len,
ulong *nr1, ulong *nr2);
my_bool (*propagate)(CHARSET_INFO *cs, const uchar *str, size_t len);
+ /*
+ Make minimum and maximum strings for the collation.
+ Put not more than "nchars" characters.
+ */
+ size_t (*min_str)(CHARSET_INFO *cs, uchar *dst, size_t dstlen, size_t nchars);
+ size_t (*max_str)(CHARSET_INFO *cs, uchar *dst, size_t dstlen, size_t nchars);
};
extern MY_COLLATION_HANDLER my_collation_8bit_bin_handler;
@@ -589,8 +595,23 @@ struct charset_info_st
uchar casedn_multiply;
uint mbminlen;
uint mbmaxlen;
+ /*
+ min_sort_char and max_sort_char represent the minimum
+ and the maximum character in the collation respectively.
+
+ For Unicode collations, these numbers are Unicode code points.
+ For non-Unicode collations these numbers are native character codes.
+ For example, in all 8bit collations these numbers are
+ in the range 0x00..0xFF.
+
+ min_sort_char and max_sort_char normally should not be used directly.
+ They are used internally in the following virtual functions:
+ - MY_COLLATION_HANDLER::like_range()
+ - MY_COLLATION_HANDLER::min_str()
+ - MY_COLLATION_HANDLER::max_str()
+ */
my_wc_t min_sort_char;
- my_wc_t max_sort_char; /* For LIKE optimization */
+ my_wc_t max_sort_char;
uchar pad_char;
my_bool escape_with_backslash_is_dangerous;
uchar levels_for_order;
@@ -852,6 +873,16 @@ struct charset_info_st
return (coll->propagate)(this, str, len);
}
+ size_t min_str(uchar *dst, size_t dstlen, size_t nchars) const
+ {
+ return (coll->min_str)(this, dst, dstlen, nchars);
+ }
+
+ size_t max_str(uchar *dst, size_t dstlen, size_t nchars) const
+ {
+ return (coll->max_str)(this, dst, dstlen, nchars);
+ }
+
#endif /* __cplusplus */
};
@@ -1110,7 +1141,7 @@ extern struct charset_info_st my_charset_big5_bin;
extern struct charset_info_st my_charset_big5_chinese_ci;
extern struct charset_info_st my_charset_big5_nopad_bin;
extern struct charset_info_st my_charset_big5_chinese_nopad_ci;
-extern struct charset_info_st my_charset_cp1250_czech_ci;
+extern struct charset_info_st my_charset_cp1250_czech_cs;
extern struct charset_info_st my_charset_cp932_bin;
extern struct charset_info_st my_charset_cp932_japanese_ci;
extern struct charset_info_st my_charset_cp932_nopad_bin;
@@ -1134,7 +1165,7 @@ extern struct charset_info_st my_charset_gbk_chinese_nopad_ci;
extern struct charset_info_st my_charset_latin1_bin;
extern struct charset_info_st my_charset_latin1_nopad_bin;
extern struct charset_info_st my_charset_latin1_german2_ci;
-extern struct charset_info_st my_charset_latin2_czech_ci;
+extern struct charset_info_st my_charset_latin2_czech_cs;
extern struct charset_info_st my_charset_sjis_bin;
extern struct charset_info_st my_charset_sjis_japanese_ci;
extern struct charset_info_st my_charset_sjis_nopad_bin;
diff --git a/include/my_minidump.h b/include/my_minidump.h
new file mode 100644
index 00000000000..0c0e843be8c
--- /dev/null
+++ b/include/my_minidump.h
@@ -0,0 +1,25 @@
+/* Copyright (c) 2021, MariaDB Corporation
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */
+
+#include <windows.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+BOOL my_create_minidump(DWORD pid, BOOL verbose);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/libmysqld/CMakeLists.txt b/libmysqld/CMakeLists.txt
index 6fb2ae3cf5b..d2cbb9a85ee 100644
--- a/libmysqld/CMakeLists.txt
+++ b/libmysqld/CMakeLists.txt
@@ -145,6 +145,9 @@ SET(SQL_EMBEDDED_SOURCES emb_qcache.cc libmysqld.c lib_sql.cc
ADD_CONVENIENCE_LIBRARY(sql_embedded ${SQL_EMBEDDED_SOURCES})
DTRACE_INSTRUMENT(sql_embedded)
ADD_DEPENDENCIES(sql_embedded GenError GenServerSource)
+IF(TARGET pcre2)
+ ADD_DEPENDENCIES(sql_embedded pcre2)
+ENDIF()
# On Windows, static embedded server library is called mysqlserver.lib
# On Unix, it is libmysqld.a
diff --git a/mysql-test/lib/My/SafeProcess/CMakeLists.txt b/mysql-test/lib/My/SafeProcess/CMakeLists.txt
index eac1f1be8bd..0004a44982d 100644
--- a/mysql-test/lib/My/SafeProcess/CMakeLists.txt
+++ b/mysql-test/lib/My/SafeProcess/CMakeLists.txt
@@ -19,7 +19,8 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include)
IF (WIN32)
ADD_EXECUTABLE(my_safe_process safe_process_win.cc)
ADD_EXECUTABLE(my_safe_kill safe_kill_win.cc)
- TARGET_LINK_LIBRARIES(my_safe_kill dbghelp psapi)
+ TARGET_INCLUDE_DIRECTORIES(my_safe_kill PRIVATE ${CMAKE_SOURCE_DIR}/include)
+ TARGET_LINK_LIBRARIES(my_safe_kill mysys psapi)
ELSE()
ADD_EXECUTABLE(my_safe_process safe_process.cc)
ENDIF()
diff --git a/mysql-test/lib/My/SafeProcess/safe_kill_win.cc b/mysql-test/lib/My/SafeProcess/safe_kill_win.cc
index 4a9d5f2b8cc..375ed80b292 100644
--- a/mysql-test/lib/My/SafeProcess/safe_kill_win.cc
+++ b/mysql-test/lib/My/SafeProcess/safe_kill_win.cc
@@ -26,19 +26,7 @@
#include <signal.h>
#include <stdlib.h>
#include <psapi.h>
-
-#ifdef _MSC_VER
-/* Silence warning in OS header dbghelp.h */
-#pragma warning(push)
-#pragma warning(disable : 4091)
-#endif
-
-#include <dbghelp.h>
-
-#ifdef _MSC_VER
-/* Silence warning in OS header dbghelp.h */
-#pragma warning(pop)
-#endif
+#include <my_minidump.h>
#include <tlhelp32.h>
#include <vector>
@@ -64,106 +52,13 @@ static std::vector<DWORD> find_children(DWORD pid)
return children;
}
-void dump_single_process(DWORD pid)
-{
- HANDLE file = 0;
- HANDLE process= 0;
- DWORD size= MAX_PATH;
- char path[MAX_PATH];
- char working_dir[MAX_PATH];
- char tmpname[MAX_PATH];
- char *filename= 0;
-
- process= OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid);
- if (!process)
- {
- fprintf(stderr, "safe_kill : cannot open process pid=%lu to create dump, last error %lu\n",
- pid, GetLastError());
- goto exit;
- }
-
- if (QueryFullProcessImageName(process, 0, path, &size) == 0)
- {
- fprintf(stderr, "safe_kill : cannot read process path for pid %lu, last error %lu\n",
- pid, GetLastError());
- goto exit;
- }
-
- filename= strrchr(path, '\\');
- if (filename)
- {
- filename++;
- // We are not interested in dump of some proceses (my_safe_process.exe,cmd.exe)
- // since they are only used to start up other programs.
- // We're interested however in their children;
- const char *exclude_programs[] = {"my_safe_process.exe","cmd.exe", 0};
- for(size_t i=0; exclude_programs[i]; i++)
- if (_stricmp(filename, exclude_programs[i]) == 0)
- goto exit;
- }
- else
- filename= path;
-
- // Add .dmp extension
- char *p;
- if ((p= strrchr(filename, '.')) == 0)
- p= filename + strlen(filename);
-
- strncpy(p, ".dmp", path + MAX_PATH - p);
-
- // Íf file with this name exist, generate unique name with .dmp extension
- if (GetFileAttributes(filename) != INVALID_FILE_ATTRIBUTES)
- {
- if (!GetTempFileName(".", filename, 0, tmpname))
- {
- fprintf(stderr, "GetTempFileName failed, last error %lu", GetLastError());
- goto exit;
- }
- strncat_s(tmpname, ".dmp", sizeof(tmpname));
- filename= tmpname;
- }
-
-
- if (!GetCurrentDirectory(MAX_PATH, working_dir))
- {
- fprintf(stderr, "GetCurrentDirectory failed, last error %lu", GetLastError());
- goto exit;
- }
-
- file= CreateFile(filename, GENERIC_READ | GENERIC_WRITE,
- 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
-
- if (file == INVALID_HANDLE_VALUE)
- {
- fprintf(stderr, "safe_kill : CreateFile() failed for file %s, working dir %s, last error = %lu\n",
- filename, working_dir, GetLastError());
- goto exit;
- }
-
- if (!MiniDumpWriteDump(process, pid, file, MiniDumpNormal, 0, 0, 0))
- {
- fprintf(stderr, "Failed to write minidump to %s, working dir %s, last error %lu\n",
- filename, working_dir, GetLastError());
- goto exit;
- }
-
- fprintf(stderr, "Minidump written to %s, directory %s\n", filename, working_dir);
-
-exit:
- if (process != 0 && process != INVALID_HANDLE_VALUE)
- CloseHandle(process);
-
- if (file != 0 && file != INVALID_HANDLE_VALUE)
- CloseHandle(file);
-}
-
static int create_dump(DWORD pid, int recursion_depth= 5)
{
if (recursion_depth < 0)
return 0;
- dump_single_process(pid);
+ my_create_minidump(pid, TRUE);
std::vector<DWORD> children= find_children(pid);
for(size_t i=0; i < children.size(); i++)
create_dump(children[i], recursion_depth -1);
diff --git a/mysql-test/lib/mtr_process.pl b/mysql-test/lib/mtr_process.pl
index a384aa584c4..42254bd29b7 100644
--- a/mysql-test/lib/mtr_process.pl
+++ b/mysql-test/lib/mtr_process.pl
@@ -109,7 +109,7 @@ sub sleep_until_file_created ($$$$$) {
my $proc= shift;
my $warn_seconds = shift;
my $sleeptime= 10; # Milliseconds
- my $loops= ($timeout * 10000) / $sleeptime;
+ my $loops= ($timeout * 1000) / $sleeptime;
my $message_time= 60;
for ( my $loop= 0; $loop <= $loops; $loop++ )
diff --git a/mysql-test/main/errors.result b/mysql-test/main/errors.result
index 44193865493..baa2e0ad3c0 100644
--- a/mysql-test/main/errors.result
+++ b/mysql-test/main/errors.result
@@ -224,10 +224,10 @@ SELECT 4;
END IF ;
END"where name = "P1";
show create procedure P1;
-ERROR HY000: Failed to load routine test.P1 (internal code -6). For more details, run SHOW WARNINGS
+ERROR 42000: Undeclared variable: foo
show warnings;
Level Code Message
Error 1327 Undeclared variable: foo
-Error 1457 Failed to load routine test.P1 (internal code -6). For more details, run SHOW WARNINGS
+Error 1305 PROCEDURE P1 does not exist
drop procedure P1;
# End of 10.4 tests
diff --git a/mysql-test/main/errors.test b/mysql-test/main/errors.test
index a4b95d48e5d..1948eebfcb3 100644
--- a/mysql-test/main/errors.test
+++ b/mysql-test/main/errors.test
@@ -275,7 +275,7 @@ SELECT 4;
END IF ;
END"where name = "P1";
---error ER_SP_PROC_TABLE_CORRUPT
+--error ER_SP_UNDECLARED_VAR
show create procedure P1;
show warnings;
diff --git a/mysql-test/main/lock_sync.result b/mysql-test/main/lock_sync.result
index 70960503fef..25b97460238 100644
--- a/mysql-test/main/lock_sync.result
+++ b/mysql-test/main/lock_sync.result
@@ -221,6 +221,8 @@ end|
# called below.
#
connection con1;
+set @save_dbug=@@debug_dbug;
+set debug_dbug="+d,cache_sp_in_show_create";
# Cache all functions used in the tests below so statements
# calling them won't need to open and lock mysql.proc table
# and we can assume that each statement locks its tables
@@ -245,6 +247,7 @@ show create function f14;
show create function f15;
show create function f16;
show create function f17;
+set debug_dbug=@save_dbug;
connection default;
#
# 1. Statements that read tables and do not use subqueries.
diff --git a/mysql-test/main/lock_sync.test b/mysql-test/main/lock_sync.test
index 16367d74800..b2cb0bc058c 100644
--- a/mysql-test/main/lock_sync.test
+++ b/mysql-test/main/lock_sync.test
@@ -235,6 +235,8 @@ let $con_aux2= con2;
let $table= t1;
connection con1;
+set @save_dbug=@@debug_dbug;
+set debug_dbug="+d,cache_sp_in_show_create";
--echo # Cache all functions used in the tests below so statements
--echo # calling them won't need to open and lock mysql.proc table
--echo # and we can assume that each statement locks its tables
@@ -260,6 +262,7 @@ show create function f14;
show create function f15;
show create function f16;
show create function f17;
+set debug_dbug=@save_dbug;
--enable_result_log
connection default;
diff --git a/mysql-test/main/sp-bugs.result b/mysql-test/main/sp-bugs.result
index 665e787442d..8c6788d03f4 100644
--- a/mysql-test/main/sp-bugs.result
+++ b/mysql-test/main/sp-bugs.result
@@ -168,7 +168,7 @@ RETURN 0;
END latin1 latin1_swedish_ci latin1_swedish_ci
SHOW CREATE FUNCTION TESTF_bug11763507;
Function sql_mode Create Function character_set_client collation_connection Database Collation
-testf_bug11763507 CREATE DEFINER=`root`@`localhost` FUNCTION `testf_bug11763507`() RETURNS int(11)
+TESTF_bug11763507 CREATE DEFINER=`root`@`localhost` FUNCTION `TESTF_bug11763507`() RETURNS int(11)
BEGIN
RETURN 0;
END latin1 latin1_swedish_ci latin1_swedish_ci
@@ -198,7 +198,7 @@ SELECT "PROCEDURE testp_bug11763507";
END latin1 latin1_swedish_ci latin1_swedish_ci
SHOW CREATE PROCEDURE TESTP_bug11763507;
Procedure sql_mode Create Procedure character_set_client collation_connection Database Collation
-testp_bug11763507 CREATE DEFINER=`root`@`localhost` PROCEDURE `testp_bug11763507`()
+TESTP_bug11763507 CREATE DEFINER=`root`@`localhost` PROCEDURE `TESTP_bug11763507`()
BEGIN
SELECT "PROCEDURE testp_bug11763507";
END latin1 latin1_swedish_ci latin1_swedish_ci
diff --git a/mysql-test/main/sp-lock.result b/mysql-test/main/sp-lock.result
index acf951f6676..ec8d8970ae3 100644
--- a/mysql-test/main/sp-lock.result
+++ b/mysql-test/main/sp-lock.result
@@ -703,9 +703,6 @@ connection default;
#
# SHOW CREATE PROCEDURE p1 called from p1, after p1 was altered
#
-# We are just covering the existing behaviour with tests. The
-# results are not necessarily correct."
-#
CREATE PROCEDURE p1()
BEGIN
SELECT get_lock("test", 10);
@@ -736,10 +733,7 @@ get_lock("test", 10)
1
Procedure sql_mode Create Procedure character_set_client collation_connection Database Collation
p1 STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION CREATE DEFINER=`root`@`localhost` PROCEDURE `p1`()
-BEGIN
-SELECT get_lock("test", 10);
-SHOW CREATE PROCEDURE p1;
-END latin1 latin1_swedish_ci latin1_swedish_ci
+BEGIN END latin1 latin1_swedish_ci latin1_swedish_ci
connection con3;
disconnect con3;
connection con2;
diff --git a/mysql-test/main/sp-lock.test b/mysql-test/main/sp-lock.test
index 83ea07d4bda..703c59e8f28 100644
--- a/mysql-test/main/sp-lock.test
+++ b/mysql-test/main/sp-lock.test
@@ -807,9 +807,6 @@ connection default;
--echo #
--echo # SHOW CREATE PROCEDURE p1 called from p1, after p1 was altered
--echo #
---echo # We are just covering the existing behaviour with tests. The
---echo # results are not necessarily correct."
---echo #
delimiter |;
CREATE PROCEDURE p1()
diff --git a/mysql-test/main/sp.result b/mysql-test/main/sp.result
index c460ecaa7bd..26de728391a 100644
--- a/mysql-test/main/sp.result
+++ b/mysql-test/main/sp.result
@@ -8869,6 +8869,25 @@ ERROR 42000: You have an error in your SQL syntax; check the manual that corresp
BEGIN
RETURN '';
END' at line 2
+SELECT VARIABLE_VALUE into @global_mem_used FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME='MEMORY_USED';
+SELECT VARIABLE_VALUE into @local_mem_used FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME='MEMORY_USED';
+CREATE PROCEDURE sp0() SELECT 1;
+SHOW CREATE PROCEDURE sp0;
+Procedure sql_mode Create Procedure character_set_client collation_connection Database Collation
+sp0 STRICT_ALL_TABLES CREATE DEFINER=`root`@`localhost` PROCEDURE `sp0`()
+SELECT 1 latin1 latin1_swedish_ci latin1_swedish_ci
+DROP PROCEDURE sp0;
+SELECT VARIABLE_VALUE into @global_mem_used FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME='MEMORY_USED';
+SELECT VARIABLE_VALUE into @local_mem_used FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME='MEMORY_USED';
+CREATE PROCEDURE sp1() SELECT 1;
+SHOW CREATE PROCEDURE sp1;
+Procedure sql_mode Create Procedure character_set_client collation_connection Database Collation
+sp1 STRICT_ALL_TABLES CREATE DEFINER=`root`@`localhost` PROCEDURE `sp1`()
+SELECT 1 latin1 latin1_swedish_ci latin1_swedish_ci
+SELECT VARIABLE_VALUE-@local_mem_used FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME='MEMORY_USED';
+VARIABLE_VALUE-@local_mem_used
+0
+DROP PROCEDURE sp1;
# End of 10.3 tests
#
# Start of 10.4 tests
diff --git a/mysql-test/main/sp.test b/mysql-test/main/sp.test
index 888cc569d6c..b1c69faa83a 100644
--- a/mysql-test/main/sp.test
+++ b/mysql-test/main/sp.test
@@ -10417,6 +10417,24 @@ END;
$$
DELIMITER ;$$
+# MDEV-20699 do not cache SP in SHOW CREATE
+# Warmup round, this might allocate some memory for session variable
+# and the output
+SELECT VARIABLE_VALUE into @global_mem_used FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME='MEMORY_USED';
+SELECT VARIABLE_VALUE into @local_mem_used FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME='MEMORY_USED';
+CREATE PROCEDURE sp0() SELECT 1;
+SHOW CREATE PROCEDURE sp0;
+DROP PROCEDURE sp0;
+
+#Check that CREATE/SHOW does not use memory in caches.
+SELECT VARIABLE_VALUE into @global_mem_used FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME='MEMORY_USED';
+SELECT VARIABLE_VALUE into @local_mem_used FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME='MEMORY_USED';
+CREATE PROCEDURE sp1() SELECT 1;
+SHOW CREATE PROCEDURE sp1;
+SELECT VARIABLE_VALUE-@local_mem_used FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME='MEMORY_USED';
+# 10.5 FIXME: This occasionally shows 56 or 64 bytes of difference!
+#SELECT VARIABLE_VALUE-@global_mem_used FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME='MEMORY_USED';
+DROP PROCEDURE sp1;
--echo # End of 10.3 tests
diff --git a/mysql-test/main/view.result b/mysql-test/main/view.result
index 0bb4bda4c28..18e0e14a6ef 100644
--- a/mysql-test/main/view.result
+++ b/mysql-test/main/view.result
@@ -6792,6 +6792,49 @@ sum(z)
DROP TABLE t1;
DROP VIEW v1;
#
+# MDEV-24454: Crash at change_item_tree
+#
+CREATE TABLE t1(f0 INT);
+CREATE VIEW v1 AS
+SELECT
+f0 AS f1
+FROM t1;
+CREATE VIEW v2 AS
+SELECT
+(SELECT GROUP_CONCAT(v1.f1 SEPARATOR ', ')
+FROM v1 n) AS f2,
+GROUP_CONCAT('' SEPARATOR ', ') AS f3
+FROM v1;
+CREATE VIEW v3 AS
+SELECT 1 as f4 FROM v2;
+CREATE PROCEDURE p1()
+SELECT * FROM v3;
+CALL p1();
+f4
+1
+CALL p1();
+f4
+1
+drop procedure p1;
+drop view v1,v2,v3;
+drop table t1;
+#
+# MDEV-25631: Crash in st_select_lex::mark_as_dependent with
+# VIEW, aggregate and subquery
+#
+CREATE TABLE t1 (i1 int);
+insert into t1 values (1),(2),(3);
+CREATE VIEW v1 AS
+SELECT t1.i1 FROM (t1 a JOIN t1 ON (t1.i1 = (SELECT t1.i1 FROM t1 b)));
+SELECT 1 FROM (SELECT count(((SELECT i1 FROM v1))) FROM v1) dt ;
+ERROR 21000: Subquery returns more than 1 row
+delete from t1 where i1 > 1;
+SELECT 1 FROM (SELECT count(((SELECT i1 FROM v1))) FROM v1) dt ;
+1
+1
+drop view v1;
+drop table t1;
+#
# End of 10.2 tests
#
#
diff --git a/mysql-test/main/view.test b/mysql-test/main/view.test
index 74f80919333..67bfb2432e8 100644
--- a/mysql-test/main/view.test
+++ b/mysql-test/main/view.test
@@ -6512,6 +6512,55 @@ DROP TABLE t1;
DROP VIEW v1;
--echo #
+--echo # MDEV-24454: Crash at change_item_tree
+--echo #
+
+CREATE TABLE t1(f0 INT);
+
+CREATE VIEW v1 AS
+SELECT
+ f0 AS f1
+FROM t1;
+
+CREATE VIEW v2 AS
+SELECT
+ (SELECT GROUP_CONCAT(v1.f1 SEPARATOR ', ')
+ FROM v1 n) AS f2,
+ GROUP_CONCAT('' SEPARATOR ', ') AS f3
+FROM v1;
+
+CREATE VIEW v3 AS
+SELECT 1 as f4 FROM v2;
+
+CREATE PROCEDURE p1()
+ SELECT * FROM v3;
+
+CALL p1();
+CALL p1();
+
+drop procedure p1;
+drop view v1,v2,v3;
+drop table t1;
+
+--echo #
+--echo # MDEV-25631: Crash in st_select_lex::mark_as_dependent with
+--echo # VIEW, aggregate and subquery
+--echo #
+
+CREATE TABLE t1 (i1 int);
+insert into t1 values (1),(2),(3); #not important
+CREATE VIEW v1 AS
+ SELECT t1.i1 FROM (t1 a JOIN t1 ON (t1.i1 = (SELECT t1.i1 FROM t1 b)));
+
+--error ER_SUBQUERY_NO_1_ROW
+SELECT 1 FROM (SELECT count(((SELECT i1 FROM v1))) FROM v1) dt ;
+delete from t1 where i1 > 1;
+SELECT 1 FROM (SELECT count(((SELECT i1 FROM v1))) FROM v1) dt ;
+
+drop view v1;
+drop table t1;
+
+--echo #
--echo # End of 10.2 tests
--echo #
diff --git a/mysql-test/suite/compat/oracle/r/sp-package.result b/mysql-test/suite/compat/oracle/r/sp-package.result
index cffb3ce7857..273c2f3ea7d 100644
--- a/mysql-test/suite/compat/oracle/r/sp-package.result
+++ b/mysql-test/suite/compat/oracle/r/sp-package.result
@@ -725,6 +725,10 @@ END
character_set_client latin1
collation_connection latin1_swedish_ci
Database Collation latin1_swedish_ci
+Warnings:
+Level Note
+Code 1585
+Message This function 'concat' has the same name as a native function
SHOW CREATE PACKAGE BODY test2;
Package body test2
sql_mode PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ORACLE,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,NO_AUTO_CREATE_USER,SIMULTANEOUS_ASSIGNMENT
@@ -745,6 +749,10 @@ END
character_set_client latin1
collation_connection latin1_swedish_ci
Database Collation latin1_swedish_ci
+Warnings:
+Level Note
+Code 1585
+Message This function 'concat' has the same name as a native function
DROP PACKAGE BODY test2;
SELECT test2.f1();
ERROR 42000: FUNCTION test.test2.f1 does not exist
diff --git a/mysql-test/suite/galera/disabled.def b/mysql-test/suite/galera/disabled.def
index 70220a1e01e..0c2b2facc2c 100644
--- a/mysql-test/suite/galera/disabled.def
+++ b/mysql-test/suite/galera/disabled.def
@@ -39,7 +39,6 @@ galera_toi_truncate : MDEV-22996 Hang on galera_toi_truncate test case
galera_trigger : MDEV-24048 galera.galera_trigger MTR fails: Result content mismatch
galera_unicode_identifiers : MDEV-26500 : galera.galera_unicode_identifiers MTR failed: InnoDB: innodb_fatal_semaphore_wait_threshold was exceeded for dict_sys.mutex
galera_var_dirty_reads : MDEV-25615 Galera test failure on galera_var_dirty_reads
-galera_var_ignore_apply_errors : MDEV-20451: Lock wait timeout exceeded in galera_var_ignore_apply_errors
galera_var_node_address : MDEV-20485 Galera test failure
galera_var_notify_cmd : MDEV-21905 Galera test galera_var_notify_cmd causes hang
galera_var_reject_queries : assertion in inline_mysql_socket_send
diff --git a/mysql-test/suite/galera/r/galera_fulltext.result b/mysql-test/suite/galera/r/galera_fulltext.result
index 94780f235ad..a22296278fa 100644
--- a/mysql-test/suite/galera/r/galera_fulltext.result
+++ b/mysql-test/suite/galera/r/galera_fulltext.result
@@ -36,59 +36,3 @@ COUNT(f1) = 1000
1
DROP TABLE t1;
DROP TABLE ten;
-connection node_1;
-SET @value=REPEAT (1,5001);
-CREATE TABLE t (a VARCHAR(5000),FULLTEXT (a)) engine=innodb;
-INSERT IGNORE INTO t VALUES(@value);
-Warnings:
-Warning 1265 Data truncated for column 'a' at row 1
-SELECT COUNT(*) FROM t;
-COUNT(*)
-1
-connection node_2;
-SELECT COUNT(*) FROM t;
-COUNT(*)
-1
-connection node_1;
-DROP TABLE t;
-CREATE TABLE t (a VARCHAR(5000)) engine=innodb;
-INSERT IGNORE INTO t VALUES(@value);
-Warnings:
-Warning 1265 Data truncated for column 'a' at row 1
-SELECT COUNT(*) FROM t;
-COUNT(*)
-1
-connection node_2;
-SELECT COUNT(*) FROM t;
-COUNT(*)
-1
-connection node_1;
-DROP TABLE t;
-connection node_1;
-SET @value=REPEAT (1,5001);
-CREATE TABLE t (a VARCHAR(5000),FULLTEXT (a)) engine=innodb DEFAULT CHARSET=utf8;
-INSERT IGNORE INTO t VALUES(@value);
-Warnings:
-Warning 1265 Data truncated for column 'a' at row 1
-SELECT COUNT(*) FROM t;
-COUNT(*)
-1
-connection node_2;
-SELECT COUNT(*) FROM t;
-COUNT(*)
-1
-connection node_1;
-DROP TABLE t;
-CREATE TABLE t (a VARCHAR(5000)) engine=innodb DEFAULT CHARSET=utf8;
-INSERT IGNORE INTO t VALUES(@value);
-Warnings:
-Warning 1265 Data truncated for column 'a' at row 1
-SELECT COUNT(*) FROM t;
-COUNT(*)
-1
-connection node_2;
-SELECT COUNT(*) FROM t;
-COUNT(*)
-1
-connection node_1;
-DROP TABLE t;
diff --git a/mysql-test/suite/galera/r/galera_partition.result b/mysql-test/suite/galera/r/galera_partition.result
index f09a0272eda..0e8894794d7 100644
--- a/mysql-test/suite/galera/r/galera_partition.result
+++ b/mysql-test/suite/galera/r/galera_partition.result
@@ -424,3 +424,5 @@ connection node_4;
connection node_1;
DROP TABLE t1;
DROP PROCEDURE p1;
+disconnect node_3;
+disconnect node_4;
diff --git a/mysql-test/suite/galera/t/galera_fulltext.test b/mysql-test/suite/galera/t/galera_fulltext.test
index 25f4f83b7b7..7e2fc5e581d 100644
--- a/mysql-test/suite/galera/t/galera_fulltext.test
+++ b/mysql-test/suite/galera/t/galera_fulltext.test
@@ -1,6 +1,4 @@
---source include/big_test.inc
--source include/galera_cluster.inc
---source include/have_innodb.inc
#
# InnoDB FULLTEXT indexes
@@ -60,50 +58,28 @@ SELECT COUNT(f1) = 1000 FROM t1 WHERE MATCH(f1) AGAINST ('abcdefjhk');
DROP TABLE t1;
DROP TABLE ten;
-#
-# MDEV-24978 : SIGABRT in __libc_message
-#
---connection node_1
-SET @value=REPEAT (1,5001);
-CREATE TABLE t (a VARCHAR(5000),FULLTEXT (a)) engine=innodb;
-INSERT IGNORE INTO t VALUES(@value);
-SELECT COUNT(*) FROM t;
-
---connection node_2
-SELECT COUNT(*) FROM t;
-
---connection node_1
-DROP TABLE t;
-CREATE TABLE t (a VARCHAR(5000)) engine=innodb;
-INSERT IGNORE INTO t VALUES(@value);
-SELECT COUNT(*) FROM t;
-
---connection node_2
-SELECT COUNT(*) FROM t;
-
---connection node_1
-DROP TABLE t;
#
# Case 2: UTF-8
+# TODO: MDEV-24978
#
---connection node_1
-SET @value=REPEAT (1,5001);
-CREATE TABLE t (a VARCHAR(5000),FULLTEXT (a)) engine=innodb DEFAULT CHARSET=utf8;
-INSERT IGNORE INTO t VALUES(@value);
-SELECT COUNT(*) FROM t;
-
---connection node_2
-SELECT COUNT(*) FROM t;
-
---connection node_1
-DROP TABLE t;
-CREATE TABLE t (a VARCHAR(5000)) engine=innodb DEFAULT CHARSET=utf8;
-INSERT IGNORE INTO t VALUES(@value);
-SELECT COUNT(*) FROM t;
-
---connection node_2
-SELECT COUNT(*) FROM t;
-
---connection node_1
-DROP TABLE t;
+#--connection node_1
+#SET @value=REPEAT (1,5001);
+#CREATE TABLE t (a VARCHAR(5000),FULLTEXT (a)) engine=innodb DEFAULT CHARSET=utf8;
+#INSERT IGNORE INTO t VALUES(@value);
+#SELECT COUNT(*) FROM t;
+#
+#--connection node_2
+#SELECT COUNT(*) FROM t;
+#
+#--connection node_1
+#DROP TABLE t;
+#CREATE TABLE t (a VARCHAR(5000)) engine=innodb DEFAULT CHARSET=utf8;
+#INSERT IGNORE INTO t VALUES(@value);
+#SELECT COUNT(*) FROM t;
+#
+#--connection node_2
+#SELECT COUNT(*) FROM t;
+#
+#--connection node_1
+#DROP TABLE t;
diff --git a/mysql-test/suite/galera/t/galera_partition.cnf b/mysql-test/suite/galera/t/galera_partition.cnf
index e6cb13ef523..525eece04ab 100644
--- a/mysql-test/suite/galera/t/galera_partition.cnf
+++ b/mysql-test/suite/galera/t/galera_partition.cnf
@@ -3,16 +3,20 @@
[mysqld.1]
wsrep_provider_options='base_port=@mysqld.1.#galera_port;gcache.size=10M;gmcast.segment=1'
wsrep_slave_threads=10
+wsrep_debug=1
[mysqld.2]
wsrep_provider_options='base_port=@mysqld.2.#galera_port;gcache.size=10M;gmcast.segment=1'
wsrep_slave_threads=10
+wsrep_debug=1
[mysqld.3]
wsrep_provider_options='base_port=@mysqld.3.#galera_port;gcache.size=10M;gmcast.segment=2'
wsrep_slave_threads=10
+wsrep_debug=1
[mysqld.4]
wsrep_provider_options='base_port=@mysqld.4.#galera_port;gcache.size=10M;gmcast.segment=3'
wsrep_slave_threads=10
+wsrep_debug=1
diff --git a/mysql-test/suite/galera/t/galera_partition.test b/mysql-test/suite/galera/t/galera_partition.test
index bf3f02eaa92..3de45d54000 100644
--- a/mysql-test/suite/galera/t/galera_partition.test
+++ b/mysql-test/suite/galera/t/galera_partition.test
@@ -11,6 +11,8 @@ call mtr.add_suppression("WSREP: ALTER TABLE isolation failure");
--connect node_4, 127.0.0.1, root, , test, $NODE_MYPORT_4
--connection node_1
+--let $wait_condition = SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+--source include/wait_condition.inc
CREATE TABLE t1(
id bigint unsigned NOT NULL AUTO_INCREMENT,
@@ -449,3 +451,7 @@ reap;
DROP TABLE t1;
DROP PROCEDURE p1;
+--disconnect node_3
+--disconnect node_4
+
+
diff --git a/mysql-test/suite/galera/t/galera_var_ignore_apply_errors.cnf b/mysql-test/suite/galera/t/galera_var_ignore_apply_errors.cnf
new file mode 100644
index 00000000000..545cc8147e0
--- /dev/null
+++ b/mysql-test/suite/galera/t/galera_var_ignore_apply_errors.cnf
@@ -0,0 +1,7 @@
+!include ../galera_2nodes.cnf
+
+[mysqld.1]
+wsrep_debug=1
+
+[mysqld.2]
+wsrep_debug=1
diff --git a/mysql-test/suite/galera/t/galera_var_ignore_apply_errors.test b/mysql-test/suite/galera/t/galera_var_ignore_apply_errors.test
index 0f8efad5163..5a00048a90e 100644
--- a/mysql-test/suite/galera/t/galera_var_ignore_apply_errors.test
+++ b/mysql-test/suite/galera/t/galera_var_ignore_apply_errors.test
@@ -3,7 +3,6 @@
#
--source include/galera_cluster.inc
---source include/have_innodb.inc
#
@@ -73,11 +72,15 @@ SET GLOBAL wsrep_on = ON;
DELETE FROM t1 WHERE f1 = 1;
--connection node_1
+--let $wait_condition = SELECT COUNT(*) = 0 FROM t1;
+--source include/wait_condition.inc
SELECT COUNT(*) as expect_0 FROM t1;
--connection node_2
--source include/galera_wait_ready.inc
--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
--source include/wait_condition.inc
+--let $wait_condition = SELECT COUNT(*) = 0 FROM t1;
+--source include/wait_condition.inc
SELECT COUNT(*) as expect_0 FROM t1;
DROP TABLE t1;
@@ -97,11 +100,15 @@ DELETE FROM t1 WHERE f1 = 2;
COMMIT;
--connection node_1
+--let $wait_condition = SELECT COUNT(*) = 1 FROM t1;
+--source include/wait_condition.inc
SELECT COUNT(*) as expect_1 FROM t1;
--connection node_2
--source include/galera_wait_ready.inc
--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
--source include/wait_condition.inc
+--let $wait_condition = SELECT COUNT(*) = 1 FROM t1;
+--source include/wait_condition.inc
SELECT COUNT(*) as expect_1 FROM t1;
DROP TABLE t1;
@@ -132,6 +139,8 @@ SELECT COUNT(*) as expect_0 FROM t1;
--let $wait_condition = SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
--source include/wait_condition.inc
SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+--let $wait_condition = SELECT COUNT(*) = 0 FROM t1;
+--source include/wait_condition.inc
SELECT COUNT(*) as expect_0 FROM t1;
DROP TABLE t1;
@@ -171,6 +180,8 @@ SELECT COUNT(*) as expect_0 FROM t1;
--let $wait_condition = SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
--source include/wait_condition.inc
SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+--let $wait_condition = SELECT COUNT(*) = 0 FROM t1;
+--source include/wait_condition.inc
SELECT COUNT(*) as expect_0 FROM t1;
DROP TABLE t1;
@@ -205,6 +216,8 @@ SELECT COUNT(*) as expect_0 FROM t1;
--let $wait_condition = SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
--source include/wait_condition.inc
SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+--let $wait_condition = SELECT COUNT(*) = 0 FROM t1;
+--source include/wait_condition.inc
SELECT COUNT(*) as expect_0 FROM t1;
DROP TABLE t1,t2;
@@ -239,6 +252,10 @@ SELECT COUNT(*) as expect_0 FROM child;
--let $wait_condition = SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
--source include/wait_condition.inc
SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
+--let $wait_condition = SELECT COUNT(*) = 0 FROM parent;
+--source include/wait_condition.inc
+--let $wait_condition = SELECT COUNT(*) = 0 FROM child;
+--source include/wait_condition.inc
SELECT COUNT(*) as expect_0 FROM parent;
SELECT COUNT(*) as expect_0 FROM child;
DROP TABLE child, parent;
diff --git a/mysql-test/suite/innodb/r/doublewrite.result b/mysql-test/suite/innodb/r/doublewrite.result
index 234d58012d3..ba1965ed4cd 100644
--- a/mysql-test/suite/innodb/r/doublewrite.result
+++ b/mysql-test/suite/innodb/r/doublewrite.result
@@ -65,6 +65,7 @@ where name = 'test/t1';
# Ensure that dirty pages of table t1 is flushed.
flush tables t1 for export;
unlock tables;
+set global innodb_log_checkpoint_now=1;
begin;
insert into t1 values (6, repeat('%', 12));
# Make the first page dirty for table t1
diff --git a/mysql-test/suite/innodb/r/innodb_defrag_stats.result b/mysql-test/suite/innodb/r/innodb_defrag_stats.result
index 2e7a2ba5197..c6fd7006f9e 100644
--- a/mysql-test/suite/innodb/r/innodb_defrag_stats.result
+++ b/mysql-test/suite/innodb/r/innodb_defrag_stats.result
@@ -3,118 +3,115 @@ DELETE FROM mysql.innodb_index_stats;
# Create table.
CREATE TABLE t1 (a INT PRIMARY KEY AUTO_INCREMENT, b VARCHAR(256),
KEY SECOND(a, b)) ENGINE=INNODB STATS_PERSISTENT=0;
-INSERT INTO t1 SELECT seq, REPEAT('A', 256) FROM seq_1_to_1024;
+INSERT INTO t1 SELECT 100*FLOOR(seq/70)+seq%70, REPEAT('A', 256)
+FROM seq_1_to_1024;
# Not enough page splits to trigger persistent stats write yet.
-select count(stat_value) = 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_page_split');
-count(stat_value) = 0
-1
-select count(stat_value) = 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_pages_freed');
-count(stat_value) = 0
-1
-select count(stat_value) = 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_leaf_pages_defrag');
-count(stat_value) = 0
-1
-INSERT INTO t1 SELECT seq, REPEAT('A', 256) FROM seq_1025_to_2048;
-# Persistent stats recorded.
-select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_page_split');
-count(stat_value) > 0
-1
-select count(stat_value) = 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_pages_freed');
-count(stat_value) = 0
-1
-select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_leaf_pages_defrag');
-count(stat_value) > 0
-1
-# Delete some rows.
+SELECT * FROM mysql.innodb_index_stats;
+database_name table_name index_name last_update stat_name stat_value sample_size stat_description
+INSERT INTO t1 SELECT 100*FLOOR(seq/70)+seq%70, REPEAT('A', 256)
+FROM seq_1025_to_1433;
BEGIN;
-delete from t1 where a between 100 * 20 and 100 * 20 + 30;
-delete from t1 where a between 100 * 19 and 100 * 19 + 30;
-delete from t1 where a between 100 * 18 and 100 * 18 + 30;
-delete from t1 where a between 100 * 17 and 100 * 17 + 30;
-delete from t1 where a between 100 * 16 and 100 * 16 + 30;
-delete from t1 where a between 100 * 15 and 100 * 15 + 30;
-delete from t1 where a between 100 * 14 and 100 * 14 + 30;
-delete from t1 where a between 100 * 13 and 100 * 13 + 30;
-delete from t1 where a between 100 * 12 and 100 * 12 + 30;
-delete from t1 where a between 100 * 11 and 100 * 11 + 30;
-delete from t1 where a between 100 * 10 and 100 * 10 + 30;
-delete from t1 where a between 100 * 9 and 100 * 9 + 30;
-delete from t1 where a between 100 * 8 and 100 * 8 + 30;
-delete from t1 where a between 100 * 7 and 100 * 7 + 30;
-delete from t1 where a between 100 * 6 and 100 * 6 + 30;
-delete from t1 where a between 100 * 5 and 100 * 5 + 30;
-delete from t1 where a between 100 * 4 and 100 * 4 + 30;
-delete from t1 where a between 100 * 3 and 100 * 3 + 30;
-delete from t1 where a between 100 * 2 and 100 * 2 + 30;
-delete from t1 where a between 100 * 1 and 100 * 1 + 30;
-COMMIT;
-select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_page_split');
-count(stat_value) > 0
-1
-select count(stat_value) = 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_pages_freed');
-count(stat_value) = 0
-1
-select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_leaf_pages_defrag');
-count(stat_value) > 0
-1
+INSERT INTO t1 SELECT 100*20+seq, REPEAT('A', 256)
+FROM seq_70_to_99;
+INSERT INTO t1 SELECT 100*19+seq, REPEAT('A', 256)
+FROM seq_70_to_99;
+INSERT INTO t1 SELECT 100*18+seq, REPEAT('A', 256)
+FROM seq_70_to_99;
+INSERT INTO t1 SELECT 100*17+seq, REPEAT('A', 256)
+FROM seq_70_to_99;
+INSERT INTO t1 SELECT 100*16+seq, REPEAT('A', 256)
+FROM seq_70_to_99;
+INSERT INTO t1 SELECT 100*15+seq, REPEAT('A', 256)
+FROM seq_70_to_99;
+INSERT INTO t1 SELECT 100*14+seq, REPEAT('A', 256)
+FROM seq_70_to_99;
+INSERT INTO t1 SELECT 100*13+seq, REPEAT('A', 256)
+FROM seq_70_to_99;
+INSERT INTO t1 SELECT 100*12+seq, REPEAT('A', 256)
+FROM seq_70_to_99;
+INSERT INTO t1 SELECT 100*11+seq, REPEAT('A', 256)
+FROM seq_70_to_99;
+INSERT INTO t1 SELECT 100*10+seq, REPEAT('A', 256)
+FROM seq_70_to_99;
+INSERT INTO t1 SELECT 100*9+seq, REPEAT('A', 256)
+FROM seq_70_to_99;
+INSERT INTO t1 SELECT 100*8+seq, REPEAT('A', 256)
+FROM seq_70_to_99;
+INSERT INTO t1 SELECT 100*7+seq, REPEAT('A', 256)
+FROM seq_70_to_99;
+INSERT INTO t1 SELECT 100*6+seq, REPEAT('A', 256)
+FROM seq_70_to_99;
+INSERT INTO t1 SELECT 100*5+seq, REPEAT('A', 256)
+FROM seq_70_to_99;
+INSERT INTO t1 SELECT 100*4+seq, REPEAT('A', 256)
+FROM seq_70_to_99;
+INSERT INTO t1 SELECT 100*3+seq, REPEAT('A', 256)
+FROM seq_70_to_99;
+INSERT INTO t1 SELECT 100*2+seq, REPEAT('A', 256)
+FROM seq_70_to_99;
+INSERT INTO t1 SELECT 100*1+seq, REPEAT('A', 256)
+FROM seq_70_to_99;
+ROLLBACK;
+SELECT @@GLOBAL.innodb_force_recovery<2 "have background defragmentation";
+have background defragmentation
+1
+SELECT table_name, index_name, stat_name FROM mysql.innodb_index_stats;
+table_name index_name stat_name
+t1 PRIMARY n_leaf_pages_defrag
+t1 PRIMARY n_leaf_pages_reserved
+t1 PRIMARY n_page_split
+t1 SECOND n_leaf_pages_defrag
+t1 SECOND n_leaf_pages_reserved
+t1 SECOND n_page_split
optimize table t1;
Table Op Msg_type Msg_text
test.t1 optimize status OK
-select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_page_split');
-count(stat_value) > 0
-1
-select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_pages_freed');
-count(stat_value) > 0
-1
-select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_leaf_pages_defrag');
-count(stat_value) > 0
-1
+SELECT table_name, index_name, stat_name FROM mysql.innodb_index_stats;
+table_name index_name stat_name
+t1 PRIMARY n_leaf_pages_defrag
+t1 PRIMARY n_leaf_pages_reserved
+t1 PRIMARY n_page_split
+t1 PRIMARY n_pages_freed
+t1 SECOND n_leaf_pages_defrag
+t1 SECOND n_leaf_pages_reserved
+t1 SECOND n_page_split
+t1 SECOND n_pages_freed
set global innodb_defragment_stats_accuracy = 40;
INSERT INTO t1 (b) SELECT b from t1;
-select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_page_split');
-count(stat_value) > 0
-1
-select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_pages_freed');
-count(stat_value) > 0
-1
-select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_leaf_pages_defrag');
-count(stat_value) > 0
-1
+SELECT table_name, index_name, stat_name FROM mysql.innodb_index_stats;
+table_name index_name stat_name
+t1 PRIMARY n_leaf_pages_defrag
+t1 PRIMARY n_leaf_pages_reserved
+t1 PRIMARY n_page_split
+t1 PRIMARY n_pages_freed
+t1 SECOND n_leaf_pages_defrag
+t1 SECOND n_leaf_pages_reserved
+t1 SECOND n_page_split
+t1 SECOND n_pages_freed
INSERT INTO t1 (b) SELECT b from t1;
-select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_page_split');
-count(stat_value) > 0
-1
-select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_pages_freed');
-count(stat_value) > 0
-1
-select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_leaf_pages_defrag');
-count(stat_value) > 0
-1
+SELECT stat_name FROM mysql.innodb_index_stats WHERE table_name='t1';
+stat_name
+n_leaf_pages_defrag
+n_leaf_pages_defrag
+n_leaf_pages_reserved
+n_leaf_pages_reserved
+n_page_split
+n_page_split
+n_pages_freed
+n_pages_freed
# Table rename should cause stats rename.
rename table t1 to t2;
-select count(stat_value) = 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_page_split');
-count(stat_value) = 0
-1
-select count(stat_value) = 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_pages_freed');
-count(stat_value) = 0
-1
-select count(stat_value) = 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_leaf_pages_defrag');
-count(stat_value) = 0
-1
-select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t2%' and stat_name in ('n_page_split');
-count(stat_value) > 0
-1
-select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t2%' and stat_name in ('n_pages_freed');
-count(stat_value) > 0
-1
-select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t2%' and stat_name in ('n_leaf_pages_defrag');
-count(stat_value) > 0
-1
-# Drop index should cause stats drop, but will not.
+SELECT table_name, index_name, stat_name FROM mysql.innodb_index_stats;
+table_name index_name stat_name
+t2 PRIMARY n_leaf_pages_defrag
+t2 PRIMARY n_leaf_pages_reserved
+t2 PRIMARY n_page_split
+t2 PRIMARY n_pages_freed
+t2 SECOND n_leaf_pages_defrag
+t2 SECOND n_leaf_pages_reserved
+t2 SECOND n_page_split
+t2 SECOND n_pages_freed
drop index SECOND on t2;
-SELECT stat_name, stat_value>0 FROM mysql.innodb_index_stats
-WHERE table_name like '%t2%' AND index_name='SECOND';
-stat_name stat_value>0
#
# MDEV-26636: Statistics must not be written for temporary tables
#
@@ -123,15 +120,12 @@ CREATE TEMPORARY TABLE t (a INT PRIMARY KEY, c CHAR(255) NOT NULL)
ENGINE=InnoDB;
INSERT INTO t SELECT seq, '' FROM seq_1_to_100;
# restart
-SELECT * FROM mysql.innodb_index_stats where table_name like '%t1%';
-database_name table_name index_name last_update stat_name stat_value sample_size stat_description
-SELECT table_name, index_name, stat_name, stat_value>0
-FROM mysql.innodb_index_stats;
-table_name index_name stat_name stat_value>0
-t2 PRIMARY n_leaf_pages_defrag 1
-t2 PRIMARY n_leaf_pages_reserved 1
-t2 PRIMARY n_page_split 1
-t2 PRIMARY n_pages_freed 0
+SELECT table_name, index_name, stat_name FROM mysql.innodb_index_stats;
+table_name index_name stat_name
+t2 PRIMARY n_leaf_pages_defrag
+t2 PRIMARY n_leaf_pages_reserved
+t2 PRIMARY n_page_split
+t2 PRIMARY n_pages_freed
# Clean up
ALTER TABLE t2 STATS_PERSISTENT=1;
DROP TABLE t2;
diff --git a/mysql-test/suite/innodb/t/doublewrite.test b/mysql-test/suite/innodb/t/doublewrite.test
index cedd2c9942b..d8dac955348 100644
--- a/mysql-test/suite/innodb/t/doublewrite.test
+++ b/mysql-test/suite/innodb/t/doublewrite.test
@@ -159,6 +159,8 @@ where name = 'test/t1';
flush tables t1 for export;
unlock tables;
+set global innodb_log_checkpoint_now=1;
+
begin;
insert into t1 values (6, repeat('%', 12));
diff --git a/mysql-test/suite/innodb/t/innodb_defrag_stats.test b/mysql-test/suite/innodb/t/innodb_defrag_stats.test
index 13e4579d3d8..ef79d8d6ade 100644
--- a/mysql-test/suite/innodb/t/innodb_defrag_stats.test
+++ b/mysql-test/suite/innodb/t/innodb_defrag_stats.test
@@ -11,75 +11,61 @@ DELETE FROM mysql.innodb_index_stats;
CREATE TABLE t1 (a INT PRIMARY KEY AUTO_INCREMENT, b VARCHAR(256),
KEY SECOND(a, b)) ENGINE=INNODB STATS_PERSISTENT=0;
-INSERT INTO t1 SELECT seq, REPEAT('A', 256) FROM seq_1_to_1024;
+INSERT INTO t1 SELECT 100*FLOOR(seq/70)+seq%70, REPEAT('A', 256)
+FROM seq_1_to_1024;
--echo # Not enough page splits to trigger persistent stats write yet.
-select count(stat_value) = 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_page_split');
-select count(stat_value) = 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_pages_freed');
-select count(stat_value) = 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_leaf_pages_defrag');
-
-INSERT INTO t1 SELECT seq, REPEAT('A', 256) FROM seq_1025_to_2048;
+SELECT * FROM mysql.innodb_index_stats;
---echo # Persistent stats recorded.
-select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_page_split');
-select count(stat_value) = 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_pages_freed');
-select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_leaf_pages_defrag');
+INSERT INTO t1 SELECT 100*FLOOR(seq/70)+seq%70, REPEAT('A', 256)
+FROM seq_1025_to_1433;
---echo # Delete some rows.
BEGIN;
let $num_delete = 20;
while ($num_delete)
{
- let $j = 100 * $num_delete;
- eval delete from t1 where a between $j and $j + 30;
+ eval INSERT INTO t1 SELECT 100*$num_delete+seq, REPEAT('A', 256)
+ FROM seq_70_to_99;
dec $num_delete;
}
-COMMIT;
+ROLLBACK;
+
+SELECT @@GLOBAL.innodb_force_recovery<2 "have background defragmentation";
+
+# Wait for defrag_pool to be processed.
-select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_page_split');
-select count(stat_value) = 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_pages_freed');
-select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_leaf_pages_defrag');
+let $wait_timeout=30;
+let $wait_condition = SELECT COUNT(*)>0 FROM mysql.innodb_index_stats;
+--source include/wait_condition.inc
+
+--sorted_result
+SELECT table_name, index_name, stat_name FROM mysql.innodb_index_stats;
optimize table t1;
-select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_page_split');
-select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_pages_freed');
-select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_leaf_pages_defrag');
+--sorted_result
+SELECT table_name, index_name, stat_name FROM mysql.innodb_index_stats;
set global innodb_defragment_stats_accuracy = 40;
INSERT INTO t1 (b) SELECT b from t1;
-select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_page_split');
-select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_pages_freed');
-select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_leaf_pages_defrag');
-
+--sorted_result
+SELECT table_name, index_name, stat_name FROM mysql.innodb_index_stats;
INSERT INTO t1 (b) SELECT b from t1;
-select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_page_split');
-select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_pages_freed');
-select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_leaf_pages_defrag');
-
+--sorted_result
+SELECT stat_name FROM mysql.innodb_index_stats WHERE table_name='t1';
--echo # Table rename should cause stats rename.
rename table t1 to t2;
-select count(stat_value) = 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_page_split');
-select count(stat_value) = 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_pages_freed');
-select count(stat_value) = 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_leaf_pages_defrag');
-
-select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t2%' and stat_name in ('n_page_split');
-select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t2%' and stat_name in ('n_pages_freed');
-select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t2%' and stat_name in ('n_leaf_pages_defrag');
+--sorted_result
+SELECT table_name, index_name, stat_name FROM mysql.innodb_index_stats;
---echo # Drop index should cause stats drop, but will not.
drop index SECOND on t2;
---sorted_result
-SELECT stat_name, stat_value>0 FROM mysql.innodb_index_stats
-WHERE table_name like '%t2%' AND index_name='SECOND';
-
--echo #
--echo # MDEV-26636: Statistics must not be written for temporary tables
--echo #
@@ -90,14 +76,12 @@ INSERT INTO t SELECT seq, '' FROM seq_1_to_100;
--source include/restart_mysqld.inc
-SELECT * FROM mysql.innodb_index_stats where table_name like '%t1%';
-
--sorted_result
-SELECT table_name, index_name, stat_name, stat_value>0
-FROM mysql.innodb_index_stats;
+SELECT table_name, index_name, stat_name FROM mysql.innodb_index_stats;
--echo # Clean up
-# DROP TABLE will not touch persistent statistics if the table has none!
+# Starting with 10.6, DROP TABLE will not touch persistent statistics
+# (not defragmentation statistics either) if the table has none!
ALTER TABLE t2 STATS_PERSISTENT=1;
DROP TABLE t2;
diff --git a/mysql-test/suite/innodb/t/undo_truncate.test b/mysql-test/suite/innodb/t/undo_truncate.test
index 9601de482b3..cf8c1a8d5e3 100644
--- a/mysql-test/suite/innodb/t/undo_truncate.test
+++ b/mysql-test/suite/innodb/t/undo_truncate.test
@@ -54,7 +54,7 @@ let $trx_after= `select substr('$trx_after',9)`;
drop table t1, t2;
-if ($trx_before != $trx_after)
+if ($trx_before > $trx_after)
{
- echo Transaction sequence mismatch: $trx_before != $trx_after;
+ echo Transaction sequence mismatch: $trx_before > $trx_after;
}
diff --git a/mysql-test/suite/plugins/r/feedback_plugin_load.result b/mysql-test/suite/plugins/r/feedback_plugin_load.result
index 5f50c9b0525..f31c7325ca1 100644
--- a/mysql-test/suite/plugins/r/feedback_plugin_load.result
+++ b/mysql-test/suite/plugins/r/feedback_plugin_load.result
@@ -24,3 +24,19 @@ VARIABLE_VALUE>0 VARIABLE_NAME
1 Collation used utf8mb3_bin
1 Collation used utf8mb3_general_ci
1 Collation used utf8mb4_bin
+prepare stmt from "SELECT VARIABLE_VALUE>0, VARIABLE_NAME FROM INFORMATION_SCHEMA.FEEDBACK WHERE VARIABLE_NAME LIKE 'Collation used %' ORDER BY VARIABLE_NAME";
+execute stmt;
+VARIABLE_VALUE>0 VARIABLE_NAME
+1 Collation used binary
+1 Collation used latin1_swedish_ci
+1 Collation used utf8mb3_bin
+1 Collation used utf8mb3_general_ci
+1 Collation used utf8mb4_bin
+execute stmt;
+VARIABLE_VALUE>0 VARIABLE_NAME
+1 Collation used binary
+1 Collation used latin1_swedish_ci
+1 Collation used utf8mb3_bin
+1 Collation used utf8mb3_general_ci
+1 Collation used utf8mb4_bin
+deallocate prepare stmt;
diff --git a/mysql-test/suite/plugins/t/feedback_plugin_load.test b/mysql-test/suite/plugins/t/feedback_plugin_load.test
index ecf678eb420..f67397afdfe 100644
--- a/mysql-test/suite/plugins/t/feedback_plugin_load.test
+++ b/mysql-test/suite/plugins/t/feedback_plugin_load.test
@@ -42,3 +42,10 @@ if (`SELECT VERSION() LIKE '%embedded%'`)
SELECT VARIABLE_VALUE>0, VARIABLE_NAME FROM INFORMATION_SCHEMA.FEEDBACK
WHERE VARIABLE_NAME LIKE 'Collation used %'
ORDER BY VARIABLE_NAME;
+
+prepare stmt from "SELECT VARIABLE_VALUE>0, VARIABLE_NAME FROM INFORMATION_SCHEMA.FEEDBACK WHERE VARIABLE_NAME LIKE 'Collation used %' ORDER BY VARIABLE_NAME";
+
+execute stmt;
+execute stmt;
+
+deallocate prepare stmt;
diff --git a/mysys/CMakeLists.txt b/mysys/CMakeLists.txt
index 269369360f1..d1dbec3e3a1 100644
--- a/mysys/CMakeLists.txt
+++ b/mysys/CMakeLists.txt
@@ -55,6 +55,7 @@ IF (WIN32)
my_winerr.c
my_winfile.c
my_conio.c
+ my_minidump.cc
my_win_popen.cc)
ENDIF()
@@ -173,7 +174,7 @@ IF(HAVE_BFD_H)
ENDIF(HAVE_BFD_H)
IF (WIN32)
- TARGET_LINK_LIBRARIES(mysys IPHLPAPI)
+ TARGET_LINK_LIBRARIES(mysys iphlpapi dbghelp)
ENDIF(WIN32)
# Need explicit pthread for gcc -fsanitize=address
diff --git a/mysys/charset-def.c b/mysys/charset-def.c
index 737a1c88a47..2e23adc5147 100644
--- a/mysys/charset-def.c
+++ b/mysys/charset-def.c
@@ -202,7 +202,7 @@ my_bool init_compiled_charsets(myf flags __attribute__((unused)))
#endif
#ifdef HAVE_CHARSET_cp1250
- add_compiled_collation(&my_charset_cp1250_czech_ci);
+ add_compiled_collation(&my_charset_cp1250_czech_cs);
#endif
#ifdef HAVE_CHARSET_cp932
@@ -213,7 +213,7 @@ my_bool init_compiled_charsets(myf flags __attribute__((unused)))
#endif
#ifdef HAVE_CHARSET_latin2
- add_compiled_collation(&my_charset_latin2_czech_ci);
+ add_compiled_collation(&my_charset_latin2_czech_cs);
#endif
#ifdef HAVE_CHARSET_eucjpms
diff --git a/mysys/my_minidump.cc b/mysys/my_minidump.cc
new file mode 100644
index 00000000000..d81aab2f764
--- /dev/null
+++ b/mysys/my_minidump.cc
@@ -0,0 +1,115 @@
+/* Copyright (c) 2021, MariaDB Corporation
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */
+
+#include <windows.h>
+#include <dbghelp.h>
+#include <stdio.h>
+#include <my_minidump.h>
+
+#define VERBOSE(fmt,...) \
+ if (verbose) { fprintf(stderr, "my_create_minidump : " fmt,__VA_ARGS__); }
+
+extern "C" BOOL my_create_minidump(DWORD pid, BOOL verbose)
+{
+ HANDLE file = 0;
+ HANDLE process= 0;
+ DWORD size= MAX_PATH;
+ char path[MAX_PATH];
+ char working_dir[MAX_PATH];
+ char tmpname[MAX_PATH];
+ char *filename= 0;
+ bool ret= FALSE;
+ process= OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid);
+ if (!process)
+ {
+ VERBOSE("cannot open process pid=%lu to create dump, last error %lu\n",
+ pid, GetLastError());
+ goto exit;
+ }
+
+ if (QueryFullProcessImageName(process, 0, path, &size) == 0)
+ {
+ VERBOSE("cannot read process path for pid %lu, last error %lu\n",
+ pid, GetLastError());
+ goto exit;
+ }
+
+ filename= strrchr(path, '\\');
+ if (filename)
+ {
+ filename++;
+ // We are not interested in dump of some proceses (my_safe_process.exe,cmd.exe)
+ // since they are only used to start up other programs.
+ // We're interested however in their children;
+ const char *exclude_programs[] = {"my_safe_process.exe","cmd.exe", 0};
+ for(size_t i=0; exclude_programs[i]; i++)
+ if (_stricmp(filename, exclude_programs[i]) == 0)
+ goto exit;
+ }
+ else
+ filename= path;
+
+ // Add .dmp extension
+ char *p;
+ if ((p= strrchr(filename, '.')) == 0)
+ p= filename + strlen(filename);
+
+ strncpy(p, ".dmp", path + MAX_PATH - p);
+
+ // Ãf file with this name exist, generate unique name with .dmp extension
+ if (GetFileAttributes(filename) != INVALID_FILE_ATTRIBUTES)
+ {
+ if (!GetTempFileName(".", filename, 0, tmpname))
+ {
+ fprintf(stderr, "GetTempFileName failed, last error %lu", GetLastError());
+ goto exit;
+ }
+ strncat_s(tmpname, ".dmp", sizeof(tmpname));
+ filename= tmpname;
+ }
+
+ if (!GetCurrentDirectory(MAX_PATH, working_dir))
+ {
+ VERBOSE("GetCurrentDirectory failed, last error %lu", GetLastError());
+ goto exit;
+ }
+
+ file= CreateFile(filename, GENERIC_READ | GENERIC_WRITE,
+ 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
+
+ if (file == INVALID_HANDLE_VALUE)
+ {
+ VERBOSE("CreateFile() failed for file %s, working dir %s, last error = %lu\n",
+ filename, working_dir, GetLastError());
+ goto exit;
+ }
+
+ if (!MiniDumpWriteDump(process, pid, file, MiniDumpNormal, 0, 0, 0))
+ {
+ VERBOSE("Failed to write minidump to %s, working dir %s, last error %lu\n",
+ filename, working_dir, GetLastError());
+ goto exit;
+ }
+
+ VERBOSE("Minidump written to %s, directory %s\n", filename, working_dir);
+ ret= TRUE;
+exit:
+ if (process != 0 && process != INVALID_HANDLE_VALUE)
+ CloseHandle(process);
+
+ if (file != 0 && file != INVALID_HANDLE_VALUE)
+ CloseHandle(file);
+ return ret;
+}
diff --git a/plugin/feedback/feedback.cc b/plugin/feedback/feedback.cc
index eb3f562f329..3b2e95f1e13 100644
--- a/plugin/feedback/feedback.cc
+++ b/plugin/feedback/feedback.cc
@@ -92,17 +92,19 @@ static COND * const OOM= (COND*)1;
static COND* make_cond(THD *thd, TABLE_LIST *tables, LEX_STRING *filter)
{
Item_cond_or *res= NULL;
- Name_resolution_context nrc;
+ /* A reference to this context will be stored in Item_field */
+ Name_resolution_context *nrc= new (thd->mem_root) Name_resolution_context;
LEX_CSTRING &db= tables->db;
LEX_CSTRING &table= tables->alias;
LEX_CSTRING &field= tables->table->field[0]->field_name;
CHARSET_INFO *cs= &my_charset_latin1;
- if (!filter->str)
+ if (!filter->str || !nrc)
return 0;
- nrc.init();
- nrc.resolve_in_table_list_only(tables);
+ nrc->init();
+ nrc->resolve_in_table_list_only(tables);
+ nrc->select_lex= tables->select_lex;
res= new (thd->mem_root) Item_cond_or(thd);
if (!res)
@@ -110,7 +112,7 @@ static COND* make_cond(THD *thd, TABLE_LIST *tables, LEX_STRING *filter)
for (; filter->str; filter++)
{
- Item_field *fld= new (thd->mem_root) Item_field(thd, &nrc, db, table,
+ Item_field *fld= new (thd->mem_root) Item_field(thd, nrc, db, table,
field);
Item_string *pattern= new (thd->mem_root) Item_string(thd, filter->str,
(uint) filter->length, cs);
diff --git a/scripts/wsrep_sst_common.sh b/scripts/wsrep_sst_common.sh
index 816121dcf5c..3d61765f6d3 100644
--- a/scripts/wsrep_sst_common.sh
+++ b/scripts/wsrep_sst_common.sh
@@ -1065,8 +1065,9 @@ check_for_dhparams()
#
verify_ca_matches_cert()
{
- local ca_path="$1"
- local cert_path="$2"
+ local ca="$1"
+ local cert="$2"
+ local path=${3:-0}
# If the openssl utility is not installed, then
# we will not do this certificate check:
@@ -1075,8 +1076,15 @@ verify_ca_matches_cert()
return
fi
- if ! "$OPENSSL_BINARY" verify -verbose -CAfile "$ca_path" "$cert_path" >/dev/null 2>&1
- then
+ local not_match=0
+
+ if [ $path -eq 0 ]; then
+ "$OPENSSL_BINARY" verify -verbose -CAfile "$ca" "$cert" >/dev/null 2>&1 || not_match=1
+ else
+ "$OPENSSL_BINARY" verify -verbose -CApath "$ca" "$cert" >/dev/null 2>&1 || not_match=1
+ fi
+
+ if [ $not_match -eq 1 ]; then
wsrep_log_error "******** FATAL ERROR ********************************************"
wsrep_log_error "* The certifcate and CA (certificate authority) do not match. *"
wsrep_log_error "* It does not appear that the certificate was issued by the CA. *"
diff --git a/scripts/wsrep_sst_mariabackup.sh b/scripts/wsrep_sst_mariabackup.sh
index 54632e5f79b..3fe3bf5c206 100644
--- a/scripts/wsrep_sst_mariabackup.sh
+++ b/scripts/wsrep_sst_mariabackup.sh
@@ -34,6 +34,7 @@ ssyslog=""
ssystag=""
BACKUP_PID=""
tcert=""
+tpath=0
tpem=""
tkey=""
tmode="DISABLED"
@@ -85,7 +86,6 @@ readonly SECRET_TAG="secret"
# Required for backup locks
# For backup locks it is 1 sent by joiner
-# 5.6.21 PXC and later can't donate to an older joiner
sst_ver=1
if [ -n "$(command -v pv)" ] && pv --help | grep -qw -- '-F'; then
@@ -339,64 +339,83 @@ get_transfer()
fi
fi
+ CN_option=",commonname=''"
+
if [ $encrypt -eq 2 ]; then
wsrep_log_info "Using openssl based encryption with socat: with crt and pem"
if [ -z "$tpem" -o -z "$tcert" ]; then
- wsrep_log_error "Both PEM and CRT files required"
+ wsrep_log_error \
+ "Both PEM file and CRT file (or path) are required"
exit 22
fi
if [ ! -r "$tpem" -o ! -r "$tcert" ]; then
- wsrep_log_error "Both PEM and CRT files must be readable"
+ wsrep_log_error \
+ "Both PEM file and CRT file (or path) must be readable"
exit 22
fi
- verify_ca_matches_cert "$tcert" "$tpem"
- tcmd="$tcmd,cert='$tpem',cafile='$tcert'$sockopt"
+ verify_ca_matches_cert "$tcert" "$tpem" $tpath
+ if [ $tpath -eq 0 ]; then
+ tcmd="$tcmd,cert='$tpem',cafile='$tcert'"
+ else
+ tcmd="$tcmd,cert='$tpem',capath='$tcert'"
+ fi
stagemsg="$stagemsg-OpenSSL-Encrypted-2"
- wsrep_log_info "$action with cert=$tpem, cafile=$tcert"
+ wsrep_log_info "$action with cert=$tpem, ca=$tcert"
elif [ $encrypt -eq 3 -o $encrypt -eq 4 ]; then
wsrep_log_info "Using openssl based encryption with socat: with key and crt"
if [ -z "$tpem" -o -z "$tkey" ]; then
- wsrep_log_error "Both certificate and key files required"
+ wsrep_log_error "Both certificate file (or path) " \
+ "and key file are required"
exit 22
fi
if [ ! -r "$tpem" -o ! -r "$tkey" ]; then
- wsrep_log_error "Both certificate and key files must be readable"
+ wsrep_log_error "Both certificate file (or path) " \
+ "and key file must be readable"
exit 22
fi
verify_cert_matches_key "$tpem" "$tkey"
stagemsg="$stagemsg-OpenSSL-Encrypted-3"
if [ -z "$tcert" ]; then
if [ $encrypt -eq 4 ]; then
- wsrep_log_error "Peer certificate required if encrypt=4"
+ wsrep_log_error \
+ "Peer certificate file (or path) required if encrypt=4"
exit 22
fi
# no verification
- tcmd="$tcmd,cert='$tpem',key='$tkey',verify=0$sockopt"
+ CN_option=""
+ tcmd="$tcmd,cert='$tpem',key='$tkey',verify=0"
wsrep_log_info "$action with cert=$tpem, key=$tkey, verify=0"
else
# CA verification
if [ ! -r "$tcert" ]; then
- wsrep_log_error "Certificate file must be readable"
+ wsrep_log_error "Certificate file or path must be readable"
exit 22
fi
- verify_ca_matches_cert "$tcert" "$tpem"
+ verify_ca_matches_cert "$tcert" "$tpem" $tpath
if [ -n "$WSREP_SST_OPT_REMOTE_USER" ]; then
CN_option=",commonname='$WSREP_SST_OPT_REMOTE_USER'"
- elif [ $encrypt -eq 4 ]; then
+ elif [ "$WSREP_SST_OPT_ROLE" = 'joiner' -o $encrypt -eq 4 ]
+ then
CN_option=",commonname=''"
elif is_local_ip "$WSREP_SST_OPT_HOST_UNESCAPED"; then
CN_option=',commonname=localhost'
else
CN_option=",commonname='$WSREP_SST_OPT_HOST_UNESCAPED'"
fi
- tcmd="$tcmd,cert='$tpem',key='$tkey',cafile='$tcert'$CN_option$sockopt"
- wsrep_log_info "$action with cert=$tpem, key=$tkey, cafile=$tcert"
+ if [ $tpath -eq 0 ]; then
+ tcmd="$tcmd,cert='$tpem',key='$tkey',cafile='$tcert'"
+ else
+ tcmd="$tcmd,cert='$tpem',key='$tkey',capath='$tcert'"
+ fi
+ wsrep_log_info "$action with cert=$tpem, key=$tkey, ca=$tcert"
fi
else
wsrep_log_info "Unknown encryption mode: encrypt=$encrypt"
exit 22
fi
+ tcmd="$tcmd$CN_option$sockopt"
+
if [ "$WSREP_SST_OPT_ROLE" = 'joiner' ]; then
tcmd="$tcmd stdio"
fi
@@ -473,6 +492,12 @@ check_server_ssl_config()
"of the tca, tcert and/or tkey in the [sst] section"
fi
fi
+ if [ -n "$tcert" ]; then
+ tcert=$(trim_string "$tcert")
+ if [ "${tcert%/}" != "$tcert" ]; then
+ tpath=1
+ fi
+ fi
}
read_cnf()
diff --git a/scripts/wsrep_sst_rsync.sh b/scripts/wsrep_sst_rsync.sh
index e16ed75cb16..ad9688011e1 100644
--- a/scripts/wsrep_sst_rsync.sh
+++ b/scripts/wsrep_sst_rsync.sh
@@ -236,11 +236,18 @@ check_server_ssl_config()
SSLMODE=$(parse_cnf "$SST_SECTIONS" 'ssl-mode' | tr [:lower:] [:upper:])
# no old-style SSL config in [sst], check for new one:
-if [ -z "$SSTKEY" -a -z "$SSTCERT" -a -z "$SSTCA" ]
-then
+if [ -z "$SSTKEY" -a -z "$SSTCERT" -a -z "$SSTCA" ]; then
check_server_ssl_config
fi
+SSTPATH=0
+if [ -n "$SSTCA" ]; then
+ SSTCA=$(trim_string "$SSTCA")
+ if [ "${SSTCA%/}" != "$SSTCA" ]; then
+ SSTPATH=1
+ fi
+fi
+
if [ -z "$SSLMODE" ]; then
# Implicit verification if CA is set and the SSL mode
# is not specified by user:
@@ -254,9 +261,19 @@ if [ -z "$SSLMODE" ]; then
fi
fi
-if [ -n "$SSTCA" ]
-then
- CAFILE_OPT="CAfile = $SSTCA"
+if [ -n "$SSTCERT" -a -n "$SSTKEY" ]; then
+ verify_cert_matches_key "$SSTCERT" "$SSTKEY"
+fi
+
+if [ -n "$SSTCA" ]; then
+ if [ $SSTPATH -eq 0 ]; then
+ CAFILE_OPT="CAfile = $SSTCA"
+ else
+ CAFILE_OPT="CApath = $SSTCA"
+ fi
+ if [ -n "$SSTCERT" ]; then
+ verify_ca_matches_cert "$SSTCA" "$SSTCERT" $SSTPATH
+ fi
else
CAFILE_OPT=""
fi
@@ -272,38 +289,38 @@ then
;;
'VERIFY_CA')
VERIFY_OPT='verifyChain = yes'
- if [ -n "$WSREP_SST_OPT_REMOTE_USER" ]; then
- CHECK_OPT="checkHost = $WSREP_SST_OPT_REMOTE_USER"
- else
- # check if the address is an ip-address (v4 or v6):
- if echo "$WSREP_SST_OPT_HOST_UNESCAPED" | \
- grep -q -E '^([0-9]+(\.[0-9]+){3}|[0-9a-fA-F]*(\:[0-9a-fA-F]*)+)$'
- then
- CHECK_OPT="checkIP = $WSREP_SST_OPT_HOST_UNESCAPED"
- else
- CHECK_OPT="checkHost = $WSREP_SST_OPT_HOST"
- fi
- if is_local_ip "$WSREP_SST_OPT_HOST_UNESCAPED"; then
- CHECK_OPT_LOCAL="checkHost = localhost"
- fi
- fi
;;
*)
wsrep_log_error "Unrecognized ssl-mode option: '$SSLMODE'"
exit 22 # EINVAL
;;
esac
- if [ -z "$CAFILE_OPT" ]; then
- wsrep_log_error "Can't have ssl-mode='$SSLMODE' without CA file"
+ if [ -z "$SSTCA" ]; then
+ wsrep_log_error "Can't have ssl-mode='$SSLMODE' without CA file or path"
exit 22 # EINVAL
fi
+ if [ -n "$WSREP_SST_OPT_REMOTE_USER" ]; then
+ CHECK_OPT="checkHost = $WSREP_SST_OPT_REMOTE_USER"
+ elif [ "$WSREP_SST_OPT_ROLE" = 'donor' ]; then
+ # check if the address is an ip-address (v4 or v6):
+ if echo "$WSREP_SST_OPT_HOST_UNESCAPED" | \
+ grep -q -E '^([0-9]+(\.[0-9]+){3}|[0-9a-fA-F]*(\:[0-9a-fA-F]*)+)$'
+ then
+ CHECK_OPT="checkIP = $WSREP_SST_OPT_HOST_UNESCAPED"
+ else
+ CHECK_OPT="checkHost = $WSREP_SST_OPT_HOST"
+ fi
+ if is_local_ip "$WSREP_SST_OPT_HOST_UNESCAPED"; then
+ CHECK_OPT_LOCAL="checkHost = localhost"
+ fi
+ fi
fi
STUNNEL=""
if [ -n "$SSLMODE" -a "$SSLMODE" != 'DISABLED' ]; then
STUNNEL_BIN="$(command -v stunnel)"
if [ -n "$STUNNEL_BIN" ]; then
- wsrep_log_info "Using stunnel for SSL encryption: CAfile: '$SSTCA', ssl-mode='$SSLMODE'"
+ wsrep_log_info "Using stunnel for SSL encryption: CA: '$SSTCA', ssl-mode='$SSLMODE'"
STUNNEL="$STUNNEL_BIN $STUNNEL_CONF"
fi
fi
diff --git a/sql/item.cc b/sql/item.cc
index d3e9c903432..82c09f595fd 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -71,11 +71,12 @@ bool cmp_items(Item *a, Item *b)
/**
Set max_sum_func_level if it is needed
*/
-inline void set_max_sum_func_level(THD *thd, SELECT_LEX *select)
+inline void set_max_sum_func_level(SELECT_LEX *select)
{
- if (thd->lex->in_sum_func &&
- thd->lex->in_sum_func->nest_level >= select->nest_level)
- set_if_bigger(thd->lex->in_sum_func->max_sum_func_level,
+ LEX *lex_s= select->parent_lex;
+ if (lex_s->in_sum_func &&
+ lex_s->in_sum_func->nest_level >= select->nest_level)
+ set_if_bigger(lex_s->in_sum_func->max_sum_func_level,
select->nest_level - 1);
}
@@ -654,6 +655,7 @@ Item_ident::Item_ident(THD *thd, Name_resolution_context *context_arg,
can_be_depended(TRUE), alias_name_used(FALSE)
{
name= field_name_arg;
+ DBUG_ASSERT(!context || context->select_lex);
}
@@ -671,6 +673,7 @@ Item_ident::Item_ident(THD *thd, TABLE_LIST *view_arg,
can_be_depended(TRUE), alias_name_used(FALSE)
{
name= field_name_arg;
+ DBUG_ASSERT(!context || context->select_lex);
}
@@ -692,7 +695,9 @@ Item_ident::Item_ident(THD *thd, Item_ident *item)
cached_field_index(item->cached_field_index),
can_be_depended(item->can_be_depended),
alias_name_used(item->alias_name_used)
-{}
+{
+ DBUG_ASSERT(!context || context->select_lex);
+}
void Item_ident::cleanup()
{
@@ -5533,6 +5538,7 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference)
Name_resolution_context *last_checked_context= context;
Item **ref= (Item **) not_found_item;
SELECT_LEX *current_sel= context->select_lex;
+ LEX *lex_s= current_sel->parent_lex;
Name_resolution_context *outer_context= 0;
SELECT_LEX *select= 0;
@@ -5634,18 +5640,18 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference)
return -1;
thd->change_item_tree(reference, rf);
select->inner_refs_list.push_back(rf, thd->mem_root);
- rf->in_sum_func= thd->lex->in_sum_func;
+ rf->in_sum_func= lex_s->in_sum_func;
}
/*
A reference is resolved to a nest level that's outer or the same as
the nest level of the enclosing set function : adjust the value of
max_arg_level for the function if it's needed.
*/
- if (thd->lex->in_sum_func &&
- thd->lex->in_sum_func->nest_level >= select->nest_level)
+ if (lex_s->in_sum_func &&
+ lex_s->in_sum_func->nest_level >= select->nest_level)
{
Item::Type ref_type= (*reference)->type();
- set_if_bigger(thd->lex->in_sum_func->max_arg_level,
+ set_if_bigger(lex_s->in_sum_func->max_arg_level,
select->nest_level);
set_field(*from_field);
base_flags|= item_base_t::FIXED;
@@ -5666,10 +5672,10 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference)
((ref_type == REF_ITEM || ref_type == FIELD_ITEM) ?
(Item_ident*) (*reference) :
0), false);
- if (thd->lex->in_sum_func &&
- thd->lex->in_sum_func->nest_level >= select->nest_level)
+ if (lex_s->in_sum_func &&
+ lex_s->in_sum_func->nest_level >= select->nest_level)
{
- set_if_bigger(thd->lex->in_sum_func->max_arg_level,
+ set_if_bigger(lex_s->in_sum_func->max_arg_level,
select->nest_level);
}
/*
@@ -5762,7 +5768,7 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference)
{
outer_context->select_lex->inner_refs_list.push_back((Item_outer_ref*)rf,
thd->mem_root);
- ((Item_outer_ref*)rf)->in_sum_func= thd->lex->in_sum_func;
+ ((Item_outer_ref*)rf)->in_sum_func= lex_s->in_sum_func;
}
thd->change_item_tree(reference, rf);
/*
@@ -5777,7 +5783,7 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference)
We can not "move" aggregate function in the place where
its arguments are not defined.
*/
- set_max_sum_func_level(thd, select);
+ set_max_sum_func_level(select);
mark_as_dependent(thd, last_checked_context->select_lex,
context->select_lex, rf,
rf, false);
@@ -5790,7 +5796,7 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference)
We can not "move" aggregate function in the place where
its arguments are not defined.
*/
- set_max_sum_func_level(thd, select);
+ set_max_sum_func_level(select);
mark_as_dependent(thd, last_checked_context->select_lex,
context->select_lex,
this, (Item_ident*)*reference, false);
@@ -5869,7 +5875,20 @@ bool Item_field::fix_fields(THD *thd, Item **reference)
DBUG_ASSERT(fixed() == 0);
Field *from_field= (Field *)not_found_field;
bool outer_fixed= false;
- SELECT_LEX *select= context->select_lex;
+ SELECT_LEX *select;
+ LEX *lex_s;
+ if (context)
+ {
+ select= context->select_lex;
+ lex_s= context->select_lex->parent_lex;
+ }
+ else
+ {
+ // No real name resolution, used somewhere in SP
+ DBUG_ASSERT(field);
+ select= NULL;
+ lex_s= NULL;
+ }
if (select && select->in_tvc)
{
@@ -5938,7 +5957,7 @@ bool Item_field::fix_fields(THD *thd, Item **reference)
We can not "move" aggregate function in the place where
its arguments are not defined.
*/
- set_max_sum_func_level(thd, select);
+ set_max_sum_func_level(select);
set_field(new_field);
depended_from= (*((Item_field**)res))->depended_from;
return 0;
@@ -5967,7 +5986,7 @@ bool Item_field::fix_fields(THD *thd, Item **reference)
We can not "move" aggregate function in the place where
its arguments are not defined.
*/
- set_max_sum_func_level(thd, select);
+ set_max_sum_func_level(select);
return FALSE;
}
}
@@ -6004,10 +6023,11 @@ bool Item_field::fix_fields(THD *thd, Item **reference)
goto mark_non_agg_field;
}
- if (thd->lex->in_sum_func &&
- thd->lex->in_sum_func->nest_level ==
+ if (lex_s &&
+ lex_s->in_sum_func &&
+ lex_s->in_sum_func->nest_level ==
select->nest_level)
- set_if_bigger(thd->lex->in_sum_func->max_arg_level,
+ set_if_bigger(lex_s->in_sum_func->max_arg_level,
select->nest_level);
/*
if it is not expression from merged VIEW we will set this field.
@@ -6073,8 +6093,9 @@ bool Item_field::fix_fields(THD *thd, Item **reference)
if (field->vcol_info)
fix_session_vcol_expr_for_read(thd, field, field->vcol_info);
if (thd->variables.sql_mode & MODE_ONLY_FULL_GROUP_BY &&
- !outer_fixed && !thd->lex->in_sum_func &&
+ !outer_fixed &&
select &&
+ !lex_s->in_sum_func &&
select->cur_pos_in_select_list != UNDEF_POS &&
select->join)
{
@@ -6109,13 +6130,13 @@ mark_non_agg_field:
*/
select_lex= context->select_lex;
}
- if (!thd->lex->in_sum_func)
+ if (!lex_s || !lex_s->in_sum_func)
select_lex->set_non_agg_field_used(true);
else
{
if (outer_fixed)
- thd->lex->in_sum_func->outer_fields.push_back(this, thd->mem_root);
- else if (thd->lex->in_sum_func->nest_level !=
+ lex_s->in_sum_func->outer_fields.push_back(this, thd->mem_root);
+ else if (lex_s->in_sum_func->nest_level !=
select->nest_level)
select_lex->set_non_agg_field_used(true);
}
@@ -7572,6 +7593,12 @@ Item *get_field_item_for_having(THD *thd, Item *item, st_select_lex *sel)
return NULL;
}
+Item *Item_ident::derived_field_transformer_for_having(THD *thd, uchar *arg)
+{
+ st_select_lex *sel= (st_select_lex *)arg;
+ context= &sel->context;
+ return this;
+}
Item *Item_field::derived_field_transformer_for_having(THD *thd, uchar *arg)
{
@@ -7591,12 +7618,13 @@ Item *Item_field::derived_field_transformer_for_having(THD *thd, uchar *arg)
Item *Item_direct_view_ref::derived_field_transformer_for_having(THD *thd,
uchar *arg)
{
+ st_select_lex *sel= (st_select_lex *)arg;
+ context= &sel->context;
if ((*ref)->marker & MARKER_SUBSTITUTION)
{
this->marker|= MARKER_SUBSTITUTION;
return this;
}
- st_select_lex *sel= (st_select_lex *)arg;
table_map tab_map= sel->master_unit()->derived->table->map;
if ((item_equal && !(item_equal->used_tables() & tab_map)) ||
!item_equal)
@@ -7859,7 +7887,9 @@ bool Item_ref::fix_fields(THD *thd, Item **reference)
{
enum_parsing_place place= NO_MATTER;
DBUG_ASSERT(fixed() == 0);
- SELECT_LEX *current_sel= thd->lex->current_select;
+
+ SELECT_LEX *current_sel= context->select_lex;
+ LEX *lex_s= context->select_lex->parent_lex;
if (set_properties_only)
{
@@ -8021,10 +8051,10 @@ bool Item_ref::fix_fields(THD *thd, Item **reference)
the nest level of the enclosing set function : adjust the value of
max_arg_level for the function if it's needed.
*/
- if (thd->lex->in_sum_func &&
- thd->lex->in_sum_func->nest_level >=
+ if (lex_s->in_sum_func &&
+ lex_s->in_sum_func->nest_level >=
last_checked_context->select_lex->nest_level)
- set_if_bigger(thd->lex->in_sum_func->max_arg_level,
+ set_if_bigger(lex_s->in_sum_func->max_arg_level,
last_checked_context->select_lex->nest_level);
return FALSE;
}
@@ -8044,10 +8074,10 @@ bool Item_ref::fix_fields(THD *thd, Item **reference)
the nest level of the enclosing set function : adjust the value of
max_arg_level for the function if it's needed.
*/
- if (thd->lex->in_sum_func &&
- thd->lex->in_sum_func->nest_level >=
+ if (lex_s->in_sum_func &&
+ lex_s->in_sum_func->nest_level >=
last_checked_context->select_lex->nest_level)
- set_if_bigger(thd->lex->in_sum_func->max_arg_level,
+ set_if_bigger(lex_s->in_sum_func->max_arg_level,
last_checked_context->select_lex->nest_level);
}
}
diff --git a/sql/item.h b/sql/item.h
index 8f955302c9c..947e46532e4 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -3504,6 +3504,7 @@ public:
Collect outer references
*/
bool collect_outer_ref_processor(void *arg) override;
+ Item *derived_field_transformer_for_having(THD *thd, uchar *arg) override;
friend bool insert_fields(THD *thd, Name_resolution_context *context,
const char *db_name,
const char *table_name, List_iterator<Item> *it,
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index 34256f641f3..58680384f55 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -5309,6 +5309,7 @@ bool subselect_hash_sj_engine::make_semi_join_conds()
context= new (thd->mem_root) Name_resolution_context;
context->init();
+ context->select_lex= item_in->unit->first_select();
context->first_name_resolution_table=
context->last_name_resolution_table= tmp_table_ref;
semi_join_conds_context= context;
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index c8a7aca5afb..5d7de582204 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -92,6 +92,7 @@ static void store_bit_fields_as_bigint_in_tempory_table(List<Item> *list)
bool Item_sum::init_sum_func_check(THD *thd)
{
SELECT_LEX *curr_sel= thd->lex->current_select;
+ LEX *lex_s= (curr_sel ? curr_sel->parent_lex : thd->lex);
if (curr_sel && curr_sel->name_visibility_map.is_clear_all())
{
for (SELECT_LEX *sl= curr_sel; sl; sl= sl->context.outer_select())
@@ -107,9 +108,9 @@ bool Item_sum::init_sum_func_check(THD *thd)
return TRUE;
}
/* Set a reference to the nesting set function if there is any */
- in_sum_func= thd->lex->in_sum_func;
+ in_sum_func= lex_s->in_sum_func;
/* Save a pointer to object to be used in items for nested set functions */
- thd->lex->in_sum_func= this;
+ lex_s->in_sum_func= this;
nest_level= thd->lex->current_select->nest_level;
ref_by= 0;
aggr_level= -1;
@@ -176,6 +177,7 @@ bool Item_sum::init_sum_func_check(THD *thd)
bool Item_sum::check_sum_func(THD *thd, Item **ref)
{
SELECT_LEX *curr_sel= thd->lex->current_select;
+ LEX *lex_s= curr_sel->parent_lex;
nesting_map allow_sum_func(thd->lex->allow_sum_func);
allow_sum_func.intersect(curr_sel->name_visibility_map);
bool invalid= FALSE;
@@ -338,7 +340,7 @@ bool Item_sum::check_sum_func(THD *thd, Item **ref)
if (sum_func() == SP_AGGREGATE_FUNC)
aggr_sel->set_custom_agg_func_used(true);
update_used_tables();
- thd->lex->in_sum_func= in_sum_func;
+ lex_s->in_sum_func= in_sum_func;
return FALSE;
}
diff --git a/sql/mysql_upgrade_service.cc b/sql/mysql_upgrade_service.cc
index dc8250ba438..61f9f2542e9 100644
--- a/sql/mysql_upgrade_service.cc
+++ b/sql/mysql_upgrade_service.cc
@@ -269,7 +269,7 @@ void stop_mysqld_service()
}
/*
- Remeber initial state of the service, we will restore it on
+ Remember initial state of the service, we will restore it on
exit.
*/
if(initial_service_state == UINT_MAX)
@@ -490,8 +490,10 @@ int main(int argc, char **argv)
CopyFile(service_properties.inifile, my_ini_bck, FALSE);
upgrade_config_file(service_properties.inifile);
- log("Phase %d/%d: Ensuring innodb slow shutdown%s", ++phase, max_phases,
- old_mysqld_exe_exists?",this can take some time":"(skipped)");
+ bool do_start_stop_server = old_mysqld_exe_exists && initial_service_state != SERVICE_RUNNING;
+
+ log("Phase %d/%d: Start and stop server in the old version, to avoid crash recovery %s", ++phase, max_phases,
+ do_start_stop_server?",this can take some time":"(skipped)");
char socket_param[FN_REFLEN];
sprintf_s(socket_param, "--socket=mysql_upgrade_service_%u",
@@ -499,11 +501,11 @@ int main(int argc, char **argv)
DWORD start_duration_ms = 0;
- if (old_mysqld_exe_exists)
+ if (do_start_stop_server)
{
- /* Start/stop server with --loose-innodb-fast-shutdown=0 */
+ /* Start/stop server with --loose-innodb-fast-shutdown=1 */
mysqld_process = (HANDLE)run_tool(P_NOWAIT, service_properties.mysqld_exe,
- defaults_file_param, "--loose-innodb-fast-shutdown=0", "--skip-networking",
+ defaults_file_param, "--loose-innodb-fast-shutdown=1", "--skip-networking",
"--enable-named-pipe", socket_param, "--skip-slave-start", NULL);
if (mysqld_process == INVALID_HANDLE_VALUE)
diff --git a/sql/sp.cc b/sql/sp.cc
index 73c9c960cf7..4ef23983f78 100644
--- a/sql/sp.cc
+++ b/sql/sp.cc
@@ -1930,8 +1930,6 @@ bool
Sp_handler::sp_show_create_routine(THD *thd,
const Database_qualified_name *name) const
{
- sp_head *sp;
-
DBUG_ENTER("sp_show_create_routine");
DBUG_PRINT("enter", ("type: %s name: %.*s",
type_str(),
@@ -1944,20 +1942,28 @@ Sp_handler::sp_show_create_routine(THD *thd,
It is "safe" to do as long as it doesn't affect the results
of the binary log or the query cache, which currently it does not.
*/
- if (sp_cache_routine(thd, name, false, &sp))
- DBUG_RETURN(TRUE);
+ sp_head *sp= 0;
- if (sp == NULL || sp->show_create_routine(thd, this))
+ DBUG_EXECUTE_IF("cache_sp_in_show_create",
+ /* Some tests need just need a way to cache SP without other side-effects.*/
+ sp_cache_routine(thd, name, false, &sp);
+ sp->show_create_routine(thd, this);
+ DBUG_RETURN(false);
+ );
+
+ bool free_sp= db_find_routine(thd, name, &sp) == SP_OK;
+ bool ret= !sp || sp->show_create_routine(thd, this);
+ if (ret)
{
/*
If we have insufficient privileges, pretend the routine
does not exist.
*/
my_error(ER_SP_DOES_NOT_EXIST, MYF(0), type_str(), name->m_name.str);
- DBUG_RETURN(TRUE);
}
-
- DBUG_RETURN(FALSE);
+ if (free_sp)
+ sp_head::destroy(sp);
+ DBUG_RETURN(ret);
}
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index a785197b282..e1221fb6f6e 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -6894,6 +6894,7 @@ set_new_item_local_context(THD *thd, Item_ident *item, TABLE_LIST *table_ref)
if (!(context= new (thd->mem_root) Name_resolution_context))
return TRUE;
context->init();
+ context->select_lex= table_ref->select_lex;
context->first_name_resolution_table=
context->last_name_resolution_table= table_ref;
item->context= context;
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 2391f630f50..f9f008602ed 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -3138,6 +3138,7 @@ void reinit_stmt_before_use(THD *thd, LEX *lex)
}
for (; sl; sl= sl->next_select_in_list())
{
+ sl->parent_lex->in_sum_func= NULL;
if (sl->changed_elements & TOUCHED_SEL_COND)
{
/* remove option which was put by mysql_explain_union() */
@@ -3272,7 +3273,6 @@ void reinit_stmt_before_use(THD *thd, LEX *lex)
lex->result->set_thd(thd);
}
lex->allow_sum_func.clear_all();
- lex->in_sum_func= NULL;
DBUG_VOID_RETURN;
}
diff --git a/sql/wsrep_schema.cc b/sql/wsrep_schema.cc
index cc8ec7a5af4..48077040f88 100644
--- a/sql/wsrep_schema.cc
+++ b/sql/wsrep_schema.cc
@@ -289,7 +289,14 @@ static int open_table(THD* thd,
NULL, lock_type);
thd->lex->query_tables_own_last= 0;
- if (!open_n_lock_single_table(thd, &tables, tables.lock_type, flags)) {
+ // No need to open table if the query was bf aborted,
+ // thd client will get ER_LOCK_DEADLOCK in the end.
+ const bool interrupted= thd->killed ||
+ (thd->is_error() &&
+ (thd->get_stmt_da()->sql_errno() == ER_QUERY_INTERRUPTED));
+
+ if (interrupted ||
+ !open_n_lock_single_table(thd, &tables, tables.lock_type, flags)) {
close_thread_tables(thd);
DBUG_RETURN(1);
}
diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc
index 121c7a5666b..360a10f29a6 100644
--- a/storage/innobase/fil/fil0fil.cc
+++ b/storage/innobase/fil/fil0fil.cc
@@ -85,13 +85,22 @@ bool fil_space_t::try_to_close(bool print_info)
if (const auto n= space.set_closing())
{
- if (print_info)
- ib::info() << "Cannot close file " << node->name
- << " because of "
- << (n & PENDING)
- << ((n & NEEDS_FSYNC)
- ? " pending operations and pending fsync"
- : " pending operations");
+ if (!print_info)
+ continue;
+ print_info= false;
+ const time_t now= time(nullptr);
+ if (now - fil_system.n_open_exceeded_time < 5)
+ continue; /* We display messages at most once in 5 seconds. */
+ fil_system.n_open_exceeded_time= now;
+
+ if (n & PENDING)
+ sql_print_information("InnoDB: Cannot close file %s because of "
+ UINT32PF " pending operations%s", node->name,
+ n & PENDING,
+ (n & NEEDS_FSYNC) ? " and pending fsync" : "");
+ else if (n & NEEDS_FSYNC)
+ sql_print_information("InnoDB: Cannot close file %s because of "
+ "pending fsync", node->name);
continue;
}
@@ -399,15 +408,18 @@ static bool fil_node_open_file(fil_node_t *node)
ut_ad(node->space->purpose != FIL_TYPE_TEMPORARY);
ut_ad(node->space->referenced());
+ const auto old_time= fil_system.n_open_exceeded_time;
+
for (ulint count= 0; fil_system.n_open >= srv_max_n_open_files; count++)
{
if (fil_space_t::try_to_close(count > 1))
count= 0;
else if (count >= 2)
{
- ib::warn() << "innodb_open_files=" << srv_max_n_open_files
- << " is exceeded (" << fil_system.n_open
- << ") files stay open)";
+ if (old_time != fil_system.n_open_exceeded_time)
+ sql_print_warning("InnoDB: innodb_open_files=" ULINTPF
+ " is exceeded (" ULINTPF " files stay open)",
+ srv_max_n_open_files, fil_system.n_open);
break;
}
else
@@ -1410,8 +1422,7 @@ fil_space_t *fil_space_t::get(uint32_t id)
if (n & STOPPING)
space= nullptr;
-
- if ((n & CLOSING) && !space->prepare())
+ else if ((n & CLOSING) && !space->prepare())
space= nullptr;
return space;
diff --git a/storage/innobase/fsp/fsp0file.cc b/storage/innobase/fsp/fsp0file.cc
index 09515bf0929..95eb9007944 100644
--- a/storage/innobase/fsp/fsp0file.cc
+++ b/storage/innobase/fsp/fsp0file.cc
@@ -399,10 +399,19 @@ Datafile::validate_for_recovery()
err = validate_first_page(0);
switch (err) {
- case DB_SUCCESS:
case DB_TABLESPACE_EXISTS:
break;
-
+ case DB_SUCCESS:
+ if (!m_defer || !m_space_id) {
+ break;
+ }
+ /* InnoDB should check whether the deferred
+ tablespace page0 can be recovered from
+ double write buffer. InnoDB should try
+ to recover only if m_space_id exists because
+ dblwr pages can be searched via {space_id, 0}.
+ m_space_id is set in read_first_page(). */
+ /* fall through */
default:
/* Re-open the file in read-write mode Attempt to restore
page 0 from doublewrite and read the space ID from a survey
@@ -413,23 +422,30 @@ Datafile::validate_for_recovery()
return(err);
}
- err = find_space_id();
- if (err != DB_SUCCESS || m_space_id == 0) {
- ib::error() << "Datafile '" << m_filepath << "' is"
- " corrupted. Cannot determine the space ID from"
- " the first 64 pages.";
- return(err);
+ if (!m_defer) {
+ err = find_space_id();
+ if (err != DB_SUCCESS || m_space_id == 0) {
+ ib::error() << "Datafile '" << m_filepath
+ << "' is corrupted. Cannot determine "
+ "the space ID from the first 64 pages.";
+ return(err);
+ }
}
+
if (m_space_id == UINT32_MAX) {
return DB_SUCCESS; /* empty file */
}
if (restore_from_doublewrite()) {
+ if (m_defer) {
+ return err;
+ }
return(DB_CORRUPTION);
}
/* Free the previously read first page and then re-validate. */
free_first_page();
+ m_defer = false;
err = validate_first_page(0);
}
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index 43504e2a3be..e38110edb60 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -6302,8 +6302,8 @@ wsrep_innobase_mysql_sort(
case MYSQL_TYPE_LONG_BLOB:
case MYSQL_TYPE_VARCHAR:
{
- uchar *tmp_str;
- ulint tmp_length;
+ uchar tmp_str[REC_VERSION_56_MAX_INDEX_COL_LEN] = {'\0'};
+ ulint tmp_length = REC_VERSION_56_MAX_INDEX_COL_LEN;
/* Use the charset number to pick the right charset struct for
the comparison. Since the MySQL function get_charset may be
@@ -6326,12 +6326,7 @@ wsrep_innobase_mysql_sort(
}
}
- // Note that strnxfrm may change length of string
- tmp_length= charset->coll->strnxfrmlen(charset, str_length);
- tmp_length= tmp_length * charset->mbmaxlen;
- tmp_length= ut_max(str_length, tmp_length) + charset->mbmaxlen;
- tmp_str= static_cast<uchar *>(ut_malloc_nokey(tmp_length));
- ut_ad(str_length <= tmp_length);
+ ut_a(str_length <= tmp_length);
memcpy(tmp_str, str, str_length);
tmp_length = charset->strnxfrm(str, str_length,
@@ -6355,7 +6350,6 @@ wsrep_innobase_mysql_sort(
ret_length = tmp_length;
}
- ut_free(tmp_str);
break;
}
case MYSQL_TYPE_DECIMAL :
@@ -6701,7 +6695,7 @@ wsrep_store_key_val_for_row(
THD* thd,
TABLE* table,
uint keynr, /*!< in: key number */
- uchar* buff, /*!< in/out: buffer for the key value (in MySQL
+ char* buff, /*!< in/out: buffer for the key value (in MySQL
format) */
uint buff_len,/*!< in: buffer length */
const uchar* record,
@@ -6710,7 +6704,7 @@ wsrep_store_key_val_for_row(
KEY* key_info = table->key_info + keynr;
KEY_PART_INFO* key_part = key_info->key_part;
KEY_PART_INFO* end = key_part + key_info->user_defined_key_parts;
- uchar* buff_start = buff;
+ char* buff_start = buff;
enum_field_types mysql_type;
Field* field;
ulint buff_space = buff_len;
@@ -6721,7 +6715,7 @@ wsrep_store_key_val_for_row(
*key_is_null = true;
for (; key_part != end; key_part++) {
- uchar *sorted = nullptr;
+ uchar sorted[REC_VERSION_56_MAX_INDEX_COL_LEN] = {'\0'};
bool part_is_null = false;
if (key_part->null_bit) {
@@ -6800,14 +6794,10 @@ wsrep_store_key_val_for_row(
true_len = key_len;
}
- const ulint max_len = true_len;
- sorted= static_cast<uchar *>(ut_malloc_nokey(max_len+1));
memcpy(sorted, data, true_len);
true_len = wsrep_innobase_mysql_sort(
mysql_type, cs->number, sorted, true_len,
- max_len);
- ut_ad(true_len <= max_len);
-
+ REC_VERSION_56_MAX_INDEX_COL_LEN);
if (wsrep_protocol_version > 1) {
/* Note that we always reserve the maximum possible
length of the true VARCHAR in the key value, though
@@ -6892,13 +6882,11 @@ wsrep_store_key_val_for_row(
true_len = key_len;
}
- const ulint max_len= true_len;
- sorted= static_cast<uchar *>(ut_malloc_nokey(max_len+1));
memcpy(sorted, blob_data, true_len);
true_len = wsrep_innobase_mysql_sort(
mysql_type, cs->number, sorted, true_len,
- max_len);
- ut_ad(true_len <= max_len);
+ REC_VERSION_56_MAX_INDEX_COL_LEN);
+
/* Note that we always reserve the maximum possible
length of the BLOB prefix in the key value. */
@@ -6974,14 +6962,10 @@ wsrep_store_key_val_for_row(
cs->mbmaxlen),
&error);
}
-
- const ulint max_len = true_len;
- sorted= static_cast<uchar *>(ut_malloc_nokey(max_len+1));
memcpy(sorted, src_start, true_len);
true_len = wsrep_innobase_mysql_sort(
mysql_type, cs->number, sorted, true_len,
- max_len);
- ut_ad(true_len <= max_len);
+ REC_VERSION_56_MAX_INDEX_COL_LEN);
if (true_len > buff_space) {
fprintf (stderr,
@@ -6996,11 +6980,6 @@ wsrep_store_key_val_for_row(
buff += true_len;
buff_space -= true_len;
}
-
- if (sorted) {
- ut_free(sorted);
- sorted= NULL;
- }
}
ut_a(buff <= buff_start + buff_len);
@@ -10041,7 +10020,7 @@ wsrep_append_key(
THD *thd,
trx_t *trx,
TABLE_SHARE *table_share,
- const uchar* key,
+ const char* key,
uint16_t key_len,
Wsrep_service_key_type key_type /*!< in: access type of this key
(shared, exclusive, semi...) */
@@ -10152,8 +10131,8 @@ ha_innobase::wsrep_append_keys(
}
if (wsrep_protocol_version == 0) {
- uchar keyval[WSREP_MAX_SUPPORTED_KEY_LENGTH+1] = {'\0'};
- uchar *key = &keyval[0];
+ char keyval[WSREP_MAX_SUPPORTED_KEY_LENGTH+1] = {'\0'};
+ char *key = &keyval[0];
bool is_null;
auto len = wsrep_store_key_val_for_row(
@@ -10194,12 +10173,12 @@ ha_innobase::wsrep_append_keys(
/* keyval[] shall contain an ordinal number at byte 0
and the actual key data shall be written at byte 1.
Hence the total data length is the key length + 1 */
- uchar keyval0[WSREP_MAX_SUPPORTED_KEY_LENGTH+1]= {'\0'};
- uchar keyval1[WSREP_MAX_SUPPORTED_KEY_LENGTH+1]= {'\0'};
- keyval0[0] = (uchar)i;
- keyval1[0] = (uchar)i;
- uchar* key0 = &keyval0[1];
- uchar* key1 = &keyval1[1];
+ char keyval0[WSREP_MAX_SUPPORTED_KEY_LENGTH+1]= {'\0'};
+ char keyval1[WSREP_MAX_SUPPORTED_KEY_LENGTH+1]= {'\0'};
+ keyval0[0] = (char)i;
+ keyval1[0] = (char)i;
+ char* key0 = &keyval0[1];
+ char* key1 = &keyval1[1];
if (!tab) {
WSREP_WARN("MariaDB-InnoDB key mismatch %s %s",
@@ -10279,16 +10258,18 @@ ha_innobase::wsrep_append_keys(
wsrep_calc_row_hash(digest, record0, table, m_prebuilt);
if (int rcode = wsrep_append_key(thd, trx, table_share,
- digest, 16, key_type)) {
+ reinterpret_cast<char*>
+ (digest), 16, key_type)) {
DBUG_RETURN(rcode);
}
if (record1) {
wsrep_calc_row_hash(
digest, record1, table, m_prebuilt);
- if (int rcode = wsrep_append_key(thd, trx, table_share,
- digest, 16,
- key_type)) {
+ if (int rcode = wsrep_append_key(
+ thd, trx, table_share,
+ reinterpret_cast<char*>(digest), 16,
+ key_type)) {
DBUG_RETURN(rcode);
}
}
diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h
index 2838abde333..365f8367292 100644
--- a/storage/innobase/include/fil0fil.h
+++ b/storage/innobase/include/fil0fil.h
@@ -1393,6 +1393,8 @@ public:
sized_ilist<fil_space_t, unflushed_spaces_tag_t> unflushed_spaces;
/** number of currently open files; protected by mutex */
ulint n_open;
+ /** last time we noted n_open exceeding the limit; protected by mutex */
+ time_t n_open_exceeded_time;
/** maximum persistent tablespace id that has ever been assigned */
uint32_t max_assigned_id;
/** nonzero if fil_node_open_file_low() should avoid moving the tablespace
diff --git a/storage/innobase/include/srw_lock.h b/storage/innobase/include/srw_lock.h
index b24e0a30857..3d0d82b81df 100644
--- a/storage/innobase/include/srw_lock.h
+++ b/storage/innobase/include/srw_lock.h
@@ -22,17 +22,24 @@ this program; if not, write to the Free Software Foundation, Inc.,
#ifdef SUX_LOCK_GENERIC
/** An exclusive-only variant of srw_lock */
-class srw_mutex final
+template<bool spinloop>
+class srw_mutex_impl final
{
pthread_mutex_t lock;
+ void wr_wait();
public:
void init() { pthread_mutex_init(&lock, nullptr); }
void destroy() { pthread_mutex_destroy(&lock); }
- void wr_lock() { pthread_mutex_lock(&lock); }
+ inline void wr_lock();
void wr_unlock() { pthread_mutex_unlock(&lock); }
bool wr_lock_try() { return !pthread_mutex_trylock(&lock); }
};
-typedef srw_mutex srw_spin_mutex;
+
+template<> void srw_mutex_impl<true>::wr_wait();
+template<>
+inline void srw_mutex_impl<false>::wr_lock() { pthread_mutex_lock(&lock); }
+template<>
+inline void srw_mutex_impl<true>::wr_lock() { if (!wr_lock_try()) wr_wait(); }
#else
/** Futex-based mutex */
template<bool spinloop>
@@ -81,15 +88,12 @@ public:
}
}
};
+#endif
typedef srw_mutex_impl<true> srw_spin_mutex;
typedef srw_mutex_impl<false> srw_mutex;
-#endif
-# if defined _WIN32 || defined SUX_LOCK_GENERIC
-# else
-template<bool spinlock> class srw_lock_impl;
-#endif
+template<bool spinloop> class srw_lock_impl;
/** Slim shared-update-exclusive lock with no recursion */
template<bool spinloop>
@@ -147,7 +151,7 @@ public:
void wr_unlock();
#else
/** mutex for synchronization; held by U or X lock holders */
- srw_mutex writer;
+ srw_mutex_impl<spinloop> writer;
/** S or U holders, and WRITER flag for X holder or waiter */
std::atomic<uint32_t> readers;
/** indicates an X request; readers=WRITER indicates granted X lock */
@@ -265,45 +269,54 @@ public:
#endif
};
-#ifdef _WIN32
+#if defined _WIN32 || defined SUX_LOCK_GENERIC
/** Slim read-write lock */
-class srw_lock_low
+template<bool spinloop>
+class srw_lock_
{
# ifdef UNIV_PFS_RWLOCK
- friend class srw_lock_impl;
+ friend srw_lock_impl<spinloop>;
# endif
+# ifdef _WIN32
SRWLOCK lock;
-public:
- void init() {}
- void destroy() {}
- void rd_lock() { AcquireSRWLockShared(&lock); }
- bool rd_lock_try() { return TryAcquireSRWLockShared(&lock); }
- void rd_unlock() { ReleaseSRWLockShared(&lock); }
- void wr_lock() { AcquireSRWLockExclusive(&lock); }
- bool wr_lock_try() { return TryAcquireSRWLockExclusive(&lock); }
- void wr_unlock() { ReleaseSRWLockExclusive(&lock); }
-};
-
-typedef srw_lock_low srw_spin_lock_low;
-#elif defined SUX_LOCK_GENERIC
-/** Slim read-write lock */
-class srw_lock_low
-{
-# ifdef UNIV_PFS_RWLOCK
- friend class srw_lock_impl;
-# endif
+# else
rw_lock_t lock;
+# endif
+
+ void rd_wait();
+ void wr_wait();
public:
- void init() { my_rwlock_init(&lock, nullptr); }
- void destroy() { rwlock_destroy(&lock); }
- void rd_lock() { rw_rdlock(&lock); }
- bool rd_lock_try() { return !rw_tryrdlock(&lock); }
- void rd_unlock() { rw_unlock(&lock); }
- void wr_lock() { rw_wrlock(&lock); }
- bool wr_lock_try() { return !rw_trywrlock(&lock); }
- void wr_unlock() { rw_unlock(&lock); }
+ void init() { IF_WIN(,my_rwlock_init(&lock, nullptr)); }
+ void destroy() { IF_WIN(,rwlock_destroy(&lock)); }
+ inline void rd_lock();
+ inline void wr_lock();
+ bool rd_lock_try()
+ { return IF_WIN(TryAcquireSRWLockShared(&lock), !rw_tryrdlock(&lock)); }
+ void rd_unlock()
+ { IF_WIN(ReleaseSRWLockShared(&lock), rw_unlock(&lock)); }
+ bool wr_lock_try()
+ { return IF_WIN(TryAcquireSRWLockExclusive(&lock), !rw_trywrlock(&lock)); }
+ void wr_unlock()
+ { IF_WIN(ReleaseSRWLockExclusive(&lock), rw_unlock(&lock)); }
};
-typedef srw_lock_low srw_spin_lock_low;
+
+template<> void srw_lock_<true>::rd_wait();
+template<> void srw_lock_<true>::wr_wait();
+
+template<>
+inline void srw_lock_<false>::rd_lock()
+{ IF_WIN(AcquireSRWLockShared(&lock), rw_rdlock(&lock)); }
+template<>
+inline void srw_lock_<false>::wr_lock()
+{ IF_WIN(AcquireSRWLockExclusive(&lock), rw_wrlock(&lock)); }
+
+template<>
+inline void srw_lock_<true>::rd_lock() { if (!rd_lock_try()) rd_wait(); }
+template<>
+inline void srw_lock_<true>::wr_lock() { if (!wr_lock_try()) wr_wait(); }
+
+typedef srw_lock_<false> srw_lock_low;
+typedef srw_lock_<true> srw_spin_lock_low;
#else
typedef ssux_lock_impl<false> srw_lock_low;
typedef ssux_lock_impl<true> srw_spin_lock_low;
@@ -398,17 +411,14 @@ public:
};
/** Slim reader-writer lock with PERFORMANCE_SCHEMA instrumentation */
-# if defined _WIN32 || defined SUX_LOCK_GENERIC
-# else
-template<bool spinlock>
-# endif
+template<bool spinloop>
class srw_lock_impl
{
PSI_rwlock *pfs_psi;
# if defined _WIN32 || defined SUX_LOCK_GENERIC
- srw_lock_low lock;
+ srw_lock_<spinloop> lock;
# else
- ssux_lock_impl<spinlock> lock;
+ ssux_lock_impl<spinloop> lock;
# endif
ATTRIBUTE_NOINLINE void psi_rd_lock(const char *file, unsigned line);
@@ -458,12 +468,7 @@ public:
bool wr_lock_try() { return lock.wr_lock_try(); }
};
-# if defined _WIN32 || defined SUX_LOCK_GENERIC
-typedef srw_lock_impl srw_lock;
-typedef srw_lock_impl srw_spin_lock;
-# else
typedef srw_lock_impl<false> srw_lock;
typedef srw_lock_impl<true> srw_spin_lock;
-# endif
#endif
diff --git a/storage/innobase/sync/srw_lock.cc b/storage/innobase/sync/srw_lock.cc
index f3c0afd64e3..7d26dd2b590 100644
--- a/storage/innobase/sync/srw_lock.cc
+++ b/storage/innobase/sync/srw_lock.cc
@@ -36,6 +36,20 @@ static inline void srw_pause(unsigned delay)
}
#ifdef SUX_LOCK_GENERIC
+template<> void srw_mutex_impl<true>::wr_wait()
+{
+ const unsigned delay= srw_pause_delay();
+
+ for (auto spin= srv_n_spin_wait_rounds; spin; spin--)
+ {
+ srw_pause(delay);
+ if (wr_lock_try())
+ return;
+ }
+
+ pthread_mutex_lock(&lock);
+}
+
template<bool spinloop>
void ssux_lock_impl<spinloop>::init()
{
@@ -247,7 +261,6 @@ inline void ssux_lock_impl<spinloop>::wait(uint32_t lk)
{ WaitOnAddress(&readers, &lk, 4, INFINITE); }
template<bool spinloop>
void ssux_lock_impl<spinloop>::wake() { WakeByAddressSingle(&readers); }
-
# else
# ifdef __linux__
# include <linux/futex.h>
@@ -282,6 +295,35 @@ template void ssux_lock_impl<false>::wake();
template void srw_mutex_impl<true>::wake();
template void ssux_lock_impl<true>::wake();
+/*
+
+Unfortunately, compilers targeting IA-32 or AMD64 currently cannot
+translate the following single-bit operations into Intel 80386 instructions:
+
+ m.fetch_or(1<<b) & 1<<b LOCK BTS b, m
+ m.fetch_and(~(1<<b)) & 1<<b LOCK BTR b, m
+ m.fetch_xor(1<<b) & 1<<b LOCK BTC b, m
+
+Hence, we will manually translate fetch_or() using GCC-style inline
+assembler code or a Microsoft intrinsic function.
+
+*/
+#if defined __GNUC__ && (defined __i386__ || defined __x86_64__)
+# define IF_FETCH_OR_GOTO(mem, bit, label) \
+ __asm__ goto("lock btsl $" #bit ", %0\n\t" \
+ "jc %l1" : : "m" (mem) : "cc", "memory" : label);
+# define IF_NOT_FETCH_OR_GOTO(mem, bit, label) \
+ __asm__ goto("lock btsl $" #bit ", %0\n\t" \
+ "jnc %l1" : : "m" (mem) : "cc", "memory" : label);
+#elif defined _MSC_VER && (defined _M_IX86 || defined _M_IX64)
+# define IF_FETCH_OR_GOTO(mem, bit, label) \
+ if (_interlockedbittestandset(reinterpret_cast<volatile long*>(&mem), bit)) \
+ goto label;
+# define IF_NOT_FETCH_OR_GOTO(mem, bit, label) \
+ if (!_interlockedbittestandset(reinterpret_cast<volatile long*>(&mem), bit))\
+ goto label;
+#endif
+
template<>
void srw_mutex_impl<true>::wait_and_lock()
{
@@ -296,55 +338,75 @@ void srw_mutex_impl<true>::wait_and_lock()
lk= lock.load(std::memory_order_relaxed);
else
{
- lk= lock.fetch_or(HOLDER, std::memory_order_relaxed);
- if (!(lk & HOLDER))
+#ifdef IF_NOT_FETCH_OR_GOTO
+ static_assert(HOLDER == (1U << 31), "compatibility");
+ IF_NOT_FETCH_OR_GOTO(*this, 31, acquired);
+ lk|= HOLDER;
+#else
+ if (!((lk= lock.fetch_or(HOLDER, std::memory_order_relaxed)) & HOLDER))
goto acquired;
+#endif
+ srw_pause(delay);
}
- srw_pause(delay);
if (!--spin)
break;
}
- for (;; wait(lk))
+ for (;;)
{
+ DBUG_ASSERT(~HOLDER & lk);
if (lk & HOLDER)
{
+ wait(lk);
+#ifdef IF_FETCH_OR_GOTO
+reload:
+#endif
lk= lock.load(std::memory_order_relaxed);
- if (lk & HOLDER)
- continue;
}
- lk= lock.fetch_or(HOLDER, std::memory_order_relaxed);
- if (!(lk & HOLDER))
+ else
{
-acquired:
+#ifdef IF_FETCH_OR_GOTO
+ static_assert(HOLDER == (1U << 31), "compatibility");
+ IF_FETCH_OR_GOTO(*this, 31, reload);
+#else
+ if ((lk= lock.fetch_or(HOLDER, std::memory_order_relaxed)) & HOLDER)
+ continue;
DBUG_ASSERT(lk);
+#endif
+acquired:
std::atomic_thread_fence(std::memory_order_acquire);
return;
}
- DBUG_ASSERT(lk > HOLDER);
}
}
template<>
void srw_mutex_impl<false>::wait_and_lock()
{
- uint32_t lk= 1 + lock.fetch_add(1, std::memory_order_relaxed);
- for (;; wait(lk))
+ for (uint32_t lk= 1 + lock.fetch_add(1, std::memory_order_relaxed);;)
{
+ DBUG_ASSERT(~HOLDER & lk);
if (lk & HOLDER)
{
+ wait(lk);
+#ifdef IF_FETCH_OR_GOTO
+reload:
+#endif
lk= lock.load(std::memory_order_relaxed);
- if (lk & HOLDER)
- continue;
}
- lk= lock.fetch_or(HOLDER, std::memory_order_relaxed);
- if (!(lk & HOLDER))
+ else
{
+#ifdef IF_FETCH_OR_GOTO
+ static_assert(HOLDER == (1U << 31), "compatibility");
+ IF_FETCH_OR_GOTO(*this, 31, reload);
+#else
+ if ((lk= lock.fetch_or(HOLDER, std::memory_order_relaxed)) & HOLDER)
+ continue;
DBUG_ASSERT(lk);
+#endif
std::atomic_thread_fence(std::memory_order_acquire);
return;
}
- DBUG_ASSERT(lk > HOLDER);
}
}
@@ -354,7 +416,23 @@ void ssux_lock_impl<spinloop>::wr_wait(uint32_t lk)
DBUG_ASSERT(writer.is_locked());
DBUG_ASSERT(lk);
DBUG_ASSERT(lk < WRITER);
+
+ if (spinloop)
+ {
+ const unsigned delay= srw_pause_delay();
+
+ for (auto spin= srv_n_spin_wait_rounds; spin; spin--)
+ {
+ srw_pause(delay);
+ lk= readers.load(std::memory_order_acquire);
+ if (lk == WRITER)
+ return;
+ DBUG_ASSERT(lk > WRITER);
+ }
+ }
+
lk|= WRITER;
+
do
{
DBUG_ASSERT(lk > WRITER);
@@ -373,36 +451,55 @@ void ssux_lock_impl<spinloop>::rd_wait()
for (;;)
{
writer.wr_lock();
- uint32_t lk= readers.fetch_add(1, std::memory_order_acquire);
- if (UNIV_UNLIKELY(lk == WRITER))
- {
- readers.fetch_sub(1, std::memory_order_relaxed);
- wake();
- writer.wr_unlock();
- pthread_yield();
- continue;
- }
- DBUG_ASSERT(!(lk & WRITER));
- break;
+ bool acquired= rd_lock_try();
+ writer.wr_unlock();
+ if (acquired)
+ break;
}
- writer.wr_unlock();
}
template void ssux_lock_impl<true>::rd_wait();
template void ssux_lock_impl<false>::rd_wait();
#endif /* SUX_LOCK_GENERIC */
+#if defined _WIN32 || defined SUX_LOCK_GENERIC
+template<> void srw_lock_<true>::rd_wait()
+{
+ const unsigned delay= srw_pause_delay();
+
+ for (auto spin= srv_n_spin_wait_rounds; spin; spin--)
+ {
+ srw_pause(delay);
+ if (rd_lock_try())
+ return;
+ }
+
+ IF_WIN(AcquireSRWLockShared(&lock), rw_rdlock(&lock));
+}
+
+template<> void srw_lock_<true>::wr_wait()
+{
+ const unsigned delay= srw_pause_delay();
+
+ for (auto spin= srv_n_spin_wait_rounds; spin; spin--)
+ {
+ srw_pause(delay);
+ if (wr_lock_try())
+ return;
+ }
+
+ IF_WIN(AcquireSRWLockExclusive(&lock), rw_wrlock(&lock));
+}
+#endif
+
#ifdef UNIV_PFS_RWLOCK
-# if defined _WIN32 || defined SUX_LOCK_GENERIC
-# define void_srw_lock void srw_lock_impl
-# else
-# define void_srw_lock template<bool spinloop> void srw_lock_impl<spinloop>
template void srw_lock_impl<false>::psi_rd_lock(const char*, unsigned);
template void srw_lock_impl<false>::psi_wr_lock(const char*, unsigned);
template void srw_lock_impl<true>::psi_rd_lock(const char*, unsigned);
template void srw_lock_impl<true>::psi_wr_lock(const char*, unsigned);
-# endif
-void_srw_lock::psi_rd_lock(const char *file, unsigned line)
+
+template<bool spinloop>
+void srw_lock_impl<spinloop>::psi_rd_lock(const char *file, unsigned line)
{
PSI_rwlock_locker_state state;
const bool nowait= lock.rd_lock_try();
@@ -418,7 +515,8 @@ void_srw_lock::psi_rd_lock(const char *file, unsigned line)
lock.rd_lock();
}
-void_srw_lock::psi_wr_lock(const char *file, unsigned line)
+template<bool spinloop>
+void srw_lock_impl<spinloop>::psi_wr_lock(const char *file, unsigned line)
{
PSI_rwlock_locker_state state;
const bool nowait= lock.wr_lock_try();
diff --git a/strings/ctype-big5.c b/strings/ctype-big5.c
index 9821584f074..1e1b21aee34 100644
--- a/strings/ctype-big5.c
+++ b/strings/ctype-big5.c
@@ -29,6 +29,7 @@
#include "strings_def.h"
#include <m_ctype.h>
+#include "ctype-mb.h"
#ifdef HAVE_CHARSET_big5
@@ -6723,7 +6724,9 @@ static MY_COLLATION_HANDLER my_collation_handler_big5_chinese_ci=
my_strcasecmp_mb,
my_instr_mb,
my_hash_sort_simple,
- my_propagate_simple
+ my_propagate_simple,
+ my_min_str_mb_simple,
+ my_max_str_mb_simple
};
@@ -6739,7 +6742,9 @@ static MY_COLLATION_HANDLER my_collation_handler_big5_bin=
my_strcasecmp_mb_bin,
my_instr_mb,
my_hash_sort_mb_bin,
- my_propagate_simple
+ my_propagate_simple,
+ my_min_str_mb_simple,
+ my_max_str_mb_simple
};
@@ -6755,7 +6760,9 @@ static MY_COLLATION_HANDLER my_collation_handler_big5_chinese_nopad_ci=
my_strcasecmp_mb,
my_instr_mb,
my_hash_sort_simple_nopad,
- my_propagate_simple
+ my_propagate_simple,
+ my_min_str_mb_simple_nopad,
+ my_max_str_mb_simple
};
@@ -6771,7 +6778,9 @@ static MY_COLLATION_HANDLER my_collation_handler_big5_nopad_bin=
my_strcasecmp_mb_bin,
my_instr_mb,
my_hash_sort_mb_nopad_bin,
- my_propagate_simple
+ my_propagate_simple,
+ my_min_str_mb_simple_nopad,
+ my_max_str_mb_simple
};
diff --git a/strings/ctype-bin.c b/strings/ctype-bin.c
index 2902c2edda1..b142cab523a 100644
--- a/strings/ctype-bin.c
+++ b/strings/ctype-bin.c
@@ -22,6 +22,7 @@
#include "strings_def.h"
#include <m_ctype.h>
+#include "ctype-simple.h"
const char charset_name_binary[]= "binary";
#define charset_name_binary_length (sizeof(charset_name_binary)-1)
@@ -497,7 +498,9 @@ MY_COLLATION_HANDLER my_collation_8bit_bin_handler =
my_strcasecmp_bin,
my_instr_bin,
my_hash_sort_8bit_bin,
- my_propagate_simple
+ my_propagate_simple,
+ my_min_str_8bit_simple,
+ my_max_str_8bit_simple
};
@@ -513,7 +516,9 @@ MY_COLLATION_HANDLER my_collation_8bit_nopad_bin_handler =
my_strcasecmp_bin,
my_instr_bin,
my_hash_sort_bin,
- my_propagate_simple
+ my_propagate_simple,
+ my_min_str_8bit_simple_nopad,
+ my_max_str_8bit_simple
};
@@ -529,7 +534,9 @@ static MY_COLLATION_HANDLER my_collation_binary_handler =
my_strcasecmp_bin,
my_instr_bin,
my_hash_sort_bin,
- my_propagate_simple
+ my_propagate_simple,
+ my_min_str_8bit_simple_nopad,
+ my_max_str_8bit_simple
};
diff --git a/strings/ctype-cp932.c b/strings/ctype-cp932.c
index 8cf2757c6b2..847d3559a39 100644
--- a/strings/ctype-cp932.c
+++ b/strings/ctype-cp932.c
@@ -19,6 +19,7 @@
#include "strings_def.h"
#include <m_ctype.h>
+#include "ctype-mb.h"
#ifdef HAVE_CHARSET_cp932
@@ -34680,7 +34681,9 @@ static MY_COLLATION_HANDLER my_collation_handler_cp932_japanese_ci=
my_strcasecmp_8bit,
my_instr_mb,
my_hash_sort_simple,
- my_propagate_simple
+ my_propagate_simple,
+ my_min_str_mb_simple,
+ my_max_str_mb_simple
};
@@ -34696,7 +34699,9 @@ static MY_COLLATION_HANDLER my_collation_handler_cp932_bin=
my_strcasecmp_mb_bin,
my_instr_mb,
my_hash_sort_mb_bin,
- my_propagate_simple
+ my_propagate_simple,
+ my_min_str_mb_simple,
+ my_max_str_mb_simple
};
@@ -34712,7 +34717,9 @@ static MY_COLLATION_HANDLER my_collation_handler_cp932_japanese_nopad_ci=
my_strcasecmp_8bit,
my_instr_mb,
my_hash_sort_simple_nopad,
- my_propagate_simple
+ my_propagate_simple,
+ my_min_str_mb_simple_nopad,
+ my_max_str_mb_simple
};
@@ -34728,7 +34735,9 @@ static MY_COLLATION_HANDLER my_collation_handler_cp932_nopad_bin=
my_strcasecmp_mb_bin,
my_instr_mb,
my_hash_sort_mb_nopad_bin,
- my_propagate_simple
+ my_propagate_simple,
+ my_min_str_mb_simple_nopad,
+ my_max_str_mb_simple
};
diff --git a/strings/ctype-czech.c b/strings/ctype-czech.c
index 40baae67dd3..ca331dc667f 100644
--- a/strings/ctype-czech.c
+++ b/strings/ctype-czech.c
@@ -69,6 +69,7 @@
#include "strings_def.h"
#include <m_ctype.h>
+#include "ctype-simple.h"
#else
@@ -605,7 +606,7 @@ static MY_UNI_IDX idx_uni_8859_2[]={
};
-static MY_COLLATION_HANDLER my_collation_latin2_czech_ci_handler =
+static MY_COLLATION_HANDLER my_collation_latin2_czech_cs_handler =
{
NULL, /* init */
my_strnncoll_czech,
@@ -617,10 +618,12 @@ static MY_COLLATION_HANDLER my_collation_latin2_czech_ci_handler =
my_strcasecmp_8bit,
my_instr_simple,
my_hash_sort_simple,
- my_propagate_simple
+ my_propagate_simple,
+ my_min_str_8bit_simple,
+ my_max_str_8bit_simple
};
-struct charset_info_st my_charset_latin2_czech_ci =
+struct charset_info_st my_charset_latin2_czech_cs =
{
2,0,0, /* number */
MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_CSSORT|
@@ -645,12 +648,12 @@ struct charset_info_st my_charset_latin2_czech_ci =
1, /* mbminlen */
1, /* mbmaxlen */
0, /* min_sort_char */
- 0, /* max_sort_char */
+ 0xAE, /* max_sort_char */
' ', /* pad char */
0, /* escape_with_backslash_is_dangerous */
4, /* levels_for_order */
&my_charset_8bit_handler,
- &my_collation_latin2_czech_ci_handler
+ &my_collation_latin2_czech_cs_handler
};
diff --git a/strings/ctype-euc_kr.c b/strings/ctype-euc_kr.c
index c3e8a2121ed..4d2b9090053 100644
--- a/strings/ctype-euc_kr.c
+++ b/strings/ctype-euc_kr.c
@@ -28,6 +28,7 @@
#include "strings_def.h"
#include <m_ctype.h>
+#include "ctype-mb.h"
#ifdef HAVE_CHARSET_euckr
@@ -9970,7 +9971,9 @@ static MY_COLLATION_HANDLER my_collation_handler_euckr_korean_ci=
my_strcasecmp_mb,
my_instr_mb,
my_hash_sort_simple,
- my_propagate_simple
+ my_propagate_simple,
+ my_min_str_mb_simple,
+ my_max_str_mb_simple
};
@@ -9986,7 +9989,9 @@ static MY_COLLATION_HANDLER my_collation_handler_euckr_bin=
my_strcasecmp_mb_bin,
my_instr_mb,
my_hash_sort_mb_bin,
- my_propagate_simple
+ my_propagate_simple,
+ my_min_str_mb_simple,
+ my_max_str_mb_simple
};
@@ -10002,7 +10007,9 @@ static MY_COLLATION_HANDLER my_collation_handler_euckr_korean_nopad_ci=
my_strcasecmp_mb,
my_instr_mb,
my_hash_sort_simple_nopad,
- my_propagate_simple
+ my_propagate_simple,
+ my_min_str_mb_simple_nopad,
+ my_max_str_mb_simple
};
@@ -10018,7 +10025,9 @@ static MY_COLLATION_HANDLER my_collation_handler_euckr_nopad_bin=
my_strcasecmp_mb_bin,
my_instr_mb,
my_hash_sort_mb_nopad_bin,
- my_propagate_simple
+ my_propagate_simple,
+ my_min_str_mb_simple_nopad,
+ my_max_str_mb_simple
};
diff --git a/strings/ctype-eucjpms.c b/strings/ctype-eucjpms.c
index 331fb68a72e..9c2b23ea918 100644
--- a/strings/ctype-eucjpms.c
+++ b/strings/ctype-eucjpms.c
@@ -30,6 +30,7 @@ ctype-ujis.c file.
#include "strings_def.h"
#include <m_ctype.h>
+#include "ctype-mb.h"
#ifdef HAVE_CHARSET_eucjpms
@@ -67508,7 +67509,9 @@ static MY_COLLATION_HANDLER my_collation_eucjpms_japanese_ci_handler =
my_strcasecmp_mb,
my_instr_mb,
my_hash_sort_simple,
- my_propagate_simple
+ my_propagate_simple,
+ my_min_str_mb_simple,
+ my_max_str_mb_simple
};
@@ -67524,7 +67527,9 @@ static MY_COLLATION_HANDLER my_collation_eucjpms_bin_handler =
my_strcasecmp_mb_bin,
my_instr_mb,
my_hash_sort_mb_bin,
- my_propagate_simple
+ my_propagate_simple,
+ my_min_str_mb_simple,
+ my_max_str_mb_simple
};
@@ -67540,7 +67545,9 @@ static MY_COLLATION_HANDLER my_collation_eucjpms_japanese_nopad_ci_handler =
my_strcasecmp_mb,
my_instr_mb,
my_hash_sort_simple_nopad,
- my_propagate_simple
+ my_propagate_simple,
+ my_min_str_mb_simple_nopad,
+ my_max_str_mb_simple
};
@@ -67556,7 +67563,9 @@ static MY_COLLATION_HANDLER my_collation_eucjpms_nopad_bin_handler =
my_strcasecmp_mb_bin,
my_instr_mb,
my_hash_sort_mb_nopad_bin,
- my_propagate_simple
+ my_propagate_simple,
+ my_min_str_mb_simple_nopad,
+ my_max_str_mb_simple
};
diff --git a/strings/ctype-gb2312.c b/strings/ctype-gb2312.c
index f801ea285b7..70ac2c9b958 100644
--- a/strings/ctype-gb2312.c
+++ b/strings/ctype-gb2312.c
@@ -26,6 +26,7 @@
#include "strings_def.h"
#include <m_ctype.h>
+#include "ctype-mb.h"
#ifdef HAVE_CHARSET_gb2312
@@ -6374,7 +6375,9 @@ static MY_COLLATION_HANDLER my_collation_handler_gb2312_chinese_ci=
my_strcasecmp_mb, /* instr */
my_instr_mb,
my_hash_sort_simple,
- my_propagate_simple
+ my_propagate_simple,
+ my_min_str_mb_simple,
+ my_max_str_mb_simple
};
@@ -6390,7 +6393,9 @@ static MY_COLLATION_HANDLER my_collation_handler_gb2312_bin=
my_strcasecmp_mb_bin,
my_instr_mb,
my_hash_sort_mb_bin,
- my_propagate_simple
+ my_propagate_simple,
+ my_min_str_mb_simple,
+ my_max_str_mb_simple
};
@@ -6406,7 +6411,9 @@ static MY_COLLATION_HANDLER my_collation_handler_gb2312_chinese_nopad_ci=
my_strcasecmp_mb,
my_instr_mb,
my_hash_sort_simple_nopad,
- my_propagate_simple
+ my_propagate_simple,
+ my_min_str_mb_simple_nopad,
+ my_max_str_mb_simple
};
@@ -6422,7 +6429,9 @@ static MY_COLLATION_HANDLER my_collation_handler_gb2312_nopad_bin=
my_strcasecmp_mb_bin,
my_instr_mb,
my_hash_sort_mb_nopad_bin,
- my_propagate_simple
+ my_propagate_simple,
+ my_min_str_mb_simple_nopad,
+ my_max_str_mb_simple
};
diff --git a/strings/ctype-gbk.c b/strings/ctype-gbk.c
index 5ede3520f3a..ba5ba02bf5e 100644
--- a/strings/ctype-gbk.c
+++ b/strings/ctype-gbk.c
@@ -28,6 +28,7 @@
#include "strings_def.h"
#include <m_ctype.h>
+#include "ctype-mb.h"
#ifdef HAVE_CHARSET_gbk
@@ -10656,7 +10657,9 @@ static MY_COLLATION_HANDLER my_collation_handler_gbk_chinese_ci=
my_strcasecmp_mb,
my_instr_mb,
my_hash_sort_simple,
- my_propagate_simple
+ my_propagate_simple,
+ my_min_str_mb_simple,
+ my_max_str_mb_simple
};
@@ -10672,7 +10675,9 @@ static MY_COLLATION_HANDLER my_collation_handler_gbk_bin=
my_strcasecmp_mb_bin,
my_instr_mb,
my_hash_sort_mb_bin,
- my_propagate_simple
+ my_propagate_simple,
+ my_min_str_mb_simple,
+ my_max_str_mb_simple
};
@@ -10688,7 +10693,9 @@ static MY_COLLATION_HANDLER my_collation_handler_gbk_chinese_nopad_ci=
my_strcasecmp_mb,
my_instr_mb,
my_hash_sort_simple_nopad,
- my_propagate_simple
+ my_propagate_simple,
+ my_min_str_mb_simple_nopad,
+ my_max_str_mb_simple
};
@@ -10704,7 +10711,9 @@ static MY_COLLATION_HANDLER my_collation_handler_gbk_nopad_bin=
my_strcasecmp_mb_bin,
my_instr_mb,
my_hash_sort_mb_nopad_bin,
- my_propagate_simple
+ my_propagate_simple,
+ my_min_str_mb_simple_nopad,
+ my_max_str_mb_simple
};
static MY_CHARSET_HANDLER my_charset_handler=
diff --git a/strings/ctype-latin1.c b/strings/ctype-latin1.c
index 2a0983ee16f..9412f212420 100644
--- a/strings/ctype-latin1.c
+++ b/strings/ctype-latin1.c
@@ -17,6 +17,7 @@
#include "strings_def.h"
#include <m_ctype.h>
+#include "ctype-simple.h"
const char charset_name_latin1[]= "latin1";
#define charset_name_latin1_length sizeof(charset_name_latin1)-1
@@ -737,7 +738,9 @@ static MY_COLLATION_HANDLER my_collation_german2_ci_handler=
my_strcasecmp_8bit,
my_instr_simple,
my_hash_sort_latin1_de,
- my_propagate_complex
+ my_propagate_complex,
+ my_min_str_8bit_simple,
+ my_max_str_8bit_simple
};
diff --git a/strings/ctype-mb.c b/strings/ctype-mb.c
index b84c91efe5f..66f82a1d09c 100644
--- a/strings/ctype-mb.c
+++ b/strings/ctype-mb.c
@@ -16,6 +16,7 @@
#include "strings_def.h"
#include <m_ctype.h>
+#include "ctype-mb.h"
#ifdef USE_MB
@@ -640,6 +641,46 @@ my_hash_sort_mb_bin(CHARSET_INFO *cs __attribute__((unused)),
}
+static inline size_t
+my_repeat_char_native(CHARSET_INFO *cs,
+ uchar *dst, size_t dst_size, size_t nchars,
+ my_wc_t native_code)
+{
+ uchar *dst0= dst;
+ uchar *dstend= dst + dst_size;
+ int chlen= my_ci_native_to_mb(cs, native_code, dst, dstend);
+ if (chlen < 1 /* Not enough space */ || !nchars)
+ return 0;
+ for (dst+= chlen, nchars--;
+ dst + chlen <= dstend && nchars > 0;
+ dst+= chlen, nchars--)
+ memcpy(dst, dst0, chlen);
+ return dst - dst0;
+}
+
+
+size_t my_min_str_mb_simple(CHARSET_INFO *cs,
+ uchar *dst, size_t dst_size, size_t nchars)
+{
+ return my_repeat_char_native(cs, dst, dst_size, nchars, cs->min_sort_char);
+}
+
+
+size_t my_min_str_mb_simple_nopad(CHARSET_INFO *cs,
+ uchar *dst, size_t dst_size, size_t nchars)
+{
+ /* For NOPAD collations, the empty string is the smallest possible */
+ return 0;
+}
+
+
+size_t my_max_str_mb_simple(CHARSET_INFO *cs,
+ uchar *dst, size_t dst_size, size_t nchars)
+{
+ return my_repeat_char_native(cs, dst, dst_size, nchars, cs->max_sort_char);
+}
+
+
/*
Fill the given buffer with 'maximum character' for given charset
SYNOPSIS
diff --git a/strings/ctype-mb.h b/strings/ctype-mb.h
new file mode 100644
index 00000000000..b6f06e8df0d
--- /dev/null
+++ b/strings/ctype-mb.h
@@ -0,0 +1,37 @@
+#ifndef CTYPE_MB_INCLUDED
+#define CTYPE_MB_INCLUDED
+/* Copyright (C) 2021 MariaDB Corporation
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */
+
+/* This file is to be include first in all files in the string directory */
+
+#undef DBUG_ASSERT_AS_PRINTF
+#include <my_global.h> /* Define standard vars */
+#include "m_string.h" /* Exernal definitions of string functions */
+
+
+size_t
+my_min_str_mb_simple(CHARSET_INFO *cs,
+ uchar *dst, size_t dst_size, size_t nchars);
+
+size_t
+my_min_str_mb_simple_nopad(CHARSET_INFO *cs,
+ uchar *dst, size_t dst_size, size_t nchars);
+
+size_t
+my_max_str_mb_simple(CHARSET_INFO *cs,
+ uchar *dst, size_t dst_size, size_t nchars);
+
+#endif /*CTYPE_MB_INCLUDED */
diff --git a/strings/ctype-simple.c b/strings/ctype-simple.c
index f9471f35f79..a0ba4357d5e 100644
--- a/strings/ctype-simple.c
+++ b/strings/ctype-simple.c
@@ -16,6 +16,7 @@
#include "strings_def.h"
#include <m_ctype.h>
+#include "ctype-simple.h"
#include "my_sys.h" /* Needed for MY_ERRNO_ERANGE */
#include <errno.h>
@@ -891,6 +892,35 @@ cnv:
}
+size_t my_min_str_8bit_simple(CHARSET_INFO *cs,
+ uchar *dst, size_t dst_size,
+ size_t nchars)
+{
+ set_if_smaller(dst_size, nchars);
+ memset(dst, cs->min_sort_char, dst_size);
+ return dst_size;
+}
+
+
+size_t my_min_str_8bit_simple_nopad(CHARSET_INFO *cs,
+ uchar *dst, size_t dst_size,
+ size_t nchars)
+{
+ /* For NOPAD collations, the empty string is always the smallest */
+ return 0;
+}
+
+
+size_t my_max_str_8bit_simple(CHARSET_INFO *cs,
+ uchar *dst, size_t dst_size,
+ size_t nchars)
+{
+ set_if_smaller(dst_size, nchars);
+ memset(dst, cs->max_sort_char, dst_size);
+ return dst_size;
+}
+
+
/*
** Compare string against string with wildcard
** 0 if matched
@@ -2104,7 +2134,9 @@ MY_COLLATION_HANDLER my_collation_8bit_simple_ci_handler =
my_strcasecmp_8bit,
my_instr_simple,
my_hash_sort_simple,
- my_propagate_simple
+ my_propagate_simple,
+ my_min_str_8bit_simple,
+ my_max_str_8bit_simple
};
@@ -2120,5 +2152,7 @@ MY_COLLATION_HANDLER my_collation_8bit_simple_nopad_ci_handler =
my_strcasecmp_8bit,
my_instr_simple,
my_hash_sort_simple_nopad,
- my_propagate_simple
+ my_propagate_simple,
+ my_min_str_8bit_simple_nopad,
+ my_max_str_8bit_simple
};
diff --git a/strings/ctype-simple.h b/strings/ctype-simple.h
new file mode 100644
index 00000000000..321c107a61f
--- /dev/null
+++ b/strings/ctype-simple.h
@@ -0,0 +1,37 @@
+#ifndef CTYPE_SIMPLE_INCLUDED
+#define CTYPE_SIMPLE_INCLUDED
+/* Copyright (C) 2021 MariaDB Corporation
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */
+
+/* This file is to be include first in all files in the string directory */
+
+#undef DBUG_ASSERT_AS_PRINTF
+#include <my_global.h> /* Define standard vars */
+#include "m_string.h" /* Exernal definitions of string functions */
+
+
+size_t
+my_min_str_8bit_simple(CHARSET_INFO *cs,
+ uchar *dst, size_t dst_size, size_t nchars);
+
+size_t
+my_min_str_8bit_simple_nopad(CHARSET_INFO *cs,
+ uchar *dst, size_t dst_size, size_t nchars);
+
+size_t
+my_max_str_8bit_simple(CHARSET_INFO *cs,
+ uchar *dst, size_t dst_size, size_t nchars);
+
+#endif /*CTYPE_SIMPLE_INCLUDED */
diff --git a/strings/ctype-sjis.c b/strings/ctype-sjis.c
index 5cef7126b07..abae90008ea 100644
--- a/strings/ctype-sjis.c
+++ b/strings/ctype-sjis.c
@@ -19,6 +19,7 @@
#include "strings_def.h"
#include <m_ctype.h>
+#include "ctype-mb.h"
#ifdef HAVE_CHARSET_sjis
@@ -34068,7 +34069,9 @@ static MY_COLLATION_HANDLER my_collation_handler_sjis_japanese_ci=
my_strcasecmp_8bit,
my_instr_mb,
my_hash_sort_simple,
- my_propagate_simple
+ my_propagate_simple,
+ my_min_str_mb_simple,
+ my_max_str_mb_simple
};
@@ -34084,7 +34087,9 @@ static MY_COLLATION_HANDLER my_collation_handler_sjis_bin=
my_strcasecmp_mb_bin,
my_instr_mb,
my_hash_sort_mb_bin,
- my_propagate_simple
+ my_propagate_simple,
+ my_min_str_mb_simple,
+ my_max_str_mb_simple
};
@@ -34100,7 +34105,9 @@ static MY_COLLATION_HANDLER my_collation_handler_sjis_japanese_nopad_ci=
my_strcasecmp_8bit,
my_instr_mb,
my_hash_sort_simple_nopad,
- my_propagate_simple
+ my_propagate_simple,
+ my_min_str_mb_simple_nopad,
+ my_max_str_mb_simple
};
@@ -34116,7 +34123,9 @@ static MY_COLLATION_HANDLER my_collation_handler_sjis_nopad_bin=
my_strcasecmp_mb_bin,
my_instr_mb,
my_hash_sort_mb_nopad_bin,
- my_propagate_simple
+ my_propagate_simple,
+ my_min_str_mb_simple_nopad,
+ my_max_str_mb_simple
};
diff --git a/strings/ctype-tis620.c b/strings/ctype-tis620.c
index 849f4897231..dac44295f3c 100644
--- a/strings/ctype-tis620.c
+++ b/strings/ctype-tis620.c
@@ -35,6 +35,7 @@
#include "strings_def.h"
#include <m_ctype.h>
+#include "ctype-simple.h"
#include "t_ctype.h"
#include <my_sys.h>
@@ -862,7 +863,9 @@ static MY_COLLATION_HANDLER my_collation_ci_handler =
my_strcasecmp_8bit,
my_instr_simple, /* QQ: To be fixed */
my_hash_sort_simple,
- my_propagate_simple
+ my_propagate_simple,
+ my_min_str_8bit_simple,
+ my_max_str_8bit_simple
};
static MY_COLLATION_HANDLER my_collation_nopad_ci_handler =
@@ -877,7 +880,9 @@ static MY_COLLATION_HANDLER my_collation_nopad_ci_handler =
my_strcasecmp_8bit,
my_instr_simple, /* QQ: To be fixed */
my_hash_sort_simple_nopad,
- my_propagate_simple
+ my_propagate_simple,
+ my_min_str_8bit_simple_nopad,
+ my_max_str_8bit_simple
};
static MY_CHARSET_HANDLER my_charset_handler=
diff --git a/strings/ctype-uca.ic b/strings/ctype-uca.ic
index e47f1e1fd82..cee12cf4d7b 100644
--- a/strings/ctype-uca.ic
+++ b/strings/ctype-uca.ic
@@ -15,6 +15,7 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include "ctype-mb.h"
#ifndef MY_FUNCTION_NAME
#error MY_FUNCTION_NAME is not defined
@@ -759,7 +760,9 @@ MY_COLLATION_HANDLER MY_FUNCTION_NAME(collation_handler)=
NULL, /* strcasecmp() */
my_instr_mb,
MY_FUNCTION_NAME(hash_sort),
- my_propagate_complex
+ my_propagate_complex,
+ my_min_str_mb_simple,
+ my_max_str_mb_simple
};
@@ -780,7 +783,9 @@ MY_COLLATION_HANDLER MY_FUNCTION_NAME(collation_handler_nopad)=
NULL, /* strcasecmp() */
my_instr_mb,
MY_FUNCTION_NAME(hash_sort_nopad),
- my_propagate_complex
+ my_propagate_complex,
+ my_min_str_mb_simple_nopad,
+ my_max_str_mb_simple
};
@@ -799,7 +804,9 @@ MY_COLLATION_HANDLER MY_FUNCTION_NAME(collation_handler_multilevel)=
NULL, /* strcasecmp() */
my_instr_mb,
MY_FUNCTION_NAME(hash_sort),
- my_propagate_complex
+ my_propagate_complex,
+ my_min_str_mb_simple,
+ my_max_str_mb_simple
};
@@ -818,7 +825,9 @@ MY_COLLATION_HANDLER MY_FUNCTION_NAME(collation_handler_nopad_multilevel)=
NULL, /* strcasecmp() */
my_instr_mb,
MY_FUNCTION_NAME(hash_sort),
- my_propagate_complex
+ my_propagate_complex,
+ my_min_str_mb_simple_nopad,
+ my_max_str_mb_simple
};
diff --git a/strings/ctype-ucs2.c b/strings/ctype-ucs2.c
index dbf0d86dc05..c230c65d3d6 100644
--- a/strings/ctype-ucs2.c
+++ b/strings/ctype-ucs2.c
@@ -20,6 +20,7 @@
#include "strings_def.h"
#include <m_ctype.h>
+#include "ctype-mb.h"
#include <my_sys.h>
#include <stdarg.h>
@@ -1513,7 +1514,9 @@ static MY_COLLATION_HANDLER my_collation_utf16_general_ci_handler =
my_strcasecmp_mb2_or_mb4,
my_instr_mb,
my_hash_sort_utf16,
- my_propagate_simple
+ my_propagate_simple,
+ my_min_str_mb_simple,
+ my_max_str_mb_simple
};
@@ -1529,7 +1532,9 @@ static MY_COLLATION_HANDLER my_collation_utf16_bin_handler =
my_strcasecmp_mb2_or_mb4,
my_instr_mb,
my_hash_sort_utf16_bin,
- my_propagate_simple
+ my_propagate_simple,
+ my_min_str_mb_simple,
+ my_max_str_mb_simple
};
@@ -1545,7 +1550,9 @@ static MY_COLLATION_HANDLER my_collation_utf16_general_nopad_ci_handler =
my_strcasecmp_mb2_or_mb4,
my_instr_mb,
my_hash_sort_utf16_nopad,
- my_propagate_simple
+ my_propagate_simple,
+ my_min_str_mb_simple_nopad,
+ my_max_str_mb_simple
};
@@ -1561,7 +1568,9 @@ static MY_COLLATION_HANDLER my_collation_utf16_nopad_bin_handler =
my_strcasecmp_mb2_or_mb4,
my_instr_mb,
my_hash_sort_utf16_nopad_bin,
- my_propagate_simple
+ my_propagate_simple,
+ my_min_str_mb_simple_nopad,
+ my_max_str_mb_simple
};
@@ -1854,7 +1863,9 @@ static MY_COLLATION_HANDLER my_collation_utf16le_general_ci_handler =
my_strcasecmp_mb2_or_mb4,
my_instr_mb,
my_hash_sort_utf16,
- my_propagate_simple
+ my_propagate_simple,
+ my_min_str_mb_simple,
+ my_max_str_mb_simple
};
@@ -1870,7 +1881,9 @@ static MY_COLLATION_HANDLER my_collation_utf16le_bin_handler =
my_strcasecmp_mb2_or_mb4,
my_instr_mb,
my_hash_sort_utf16_bin,
- my_propagate_simple
+ my_propagate_simple,
+ my_min_str_mb_simple,
+ my_max_str_mb_simple
};
@@ -1886,7 +1899,9 @@ static MY_COLLATION_HANDLER my_collation_utf16le_general_nopad_ci_handler =
my_strcasecmp_mb2_or_mb4,
my_instr_mb,
my_hash_sort_utf16_nopad,
- my_propagate_simple
+ my_propagate_simple,
+ my_min_str_mb_simple_nopad,
+ my_max_str_mb_simple
};
@@ -1902,7 +1917,9 @@ static MY_COLLATION_HANDLER my_collation_utf16le_nopad_bin_handler =
my_strcasecmp_mb2_or_mb4,
my_instr_mb,
my_hash_sort_utf16_nopad_bin,
- my_propagate_simple
+ my_propagate_simple,
+ my_min_str_mb_simple_nopad,
+ my_max_str_mb_simple
};
@@ -2680,7 +2697,9 @@ static MY_COLLATION_HANDLER my_collation_utf32_general_ci_handler =
my_strcasecmp_mb2_or_mb4,
my_instr_mb,
my_hash_sort_utf32,
- my_propagate_simple
+ my_propagate_simple,
+ my_min_str_mb_simple,
+ my_max_str_mb_simple
};
@@ -2696,7 +2715,9 @@ static MY_COLLATION_HANDLER my_collation_utf32_bin_handler =
my_strcasecmp_mb2_or_mb4,
my_instr_mb,
my_hash_sort_utf32,
- my_propagate_simple
+ my_propagate_simple,
+ my_min_str_mb_simple,
+ my_max_str_mb_simple
};
@@ -2712,7 +2733,9 @@ static MY_COLLATION_HANDLER my_collation_utf32_general_nopad_ci_handler =
my_strcasecmp_mb2_or_mb4,
my_instr_mb,
my_hash_sort_utf32_nopad,
- my_propagate_simple
+ my_propagate_simple,
+ my_min_str_mb_simple_nopad,
+ my_max_str_mb_simple
};
@@ -2728,7 +2751,9 @@ static MY_COLLATION_HANDLER my_collation_utf32_nopad_bin_handler =
my_strcasecmp_mb2_or_mb4,
my_instr_mb,
my_hash_sort_utf32_nopad,
- my_propagate_simple
+ my_propagate_simple,
+ my_min_str_mb_simple_nopad,
+ my_max_str_mb_simple
};
@@ -3271,7 +3296,9 @@ static MY_COLLATION_HANDLER my_collation_ucs2_general_ci_handler =
my_strcasecmp_mb2_or_mb4,
my_instr_mb,
my_hash_sort_ucs2,
- my_propagate_simple
+ my_propagate_simple,
+ my_min_str_mb_simple,
+ my_max_str_mb_simple
};
@@ -3287,7 +3314,9 @@ static MY_COLLATION_HANDLER my_collation_ucs2_bin_handler =
my_strcasecmp_mb2_or_mb4,
my_instr_mb,
my_hash_sort_ucs2_bin,
- my_propagate_simple
+ my_propagate_simple,
+ my_min_str_mb_simple,
+ my_max_str_mb_simple
};
@@ -3303,7 +3332,9 @@ static MY_COLLATION_HANDLER my_collation_ucs2_general_nopad_ci_handler =
my_strcasecmp_mb2_or_mb4,
my_instr_mb,
my_hash_sort_ucs2_nopad,
- my_propagate_simple
+ my_propagate_simple,
+ my_min_str_mb_simple_nopad,
+ my_max_str_mb_simple
};
@@ -3319,7 +3350,9 @@ static MY_COLLATION_HANDLER my_collation_ucs2_nopad_bin_handler =
my_strcasecmp_mb2_or_mb4,
my_instr_mb,
my_hash_sort_ucs2_nopad_bin,
- my_propagate_simple
+ my_propagate_simple,
+ my_min_str_mb_simple_nopad,
+ my_max_str_mb_simple
};
diff --git a/strings/ctype-ujis.c b/strings/ctype-ujis.c
index 8664ea3f757..79c552fd430 100644
--- a/strings/ctype-ujis.c
+++ b/strings/ctype-ujis.c
@@ -29,6 +29,7 @@
#include "strings_def.h"
#include <m_ctype.h>
+#include "ctype-mb.h"
#ifdef HAVE_CHARSET_ujis
@@ -67252,7 +67253,9 @@ static MY_COLLATION_HANDLER my_collation_ujis_japanese_ci_handler =
my_strcasecmp_mb,
my_instr_mb,
my_hash_sort_simple,
- my_propagate_simple
+ my_propagate_simple,
+ my_min_str_mb_simple,
+ my_max_str_mb_simple
};
@@ -67268,7 +67271,9 @@ static MY_COLLATION_HANDLER my_collation_ujis_bin_handler =
my_strcasecmp_mb_bin,
my_instr_mb,
my_hash_sort_mb_bin,
- my_propagate_simple
+ my_propagate_simple,
+ my_min_str_mb_simple,
+ my_max_str_mb_simple
};
@@ -67284,7 +67289,9 @@ static MY_COLLATION_HANDLER my_collation_ujis_japanese_nopad_ci_handler =
my_strcasecmp_mb,
my_instr_mb,
my_hash_sort_simple_nopad,
- my_propagate_simple
+ my_propagate_simple,
+ my_min_str_mb_simple_nopad,
+ my_max_str_mb_simple
};
@@ -67300,7 +67307,9 @@ static MY_COLLATION_HANDLER my_collation_ujis_nopad_bin_handler =
my_strcasecmp_mb_bin,
my_instr_mb,
my_hash_sort_mb_nopad_bin,
- my_propagate_simple
+ my_propagate_simple,
+ my_min_str_mb_simple_nopad,
+ my_max_str_mb_simple
};
diff --git a/strings/ctype-utf8.c b/strings/ctype-utf8.c
index 74b50a1ec2f..28e01d71bde 100644
--- a/strings/ctype-utf8.c
+++ b/strings/ctype-utf8.c
@@ -21,6 +21,7 @@
#include "strings_def.h"
#include <m_ctype.h>
+#include "ctype-mb.h"
#ifndef EILSEQ
#define EILSEQ ENOENT
@@ -5647,7 +5648,9 @@ static MY_COLLATION_HANDLER my_collation_utf8mb3_general_ci_handler =
my_strcasecmp_utf8mb3,
my_instr_mb,
my_hash_sort_utf8mb3,
- my_propagate_complex
+ my_propagate_complex,
+ my_min_str_mb_simple,
+ my_max_str_mb_simple
};
@@ -5663,7 +5666,9 @@ static MY_COLLATION_HANDLER my_collation_utf8mb3_general_mysql500_ci_handler =
my_strcasecmp_utf8mb3,
my_instr_mb,
my_hash_sort_utf8mb3,
- my_propagate_complex
+ my_propagate_complex,
+ my_min_str_mb_simple,
+ my_max_str_mb_simple
};
@@ -5679,7 +5684,9 @@ static MY_COLLATION_HANDLER my_collation_utf8mb3_bin_handler =
my_strcasecmp_mb_bin,
my_instr_mb,
my_hash_sort_mb_bin,
- my_propagate_simple
+ my_propagate_simple,
+ my_min_str_mb_simple,
+ my_max_str_mb_simple
};
@@ -5695,7 +5702,9 @@ static MY_COLLATION_HANDLER my_collation_utf8mb3_general_nopad_ci_handler =
my_strcasecmp_utf8mb3,
my_instr_mb,
my_hash_sort_utf8mb3_nopad,
- my_propagate_complex
+ my_propagate_complex,
+ my_min_str_mb_simple_nopad,
+ my_max_str_mb_simple
};
@@ -5711,7 +5720,9 @@ static MY_COLLATION_HANDLER my_collation_utf8mb3_nopad_bin_handler =
my_strcasecmp_mb_bin,
my_instr_mb,
my_hash_sort_mb_nopad_bin,
- my_propagate_simple
+ my_propagate_simple,
+ my_min_str_mb_simple_nopad,
+ my_max_str_mb_simple
};
@@ -6041,7 +6052,9 @@ static MY_COLLATION_HANDLER my_collation_cs_handler =
my_strcasecmp_utf8mb3,
my_instr_mb,
my_hash_sort_utf8mb3,
- my_propagate_simple
+ my_propagate_simple,
+ my_min_str_mb_simple,
+ my_max_str_mb_simple
};
struct charset_info_st my_charset_utf8mb3_general_cs=
@@ -7359,7 +7372,9 @@ static MY_COLLATION_HANDLER my_collation_filename_handler =
my_strcasecmp_utf8mb3,
my_instr_mb,
my_hash_sort_utf8mb3,
- my_propagate_complex
+ my_propagate_complex,
+ my_min_str_mb_simple,
+ my_max_str_mb_simple
};
static MY_CHARSET_HANDLER my_charset_filename_handler=
@@ -8003,7 +8018,9 @@ static MY_COLLATION_HANDLER my_collation_utf8mb4_general_ci_handler=
my_strcasecmp_utf8mb4,
my_instr_mb,
my_hash_sort_utf8mb4,
- my_propagate_complex
+ my_propagate_complex,
+ my_min_str_mb_simple,
+ my_max_str_mb_simple
};
@@ -8019,7 +8036,9 @@ static MY_COLLATION_HANDLER my_collation_utf8mb4_bin_handler =
my_strcasecmp_mb_bin,
my_instr_mb,
my_hash_sort_mb_bin,
- my_propagate_simple
+ my_propagate_simple,
+ my_min_str_mb_simple,
+ my_max_str_mb_simple
};
@@ -8035,7 +8054,9 @@ static MY_COLLATION_HANDLER my_collation_utf8mb4_general_nopad_ci_handler=
my_strcasecmp_utf8mb4,
my_instr_mb,
my_hash_sort_utf8mb4_nopad,
- my_propagate_complex
+ my_propagate_complex,
+ my_min_str_mb_simple_nopad,
+ my_max_str_mb_simple
};
@@ -8051,7 +8072,9 @@ static MY_COLLATION_HANDLER my_collation_utf8mb4_nopad_bin_handler =
my_strcasecmp_mb_bin,
my_instr_mb,
my_hash_sort_mb_nopad_bin,
- my_propagate_simple
+ my_propagate_simple,
+ my_min_str_mb_simple_nopad,
+ my_max_str_mb_simple
};
diff --git a/strings/ctype-win1250ch.c b/strings/ctype-win1250ch.c
index a53a9768fde..689b20b8936 100644
--- a/strings/ctype-win1250ch.c
+++ b/strings/ctype-win1250ch.c
@@ -42,6 +42,8 @@
#include "strings_def.h"
#include <m_ctype.h>
+#include "ctype-simple.h"
+
#else
@@ -671,7 +673,7 @@ my_like_range_win1250ch(CHARSET_INFO *cs __attribute__((unused)),
}
-static MY_COLLATION_HANDLER my_collation_czech_ci_handler =
+static MY_COLLATION_HANDLER my_collation_czech_cs_handler =
{
NULL, /* init */
my_strnncoll_win1250ch,
@@ -683,11 +685,13 @@ static MY_COLLATION_HANDLER my_collation_czech_ci_handler =
my_strcasecmp_8bit,
my_instr_simple,
my_hash_sort_simple,
- my_propagate_simple
+ my_propagate_simple,
+ my_min_str_8bit_simple,
+ my_max_str_8bit_simple
};
-struct charset_info_st my_charset_cp1250_czech_ci =
+struct charset_info_st my_charset_cp1250_czech_cs =
{
34,0,0, /* number */
MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_CSSORT|
@@ -712,12 +716,12 @@ struct charset_info_st my_charset_cp1250_czech_ci =
1, /* mbminlen */
1, /* mbmaxlen */
0, /* min_sort_char */
- 0, /* max_sort_char */
+ 0xFF, /* max_sort_char */
' ', /* pad char */
0, /* escape_with_backslash_is_dangerous */
2, /* levels_for_order */
&my_charset_8bit_handler,
- &my_collation_czech_ci_handler
+ &my_collation_czech_cs_handler
};
diff --git a/support-files/mysql.server.sh b/support-files/mysql.server.sh
index cbd6b472148..d2c824697d1 100644
--- a/support-files/mysql.server.sh
+++ b/support-files/mysql.server.sh
@@ -91,16 +91,15 @@ datadir_set=
#
# Use LSB init script functions for printing messages, if possible
-#
+# Include non-LSB RedHat init functions to make systemctl redirect work
+init_functions="/etc/init.d/functions"
lsb_functions="/lib/lsb/init-functions"
-if test -f $lsb_functions ; then
+if test -f $lsb_functions; then
. $lsb_functions
-else
- # Include non-LSB RedHat init functions to make systemctl redirect work
- init_functions="/etc/init.d/functions"
- if test -f $init_functions; then
- . $init_functions
- fi
+fi
+
+if test -f $init_functions; then
+ . $init_functions
log_success_msg()
{
echo " SUCCESS! $@"
diff --git a/unittest/strings/strings-t.c b/unittest/strings/strings-t.c
index 39e48a33627..2141d09c949 100644
--- a/unittest/strings/strings-t.c
+++ b/unittest/strings/strings-t.c
@@ -760,11 +760,264 @@ test_strcollsp()
}
+typedef struct
+{
+ size_t size;
+ size_t nchars;
+ LEX_CSTRING min;
+ LEX_CSTRING max;
+} MINMAX_PARAM;
+
+
+static MINMAX_PARAM minmax_param_latin1_swedish_ci[]=
+{
+ {0, 0, {CSTR("")}, {CSTR("")}},
+ {0, 1, {CSTR("")}, {CSTR("")}},
+ {0, 2, {CSTR("")}, {CSTR("")}},
+ {0, 3, {CSTR("")}, {CSTR("")}},
+ {1, 0, {CSTR("")}, {CSTR("")}},
+ {1, 1, {CSTR("\x00")}, {CSTR("\xFF")}},
+ {1, 2, {CSTR("\x00")}, {CSTR("\xFF")}},
+ {1, 3, {CSTR("\x00")}, {CSTR("\xFF")}},
+ {2, 0, {CSTR("")}, {CSTR("")}},
+ {2, 1, {CSTR("\x00")}, {CSTR("\xFF")}},
+ {2, 2, {CSTR("\x00\x00")}, {CSTR("\xFF\xFF")}},
+ {2, 3, {CSTR("\x00\x00")}, {CSTR("\xFF\xFF")}},
+ {3, 0, {CSTR("")}, {CSTR("")}},
+ {3, 1, {CSTR("\x00")}, {CSTR("\xFF")}},
+ {3, 2, {CSTR("\x00\x00")}, {CSTR("\xFF\xFF")}},
+ {3, 3, {CSTR("\x00\x00\x00")}, {CSTR("\xFF\xFF\xFF")}}
+};
+
+
+static MINMAX_PARAM minmax_param_latin1_nopad_bin[]=
+{
+ {0, 0, {CSTR("")}, {CSTR("")}},
+ {0, 1, {CSTR("")}, {CSTR("")}},
+ {0, 2, {CSTR("")}, {CSTR("")}},
+ {0, 3, {CSTR("")}, {CSTR("")}},
+ {1, 0, {CSTR("")}, {CSTR("")}},
+ {1, 1, {CSTR("")}, {CSTR("\xFF")}},
+ {1, 2, {CSTR("")}, {CSTR("\xFF")}},
+ {1, 3, {CSTR("")}, {CSTR("\xFF")}},
+ {2, 0, {CSTR("")}, {CSTR("")}},
+ {2, 1, {CSTR("")}, {CSTR("\xFF")}},
+ {2, 2, {CSTR("")}, {CSTR("\xFF\xFF")}},
+ {2, 3, {CSTR("")}, {CSTR("\xFF\xFF")}},
+ {3, 0, {CSTR("")}, {CSTR("")}},
+ {3, 1, {CSTR("")}, {CSTR("\xFF")}},
+ {3, 2, {CSTR("")}, {CSTR("\xFF\xFF")}},
+ {3, 3, {CSTR("")}, {CSTR("\xFF\xFF\xFF")}}
+};
+
+
+static MINMAX_PARAM minmax_param_utf8mb3_unicode_ci[]=
+{
+ {0, 0, {CSTR("")}, {CSTR("")}},
+ {0, 1, {CSTR("")}, {CSTR("")}},
+ {0, 2, {CSTR("")}, {CSTR("")}},
+ {0, 3, {CSTR("")}, {CSTR("")}},
+ {1, 0, {CSTR("")}, {CSTR("")}},
+ {1, 1, {CSTR("\x09")}, {CSTR("")}},
+ {1, 2, {CSTR("\x09")}, {CSTR("")}},
+ {1, 3, {CSTR("\x09")}, {CSTR("")}},
+ {2, 0, {CSTR("")}, {CSTR("")}},
+ {2, 1, {CSTR("\x09")}, {CSTR("")}},
+ {2, 2, {CSTR("\x09\x09")}, {CSTR("")}},
+ {2, 3, {CSTR("\x09\x09")}, {CSTR("")}},
+ {3, 0, {CSTR("")}, {CSTR("")}},
+ {3, 1, {CSTR("\x09")}, {CSTR("\xEF\xBF\xBF")}},
+ {3, 2, {CSTR("\x09\x09")}, {CSTR("\xEF\xBF\xBF")}},
+ {3, 3, {CSTR("\x09\x09\x09")}, {CSTR("\xEF\xBF\xBF")}},
+ {4, 0, {CSTR("")}, {CSTR("")}},
+ {4, 1, {CSTR("\x09")}, {CSTR("\xEF\xBF\xBF")}},
+ {4, 2, {CSTR("\x09\x09")}, {CSTR("\xEF\xBF\xBF")}},
+ {4, 3, {CSTR("\x09\x09\x09")}, {CSTR("\xEF\xBF\xBF")}},
+ {5, 0, {CSTR("")}, {CSTR("")}},
+ {5, 1, {CSTR("\x09")}, {CSTR("\xEF\xBF\xBF")}},
+ {5, 2, {CSTR("\x09\x09")}, {CSTR("\xEF\xBF\xBF")}},
+ {5, 3, {CSTR("\x09\x09\x09")}, {CSTR("\xEF\xBF\xBF")}},
+ {6, 0, {CSTR("")}, {CSTR("")}},
+ {6, 1, {CSTR("\x09")}, {CSTR("\xEF\xBF\xBF")}},
+ {6, 2, {CSTR("\x09\x09")}, {CSTR("\xEF\xBF\xBF\xEF\xBF\xBF")}},
+ {6, 3, {CSTR("\x09\x09\x09")}, {CSTR("\xEF\xBF\xBF\xEF\xBF\xBF")}},
+ {7, 0, {CSTR("")}, {CSTR("")}},
+ {7, 1, {CSTR("\x09")}, {CSTR("\xEF\xBF\xBF")}},
+ {7, 2, {CSTR("\x09\x09")}, {CSTR("\xEF\xBF\xBF\xEF\xBF\xBF")}},
+ {7, 3, {CSTR("\x09\x09\x09")}, {CSTR("\xEF\xBF\xBF\xEF\xBF\xBF")}},
+ {8, 0, {CSTR("")}, {CSTR("")}},
+ {8, 1, {CSTR("\x09")}, {CSTR("\xEF\xBF\xBF")}},
+ {8, 2, {CSTR("\x09\x09")}, {CSTR("\xEF\xBF\xBF\xEF\xBF\xBF")}},
+ {8, 3, {CSTR("\x09\x09\x09")}, {CSTR("\xEF\xBF\xBF\xEF\xBF\xBF")}},
+ {9, 0, {CSTR("")}, {CSTR("")}},
+ {9, 1, {CSTR("\x09")}, {CSTR("\xEF\xBF\xBF")}},
+ {9, 2, {CSTR("\x09\x09")}, {CSTR("\xEF\xBF\xBF\xEF\xBF\xBF")}},
+ {9, 3, {CSTR("\x09\x09\x09")}, {CSTR("\xEF\xBF\xBF\xEF\xBF\xBF\xEF\xBF\xBF")}},
+};
+
+
+#ifdef HAVE_CHARSET_big5
+static MINMAX_PARAM minmax_param_big5_chinese_ci[]=
+{
+ {0, 0, {CSTR("")}, {CSTR("")}},
+ {0, 1, {CSTR("")}, {CSTR("")}},
+ {0, 2, {CSTR("")}, {CSTR("")}},
+ {0, 3, {CSTR("")}, {CSTR("")}},
+ {1, 0, {CSTR("")}, {CSTR("")}},
+ {1, 1, {CSTR("\x00")}, {CSTR("")}},
+ {1, 2, {CSTR("\x00")}, {CSTR("")}},
+ {1, 3, {CSTR("\x00")}, {CSTR("")}},
+ {2, 0, {CSTR("")}, {CSTR("")}},
+ {2, 1, {CSTR("\x00")}, {CSTR("\xF9\xD5")}},
+ {2, 2, {CSTR("\x00\x00")}, {CSTR("\xF9\xD5")}},
+ {2, 3, {CSTR("\x00\x00")}, {CSTR("\xF9\xD5")}},
+ {3, 0, {CSTR("")}, {CSTR("")}},
+ {3, 1, {CSTR("\x00")}, {CSTR("\xF9\xD5")}},
+ {3, 2, {CSTR("\x00\x00")}, {CSTR("\xF9\xD5")}},
+ {3, 3, {CSTR("\x00\x00\x00")}, {CSTR("\xF9\xD5")}},
+ {4, 0, {CSTR("")}, {CSTR("")}},
+ {4, 1, {CSTR("\x00")}, {CSTR("\xF9\xD5")}},
+ {4, 2, {CSTR("\x00\x00")}, {CSTR("\xF9\xD5\xF9\xD5")}},
+ {4, 3, {CSTR("\x00\x00\x00")}, {CSTR("\xF9\xD5\xF9\xD5")}},
+ {5, 0, {CSTR("")}, {CSTR("")}},
+ {5, 1, {CSTR("\x00")}, {CSTR("\xF9\xD5")}},
+ {5, 2, {CSTR("\x00\x00")}, {CSTR("\xF9\xD5\xF9\xD5")}},
+ {5, 3, {CSTR("\x00\x00\x00")}, {CSTR("\xF9\xD5\xF9\xD5")}},
+ {6, 0, {CSTR("")}, {CSTR("")}},
+ {6, 1, {CSTR("\x00")}, {CSTR("\xF9\xD5")}},
+ {6, 2, {CSTR("\x00\x00")}, {CSTR("\xF9\xD5\xF9\xD5")}},
+ {6, 3, {CSTR("\x00\x00\x00")}, {CSTR("\xF9\xD5\xF9\xD5\xF9\xD5")}},
+ {7, 0, {CSTR("")}, {CSTR("")}},
+ {7, 1, {CSTR("\x00")}, {CSTR("\xF9\xD5")}},
+ {7, 2, {CSTR("\x00\x00")}, {CSTR("\xF9\xD5\xF9\xD5")}},
+ {7, 3, {CSTR("\x00\x00\x00")}, {CSTR("\xF9\xD5\xF9\xD5\xF9\xD5")}},
+ {8, 0, {CSTR("")}, {CSTR("")}},
+ {8, 1, {CSTR("\x00")}, {CSTR("\xF9\xD5")}},
+ {8, 2, {CSTR("\x00\x00")}, {CSTR("\xF9\xD5\xF9\xD5")}},
+ {8, 3, {CSTR("\x00\x00\x00")}, {CSTR("\xF9\xD5\xF9\xD5\xF9\xD5")}},
+ {9, 0, {CSTR("")}, {CSTR("")}},
+ {9, 1, {CSTR("\x00")}, {CSTR("\xF9\xD5")}},
+ {9, 2, {CSTR("\x00\x00")}, {CSTR("\xF9\xD5\xF9\xD5")}},
+ {9, 3, {CSTR("\x00\x00\x00")}, {CSTR("\xF9\xD5\xF9\xD5\xF9\xD5")}},
+};
+#endif
+
+#ifdef HAVE_CHARSET_cp1250
+static MINMAX_PARAM minmax_param_cp1250_czech_cs[]=
+{
+ {0, 0, {CSTR("")}, {CSTR("")}},
+ {0, 1, {CSTR("")}, {CSTR("")}},
+ {0, 2, {CSTR("")}, {CSTR("")}},
+ {0, 3, {CSTR("")}, {CSTR("")}},
+ {1, 0, {CSTR("")}, {CSTR("")}},
+ {1, 1, {CSTR("\x00")}, {CSTR("\xFF")}},
+ {1, 2, {CSTR("\x00")}, {CSTR("\xFF")}},
+ {1, 3, {CSTR("\x00")}, {CSTR("\xFF")}},
+ {2, 0, {CSTR("")}, {CSTR("")}},
+ {2, 1, {CSTR("\x00")}, {CSTR("\xFF")}},
+ {2, 2, {CSTR("\x00\x00")}, {CSTR("\xFF\xFF")}},
+ {2, 3, {CSTR("\x00\x00")}, {CSTR("\xFF\xFF")}},
+ {3, 0, {CSTR("")}, {CSTR("")}},
+ {3, 1, {CSTR("\x00")}, {CSTR("\xFF")}},
+ {3, 2, {CSTR("\x00\x00")}, {CSTR("\xFF\xFF")}},
+ {3, 3, {CSTR("\x00\x00\x00")}, {CSTR("\xFF\xFF\xFF")}}
+};
+#endif
+
+
+#ifdef HAVE_CHARSET_latin2
+static MINMAX_PARAM minmax_param_latin2_czech_cs[]=
+{
+ {0, 0, {CSTR("")}, {CSTR("")}},
+ {0, 1, {CSTR("")}, {CSTR("")}},
+ {0, 2, {CSTR("")}, {CSTR("")}},
+ {0, 3, {CSTR("")}, {CSTR("")}},
+ {1, 0, {CSTR("")}, {CSTR("")}},
+ {1, 1, {CSTR("\x00")}, {CSTR("\xAE")}},
+ {1, 2, {CSTR("\x00")}, {CSTR("\xAE")}},
+ {1, 3, {CSTR("\x00")}, {CSTR("\xAE")}},
+ {2, 0, {CSTR("")}, {CSTR("")}},
+ {2, 1, {CSTR("\x00")}, {CSTR("\xAE")}},
+ {2, 2, {CSTR("\x00\x00")}, {CSTR("\xAE\xAE")}},
+ {2, 3, {CSTR("\x00\x00")}, {CSTR("\xAE\xAE")}},
+ {3, 0, {CSTR("")}, {CSTR("")}},
+ {3, 1, {CSTR("\x00")}, {CSTR("\xAE")}},
+ {3, 2, {CSTR("\x00\x00")}, {CSTR("\xAE\xAE")}},
+ {3, 3, {CSTR("\x00\x00\x00")}, {CSTR("\xAE\xAE\xAE")}}
+};
+#endif
+
+
+static int test_minmax_str_one(CHARSET_INFO *cs,
+ const MINMAX_PARAM *params, size_t count)
+{
+ size_t i;
+ int failed_total= 0;
+ for (i= 0; i < count; i++)
+ {
+ int failed;
+ char min[32], hmin[64];
+ char max[32], hmax[64];
+ const MINMAX_PARAM *prm= &params[i];
+ size_t minlen= cs->coll->min_str(cs, (uchar *) min, prm->size,
+ prm->nchars);
+ size_t maxlen= cs->coll->max_str(cs, (uchar *) max, prm->size,
+ prm->nchars);
+ failed= minlen != prm->min.length || memcmp(min, prm->min.str, minlen) ||
+ maxlen != prm->max.length || memcmp(max, prm->max.str, maxlen);
+
+ str2hex(hmin, sizeof(hmin), min, minlen);
+ str2hex(hmax, sizeof(hmax), max, maxlen);
+ diag("%-32s %2d %2d %-10s %-10s%s",
+ cs->coll_name.str, (int) prm->size, (int) prm->nchars, hmin, hmax,
+ failed ? " FAILED" : "");
+ if (failed)
+ {
+ str2hex(hmin, sizeof(hmin), prm->min.str, prm->min.length);
+ str2hex(hmax, sizeof(hmax), prm->max.str, prm->max.length);
+ diag("%-40s %-10s %-10s EXPECTED", cs->coll_name.str, hmin, hmax);
+ }
+ failed_total+= failed;
+ }
+ return failed_total;
+}
+
+
+static int test_minmax_str()
+{
+ int failed= 0;
+ failed+= test_minmax_str_one(&my_charset_latin1_nopad_bin,
+ minmax_param_latin1_nopad_bin,
+ array_elements(minmax_param_latin1_nopad_bin));
+ failed+= test_minmax_str_one(&my_charset_latin1,
+ minmax_param_latin1_swedish_ci,
+ array_elements(minmax_param_latin1_swedish_ci));
+ failed+= test_minmax_str_one(&my_charset_utf8mb3_unicode_ci,
+ minmax_param_utf8mb3_unicode_ci,
+ array_elements(minmax_param_utf8mb3_unicode_ci));
+#ifdef HAVE_CHARSET_big5
+ failed+= test_minmax_str_one(&my_charset_big5_chinese_ci,
+ minmax_param_big5_chinese_ci,
+ array_elements(minmax_param_big5_chinese_ci));
+#endif
+#ifdef HAVE_CHARSET_cp1250
+ failed+= test_minmax_str_one(&my_charset_cp1250_czech_cs,
+ minmax_param_cp1250_czech_cs,
+ array_elements(minmax_param_cp1250_czech_cs));
+#endif
+#ifdef HAVE_CHARSET_latin2
+ failed+= test_minmax_str_one(&my_charset_latin2_czech_cs,
+ minmax_param_latin2_czech_cs,
+ array_elements(minmax_param_latin2_czech_cs));
+#endif
+ return failed;
+}
+
int main()
{
size_t i, failed= 0;
- plan(2);
+ plan(3);
diag("Testing my_like_range_xxx() functions");
for (i= 0; i < array_elements(charset_list); i++)
@@ -782,5 +1035,9 @@ int main()
failed= test_strcollsp();
ok(failed == 0, "Testing my_ci_strnncollsp()");
+ diag("Testing min_str() and max_str()");
+ failed= test_minmax_str();
+ ok(failed == 0, "Testing min_str() and max_str() functions");
+
return exit_status();
}