diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2021-09-30 11:01:07 +0300 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2021-09-30 11:01:07 +0300 |
commit | b36d6f92a865e519271925f68802d599e62cf26c (patch) | |
tree | 27c9bd08266f17aaa712d84f14bf41f657ad9fb3 | |
parent | 8dd4794c4e11b8790fadf0c203bcd118e7b755e8 (diff) | |
parent | a49e394399859b23ba609d0058b498cfa876cac4 (diff) | |
download | mariadb-git-b36d6f92a865e519271925f68802d599e62cf26c.tar.gz |
Merge 10.6 into 10.7
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= ¶ms[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(); } |