diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
deleted file mode 100644
index 7a34e193b3548..0000000000000
--- a/.github/pull_request_template.md
+++ /dev/null
@@ -1,51 +0,0 @@
-
-
-
-- [x] *The Jira issue number for this PR is: MDEV-______*
-
-
-## Description
-TODO: fill description here
-
-## Release Notes
-TODO: What should the release notes say about this change?
-Include any changed system variables, status variables or behaviour. Optionally list any https://mariadb.com/kb/ pages that need changing.
-
-## How can this PR be tested?
-
-TODO: modify the automated test suite to verify that the PR causes MariaDB to behave as intended.
-Consult the documentation on ["Writing good test cases"](https://mariadb.org/get-involved/getting-started-for-developers/writing-good-test-cases-mariadb-server).
-
-
-If the changes are not amenable to automated testing, please explain why not and carefully describe how to test manually.
-
-
-## Basing the PR against the correct MariaDB version
-- [ ] *This is a new feature or a refactoring, and the PR is based against the `main` branch.*
-- [ ] *This is a bug fix, and the PR is based against the earliest maintained branch in which the bug can be reproduced.*
-
-
-## PR quality check
-- [ ] I checked the [CODING_STANDARDS.md](https://github.com/MariaDB/server/blob/-/CODING_STANDARDS.md) file and my PR conforms to this where appropriate.
-- [ ] For any trivial modifications to the PR, I am ok with the reviewer making the changes themselves.
diff --git a/.github/workflows/label_recent_prs.yaml b/.github/workflows/label_recent_prs.yaml
new file mode 100644
index 0000000000000..b7c188f811a52
--- /dev/null
+++ b/.github/workflows/label_recent_prs.yaml
@@ -0,0 +1,78 @@
+name: Label recent pull requests
+
+on:
+ schedule:
+ - cron: "0 2 * * *" # 02:00 UTC daily
+ workflow_dispatch: # allow manual runs
+
+permissions:
+ contents: read
+ pull-requests: write
+ issues: write
+
+jobs:
+ label-prs:
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Auto-label PRs
+ env:
+ REPO: ${{ github.repository }}
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ run: |
+ REPO=MariaDB/server
+ set -euo pipefail
+
+ # List first 200 PRs lacking classification labels as JSON
+ gh pr list \
+ --repo "$REPO" \
+ --search 'is:pr AND -label:"External Contribution" AND -label:"MariaDB Foundation" AND -label:"MariaDB Corporation" AND -label:"Codership" AND created:>2025-11' \
+ --limit 200 \
+ -s all \
+ --json number,author \
+ --jq '.[]' |
+ while read -r pr; do
+ pr_number=$(echo "$pr" | jq -r '.number')
+ author=$(echo "$pr" | jq -r '.author.login')
+
+ echo "Evaluating PR #$pr_number by $author"
+
+ # Check if author is in the developers team
+ if gh api \
+ -H "Accept: application/vnd.github+json" \
+ "/orgs/MariaDB/teams/developers/members/$author" \
+ >/dev/null 2>&1; then
+ echo "Author is in developers team"
+ is_developer=1
+ else
+ is_developer=0
+ echo "Author is not in developers team"
+ fi
+ # Check if author is in the staff team
+ if gh api \
+ -H "Accept: application/vnd.github+json" \
+ "/orgs/MariaDB/teams/staff/members/$author" \
+ >/dev/null 2>&1; then
+ echo "Author is in staff team"
+ is_foundation=1
+ else
+ is_foundation=0
+ echo "Author is not in staff team"
+ fi
+
+ if [[ "$is_foundation" -ne 0 ]]; then
+ label="MariaDB Foundation"
+ else
+ if [[ "$is_developer" -ne 0 ]]; then
+ label="MariaDB Corporation"
+ else
+ label="External Contribution"
+ fi
+ fi
+
+ echo "Applying label [$label] to PR#[$pr_number] by [$author]"
+
+ gh issue edit "$pr_number" \
+ --repo "$REPO" \
+ --add-label "$label"
+ done
diff --git a/.github/workflows/windows-arm64.yml b/.github/workflows/windows-arm64.yml
index 26c9154a728c9..a061849cc25b1 100644
--- a/.github/workflows/windows-arm64.yml
+++ b/.github/workflows/windows-arm64.yml
@@ -48,4 +48,10 @@ jobs:
$env:PATH = "C:\Strawberry\perl\bin;$env:PATH;C:\Program Files (x86)\Windows Kits\10\Debuggers\arm64"
#Calculate parallel as 4 * number of processors
$parallel = 4 * [int]$env:NUMBER_OF_PROCESSORS
- perl bld\mysql-test\mysql-test-run.pl --force --parallel=$parallel --suite=main --mysqld=--loose-innodb-flush-log-at-trx-commit=2
+ # create case-sensitive directory to run tests in
+ $tmp = (Get-Item $env:TEMP).FullName
+ $tmp = $tmp -replace '\\','/'
+ $cidir = "$tmp/ci"
+ mkdir $cidir
+ fsutil file setCaseSensitiveInfo $cidir enable
+ perl bld\mysql-test\mysql-test-run.pl --force --parallel=$parallel --suite=main,innodb --vardir=$cidir/var --mysqld=--lower-case-table-names=0 --mysqld=--loose-innodb-flush-log-at-trx-commit=2 --mysqld=--debug-no-sync
diff --git a/.gitignore b/.gitignore
index 35700623da4ff..acc7d75c224ef 100644
--- a/.gitignore
+++ b/.gitignore
@@ -26,10 +26,12 @@ install_manifest*.txt
CPackConfig.cmake
CPackSourceConfig.cmake
CTestTestfile.cmake
+mariadb-plugin-columnstore.install.generated
Docs/INFO_BIN
Docs/INFO_SRC
Makefile
TAGS
+mariadb-plugin-columnstore.install.generated
Testing/
tmp/
VERSION.dep
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index c0e0fd349626c..043a68970ac70 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -530,14 +530,12 @@ fedora upgrade-from:
matrix:
# Get latest versions of all major versions
- UPGRADE_PATH:
- - "10.6>11.4"
- - "10.3"
- - "10.4"
- - "10.4.8" # Test unexpected table rebuilds as in https://jira.mariadb.org/browse/MDEV-28727
+ - "10.6>11.8"
- "10.5"
- "10.6"
- "10.11"
- "11.4"
+ - "11.8"
script:
- |
if [[ $UPGRADE_PATH == *">"* ]]; then
diff --git a/BUILD/SETUP.sh b/BUILD/SETUP.sh
index 5b02a8aaa24d7..3c4cf829b36e7 100755
--- a/BUILD/SETUP.sh
+++ b/BUILD/SETUP.sh
@@ -132,7 +132,7 @@ get_make_parallel_flag
SSL_LIBRARY=--with-ssl=system
if [ "x$warning_mode" = "xpedantic" ]; then
- warnings="-W -Wall -ansi -pedantic -Wno-long-long -Wno-unused -D_POSIX_SOURCE"
+ warnings="-W -Wall -ansi -pedantic -Wno-long-long -Wno-unused -Wno-format-truncation -D_POSIX_SOURCE"
c_warnings="$warnings"
cxx_warnings="$warnings -std=c++98"
# NOTE: warning mode should not influence optimize/debug mode.
diff --git a/BUILD/compile-pentium64-asan-max b/BUILD/compile-pentium64-asan-max
index cedf5254e59a6..f2ebc146b27c2 100755
--- a/BUILD/compile-pentium64-asan-max
+++ b/BUILD/compile-pentium64-asan-max
@@ -23,7 +23,7 @@ path=`dirname $0`
#
extra_flags="$pentium64_cflags $debug_cflags -lasan -O -g -fsanitize=address -USAFEMALLOC -UFORCE_INIT_OF_VARS -Wno-uninitialized -Wno-maybe-uninitialized -DMYSQL_SERVER_SUFFIX=-asan-max"
-extra_configs="$pentium_configs $debug_configs $valgrind_configs $max_configs $disable_asan_plugins"
+extra_configs="$pentium_configs $debug_configs $valgrind_configs $max_configs $disable_asan_plugins --with-asan=ON"
export LDFLAGS="-ldl"
. "$path/FINISH.sh"
diff --git a/BUILD/compile-pentium64-ubsan b/BUILD/compile-pentium64-ubsan
index c5459a1b2fc43..d14b2f9911537 100755
--- a/BUILD/compile-pentium64-ubsan
+++ b/BUILD/compile-pentium64-ubsan
@@ -31,7 +31,7 @@ path=`dirname $0`
# the destination
#
-extra_flags="$pentium64_cflags $debug_cflags -fsanitize=undefined -DWITH_UBSAN -Wno-conversion -Wno-uninitialized"
+extra_flags="$pentium64_cflags $debug_cflags -fsanitize=undefined -DWITH_UBSAN -Wno-conversion -Wno-uninitialized -Wno-unused-parameter"
extra_configs="$pentium_configs $debug_configs -DWITH_UBSAN=ON -DMYSQL_MAINTAINER_MODE=NO --without-spider"
. "$path/FINISH.sh"
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 560e7b87d33ed..e425ccd61d2e7 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -246,6 +246,10 @@ ENDIF()
OPTION(WITH_MSAN "Enable memory sanitizer" OFF)
IF (WITH_MSAN)
MY_CHECK_AND_SET_COMPILER_FLAG("-fsanitize=memory -fsanitize-memory-track-origins -U_FORTIFY_SOURCE")
+ IF (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER "20.0")
+ # workaround for https://github.com/llvm/llvm-project/issues/179605
+ SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -O1")
+ ENDIF()
IF(NOT (have_C__fsanitize_memory__fsanitize_memory_track_origins__U_FORTIFY_SOURCE
AND have_CXX__fsanitize_memory__fsanitize_memory_track_origins__U_FORTIFY_SOURCE))
MESSAGE(FATAL_ERROR "Compiler doesn't support -fsanitize=memory flags")
@@ -296,9 +300,13 @@ IF(CMAKE_C_COMPILER_ID STREQUAL "GNU" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -D_GLIBCXX_DEBUG -D_GLIBCXX_ASSERTIONS")
ENDIF()
-OPTION(ENABLE_GCOV "Enable gcov (debug, Linux builds only)" OFF)
+OPTION(ENABLE_GCOV "Enable gcov (debug, macOS and Linux builds only)" OFF)
IF (ENABLE_GCOV)
- MY_CHECK_AND_SET_COMPILER_FLAG("-DHAVE_gcov -fprofile-arcs -ftest-coverage -lgcov" DEBUG)
+ IF (CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
+ MY_CHECK_AND_SET_COMPILER_FLAG("--coverage" DEBUG)
+ ELSE()
+ MY_CHECK_AND_SET_COMPILER_FLAG("-DHAVE_gcov -fprofile-arcs -ftest-coverage -lgcov" DEBUG)
+ ENDIF()
ENDIF()
OPTION(WITHOUT_PACKED_SORT_KEYS "disable packed sort keys" OFF)
@@ -553,32 +561,8 @@ IF(SOURCE_REVISION OR
${PROJECT_BINARY_DIR}/include/source_revision.h )
ENDIF()
-CONFIGURE_FILE(
- ${CMAKE_SOURCE_DIR}/cmake/info_macros.cmake.in
- ${CMAKE_BINARY_DIR}/info_macros.cmake @ONLY)
-
-# Handle the "INFO_*" files.
-INCLUDE(${CMAKE_BINARY_DIR}/info_macros.cmake)
-# Source: This can be done during the cmake phase, all information is
-# available, but should be repeated on each "make" just in case someone
-# does "cmake ; make ; git pull ; make".
-CREATE_INFO_SRC(${CMAKE_BINARY_DIR}/Docs)
-ADD_CUSTOM_TARGET(INFO_SRC ALL
- COMMAND ${CMAKE_COMMAND} -P ${CMAKE_SOURCE_DIR}/cmake/info_src.cmake
- WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
-)
-# Build flags: This must be postponed to the make phase.
-ADD_CUSTOM_TARGET(INFO_BIN ALL
- COMMAND ${CMAKE_COMMAND} -P ${CMAKE_SOURCE_DIR}/cmake/info_bin.cmake
- WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
-)
-
INSTALL_DOCUMENTATION(README.md CREDITS COPYING THIRDPARTY COMPONENT Readme)
-# MDEV-6526 these files are not installed anymore
-#INSTALL_DOCUMENTATION(${CMAKE_BINARY_DIR}/Docs/INFO_SRC
-# ${CMAKE_BINARY_DIR}/Docs/INFO_BIN)
-
IF(UNIX)
INSTALL_DOCUMENTATION(Docs/INSTALL-BINARY COMPONENT Readme)
IF(WITH_WSREP)
diff --git a/CODING_STANDARDS.md b/CODING_STANDARDS.md
index 7c0b9e473c424..47c572408e01e 100644
--- a/CODING_STANDARDS.md
+++ b/CODING_STANDARDS.md
@@ -187,7 +187,7 @@ C file names use the `.c` extension, C++ files use the `.cc` extension and heade
### Language standards
-For pure-C files we use C99 (starting with 10.4.25) and for C++ we use C++11 (starting with 11.8.1).
+For pure-C files we use C99 (starting with 10.4.25) and for C++ we use C++17 (starting with 11.8.1).
The code need to be able to compile on multiple platforms using different compilers (for example: Windows / Linux, x86_64 / ARM).
### Line lengths
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index c6744bee19999..afceafb81729d 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -5,15 +5,15 @@ MariaDB Server has a vibrant community contributing in a wide range of areas. Th
### Engage online with other community members
---
- [MariaDB on Zulip](https://mariadb.zulipchat.com/)
-- [maria-developers mailing list](http://launchpad.net/~maria-developers)
-- [maria-discuss mailing list](http://launchpad.net/~maria-discuss)
-- [maria-docs mailing list](http://launchpad.net/~maria-docs)
-- The MariaDB Foundation and MariaDB Corporation have a presence on Reddit, Twitter and Facebook. See the [social media page](https://mariadb.com/kb/en/mariadb/social-media/).
+- [maria-developers mailing list](https://lists.mariadb.org/postorius/lists/developers.lists.mariadb.org/)
+- [maria-discuss mailing list](https://lists.mariadb.org/postorius/lists/discuss.lists.mariadb.org/)
+- [maria-docs mailing list](https://lists.mariadb.org/postorius/lists/docs.lists.mariadb.org/)
+- The MariaDB Foundation and MariaDB Corporation have a presence on Reddit, Twitter and Facebook. See the [social media page](https://mariadb.com/docs/general-resources/community/joining-the-community).
### Help document MariaDB
----
-- Contribute towards [documenting MariaDB Server](https://mariadb.com/kb/en/meta/writing-editing-library-articles/) and its ecosystem by adding new content or improving existing content.
-- [Translate](https://mariadb.com/kb/en/meta/translating-library-articles/) existing documentation.
+- Contribute towards [documenting MariaDB Server](https://mariadb.com/docs/general-resources/about/readme/contributing-documentation) and its ecosystem by adding new content or improving existing content.
+- [Translate](https://mariadb.com/docs/general-resources/about/readme/contributing-documentation) existing documentation.
### Help debug and develop MariaDB
-----
@@ -44,4 +44,4 @@ New contributors can ask questions any time, but we will provide immediate feedb
### Additional resources
----
- [MariaDB Foundation ](https://mariadb.org/)
- - [Knowledge Base](https://mariadb.com/kb/en/)
+ - [MariaDB Documentation](https://mariadb.com/docs/)
diff --git a/CREDITS b/CREDITS
index 42f1697f992bf..9363b3d685897 100644
--- a/CREDITS
+++ b/CREDITS
@@ -66,7 +66,7 @@ following services to the MariaDB community:
- Bug fixing in MariaDB (for bugs that affects a large part of the community)
- Building the official MariaDB binaries
- Maintaining https://mariadb.org
-- Documenting MariaDB in the MariaDB Knowledge Base https://mariadb.com/kb
+- Documenting MariaDB in the MariaDB Documentation https://mariadb.com/kb
To be able to do the above we need help from corporations and individuals!
diff --git a/Docs/mysql.info b/Docs/mysql.info
deleted file mode 100644
index 02692f341d3a0..0000000000000
--- a/Docs/mysql.info
+++ /dev/null
@@ -1,11 +0,0 @@
-MariaDB is in most aspects identical to MySQL.
-
-Differences between MySQL and MariaDB can be found at:
-https://mariadb.com/kb/en/mariadb-vs-mysql-features/
-https://mariadb.com/kb/en/mariadb-vs-mysql-compatibility/
-
-The MariaDB manual can be found at:
-https://mariadb.com/kb/
-
-The MySQL Reference Manual is available in various formats on
-http://dev.mysql.com/doc.
diff --git a/Docs/replication/binlog.md b/Docs/replication/binlog.md
new file mode 100644
index 0000000000000..cea6ac9e7e8b2
--- /dev/null
+++ b/Docs/replication/binlog.md
@@ -0,0 +1,151 @@
+# New binlog implementation
+
+This document describes the new binlog implementation that is enabled using
+the `--binlog-storage-engine` option.
+
+The new binlog uses a more efficient on-disk format that is integrated with
+the InnoDB write-ahead log. This provides two main benefits:
+
+1. The binlog will always be recovered into a consistent state after a crash. This makes it possible to use the options `--innodb-flush-log-at-trx-commit=0` or `--innodb-flush-log-at-trx-commit=2`, which can give a huge performance improvement depending on disk speed and transaction concurrency.
+2. When using the option `--innodb-flush-log-at-trx-commit=1`, commits are more efficient since there is no expensive two-phase commit between the binlog and the InnoDB storage engine.
+
+## Using the new binlog
+
+To use the new binlog, configure the server with the following two options:
+1. `log_bin`
+2. `binlog_storage_engine=innodb`
+
+Note that the `log_bin` option must be specified like that, without any argument; the option is not an on-off-switch.
+
+Optionally, the directory in which to store binlog files can be specified with `binlog_directory=
`. By default, the data directory is used.
+
+Note that using the new binlog is mutually exclusive with the traditional binlog format. Configuring an existing server to use the new binlog format will effectively ignore any old binlog files. This limitation may be relaxed in a future version of MariaDB.
+
+## Replicating with the new binlog
+
+Configuration of replication from a master using the new binlog is done in the usual way. Slaves must be configured to use Global Transaction ID (GTID) to connect to the master (this is the default). The old filename/offset-based replication position is not available when using the new binlog implementation on the master.
+
+## Working with the binlog files
+
+The binlog files will be written to the data directory (or to the directory configured with `--binlog-directory`). The files are named `binlog-000000.ibb`, `binlog-000001.ibb`, ... and so on.
+
+The size of each binlog file is determined by the value of `max_binlog_size` (by default 1 GB). The binlog files are pre-allocated, so they will always have the configured size, with the last one or two files being possibly partially empty. The exception is when the command `FLUSH BINARY LOGS` is used; then the last active binlog file will be truncated to the used part of it, and binlog writes will continue in the following file.
+
+The list of current binlog files can be obtained with the command `SHOW BINLOG EVENTS`. Note that there is no binlog index file (`.index`) like with the traditional binlog format, nor are there any GTID index files (`.idx`) or GTID state (`.state`) file (`.state`).
+
+Instead of the GTID index and state files, the new binlog periodically writes GTID *state records* into the binlog containing the equivalent information. When a slave connects to the master, as well as when the server starts up, the binlog will be scanned from the last GTID state record to find or recover the correct GTID position. The `--innodb-binlog-state-interval` configuration option controls the interval (in bytes) between writing a state record. Thus, this option can be increased to reduce the overhead of state records, or decreased to speed up finding the initial GTID position at slave connect. The overhead however is small either way, and normally there is little reason to change the default. The status variables `binlog_gtid_index_hit` and `binlog_gtid_index_miss` are not used with the new binlog implementation.
+
+Binlog files can be purged (removed) automatically after a configured time or disk space usage, provided they are no longer needed by active replication slaves or for possible crash recovery. This is configured using the options `binlog_expire_log_seconds`, `binlog_expire_log_days`, `max_binlog_total_size`, and `slave_connections_needed_for_purge`.
+
+The contents of binlog files can be inspected in two ways:
+1. From within the server, using the command `SHOW BINLOG EVENTS`.
+2. Independent of the server, using the `mariadb-binlog` command-line program.
+
+Unlike in the traditional binlog format, one binlog event can be stored in multiple different binlog files, and different parts of individual events can be interleaved with one another in each file. The `mariadb-binlog` program will coalesce the different parts of each event as necessary, so the output of the program is a consistent, non-interleaved stream of events. To obtain a correct seequnce of events across multiple binlog files, all binlog files should be passed to the `mariadb-binlog` program at once in correct order; this ensures that events that cross file boundaries are included in the output exactly once.
+
+When using the `--start-position` and `--stop-position` options of `mariadb-binlog`, it is recommended to use GTID positions. The event file offsets used in the tranditional binlog format are not used in the new binlog, and will mostly be reported as zero.
+
+The `--binlog-checksum` option is no longer used with the new binlog implementation. The binlog files are always checksummed, with a CRC32 at the end of each page. To have checksum of the data sent on the network between the master and the slave (in addition to the normal TCP checksums), use the `MASTER_SSL` option for `CHANGE MASTER` to make the connection use SSL.
+
+## Using the new binlog with mariadb-backup
+
+The `mariadb-backup` program will by default back up the binlog files together with the rest of the server data. This fixes a long-standing limitation of the old binlog that it is missing from backups made with `mariadb-backup`.
+
+The binlog files are backed up in a transactionally consistent way, just like other InnoDB data. This means that a restored backup can be used to setup a new slave simply by using the `MASTER_DEMOTE_TO_SLAVE=1` option of `CHANGE MASTER`.
+
+The server being backed up is not blocked during the copy of the binlog files; only `RESET MASTER`, `PURGE BINARY LOGS` and `FLUSH BINARY LOGS` are blocked by default. This blocking can be disabled with the option `--no-lock` option.
+
+To omit the binlog files from the backup (ie. to save space in the backup when the binlog files are known to be not needed), use the `--skip-binlog` option on both the `mariadb-backup --backup` and `mariadb-backup --prepare` step. Note that when binlog files are omitted from the backup, the restored server will behave as if `RESET MASTER` was run on it just at the point of the backup. Also note that any transactions that were prepared, but not yet committed, at the time of the backup will be rolled back when the restored server starts up for the first time.
+
+## `FLUSH BINARY LOGS`
+
+Binlog files are pre-allocated for efficiency. When binlog file N is filled up, any remainder event data continues in file N+1, and and empty file N+2 is pre-allocated in the background. This means that binlog files are always exactly `--max-binlog-size` bytes long; and if the server restarts, binlog writing continues at the point reached before shutdown.
+
+The exception is when the `FLUSH BINARY LOGS` command is run. This pads the current binlog file up to the next page boundary, truncates the file, and switches to the next file. This can thus leave the binlog file smaller than `--max-binlog-size` (but always a multiple of the binlog page size).
+
+The `FLUSH BINARY LOGS DELETE_DOMAIN_ID=N` can be used to remove an old domain id from the `@@gtid_binlog_pos`. This requires that the domain is not in use in any existing binlog files; a combination of running `FLUSH BINARY LOGS` and `PURGE BINARY LOGS TO` can help ensure this. If the domain id N is already deleted, a warning is issues but the `FLUSH BINARY LOGS` operation is still run (this is for consistency, but is different from the old binlog implementation, where the `FLUSH` is skipped if the domain id was already deleted.
+
+## Upgrading
+
+When switching an existing server to use the new binlog format, the old binlog files will not be available after the switch, as the two formats are mutually exclusive.
+
+If the old binlog files are not needed after the transition, no special actions are needed. Just stop the server and restart with the configuration `--log-bin --binlog-storage-engine=innodb`. The new binlog will start empty. The old binlog files can be removed manually afterwards.
+
+Optionally, note down the value of `@@binlog_gtid_state` and execute `SET GLOBAL binlog_gtid_state=` as the first thing after starting up, to preserve the GTID state. This can be used to migrate a replication setup. First stop all writes to the master, and let all slaves catch up. Then note down the value of `@@binlog_gtid_state`, restart the master with `--binlog-storage-engine=innodb`, and restore `@@binlog_gtid_state`. Then the slaves will be able to connect and continue from where they left off.
+
+Alternatively, live migration can be done by switching a slave first. Restart a slave with the new `binlog-storage-engine=innodb` option and let the slave replicate for a while until it has sufficient binlog data in the new binlog format. Then promote the slave as the new master. The other slaves can then be stopped, switched to the new binlog, and restarted, as convenient.
+
+When using the new binlog format for a new installation, nothing special is needed. Just configure `--binlog-storage-engine=innodb` on the new server installation.
+
+When the new binlog format is enabled on a master, the slaves should be upgraded to at least MariaDB version 12.3 first. The slave can be switched to the new binlog format without upgrading the master first. The master and slave can use the old or the new binlog format independently of one another.
+
+## Using the new binlog with 3rd-party programs
+
+The new binlog uses a different on-disk format than the traditional binlog. The format of individual replication events is the same; however the files stored on disk are page-based, and each page has some encapsulation of event data to support splitting events in multiple pieces etc.
+
+This means that existing 3rd-party programs that read the binlog files directly will need to be modified to support the new format. Until then, such programs will require using the traditional binlog format.
+
+The protocol for reading binlog data from a running server (eg. for a connecting slave) is however mostly unchanged. This means existing programs that read binlog events from a running server may be able to function unmodified with the new binlog. Similarly, `mariadb-binlog` with the `--read-from-remote-server` option works as usual.
+
+A difference is that file offsets and file bondaries are no longer meaningful and no longer reported to the connecting client. There are no rotate events at the end of a file to specify the name of the following file, nor is there a new format description event at the start of each new file. Effectively, the binlog appears as a single unbroken stream of events to clients. The position from which to start receiving binlog events from the server should be specified using a GTID position; specifying a filename and file offset is not available.
+
+### Documentation of the binlog file format
+
+A binlog file consists of a sequence of pages. The page size is currently fixed at 16kByte. The size of a binlog file is set with the `--max-binlog-size` option. Each page has a CRC32 in the last 4 bytes; all remaining bytes are used for data.
+
+Numbers are stored in little-endian format. Some numbers are stored as compressed integers. A compressed integer consists of 1-9 bytes. The lower 3 bits determine the number of bytes used. The number of bytes is one more than the value in the lower 3 bits, except that a value of 7 means that 9 bytes are used. The value of the number stored is the little-endian value of the used bytes, right-shifted by 3.
+
+The first page in each binlog file is a file header page, with the following format:
+
+| Offset | Size | Description |
+| -----: | ---: | :---------- |
+| 0 | 4 | 4-byte MAGIC value 0x010dfefe to identify the file as a binlog file. |
+| 4 | 4 | The log-2 of the page size, currently fixed at 14 for a 16kByte page size. |
+| 8 | 4 | Major file version, currently 1. A new major version is not readable by older server versions. |
+| 12 | 4 | Minor file version, currently 0. New minor versions are backwards-compatible with older server versions. |
+| 16 | 8 | The file number (same as the number in the `binlog-NNNNNN.ibb` file name), for consistency check. |
+| 24 | 8 | The size of the file, in pages. |
+| 32 | 8 | The InnoDB LSN corresponding to the start of the file, used for crash recovery. |
+| 40 | 8 | The value of `--innodb-binlog-state-interval` used in the file. |
+| 48 | 8 | The file number of the earliest file into which this file may contain references into (such references occur when a large event group is split into multiple pieces, called out-of-band or oob records, and are used to locate all the pieces of event data from the final commit record). Used to prevent purging binlog files that contain data that may still be needed. |
+| 56 | 8 | The file number of the earliest file containing pending XA transactions that may still be active. |
+| 64 | 448 | Unused. |
+| 512 | 4 | Extra CRC32. This is used for future expansion to support configurable binlog page size. The header page can be read and checksummed as a 512-byte page, after which the real page size can be determined from the value at offset 4. |
+
+Remaining pages in the file are data pages. Data is structured as a sequence of *records*; each record consists of one or more chunks. A page contains one or more chunks; a record can span multiple pages, but a chunk always fits within one page. Chunks are a minumum of 4 bytes long; any remaining 1-3 bytes of data in a page are filled with the byte 0xff. Unused bytes in a page are set to 0x00.
+
+A chunk consists of a *type byte*, two *length bytes* (little endian), and the *data bytes*. The length bytes count only the data bytes, so if the length bytes are 0x0001, then the total size of the chunk is 4 bytes.
+
+The high two bits of the type byte are used to collect chunks into records:
+- Bit 7 is clear for the first chunk in a record, and set for all following chunks in the record.
+- Bit 6 is set for the last chunk in a record, and clear for any prior chunks.
+
+These are the chunk types used:
+
+| Type | Description |
+| ---: | :---------- |
+| 0 | (not a real type, 0 is an unused byte and denotes end-of-file in the current binlog file). |
+| 1 | A commit record, containing binlog event data. First a compressed integer of the number of oob records referenced by the commit record, if any; then if non-zero, four more compressed integers of the file number and offset of the first and last such reference. This is followed by another similar 1 or 5 compressed integers, only used in the special case where transactional and non-transactional updates are mixed in a single event group. The remainder bytes are the payload data. |
+| 2 | This is a GTID state record, written every `--innodb-binlog-state-interval` bytes. It consists of a sequence of compressed integers. The first is the number of GTIDs in the GTID state stored in the record. The second is one more than the earliest file number containing possibly still active XA transactions (used for crash recovery), or 0 for none. After this comes N*3 compressed integers, each representing a GTID in the GTID state. |
+| 3 | This is an out-of-band (oob) data record. It is used to split large event groups into smaller pieces, organized as a forest of perfect binary trees. The record starts with 5 compressed integers: A node index (starts at 0 and increments for each oob record in an event group); the file number and offset of the left child oob node; and the file number and offset of the right child oob node. Remainder bytes are the payload event data. |
+| 4 | This is a filler record, it is used to pad out the last page of a binlog file which is truncated due to `FLUSH BINARY LOGS`. |
+| 5 | This is an XA PREPARE record, used for consistent crash recovery of user XA transactions. It starts with 1 byte counting the number of storage engines participating in the transaction. Then follows the XID (4 byte formatID; 1 byte gtrid length; 1 byte bqual length; and the characters of the XID name). Finally 5 compressed integers: the number of referenced oob nodes; the file number and offset of the first one; and the file number and offset of the last one. |
+| 6 | This is an XA complete record, used for recovery purposes for internal 2-phase commit transactions and user XA. The first byte is a type byte, which is 0 for commit and 1 for XA rollback. Then follows 6-134 bytes of the XID, in the same format as for the XA PREPARE record. |
+
+## Not supported
+
+A few things are not supported with the new binlog implementation. Some of
+these should be supported in a later version of MariaDB. Some of these are
+legacy stuff that fundamentally works poorly or is otherwise undesirable,
+and are intentionally removed in the new binlog implementation.
+
+- Old-style filename/offset replication positions are not available with the new binlog. Slaves must be configured to use GTID (this is the default). Event offsets are generally reported as zero. `MASTER_POS_WAIT()` is not available, `MASTER_GTID_WAIT()` should be used instead. Similarly, `BINLOG_GTID_POS()` is not available.
+- Using savepoints inside triggers is not supported. This is because of bugs and inconsistencies like in MDEV38465. Now executing a `SAVEPOINT` or `ROLLBACK TO SAVEPOINT` statement in a trigger will consistently error and roll back the entire statement.
+- Semi-synchronous replication is not supported in the first version. It will be supported as normal eventually using the `AFTER_COMMIT` option. The `AFTER_SYNC` option cannot be supported, as the expensive two-phase commit between binlog and engine is no longer needed (`AFTER_SYNC` waits for slave acknowledgement in the middle of the two-phase commit). Likewise, `--init-rpl-role` is not supported.
+- The new binlog implementation cannot be used with Galera.
+- In the initial version, only InnoDB is available as an engine for the binlog (`--binlog-storage-engine=innodb`). It the future, other transactional storage engines could implement storing the binlog themselves (performance is best when the binlog is implemented in the same engine as the tables that are updated).
+- The `sync_binlog` option is no longer needed and is effectively ignored. Since the binlog files are now crash-safe without needing any syncing. The durability of commits is now controlled solely by the `--innodb-flush-log-at-trx-commit` option, which now applies to both binlog files and InnoDB table data.
+- The command `RESET MASTER TO` is not available with the new binlog.
+- The `--tc-heuristic-recover` option is not needed with the new binlog and cannot be used. Any pending prepared transactions will always be rolled back or committed to be consistent with the binlog. If the binlog is empty (ie. has been deleted manually), pending transactions will be rolled back.
+- Binlog encryption is not available. It is suggested to use filesystem-level encryption facilities of the operating system instead, and/or use SSL for the slave's connection to the master.
+- SHOW BINLOG EVENTS FROM will not give an error for a position that starts in the middle of an event group. Instead, it will start from the first GTID event following the position (or return empty, if the position is past the end).
diff --git a/README.md b/README.md
index f4fab1bd3a35a..7bbf3a3dadd97 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,7 @@
## MariaDB: The innovative open source database
-MariaDB was designed as a drop-in replacement of MySQL(R) with more
+MariaDB was designed as a drop-in replacement for MySQL(R) with more
features, new storage engines, fewer bugs, and better performance.
MariaDB is brought to you by the MariaDB Foundation and the MariaDB Corporation.
diff --git a/VERSION b/VERSION
index 16156243e5bfa..11568327cf958 100644
--- a/VERSION
+++ b/VERSION
@@ -1,4 +1,4 @@
-MYSQL_VERSION_MAJOR=12
+MYSQL_VERSION_MAJOR=13
MYSQL_VERSION_MINOR=0
-MYSQL_VERSION_PATCH=2
-SERVER_MATURITY=stable
+MYSQL_VERSION_PATCH=0
+SERVER_MATURITY=alpha
diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt
index 79e452f680137..1a56e55d5ac3c 100644
--- a/client/CMakeLists.txt
+++ b/client/CMakeLists.txt
@@ -64,8 +64,7 @@ TARGET_LINK_LIBRARIES(import_util PRIVATE pcre2-posix pcre2-8)
TARGET_INCLUDE_DIRECTORIES(import_util PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
MYSQL_ADD_EXECUTABLE(mariadb-import mysqlimport.cc)
-TARGET_INCLUDE_DIRECTORIES(mariadb-import PRIVATE ${CMAKE_SOURCE_DIR}/tpool)
-TARGET_LINK_LIBRARIES(mariadb-import PRIVATE tpool ${CLIENT_LIB} import_util)
+TARGET_LINK_LIBRARIES(mariadb-import PRIVATE tpool_min ${CLIENT_LIB} import_util)
MYSQL_ADD_EXECUTABLE(mariadb-upgrade mysql_upgrade.c COMPONENT Server)
@@ -78,7 +77,7 @@ TARGET_LINK_LIBRARIES(mariadb-show ${CLIENT_LIB})
MYSQL_ADD_EXECUTABLE(mariadb-plugin mysql_plugin.c)
TARGET_LINK_LIBRARIES(mariadb-plugin ${CLIENT_LIB})
-MYSQL_ADD_EXECUTABLE(mariadb-binlog mysqlbinlog.cc)
+MYSQL_ADD_EXECUTABLE(mariadb-binlog mysqlbinlog.cc mysqlbinlog-engine.cc)
TARGET_LINK_LIBRARIES(mariadb-binlog ${CLIENT_LIB} mysys_ssl)
MYSQL_ADD_EXECUTABLE(mariadb-admin mysqladmin.cc ../sql/password.c)
diff --git a/client/my_readline.h b/client/my_readline.h
index ec43d81f2c0a8..2ff5edcf31c58 100644
--- a/client/my_readline.h
+++ b/client/my_readline.h
@@ -34,9 +34,10 @@ typedef struct st_line_buffer
bool truncated;
} LINE_BUFFER;
-extern LINE_BUFFER *batch_readline_init(ulong max_size,FILE *file);
extern LINE_BUFFER *batch_readline_command(LINE_BUFFER *buffer, char * str);
extern char *batch_readline(LINE_BUFFER *buffer, bool binary_mode);
extern void batch_readline_end(LINE_BUFFER *buffer);
+extern bool init_line_buffer(LINE_BUFFER *buffer, File file, ulong size,
+ ulong max_size);
#endif /* CLIENT_MY_READLINE_INCLUDED */
diff --git a/client/mysql.cc b/client/mysql.cc
index 607773071be0f..3158d270ae7d5 100644
--- a/client/mysql.cc
+++ b/client/mysql.cc
@@ -1216,6 +1216,88 @@ inline int get_command_index(char cmd_char)
return -1;
}
+static LINE_BUFFER *batch_readline_init(ulong max_size, const char *path)
+{
+ LINE_BUFFER *line_buff;
+ File file;
+ MY_STAT input_file_stat;
+ char buff[FN_REFLEN + 512];
+
+ if (path)
+ {
+ file= my_open(path, O_RDONLY | O_BINARY, MYF(0));
+ if (file < 0 && my_errno == ENOENT && script_dir)
+ {
+ char full_path[FN_REFLEN];
+ strxnmov(full_path, sizeof(full_path)-1, script_dir, "/", path, NULL);
+ file= my_open(full_path, O_RDONLY | O_BINARY, MYF(0));
+ }
+ if (file < 0)
+ {
+#ifdef _WIN32
+ if (my_errno == EACCES && my_stat(path, &input_file_stat, MYF(0)) &&
+ MY_S_ISDIR(input_file_stat.st_mode))
+ my_snprintf(buff, sizeof(buff), "Can't read from a directory '%.*s'",
+ FN_REFLEN, path);
+ else
+#endif
+ my_snprintf(buff, sizeof(buff), "Failed to open file '%.*s', error: %d",
+ FN_REFLEN, path, my_errno);
+ put_info(buff, INFO_ERROR, 0);
+ return 0;
+ }
+ }
+ else
+ {
+ file= my_fileno(stdin);
+ }
+
+ if (my_fstat(file, &input_file_stat, MYF(0)))
+ {
+ my_snprintf(buff, sizeof(buff), "Failed to stat file '%.*s', error: %d",
+ FN_REFLEN, path ? path : "stdin", my_errno);
+ goto err1;
+ }
+
+ if (MY_S_ISDIR(input_file_stat.st_mode))
+ {
+ my_snprintf(buff, sizeof(buff), "Can't read from a directory '%.*s'",
+ FN_REFLEN, path ? path : "stdin");
+ goto err1;
+ }
+
+#ifndef _WIN32
+ if (MY_S_ISBLK(input_file_stat.st_mode))
+ {
+ my_snprintf(buff, sizeof(buff), "Can't read from a block device '%.*s'",
+ FN_REFLEN, path ? path : "stdin");
+ goto err1;
+ }
+#endif
+
+ if (!(line_buff= (LINE_BUFFER*) my_malloc(PSI_NOT_INSTRUMENTED,
+ sizeof(*line_buff),
+ MYF(MY_WME | MY_ZEROFILL))))
+ {
+ goto err;
+ }
+
+ if (init_line_buffer(line_buff, file, IO_SIZE, max_size))
+ {
+ my_free(line_buff);
+ goto err;
+ }
+
+ return line_buff;
+
+err1:
+ put_info(buff, INFO_ERROR, 0);
+err:
+ if (path)
+ my_close(file, MYF(0));
+ return 0;
+}
+
static int delimiter_index= -1;
static int charset_index= -1;
static int sandbox_index= -1;
@@ -1290,10 +1372,8 @@ int main(int argc,char *argv[])
}
if (status.batch && !status.line_buff &&
- !(status.line_buff= batch_readline_init(MAX_BATCH_BUFFER_SIZE, stdin)))
+ !(status.line_buff= batch_readline_init(MAX_BATCH_BUFFER_SIZE, NULL)))
{
- put_info("Can't initialize batch_readline - may be the input source is "
- "a directory or a block device.", INFO_ERROR, 0);
free_defaults(defaults_argv);
my_end(0);
exit(1);
@@ -1344,6 +1424,11 @@ int main(int argc,char *argv[])
mysql_thread_id(&mysql), server_version_string(&mysql));
put_info((char*) glob_buffer.ptr(),INFO_INFO);
put_info(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000"), INFO_INFO);
+#if SERVER_MATURITY_LEVEL < MariaDB_PLUGIN_MATURITY_STABLE
+ put_info("Help others discover MariaDB."
+ " Star it on GitHub: https://github.com/MariaDB/server\n",
+ INFO_INFO);
+#endif
}
#ifdef HAVE_READLINE
@@ -1409,9 +1494,7 @@ int main(int argc,char *argv[])
if (opt_outfile)
end_tee();
mysql_end(0);
-#ifndef _lint
- DBUG_RETURN(0); // Keep compiler happy
-#endif
+ DBUG_RETURN(0);
}
sig_handler mysql_end(int sig)
@@ -2691,7 +2774,7 @@ static bool add_line(String &buffer, char *line, size_t line_length,
}
buffer.length(0);
}
- else if (!*ml_comment &&
+ else if (!*ml_comment && *ss_comment != SSC_HINT &&
(!*in_string &&
(inchar == '#' ||
(inchar == '-' && pos[1] == '-' &&
@@ -2912,7 +2995,9 @@ static void fix_history(String *final_command)
ptr++;
}
if (total_lines > 1)
- add_history(fixed_buffer.ptr());
+ {
+ add_history(fixed_buffer.c_ptr());
+ }
}
/*
@@ -3235,6 +3320,12 @@ static int reconnect(void)
}
#ifndef EMBEDDED_LIBRARY
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wvarargs"
+/* CONC-789 */
+#endif
+
static void status_info_cb(void *data, enum enum_mariadb_status_info type, ...)
{
va_list ap;
@@ -3250,6 +3341,10 @@ static void status_info_cb(void *data, enum enum_mariadb_status_info type, ...)
}
va_end(ap);
}
+
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
#else
#define mysql_optionsv(A,B,C,D) do { } while(0)
#endif
@@ -3533,8 +3628,6 @@ static int com_go(String *buffer, char *)
old_buffer.copy();
}
- /* Remove garbage for nicer messages */
- LINT_INIT_STRUCT(buff[0]);
remove_cntrl(*buffer);
if (buffer->is_empty())
@@ -4734,11 +4827,9 @@ static int com_connect(String *buffer, char *line)
static int com_source(String *, char *line)
{
char source_name[FN_REFLEN], *end, *param;
- char full_path[FN_REFLEN];
LINE_BUFFER *line_buff;
int error;
STATUS old_status;
- FILE *sql_file;
my_bool save_ignore_errors;
if (status.sandbox)
@@ -4758,27 +4849,10 @@ static int com_source(String *, char *line)
end--;
end[0]=0;
unpack_filename(source_name,source_name);
- /* open file name */
- if (!(sql_file = my_fopen(source_name, O_RDONLY | O_BINARY,MYF(0))))
- {
- if (script_dir)
- {
- snprintf(full_path, sizeof(full_path), "%s/%s", script_dir, source_name);
- sql_file = my_fopen(full_path, O_RDONLY | O_BINARY, MYF(0));
- }
- }
-
- if (!sql_file)
- {
- char buff[FN_REFLEN + 60];
- sprintf(buff, "Failed to open file '%s', error: %d", source_name, errno);
- return put_info(buff, INFO_ERROR, 0);
- }
- if (!(line_buff= batch_readline_init(MAX_BATCH_BUFFER_SIZE, sql_file)))
+ if (!(line_buff= batch_readline_init(MAX_BATCH_BUFFER_SIZE, source_name)))
{
- my_fclose(sql_file,MYF(0));
- return put_info("Can't initialize batch_readline", INFO_ERROR, 0);
+ return ignore_errors ? -1 : 1;
}
/* Save old status */
@@ -4797,7 +4871,7 @@ static int com_source(String *, char *line)
ignore_errors= save_ignore_errors;
status=old_status; // Continue as before
in_com_source= aborted= 0;
- my_fclose(sql_file,MYF(0));
+ my_close(line_buff->file, MYF(0));
batch_readline_end(line_buff);
/*
If we got an error during source operation, don't abort the client
diff --git a/client/mysqladmin.cc b/client/mysqladmin.cc
index 304e26afa3b4f..ef04f3d2938b0 100644
--- a/client/mysqladmin.cc
+++ b/client/mysqladmin.cc
@@ -285,9 +285,7 @@ get_one_option(const struct my_option *opt, const char *argument,
opt_verbose= 0;
break;
case OPT_CHARSETS_DIR:
-#if MYSQL_VERSION_ID > 32300
charsets_dir = argument;
-#endif
break;
case OPT_MYSQL_PROTOCOL:
if ((opt_protocol= find_type_with_warning(argument, &sql_protocol_typelib,
@@ -684,7 +682,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
}
if (maybe_disable_binlog(mysql))
return -1;
- sprintf(buff,"create database `%.*s`",FN_REFLEN,argv[1]);
+ snprintf(buff, sizeof(buff), "create database `%.*s`",FN_REFLEN,argv[1]);
if (mysql_query(mysql,buff))
{
my_printf_error(0,"CREATE DATABASE failed; error: '%-.200s'",
@@ -725,7 +723,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
if (opt_shutdown_wait_for_slaves)
{
- sprintf(buff, "SHUTDOWN WAIT FOR ALL SLAVES");
+ snprintf(buff, sizeof(buff), "SHUTDOWN WAIT FOR ALL SLAVES");
if (mysql_query(mysql, buff))
{
my_printf_error(0, "%s failed; error: '%-.200s'",
@@ -1128,7 +1126,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
}
else
crypted_pw[0]=0; /* No password */
- sprintf(buff,"set password='%s',sql_log_off=0",crypted_pw);
+ snprintf(buff, sizeof(buff), "set password='%s',sql_log_off=0",crypted_pw);
if (mysql_query(mysql,"set sql_log_off=1"))
{
@@ -1309,9 +1307,9 @@ static void usage(void)
my_print_help(my_long_options);
my_print_variables(my_long_options);
puts("\nWhere command is a one or more of: (Commands may be shortened)\n\
- create databasename Create a new database\n\
- debug Instruct server to write debug information to log\n\
- drop databasename Delete a database and all its tables\n\
+ create databasename Create a new database\n\
+ debug Instruct server to write debug information to log\n\
+ drop databasename Delete a database and all its tables\n\
extended-status Gives an extended status message from the server\n\
flush-all-statistics Flush all statistics tables\n\
flush-all-status Flush status and statistics\n\
@@ -1333,25 +1331,21 @@ static void usage(void)
flush-threads Flush the thread cache\n\
flush-user-statistics Flush user statistics\n\
flush-user-resources Flush user resources\n\
- kill id,id,... Kill mysql threads");
-#if MYSQL_VERSION_ID >= 32200
- puts("\
+ kill id,id,... Kill mysql threads\n\
password [new-password] Change old password to new-password in current format\n\
- old-password [new-password] Change old password to new-password in old format");
-#endif
- puts("\
- ping Check if mysqld is alive\n\
- processlist Show list of active threads in server\n\
- reload Reload grant tables\n\
- refresh Flush all tables and close and open logfiles\n\
- shutdown Take server down\n\
- status Gives a short status message from the server\n\
- start-all-slaves Start all slaves\n\
- start-slave Start slave\n\
- stop-all-slaves Stop all slaves\n\
- stop-slave Stop slave\n\
+ old-password [new-password] Change old password to new-password in old format\n\
+ ping Check if mysqld is alive\n\
+ processlist Show list of active threads in server\n\
+ reload Reload grant tables\n\
+ refresh Flush all tables and close and open logfiles\n\
+ shutdown Take server down\n\
+ status Gives a short status message from the server\n\
+ start-all-slaves Start all slaves\n\
+ start-slave Start slave\n\
+ stop-all-slaves Stop all slaves\n\
+ stop-slave Stop slave\n\
variables Prints variables available\n\
- version Get version info from server");
+ version Get version info from server");
}
@@ -1373,7 +1367,7 @@ static int drop_db(MYSQL *mysql, const char *db)
return -1;
}
}
- sprintf(name_buff,"drop database `%.*s`",FN_REFLEN,db);
+ snprintf(name_buff,sizeof(name_buff), "drop database `%.*s`",FN_REFLEN,db);
if (mysql_query(mysql,name_buff))
{
my_printf_error(0, "DROP DATABASE %s failed;\nerror: '%s'", error_flags,
diff --git a/client/mysqlbinlog-engine.cc b/client/mysqlbinlog-engine.cc
new file mode 100644
index 0000000000000..c67d5aa2d8a2b
--- /dev/null
+++ b/client/mysqlbinlog-engine.cc
@@ -0,0 +1,1185 @@
+/* Copyright (c) 2025, Kristian Nielsen.
+
+ 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 */
+
+/*
+ Code for reading engine-implemented binlog from the mysqlbinlog client
+ program.
+*/
+
+#include
+#include
+#include
+#include "client_priv.h"
+#include "mysqlbinlog-engine.h"
+#include "my_compr_int.h"
+#include "my_dir.h"
+
+
+const char *INNODB_BINLOG_MAGIC= "\xfe\xfe\x0d\x01";
+static constexpr uint32_t INNODB_BINLOG_FILE_VERS_MAJOR= 1;
+
+static uint32_t binlog_page_size;
+
+/*
+ Some code here is copied from storage/innobase/handler/innodb_binlog.cc and
+ storage/innodb_binlog/fsp/fsp_binlog.cc and modified for use in the
+ mysqlbinlog command-line client.
+
+ Normally it is desirable to share code rather than copy/modify it, but
+ special considerations apply here:
+
+ - Normally, it is desirable to share the code so that modifications to the
+ logic are automatically kept in sync between the two use cases. However
+ in the case of the binlog, non-backwards compatible changes are highly
+ undesirable, and having a separate reader implementation in mysqlbinlog
+ is actually useful to detect any unintended or non-desirable changes to
+ the format that prevent old code from reading it. The binlog files
+ should remain readable to old mysqlbinlog versions if at all possible,
+ as well as to any other 3rd-party readers.
+
+ - The main purpose of the code inside InnoDB is to very efficiently allow
+ reading of binlog data concurrently with active writing threads and
+ concurrently with page fifo asynchroneous flushing. In contrast, the
+ purpose of the mysqlclient code is to have a simple stand-alone command
+ line reader of the files. These two use cases are sufficiently
+ different, and the code frameworks used for storage/innobase/ and
+ client/ likewise sufficiently different, that code-sharing seems more
+ troublesome than beneficial here.
+*/
+
+static constexpr uint32_t BINLOG_PAGE_SIZE_MAX= 65536;
+#define BINLOG_PAGE_DATA 0
+#define BINLOG_PAGE_CHECKSUM 4
+#define BINLOG_PAGE_DATA_END BINLOG_PAGE_CHECKSUM
+
+#define BINLOG_NAME_BASE "binlog-"
+#define BINLOG_NAME_EXT ".ibb"
+
+enum fsp_binlog_chunk_types {
+ /* Zero means no data, effectively EOF. */
+ FSP_BINLOG_TYPE_EMPTY= 0,
+ /* A binlogged committed event group. */
+ FSP_BINLOG_TYPE_COMMIT= 1,
+ /* A binlog GTID state record. */
+ FSP_BINLOG_TYPE_GTID_STATE= 2,
+ /* Out-of-band event group data. */
+ FSP_BINLOG_TYPE_OOB_DATA= 3,
+ /* Dummy record, use to fill remainder of page (eg. FLUSH BINARY LOGS). */
+ FSP_BINLOG_TYPE_DUMMY= 4,
+ /* Must be one more than the last type. */
+ FSP_BINLOG_TYPE_END,
+
+ /* Padding data at end of page. */
+ FSP_BINLOG_TYPE_FILLER= 0xff
+};
+static constexpr uint32_t FSP_BINLOG_FLAG_BIT_CONT= 7;
+static constexpr uint32_t FSP_BINLOG_FLAG_CONT= (1 << FSP_BINLOG_FLAG_BIT_CONT);
+static constexpr uint32_t FSP_BINLOG_FLAG_BIT_LAST= 6;
+static constexpr uint32_t FSP_BINLOG_FLAG_LAST= (1 << FSP_BINLOG_FLAG_BIT_LAST);
+static constexpr uint32_t FSP_BINLOG_TYPE_MASK=
+ ~(FSP_BINLOG_FLAG_CONT | FSP_BINLOG_FLAG_LAST);
+static constexpr uint64_t ALLOWED_NESTED_RECORDS=
+ /* GTID STATE at start of page can occur in the middle of other record. */
+ ((uint64_t)1 << FSP_BINLOG_TYPE_GTID_STATE) |
+ /* DUMMY data at tablespace end can occur in the middle of other record. */
+ ((uint64_t)1 << FSP_BINLOG_TYPE_DUMMY)
+ ;
+
+
+static char binlog_dir[FN_REFLEN + 1];
+
+
+class chunk_reader_mysqlbinlog {
+public:
+ enum chunk_reader_status {
+ CHUNK_READER_ERROR= -1,
+ CHUNK_READER_EOF= 0,
+ CHUNK_READER_FOUND= 1
+ };
+
+ /*
+ Current state, can be obtained from save_pos() and later passed to
+ restore_pos().
+ */
+ struct saved_position {
+ /* Current position file. */
+ uint64_t file_no;
+ /* Current position page. */
+ uint32_t page_no;
+ /* Start of current chunk inside page. */
+ uint32_t in_page_offset;
+ /*
+ The length of the current chunk, once the chunk type has been read.
+ If 0, it means the chunk type (and length) has not yet been read.
+ */
+ uint32_t chunk_len;
+ /* The read position inside the current chunk. */
+ uint32_t chunk_read_offset;
+ uchar chunk_type;
+ /* When set, read will skip the current chunk, if any. */
+ bool skip_current;
+ /* Set while we are in the middle of reading a record. */
+ bool in_record;
+ } s;
+
+ /* Length of the currently open file, valid if cur_file_handle != -1. */
+ uint64_t cur_file_length;
+ /* Buffer for reading a page from a binlog file. */
+ uchar *page_buffer;
+ /* Open file handle to tablespace file_no, or -1. */
+ File cur_file_handle;
+ /*
+ Flag used to skip the rest of any partial chunk we might be starting in
+ the middle of.
+ */
+ bool skipping_partial;
+ /* If the s.file_no / s.page_no is loaded in the page buffer. */
+ bool page_loaded;
+
+ chunk_reader_mysqlbinlog();
+ void set_page_buf(uchar *in_page_buf) { page_buffer= in_page_buf; }
+ ~chunk_reader_mysqlbinlog();
+
+ /* Current type, or FSP_BINLOG_TYPE_FILLER if between records. */
+ uchar cur_type() { return (uchar)(s.chunk_type & FSP_BINLOG_TYPE_MASK); }
+ bool cur_is_cont() { return (s.chunk_type & FSP_BINLOG_FLAG_CONT) != 0; }
+ bool end_of_record() { return !s.in_record; }
+ bool is_end_of_page() noexcept
+ {
+ return s.in_page_offset >= binlog_page_size - (BINLOG_PAGE_DATA_END + 3);
+ }
+ bool is_end_of_file() noexcept
+ {
+ return current_pos() + (BINLOG_PAGE_DATA_END + 3) >= cur_file_length;
+ }
+ static int read_error_corruption(uint64_t file_no, uint64_t page_no,
+ const char *msg);
+ int read_error_corruption(const char *msg)
+ {
+ return read_error_corruption(s.file_no, s.page_no, msg);
+ }
+ enum chunk_reader_status fetch_current_page();
+ /*
+ Try to read max_len bytes from a record into buffer.
+
+ If multipage is true, will move across pages to read following
+ continuation chunks, if any, to try and read max_len total bytes. Only if
+ the record ends before max_len bytes is less amount of bytes returned.
+
+ If multipage is false, will read as much is available on one page (up to
+ max of max_len), and then return.
+
+ Returns number of bytes read, or -1 for error.
+ Returns 0 if the chunk_reader is pointing to start of a chunk at the end
+ of the current binlog (ie. end-of-file).
+ */
+ int read_data(uchar *buffer, int max_len, bool multipage);
+ /* Read the file header of current file_no. */
+ int parse_file_header();
+
+ /* Save current position, and restore it later. */
+ void save_pos(saved_position *out_pos) { *out_pos= s; }
+ void restore_pos(saved_position *pos);
+ void seek(uint64_t file_no, uint64_t offset);
+
+ /*
+ Make next read_data() skip any data from the current chunk (if any), and
+ start reading data only from the beginning of the next chunk. */
+ void skip_current() { if (s.in_record) s.skip_current= true; }
+ /*
+ Used initially, after seeking potentially into the middle of a (commit)
+ record, to skip any continuation chunks until we reach the start of the
+ first real record.
+ */
+ void skip_partial(bool skip) { skipping_partial= skip; }
+ uint64_t current_pos() {
+ return (s.page_no * binlog_page_size) + s.in_page_offset;
+ }
+ void set_fd(File fd);
+};
+
+
+class oob_reader_mysqlbinlog {
+ enum oob_states {
+ /* The initial state, about to visit the node for the first time. */
+ ST_initial,
+ /* State of leaf node while traversing the prior trees in the forest. */
+ ST_traversing_prior_trees,
+ /* State of non-leaf node while traversing its left sub-tree. */
+ ST_traversing_left_child,
+ /* State of non-leaf node while traversing its right sub-tree. */
+ ST_traversing_right_child,
+ /* State of node while reading out its data. */
+ ST_self
+ };
+
+ /*
+ Stack entry for one node currently taking part in post-order traversal.
+ We maintain a stack of pending nodes during the traversal, as the traversal
+ happens in a state machine rather than by recursion.
+ */
+ struct stack_entry {
+ /* Saved position after reading header. */
+ chunk_reader_mysqlbinlog::saved_position saved_pos;
+ /* The location of this node's OOB record. */
+ uint64_t file_no;
+ uint64_t offset;
+ /* Right child, to be traversed after left child. */
+ uint64_t right_file_no;
+ uint64_t right_offset;
+ /* Offset of real data in this node, after header. */
+ uint32_t header_len;
+ /* Amount of data read into rd_buf, and amount used to parse header. */
+ uint32_t rd_buf_len;
+ uint32_t rd_buf_sofar;
+ /* Current state in post-order traversal state machine. */
+ enum oob_states state;
+ /* Buffer for reading header. */
+ uchar rd_buf[5*COMPR_INT_MAX64];
+ /*
+ True when the node is reached using only left child pointers, false
+ otherwise. Used to identify the left-most leaf in a tree which points to
+ a prior tree that must be traversed first.
+ */
+ bool is_leftmost;
+ };
+ std::vectorstack;
+
+ /* State machine current state. */
+ enum oob_states state;
+
+public:
+ oob_reader_mysqlbinlog();
+ ~oob_reader_mysqlbinlog();
+
+ void start_traversal(uint64_t file_no, uint64_t offset);
+ bool oob_traversal_done() { return stack.empty(); }
+ int read_data(chunk_reader_mysqlbinlog *chunk_rd, uchar *buf, int max_len);
+
+private:
+ void push_state(enum oob_states state, uint64_t file_no, uint64_t offset,
+ bool is_leftmost);
+};
+
+
+class binlog_reader_innodb : public handler_binlog_reader {
+ enum reader_states {
+ ST_read_next_event_group, ST_read_oob_data, ST_read_commit_record
+ };
+
+ chunk_reader_mysqlbinlog chunk_rd;
+ oob_reader_mysqlbinlog oob_reader;
+ chunk_reader_mysqlbinlog::saved_position saved_commit_pos;
+
+ /* Out-of-band data to read after commit record, if any. */
+ uint64_t oob_count;
+ uint64_t oob_last_file_no;
+ uint64_t oob_last_offset;
+ /* Any secondary out-of-band data to be also read. */
+ uint64_t oob_count2;
+ uint64_t oob_last_file_no2;
+ uint64_t oob_last_offset2;
+ /*
+ The starting file_no. We stop once we've read the last record in this file
+ (which may span into the next file).
+ */
+ uint64_t start_file_no;
+ /* Buffer to hold a page read directly from the binlog file. */
+ uchar *page_buf;
+ /* Keep track of pending bytes in the rd_buf. */
+ uint32_t rd_buf_len;
+ uint32_t rd_buf_sofar;
+ /* State for state machine reading chunks one by one. */
+ enum reader_states state;
+
+ /* Used to read the header of the commit record. */
+ uchar rd_buf[5*COMPR_INT_MAX64];
+private:
+ int read_data(uchar *buf, uint32_t len);
+
+public:
+ binlog_reader_innodb();
+ virtual ~binlog_reader_innodb();
+ virtual int read_binlog_data(uchar *buf, uint32_t len) override;
+ virtual bool data_available() override;
+ virtual bool wait_available(THD *thd, const struct timespec *abstime) override;
+ virtual int init_gtid_pos(THD *thd, slave_connection_state *pos,
+ rpl_binlog_state_base *state) override;
+ virtual int init_legacy_pos(THD *thd, const char *filename,
+ ulonglong offset) override;
+ virtual void enable_single_file() override;
+ bool is_valid() { return page_buf != nullptr; }
+ bool init_from_fd_pos(File fd, ulonglong start_position);
+};
+
+
+static int
+read_page_mysqlbinlog(File fd, uchar *buf, uint32_t page_no) noexcept
+{
+ size_t read= my_pread(fd, buf, binlog_page_size,
+ (my_off_t)page_no * binlog_page_size, MYF(0));
+ int res= 1;
+ if (likely(read == binlog_page_size))
+ {
+ const uint32_t payload= (uint32_t)binlog_page_size - BINLOG_PAGE_CHECKSUM;
+ uint32_t crc32= uint4korr(buf + payload);
+ /* Allow a completely zero (empty) page as well. */
+ if (unlikely(crc32 != my_crc32c(0, buf, payload)) &&
+ (buf[0] != 0 || 0 != memcmp(buf, buf+1, binlog_page_size - 1)))
+ {
+ res= -1;
+ my_errno= EIO;
+ }
+ }
+ else if (read == (size_t)-1)
+ res= -1;
+ else
+ res= 0;
+
+ return res;
+}
+
+
+chunk_reader_mysqlbinlog::chunk_reader_mysqlbinlog()
+ : s { 0, 0, 0, 0, 0, FSP_BINLOG_TYPE_FILLER, false, false },
+ cur_file_length(0),
+ cur_file_handle((File)-1),
+ skipping_partial(false), page_loaded(false)
+{
+}
+
+
+chunk_reader_mysqlbinlog::~chunk_reader_mysqlbinlog()
+{
+ if (cur_file_handle >= (File)0)
+ my_close(cur_file_handle, MYF(0));
+}
+
+
+int
+chunk_reader_mysqlbinlog::read_error_corruption(uint64_t file_no, uint64_t page_no,
+ const char *msg)
+{
+ error("Corrupt InnoDB binlog found on page %" PRIu64 " in binlog number "
+ "%" PRIu64 ": %s", page_no, file_no, msg);
+ return -1;
+}
+
+
+int
+chunk_reader_mysqlbinlog::read_data(uchar *buffer, int max_len, bool multipage)
+{
+ uint32_t size;
+ int sofar= 0;
+
+read_more_data:
+ if (max_len == 0)
+ return sofar;
+
+ if (!page_loaded)
+ {
+ enum chunk_reader_status res= fetch_current_page();
+ if (res == CHUNK_READER_EOF)
+ return 0;
+ if (res == CHUNK_READER_ERROR)
+ return -1;
+ }
+
+ if (s.chunk_len == 0)
+ {
+ uchar type;
+ /*
+ This code gives warning "comparison of unsigned expression in ‘< 0’ is
+ always false" when BINLOG_PAGE_DATA is 0.
+
+ So use a static assert for now; if it ever triggers, replace it with this
+ code:
+
+ if (s.in_page_offset < BINLOG_PAGE_DATA)
+ s.in_page_offset= BINLOG_PAGE_DATA;
+ */
+ if (0)
+ static_assert(BINLOG_PAGE_DATA == 0,
+ "Replace static_assert with code from above comment");
+
+ /* Check for end-of-file. */
+ if ((s.page_no * binlog_page_size) + s.in_page_offset >= cur_file_length)
+ return sofar;
+
+ if (s.in_page_offset >= binlog_page_size - (BINLOG_PAGE_DATA_END + 3) ||
+ page_buffer[s.in_page_offset] == FSP_BINLOG_TYPE_FILLER)
+ {
+ DBUG_ASSERT(s.in_page_offset >= binlog_page_size - BINLOG_PAGE_DATA_END ||
+ page_buffer[s.in_page_offset] == FSP_BINLOG_TYPE_FILLER);
+ goto go_next_page;
+ }
+
+ type= page_buffer[s.in_page_offset];
+ if (type == 0)
+ return 0;
+
+ /*
+ Consistency check on the chunks. A record must consist in a sequence of
+ chunks of the same type, all but the first must have the
+ FSP_BINLOG_FLAG_BIT_CONT bit set, and the final one must have the
+ FSP_BINLOG_FLAG_BIT_LAST bit set.
+ */
+ if (!s.in_record)
+ {
+ if (type & FSP_BINLOG_FLAG_CONT && !s.skip_current)
+ {
+ if (skipping_partial)
+ {
+ s.chunk_len= page_buffer[s.in_page_offset + 1] |
+ ((uint32_t)page_buffer[s.in_page_offset + 2] << 8);
+ s.skip_current= true;
+ goto skip_chunk;
+ }
+ else
+ return read_error_corruption(s.file_no, s.page_no, "Binlog record "
+ "starts with continuation chunk");
+ }
+ }
+ else
+ {
+ if ((type ^ s.chunk_type) & FSP_BINLOG_TYPE_MASK)
+ {
+ /*
+ As a special case, we must allow a GTID state to appear in the
+ middle of a record.
+ */
+ if (((uint64_t)1 << (type & FSP_BINLOG_TYPE_MASK)) &
+ ALLOWED_NESTED_RECORDS)
+ {
+ s.chunk_len= page_buffer[s.in_page_offset + 1] |
+ ((uint32_t)page_buffer[s.in_page_offset + 2] << 8);
+ goto skip_chunk;
+ }
+ /* Chunk type changed in the middle. */
+ return read_error_corruption(s.file_no, s.page_no, "Binlog record missing "
+ "end chunk");
+ }
+ if (!(type & FSP_BINLOG_FLAG_CONT))
+ {
+ /* START chunk without END chunk. */
+ return read_error_corruption(s.file_no, s.page_no, "Binlog record missing "
+ "end chunk");
+ }
+ }
+
+ s.skip_current= false;
+ s.chunk_type= type;
+ s.in_record= true;
+ s.chunk_len= page_buffer[s.in_page_offset + 1] |
+ ((uint32_t)page_buffer[s.in_page_offset + 2] << 8);
+ s.chunk_read_offset= 0;
+ }
+
+ /* Now we have a chunk available to read data from. */
+ DBUG_ASSERT(s.chunk_read_offset < s.chunk_len);
+ if (s.skip_current &&
+ (s.chunk_read_offset > 0 || (s.chunk_type & FSP_BINLOG_FLAG_CONT)))
+ {
+ /*
+ Skip initial continuation chunks.
+ Used to be able to start reading potentially in the middle of a record,
+ ie. at a GTID state point.
+ */
+ s.chunk_read_offset= s.chunk_len;
+ }
+ else
+ {
+ size= std::min((uint32_t)max_len, s.chunk_len - s.chunk_read_offset);
+ memcpy(buffer, page_buffer + s.in_page_offset + 3 + s.chunk_read_offset, size);
+ buffer+= size;
+ s.chunk_read_offset+= size;
+ max_len-= size;
+ sofar+= size;
+ }
+
+ if (s.chunk_len > s.chunk_read_offset)
+ {
+ DBUG_ASSERT(max_len == 0 /* otherwise would have read more */);
+ return sofar;
+ }
+
+ /* We have read all of the chunk. Move to next chunk or end of the record. */
+skip_chunk:
+ s.in_page_offset+= 3 + s.chunk_len;
+ s.chunk_len= 0;
+ s.chunk_read_offset= 0;
+
+ if (s.chunk_type & FSP_BINLOG_FLAG_LAST)
+ {
+ s.in_record= false; /* End of record. */
+ s.skip_current= false;
+ }
+
+ if (s.in_page_offset >= binlog_page_size - (BINLOG_PAGE_DATA_END + 3) &&
+ (s.page_no * binlog_page_size) + s.in_page_offset < cur_file_length)
+ {
+go_next_page:
+ /* End of page reached, move to the next page. */
+ ++s.page_no;
+ page_loaded= false;
+ s.in_page_offset= 0;
+
+ if (cur_file_handle >= (File)0 &&
+ (s.page_no * binlog_page_size) >= cur_file_length)
+ {
+ /* Move to the next file. */
+ my_close(cur_file_handle, MYF(0));
+ cur_file_handle= (File)-1;
+ cur_file_length= ~(uint64_t)0;
+ ++s.file_no;
+ s.page_no= 1; /* Skip the header page. */
+ }
+ }
+
+ if (sofar > 0 && (!multipage || !s.in_record))
+ return sofar;
+
+ goto read_more_data;
+}
+
+
+oob_reader_mysqlbinlog::oob_reader_mysqlbinlog()
+{
+ /* Nothing. */
+}
+
+
+oob_reader_mysqlbinlog::~oob_reader_mysqlbinlog()
+{
+ /* Nothing. */
+}
+
+
+void
+oob_reader_mysqlbinlog::push_state(enum oob_states state, uint64_t file_no,
+ uint64_t offset, bool is_leftmost)
+{
+ stack_entry new_entry;
+ new_entry.state= state;
+ new_entry.file_no= file_no;
+ new_entry.offset= offset;
+ new_entry.is_leftmost= is_leftmost;
+ stack.emplace_back(std::move(new_entry));
+}
+
+
+void
+oob_reader_mysqlbinlog::start_traversal(uint64_t file_no, uint64_t offset)
+{
+ stack.clear();
+ push_state(ST_initial, file_no, offset, true);
+}
+
+
+/*
+ Read from out-of-band event group data.
+
+ Does a state-machine incremental traversal of the forest of perfect binary
+ trees of oob records in the event group. May read just the data available
+ on one page, thus returning less than the requested number of bytes (this
+ is to prefer to inspect each page only once, returning data page-by-page as
+ long as reader asks for at least a full page worth of data).
+*/
+int
+oob_reader_mysqlbinlog::read_data(chunk_reader_mysqlbinlog *chunk_rd,
+ uchar *buf, int len)
+{
+ stack_entry *e;
+ uint64_t chunk_idx;
+ uint64_t left_file_no;
+ uint64_t left_offset;
+ int res;
+ const uchar *p_end;
+ const uchar *p;
+ std::pair v_and_p;
+ int size;
+
+ if (stack.empty())
+ {
+ DBUG_ASSERT(0 /* Should not call when no more oob data to read. */);
+ return 0;
+ }
+
+again:
+ e= &(stack[stack.size() - 1]);
+ switch (e->state)
+ {
+ case ST_initial:
+ chunk_rd->seek(e->file_no, e->offset);
+ static_assert(sizeof(e->rd_buf) == 5*COMPR_INT_MAX64,
+ "rd_buf size must match code using it");
+ res= chunk_rd->read_data(e->rd_buf, 5*COMPR_INT_MAX64, true);
+ if (res < 0)
+ return -1;
+ if (chunk_rd->cur_type() != FSP_BINLOG_TYPE_OOB_DATA)
+ return chunk_rd->read_error_corruption("Wrong chunk type");
+ if (res == 0)
+ return chunk_rd->read_error_corruption("Unexpected EOF, expected "
+ "oob chunk");
+ e->rd_buf_len= res;
+ p_end= e->rd_buf + res;
+ v_and_p= compr_int_read(e->rd_buf);
+ p= v_and_p.second;
+ if (p > p_end)
+ return chunk_rd->read_error_corruption("Short chunk");
+ chunk_idx= v_and_p.first;
+ (void)chunk_idx;
+
+ v_and_p= compr_int_read(p);
+ p= v_and_p.second;
+ if (p > p_end)
+ return chunk_rd->read_error_corruption("Short chunk");
+ left_file_no= v_and_p.first;
+ v_and_p= compr_int_read(p);
+ p= v_and_p.second;
+ if (p > p_end)
+ return chunk_rd->read_error_corruption("Short chunk");
+ left_offset= v_and_p.first;
+
+ v_and_p= compr_int_read(p);
+ p= v_and_p.second;
+ if (p > p_end)
+ return chunk_rd->read_error_corruption("Short chunk");
+ e->right_file_no= v_and_p.first;
+ v_and_p= compr_int_read(p);
+ p= v_and_p.second;
+ if (p > p_end)
+ return chunk_rd->read_error_corruption("Short chunk");
+ e->right_offset= v_and_p.first;
+ e->rd_buf_sofar= (uint32_t)(p - e->rd_buf);
+ if (left_file_no == 0 && left_offset == 0)
+ {
+ /* Leaf node. */
+ if (e->is_leftmost && !(e->right_file_no == 0 && e->right_offset == 0))
+ {
+ /* Traverse the prior tree(s) in the forst. */
+ e->state= ST_traversing_prior_trees;
+ chunk_rd->save_pos(&e->saved_pos);
+ push_state(ST_initial, e->right_file_no, e->right_offset, true);
+ }
+ else
+ e->state= ST_self;
+ }
+ else
+ {
+ e->state= ST_traversing_left_child;
+ chunk_rd->save_pos(&e->saved_pos);
+ push_state(ST_initial, left_file_no, left_offset, e->is_leftmost);
+ }
+ goto again;
+
+ case ST_traversing_prior_trees:
+ chunk_rd->restore_pos(&e->saved_pos);
+ e->state= ST_self;
+ goto again;
+
+ case ST_traversing_left_child:
+ e->state= ST_traversing_right_child;
+ push_state(ST_initial, e->right_file_no, e->right_offset, false);
+ goto again;
+
+ case ST_traversing_right_child:
+ chunk_rd->restore_pos(&e->saved_pos);
+ e->state= ST_self;
+ goto again;
+
+ case ST_self:
+ size= 0;
+ if (e->rd_buf_len > e->rd_buf_sofar)
+ {
+ /* Use any excess data from when the header was read. */
+ size= std::min((int)(e->rd_buf_len - e->rd_buf_sofar), len);
+ memcpy(buf, e->rd_buf + e->rd_buf_sofar, size);
+ e->rd_buf_sofar+= size;
+ len-= size;
+ buf+= size;
+ }
+
+ if (len > 0 && !chunk_rd->end_of_record())
+ {
+ res= chunk_rd->read_data(buf, len, false);
+ if (res < 0)
+ return -1;
+ size+= res;
+ }
+
+ if (chunk_rd->end_of_record())
+ {
+ /* This oob record done, pop the state. */
+ DBUG_ASSERT(!stack.empty());
+ stack.erase(stack.end() - 1, stack.end());
+ }
+ return size;
+
+ default:
+ DBUG_ASSERT(0);
+ return -1;
+ }
+}
+
+
+binlog_reader_innodb::binlog_reader_innodb()
+ : oob_count(0), oob_last_file_no(0), oob_last_offset(0),
+ oob_count2(0), oob_last_file_no2(0), oob_last_offset2(0),
+ start_file_no(~(uint64_t)0),
+ rd_buf_len(0), rd_buf_sofar(0), state(ST_read_next_event_group)
+{
+ page_buf= (uchar *)
+ my_malloc(PSI_NOT_INSTRUMENTED, BINLOG_PAGE_SIZE_MAX, MYF(MY_WME));
+ chunk_rd.set_page_buf(page_buf);
+}
+
+
+binlog_reader_innodb::~binlog_reader_innodb()
+{
+ my_free(page_buf);
+}
+
+
+void
+chunk_reader_mysqlbinlog::set_fd(File fd)
+{
+ if (cur_file_handle != (File)-1)
+ {
+ my_close(cur_file_handle, MYF(0));
+ cur_file_length= ~(uint64_t)0;
+ page_loaded= false;
+ }
+ cur_file_handle= fd;
+ my_off_t old_pos= my_tell(fd, MYF(0));
+ if (old_pos != (my_off_t)-1)
+ {
+ /* Will be ~0 if we cannot seek the file. */
+ cur_file_length= my_seek(fd, 0, SEEK_END, MYF(0));
+ my_seek(fd, old_pos, SEEK_SET, MYF(0));
+ }
+}
+
+
+bool
+binlog_reader_innodb::data_available()
+{
+ DBUG_ASSERT(0 /* Should not be used in mysqlbinlog. */);
+ return true;
+}
+
+
+bool
+binlog_reader_innodb::wait_available(THD *thd, const struct timespec *abstime)
+{
+ DBUG_ASSERT(0 /* Should not be used in mysqlbinlog. */);
+ return true;
+}
+
+
+int
+binlog_reader_innodb::init_gtid_pos(THD *thd, slave_connection_state *pos,
+ rpl_binlog_state_base *state)
+{
+ DBUG_ASSERT(0 /* Should not be used in mysqlbinlog. */);
+ return 1;
+}
+
+
+int
+binlog_reader_innodb::init_legacy_pos(THD *thd, const char *filename,
+ ulonglong offset)
+{
+ DBUG_ASSERT(0 /* Should not be used in mysqlbinlog. */);
+ return 1;
+}
+
+
+void
+binlog_reader_innodb::enable_single_file()
+{
+ DBUG_ASSERT(0 /* Should not be used in mysqlbinlog. */);
+}
+
+
+int
+binlog_reader_innodb::read_binlog_data(uchar *buf, uint32_t len)
+{
+ int res= read_data(buf, len);
+ return res;
+}
+
+
+bool
+binlog_reader_innodb::init_from_fd_pos(File fd, ulonglong start_position)
+{
+ chunk_rd.set_fd(fd);
+ if (chunk_rd.parse_file_header())
+ return true;
+ uint64_t prev_start_file_no= start_file_no;
+ start_file_no= chunk_rd.s.file_no;
+ if (prev_start_file_no != ~(uint64_t)0 &&
+ prev_start_file_no + 1 == chunk_rd.s.file_no)
+ {
+ /* Continuing in the file following the previous one. */
+ }
+ else
+ {
+ if (start_position < binlog_page_size)
+ start_position= binlog_page_size;
+ chunk_rd.seek(chunk_rd.s.file_no, (uint64_t)start_position);
+ chunk_rd.skip_partial(true);
+ }
+ return false;
+}
+
+
+int binlog_reader_innodb::read_data(uchar *buf, uint32_t len)
+{
+ int res;
+ const uchar *p_end;
+ const uchar *p;
+ std::pair v_and_p;
+ int sofar= 0;
+
+again:
+ switch (state)
+ {
+ case ST_read_next_event_group:
+ if (chunk_rd.s.file_no > start_file_no ||
+ (chunk_rd.s.file_no == start_file_no && chunk_rd.is_end_of_file()))
+ {
+ /*
+ We have read the entire file, return EOF.
+ If the user specified to read the following file also, we may
+ continue where we left in that file later.
+ */
+ return sofar;
+ }
+ static_assert(sizeof(rd_buf) == 5*COMPR_INT_MAX64,
+ "rd_buf size must match code using it");
+ res= chunk_rd.read_data(rd_buf, 5*COMPR_INT_MAX64, true);
+ if (res < 0)
+ return res;
+ if (res == 0)
+ return sofar;
+ if (chunk_rd.cur_type() != FSP_BINLOG_TYPE_COMMIT)
+ {
+ chunk_rd.skip_current();
+ goto again;
+ }
+ /* Found the start of a commit record. */
+ chunk_rd.skip_partial(false);
+
+ /* Read the header of the commit record to see if there's any oob data. */
+ rd_buf_len= res;
+ p_end= rd_buf + res;
+ v_and_p= compr_int_read(rd_buf);
+ p= v_and_p.second;
+ if (p > p_end)
+ return chunk_rd.read_error_corruption("Short chunk");
+ oob_count= v_and_p.first;
+ oob_count2= 0;
+
+ if (oob_count > 0)
+ {
+ /* Skip the pointer to first chunk. */
+ v_and_p= compr_int_read(p);
+ p= v_and_p.second;
+ if (p > p_end)
+ return chunk_rd.read_error_corruption("Short chunk");
+ v_and_p= compr_int_read(p);
+ p= v_and_p.second;
+ if (p > p_end)
+ return chunk_rd.read_error_corruption("Short chunk");
+
+ v_and_p= compr_int_read(p);
+ p= v_and_p.second;
+ if (p > p_end)
+ return chunk_rd.read_error_corruption("Short chunk");
+ oob_last_file_no= v_and_p.first;
+ v_and_p= compr_int_read(p);
+ p= v_and_p.second;
+ if (p > p_end)
+ return chunk_rd.read_error_corruption("Short chunk");
+ oob_last_offset= v_and_p.first;
+
+ /* Check for any secondary oob data. */
+ v_and_p= compr_int_read(p);
+ p= v_and_p.second;
+ if (p > p_end)
+ return chunk_rd.read_error_corruption("Short chunk");
+ oob_count2= v_and_p.first;
+
+ if (oob_count2 > 0)
+ {
+ /* Skip the pointer to first chunk. */
+ v_and_p= compr_int_read(p);
+ p= v_and_p.second;
+ if (p > p_end)
+ return chunk_rd.read_error_corruption("Short chunk");
+ v_and_p= compr_int_read(p);
+ p= v_and_p.second;
+ if (p > p_end)
+ return chunk_rd.read_error_corruption("Short chunk");
+
+ v_and_p= compr_int_read(p);
+ p= v_and_p.second;
+ if (p > p_end)
+ return chunk_rd.read_error_corruption("Short chunk");
+ oob_last_file_no2= v_and_p.first;
+ v_and_p= compr_int_read(p);
+ p= v_and_p.second;
+ if (p > p_end)
+ return chunk_rd.read_error_corruption("Short chunk");
+ oob_last_offset2= v_and_p.first;
+ }
+ }
+
+ rd_buf_sofar= (uint32_t)(p - rd_buf);
+ state= ST_read_commit_record;
+ goto again;
+
+ case ST_read_commit_record:
+ if (rd_buf_len > rd_buf_sofar)
+ {
+ /* Use any excess data from when the header was read. */
+ int size= std::min((int)(rd_buf_len - rd_buf_sofar), (int)len);
+ memcpy(buf, rd_buf + rd_buf_sofar, size);
+ rd_buf_sofar+= size;
+ len-= size;
+ buf+= size;
+ sofar+= size;
+ }
+
+ if (len > 0 && !chunk_rd.end_of_record())
+ {
+ res= chunk_rd.read_data(buf, len, false);
+ if (res < 0)
+ return -1;
+ len-= res;
+ buf+= res;
+ sofar+= res;
+ }
+
+ if (rd_buf_sofar == rd_buf_len && chunk_rd.end_of_record())
+ {
+ if (oob_count == 0)
+ {
+ state= ST_read_next_event_group;
+ if (len > 0 && !chunk_rd.is_end_of_page())
+ {
+ /*
+ Let us try to read more data from this page. The goal is to read
+ from each page only once, as long as caller passes in a buffer at
+ least as big as our page size. Though commit record header that
+ spans a page boundary or oob records can break this property.
+ */
+ goto again;
+ }
+ }
+ else
+ {
+ oob_reader.start_traversal(oob_last_file_no, oob_last_offset);
+ chunk_rd.save_pos(&saved_commit_pos);
+ state= ST_read_oob_data;
+ }
+ if (sofar == 0)
+ goto again;
+ }
+
+ return sofar;
+
+ case ST_read_oob_data:
+ res= oob_reader.read_data(&chunk_rd, buf, len);
+ if (res < 0)
+ return -1;
+ if (oob_reader.oob_traversal_done())
+ {
+ if (oob_count2 > 0)
+ {
+ /* Switch over to secondary oob data. */
+ oob_count= oob_count2;
+ oob_count2= 0;
+ oob_last_file_no= oob_last_file_no2;
+ oob_last_offset= oob_last_offset2;
+ oob_reader.start_traversal(oob_last_file_no, oob_last_offset);
+ state= ST_read_oob_data;
+ }
+ else
+ {
+ chunk_rd.restore_pos(&saved_commit_pos);
+ state= ST_read_next_event_group;
+ }
+ }
+ if (res == 0)
+ {
+ DBUG_ASSERT(0 /* Should have had oob_traversal_done() last time then. */);
+ if (sofar == 0)
+ goto again;
+ }
+ return sofar + res;
+
+ default:
+ DBUG_ASSERT(0);
+ return -1;
+ }
+}
+
+
+int
+chunk_reader_mysqlbinlog::parse_file_header()
+{
+ binlog_page_size= BINLOG_HEADER_PAGE_SIZE; // Until we get the real page size
+ if (read_page_mysqlbinlog(cur_file_handle, page_buffer, 0) <= 0)
+ {
+ error("Cannot read first page of InnoDB binlog file");
+ return -1;
+ }
+ const uint32_t payload= BINLOG_HEADER_PAGE_SIZE - BINLOG_PAGE_CHECKSUM;
+ uint32_t crc32= uint4korr(page_buffer + payload);
+ if (crc32 != my_crc32c(0, page_buffer, payload))
+ {
+ error("Invalid checksum on first page, cannot read binlog file");
+ return -1;
+ }
+ uint32_t vers_major= uint4korr(page_buffer + 8);
+ if (vers_major > INNODB_BINLOG_FILE_VERS_MAJOR)
+ {
+ error("Unsupported version of InnoDB binlog file, cannot read");
+ return -1;
+ }
+ binlog_page_size= 1 << uint4korr(page_buffer + 4);
+ s.file_no= uint8korr(page_buffer + 16);
+ return 0;
+}
+
+
+enum chunk_reader_mysqlbinlog::chunk_reader_status
+chunk_reader_mysqlbinlog::fetch_current_page()
+{
+ uint64_t offset;
+ page_loaded= false;
+ for (;;)
+ {
+ if (cur_file_handle < (File)0)
+ {
+ char filename[FN_REFLEN + 1];
+ MY_STAT stat_buf;
+
+ snprintf(filename, FN_REFLEN,
+ "%s/" BINLOG_NAME_BASE "%06" PRIu64 BINLOG_NAME_EXT,
+ binlog_dir, s.file_no);
+ cur_file_handle= my_open(filename, O_RDONLY | O_BINARY, MYF(MY_WME));
+ if (cur_file_handle < (File)0) {
+ cur_file_handle= (File)-1;
+ cur_file_length= ~(uint64_t)0;
+ /*
+ For mysqlbinlog where the user specifies the file, treat a missing
+ file as EOF, on the idea that we read as much as possible from what
+ the user supplied. But still use MY_WME in the my_open() to give
+ some indication that we stopped due to a missing file.
+ */
+ return errno == ENOENT ? CHUNK_READER_EOF : CHUNK_READER_ERROR;
+ }
+ if (my_fstat(cur_file_handle, &stat_buf, MYF(0))) {
+ error("Cannot stat() file '%s', errno: %d", filename, errno);
+ my_close(cur_file_handle, MYF(0));
+ cur_file_handle= (File)-1;
+ cur_file_length= ~(uint64_t)0;
+ return CHUNK_READER_ERROR;
+ }
+ cur_file_length= stat_buf.st_size;
+ }
+
+ offset= (s.page_no * binlog_page_size) | s.in_page_offset;
+ if (offset >= cur_file_length) {
+ /* End of this file, move to the next one. */
+ goto_next_file:
+ if (cur_file_handle >= (File)0)
+ {
+ my_close(cur_file_handle, MYF(0));
+ cur_file_handle= (File)-1;
+ cur_file_length= ~(uint64_t)0;
+ }
+ ++s.file_no;
+ s.page_no= 1; /* Skip the header page. */
+ continue;
+ }
+ break;
+ }
+
+ int res= read_page_mysqlbinlog(cur_file_handle, page_buffer, s.page_no);
+ if (res < 0)
+ return CHUNK_READER_ERROR;
+ if (res == 0)
+ goto goto_next_file;
+ page_loaded= true;
+ return CHUNK_READER_FOUND;
+}
+
+
+void
+chunk_reader_mysqlbinlog::restore_pos(chunk_reader_mysqlbinlog::saved_position *pos)
+{
+ if (cur_file_handle != (File)-1 && pos->file_no != s.file_no)
+ {
+ /* Seek to a different file than currently open, close it. */
+ my_close(cur_file_handle, MYF(0));
+ cur_file_handle= (File)-1;
+ cur_file_length= ~(uint64_t)0;
+ }
+ s= *pos;
+ page_loaded= false;
+}
+
+
+void
+chunk_reader_mysqlbinlog::seek(uint64_t file_no, uint64_t offset)
+{
+ saved_position pos {
+ file_no, (uint32_t)(offset / binlog_page_size),
+ (uint32_t)(offset % binlog_page_size),
+ 0, 0, FSP_BINLOG_TYPE_FILLER, false, false };
+ restore_pos(&pos);
+}
+
+
+bool
+open_engine_binlog(handler_binlog_reader *generic_reader,
+ ulonglong start_position,
+ const char *filename, IO_CACHE *opened_cache)
+{
+ binlog_reader_innodb *reader= (binlog_reader_innodb *)generic_reader;
+ if (!reader->is_valid())
+ {
+ error("Out of memory allocating page buffer");
+ return true;
+ }
+ static_assert(sizeof(binlog_dir) >= FN_REFLEN + 1,
+ "dirname_part() needs up to FN_REFLEN char buffer");
+ size_t dummy;
+ dirname_part(binlog_dir, filename, &dummy);
+ if (!strlen(binlog_dir))
+ strncpy(binlog_dir, ".", sizeof(binlog_dir) - 1);
+ return reader->init_from_fd_pos(dup(opened_cache->file), start_position);
+}
+
+
+handler_binlog_reader *
+get_binlog_reader_innodb()
+{
+ return new binlog_reader_innodb();
+}
diff --git a/client/mysqlbinlog-engine.h b/client/mysqlbinlog-engine.h
new file mode 100644
index 0000000000000..1438abeb48069
--- /dev/null
+++ b/client/mysqlbinlog-engine.h
@@ -0,0 +1,32 @@
+/* Copyright (c) 2025, Kristian Nielsen.
+
+ 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
+#include
+
+#include "handler_binlog_reader.h"
+
+
+static constexpr uint32_t BINLOG_HEADER_PAGE_SIZE= 512;
+extern const char *INNODB_BINLOG_MAGIC;
+
+extern handler_binlog_reader *get_binlog_reader_innodb();
+extern bool open_engine_binlog(handler_binlog_reader *reader,
+ ulonglong start_position,
+ const char *filename, IO_CACHE *opened_cache);
+
+
+/* Shared functions defined in mysqlbinlog.cc */
+extern void error(const char *format, ...) ATTRIBUTE_FORMAT(printf, 1, 2);
diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc
index 634ea945c1803..5393bd98e6f83 100644
--- a/client/mysqlbinlog.cc
+++ b/client/mysqlbinlog.cc
@@ -43,6 +43,8 @@
#include "sql_priv.h"
#include "sql_basic_types.h"
#include
+#include "handler_binlog_reader.h"
+#include "mysqlbinlog-engine.h"
#include "log_event.h"
#include "compat56.h"
#include "sql_common.h"
@@ -70,7 +72,6 @@ extern "C" unsigned char *mysql_net_store_length(unsigned char *packet, size_t l
Rpl_filter *binlog_filter= 0;
-#define BIN_LOG_HEADER_SIZE 4
#define PROBE_HEADER_LEN (EVENT_LEN_OFFSET+4)
/* Needed for Rpl_filter */
@@ -109,7 +110,7 @@ static const char *load_groups[]=
{ "mysqlbinlog", "mariadb-binlog", "client", "client-server", "client-mariadb",
0 };
-static void error(const char *format, ...) ATTRIBUTE_FORMAT(printf, 1, 2);
+void error(const char *format, ...) ATTRIBUTE_FORMAT(printf, 1, 2);
static void warning(const char *format, ...) ATTRIBUTE_FORMAT(printf, 1, 2);
static bool one_database=0, one_table=0, to_last_remote_log= 0, disable_log_bin= 0;
@@ -203,6 +204,14 @@ enum Exit_status {
OK_EOF,
};
+
+static enum Binlog_format {
+ ORIGINAL_BINLOG_FORMAT, INNODB_BINLOG_FORMAT
+} binlog_format= ORIGINAL_BINLOG_FORMAT;
+
+static handler_binlog_reader *engine_binlog_reader;
+
+
/**
Pointer to the last read Annotate_rows_log_event. Having read an
Annotate_rows event, we should not print it immediately because all
@@ -221,8 +230,17 @@ static void free_annotate_event()
}
}
-Log_event* read_remote_annotate_event(uchar* net_buf, ulong event_len,
- const char **error_msg)
+/**
+ The typical logic for an event read from a remote server is to register the
+ temp_buf of the net object to the event, such that each event will re-use
+ this same buffer. However, some events are re-referenced later, and their
+ memory/data is still needed. For example, Table_map_log_events are needed
+ for Partial_rows_log_events, as they are re-output for the last event in
+ the group.
+*/
+Log_event *read_self_managing_buffer_event_from_net(uchar *net_buf,
+ ulong event_len,
+ const char **error_msg)
{
uchar *event_buf;
Log_event* event;
@@ -309,17 +327,18 @@ class Load_log_processor
filename. The numerical suffix will be written to this position.
Note that there must be a least five bytes of allocated memory
after file_name_end.
+ @param[in] file_name_end_size Size of the memory area pointed to file_name_end.
@retval -1 Error (can't find new filename).
@retval >=0 Found file.
*/
- File create_unique_file(char *filename, char *file_name_end)
+ File create_unique_file(char *filename, char *file_name_end, size_t file_name_end_size)
{
File res;
/* If we have to try more than 1000 times, something is seriously wrong */
for (uint version= 0; version<1000; version++)
{
- sprintf(file_name_end,"-%x",version);
+ snprintf(file_name_end, file_name_end_size,"-%x",version);
if ((res= my_create(filename,0,
O_CREAT|O_EXCL|O_BINARY|O_WRONLY,MYF(0)))!=-1)
return res;
@@ -441,9 +460,9 @@ Exit_status Load_log_processor::process_first_event(const char *bname,
ptr= fname + target_dir_name_len;
memcpy(ptr,bname,blen);
ptr+= blen;
- ptr+= sprintf(ptr, "-%x", file_id);
+ ptr+= snprintf(ptr, full_len - (ptr - fname), "-%x", file_id);
- if ((file= create_unique_file(fname,ptr)) < 0)
+ if ((file= create_unique_file(fname,ptr,full_len - (ptr - fname))) < 0)
{
error("Could not construct local filename %s%s.",
target_dir_name,bname);
@@ -690,13 +709,15 @@ static bool print_base64(PRINT_EVENT_INFO *print_event_info, Log_event *ev)
{
/*
These events must be printed in base64 format, if printed.
+ In the original binlog format (no --binlog-storage-engine),
base64 format requires a FD event to be safe, so if no FD
event has been printed, we give an error. Except if user
passed --short-form, because --short-form disables printing
row events.
*/
- if (!print_event_info->printed_fd_event && !short_form &&
+ if (binlog_format == ORIGINAL_BINLOG_FORMAT &&
+ !print_event_info->printed_fd_event && !short_form &&
opt_base64_output_mode != BASE64_OUTPUT_DECODE_ROWS &&
opt_base64_output_mode != BASE64_OUTPUT_NEVER)
{
@@ -712,6 +733,66 @@ static bool print_base64(PRINT_EVENT_INFO *print_event_info, Log_event *ev)
return ev->print(result_file, print_event_info);
}
+static bool print_partial_row_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev)
+{
+ bool result= 0;
+ Partial_rows_log_event *prle= static_cast(ev);
+ if (prle->seq_no == 1)
+ {
+ /*
+ First Partial_row_event in the group, we can get our Rows_log_event
+ header info here for filtering.
+ */
+ const uchar *rows_data_begin= prle->ev_buffer_base + prle->start_offset;
+ Log_event_type event_type= (Log_event_type)(uchar)rows_data_begin[EVENT_TYPE_OFFSET];
+ uint8 const post_header_len= glob_description_event->post_header_len[event_type-1];
+ const uchar *table_id_ptr= rows_data_begin +
+ print_event_info->common_header_len +
+ RW_MAPID_OFFSET;
+
+ ulonglong table_id;
+ if (post_header_len == 6)
+ table_id= uint4korr(table_id_ptr);
+ else
+ table_id= (ulonglong) uint6korr(table_id_ptr);
+
+ /*
+ Cache the flags of the Rows_log_event to use it for the last
+ Partial_rows_log_event in the group
+ */
+ uint32 rows_ev_flags=
+ uint2korr(rows_data_begin + print_event_info->common_header_len +
+ post_header_len + RW_MAPID_OFFSET + RW_FLAGS_OFFSET);
+ print_event_info->partial_rows_rows_ev_flags= rows_ev_flags;
+
+ if (print_event_info->m_table_map_ignored.get_table(table_id))
+ print_event_info->deactivate_current_partial_rows_ev_group();
+ }
+
+ if (print_event_info->is_partial_rows_ev_group_active())
+ result= prle->print(result_file, print_event_info);
+
+ /* Last fragment */
+ if (prle->seq_no == prle->total_fragments)
+ {
+ /*
+ If this is the last Partial_rows_log_event in the group and the
+ underlying Rows_log_event is the last in the transaction, then it is safe
+ to clear the table_maps because they won't be used again.
+ */
+ if (print_event_info->partial_rows_rows_ev_flags &
+ Rows_log_event::STMT_END_F)
+ print_event_info->m_table_map_ignored.clear_tables();
+
+ /*
+ Active the next Partial_rows_log_event group as default
+ */
+ print_event_info->activate_current_partial_rows_ev_group();
+ }
+
+ return result;
+}
+
static bool print_row_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
ulonglong table_id, bool is_stmt_end)
@@ -755,6 +836,10 @@ static bool print_row_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
/*
Now is safe to clear ignored map (clear_tables will also
delete original table map events stored in the map).
+
+ Note print_event_info->m_table_map is not cleared here because it is used
+ when printing the number of events in the Rows_log_event. Instead, this
+ map is cleared when a new transaction is started.
*/
if (print_event_info->m_table_map_ignored.count() > 0)
print_event_info->m_table_map_ignored.clear_tables();
@@ -897,7 +982,7 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
/*
Run time estimation of the output window configuration.
- Do not validate GLLE information is start position is provided as a file
+ Do not validate GLLE information if start position is provided as a file
offset.
*/
if (ev_type == GTID_LIST_EVENT && ev->when)
@@ -969,6 +1054,13 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
print_event_info->deactivate_current_event_group();
}
+ /*
+ Start a new GTID event with a fresh table map state. This is because
+ table maps are cached for each transaction, e.g. for
+ Partial_rows_log_event printing.
+ */
+ print_event_info->m_table_map.clear_tables();
+
/*
Where we always ensure the initial binlog state is valid, we only
continually monitor the GTID stream for validity if we are in GTID
@@ -1187,13 +1279,22 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
case TABLE_MAP_EVENT:
{
Table_map_log_event *map= ((Table_map_log_event *)ev);
+ destroy_evt= FALSE;
+
if (shall_skip_database(map->get_db_name()) ||
shall_skip_table(map->get_table_name()))
{
print_event_info->m_table_map_ignored.set_table(map->get_table_id(), map);
- destroy_evt= FALSE;
goto end;
}
+
+ /*
+ Always keep the Table_map_log_event around in case a group of
+ Partial_rows_log_events is seen, where we will write the content of
+ the Table_map_log_event for the last fragment so it can be re-applied.
+ */
+ print_event_info->m_table_map.set_table(map->get_table_id(), map);
+
#ifdef WHEN_FLASHBACK_REVIEW_READY
/* Create review table for Flashback */
if (opt_flashback_review)
@@ -1360,6 +1461,12 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
destroy_evt= FALSE;
break;
}
+ case PARTIAL_ROW_DATA_EVENT:
+ {
+ if (print_partial_row_event(print_event_info, ev))
+ goto err;
+ break;
+ }
case START_ENCRYPTION_EVENT:
glob_description_event->start_decryption((Start_encryption_log_event*)ev);
/* fall through */
@@ -1755,7 +1862,7 @@ static void error_or_warning(const char *format, va_list args, const char *msg)
@param format Printf-style format string, followed by printf
varargs.
*/
-static void error(const char *format,...)
+void error(const char *format,...)
{
va_list args;
va_start(args, format);
@@ -1851,6 +1958,7 @@ static void cleanup()
delete_dynamic(&binlog_events);
delete_dynamic(&events_in_stmt);
}
+ delete engine_binlog_reader;
DBUG_VOID_RETURN;
}
@@ -2458,6 +2566,8 @@ static Exit_status dump_log_entries(const char* logname)
rc= (remote_opt ? dump_remote_log_entries(&print_event_info, logname) :
dump_local_log_entries(&print_event_info, logname));
+ print_event_info.m_table_map.clear_tables();
+
if (rc == ERROR_STOP)
return rc;
@@ -2533,6 +2643,7 @@ static Exit_status check_master_version()
if (position_gtid_filter &&
position_gtid_filter->get_num_start_gtids() > 0)
{
+ to_last_remote_log= TRUE;
char str_buf[256];
String query_str(str_buf, sizeof(str_buf), system_charset_info);
query_str.length(0);
@@ -2547,7 +2658,7 @@ static Exit_status check_master_version()
char buf[256];
rpl_gtid *start_gtid= &start_gtids[gtid_idx];
- sprintf(buf, "%u-%u-%llu",
+ snprintf(buf, sizeof(buf), "%u-%u-%llu",
start_gtid->domain_id, start_gtid->server_id,
start_gtid->seq_no);
query_str.append(buf, strlen(buf));
@@ -2573,6 +2684,7 @@ static Exit_status check_master_version()
case 10:
case 11:
case 12:
+ case 13:
glob_description_event= new Format_description_log_event(4);
break;
default:
@@ -2605,12 +2717,15 @@ static Exit_status handle_event_text_mode(PRINT_EVENT_INFO *print_event_info,
NET *net= &mysql->net;
DBUG_ENTER("handle_event_text_mode");
- if (net->read_pos[5] == ANNOTATE_ROWS_EVENT)
+ if (net->read_pos[5] == ANNOTATE_ROWS_EVENT ||
+ net->read_pos[5] == TABLE_MAP_EVENT)
{
- if (!(ev= read_remote_annotate_event(net->read_pos + 1, *len - 1,
- &error_msg)))
+ if (!(ev= read_self_managing_buffer_event_from_net(net->read_pos + 1,
+ *len - 1, &error_msg)))
{
- error("Could not construct annotate event object: %s", error_msg);
+ error("Could not construct %s event object: %s",
+ net->read_pos[5] == ANNOTATE_ROWS_EVENT ? "annotate" : "table_map",
+ error_msg);
DBUG_RETURN(ERROR_STOP);
}
}
@@ -2988,7 +3103,35 @@ static Exit_status check_header(IO_CACHE* file,
error("Failed reading header; probably an empty file.");
return ERROR_STOP;
}
- if (memcmp(header, BINLOG_MAGIC, sizeof(header)))
+ if (0 == memcmp(header, INNODB_BINLOG_MAGIC, sizeof(header)))
+ {
+ binlog_format= INNODB_BINLOG_FORMAT;
+ if (!engine_binlog_reader)
+ {
+ engine_binlog_reader= get_binlog_reader_innodb();
+ if (!engine_binlog_reader)
+ {
+ error("Out of memory setting up reader for InnoDB-implemented binlog.");
+ return ERROR_STOP;
+ }
+ }
+ /*
+ New engine-implemented binlog always does checksum verification on the
+ page level.
+ */
+ opt_verify_binlog_checksum= 0;
+ /*
+ New engine-implemented binlog does not contain format description
+ events.
+ */
+ goto end;
+ }
+ else if (header[0] == '\0' && !memcmp(header, header+1, sizeof(header)-1))
+ {
+ /* This is an empty InnoDB binlog file, pre-allocated but not yet used. */
+ return OK_EOF;
+ }
+ else if (memcmp(header, BINLOG_MAGIC, sizeof(header)))
{
error("File is not a binary log file.");
return ERROR_STOP;
@@ -3098,6 +3241,7 @@ static Exit_status check_header(IO_CACHE* file,
break;
}
}
+end:
my_b_seek(file, pos);
return OK_CONTINUE;
}
@@ -3135,8 +3279,19 @@ static Exit_status dump_local_log_entries(PRINT_EVENT_INFO *print_event_info,
my_close(fd, MYF(MY_WME));
return ERROR_STOP;
}
- if ((retval= check_header(file, print_event_info, logname)) != OK_CONTINUE)
+ retval= check_header(file, print_event_info, logname);
+ if (retval != OK_CONTINUE)
+ {
+ if (retval == OK_EOF)
+ {
+ /*
+ Empty InnoDB-implemented binlog file. Just skip it (but still
+ continue with any following files user specified).
+ */
+ retval= OK_CONTINUE;
+ }
goto end;
+ }
}
else
{
@@ -3162,8 +3317,13 @@ static Exit_status dump_local_log_entries(PRINT_EVENT_INFO *print_event_info,
error("Failed to init IO cache.");
return ERROR_STOP;
}
- if ((retval= check_header(file, print_event_info, logname)) != OK_CONTINUE)
+ retval= check_header(file, print_event_info, logname);
+ if (retval != OK_CONTINUE)
+ {
+ if (retval == OK_EOF)
+ retval= OK_CONTINUE;
goto end;
+ }
if (start_position)
{
/* skip 'start_position' characters from stdin */
@@ -3192,15 +3352,56 @@ static Exit_status dump_local_log_entries(PRINT_EVENT_INFO *print_event_info,
error("Failed reading from file.");
goto err;
}
+ if (binlog_format == INNODB_BINLOG_FORMAT)
+ {
+ if (open_engine_binlog(engine_binlog_reader, start_position, logname, file))
+ goto err;
+ }
for (;;)
{
char llbuff[21];
my_off_t old_off = my_b_tell(file);
int read_error;
+ Log_event* ev;
- Log_event* ev = Log_event::read_log_event(file, &read_error,
- glob_description_event,
- opt_verify_binlog_checksum);
+ if (binlog_format == INNODB_BINLOG_FORMAT)
+ {
+ String packet;
+ int res= engine_binlog_reader->read_log_event(&packet, 0, MAX_MAX_ALLOWED_PACKET);
+ if (res == LOG_READ_EOF)
+ {
+ ev= nullptr;
+ read_error= 0;
+ }
+ else if (res < 0)
+ {
+ ev= nullptr;
+ read_error= -1;
+ }
+ else
+ {
+ const char *errmsg= nullptr;
+ ev= Log_event::read_log_event((uchar *)packet.ptr(), packet.length(),
+ &errmsg, glob_description_event,
+ FALSE, FALSE);
+ if (!ev)
+ {
+ error("Error reading event: %s", errmsg);
+ read_error= -1;
+ }
+ else
+ {
+ ev->register_temp_buf((uchar *)packet.release(), true);
+ read_error= 0;
+ }
+ }
+ }
+ else
+ {
+ ev= Log_event::read_log_event(file, &read_error,
+ glob_description_event,
+ opt_verify_binlog_checksum);
+ }
if (!ev)
{
/*
@@ -3226,6 +3427,7 @@ static Exit_status dump_local_log_entries(PRINT_EVENT_INFO *print_event_info,
the size of the event, unless the event is encrypted.
*/
DBUG_ASSERT(
+ binlog_format == INNODB_BINLOG_FORMAT ||
((ev->get_type_code() == UNKNOWN_EVENT &&
((Unknown_log_event *) ev)->what == Unknown_log_event::ENCRYPTED)) ||
old_off + ev->data_written == my_b_tell(file));
diff --git a/client/mysqldump.cc b/client/mysqldump.cc
index 183ef09b30652..d86eda1a43e66 100644
--- a/client/mysqldump.cc
+++ b/client/mysqldump.cc
@@ -133,7 +133,7 @@ static my_bool verbose= 0, opt_no_create_info= 0, opt_no_data= 0, opt_no_data_m
opt_events= 0, opt_comments_used= 0,
opt_alltspcs=0, opt_notspcs= 0, opt_logging,
opt_header=0, opt_update_history= 0,
- opt_drop_trigger= 0, opt_dump_history= 0;
+ opt_drop_trigger= 0, opt_dump_history= 0, opt_wildcards= 0;
#define OPT_SYSTEM_ALL 1
#define OPT_SYSTEM_USERS 2
#define OPT_SYSTEM_PLUGINS 4
@@ -142,7 +142,7 @@ static my_bool verbose= 0, opt_no_create_info= 0, opt_no_data= 0, opt_no_data_m
#define OPT_SYSTEM_STATS 32
#define OPT_SYSTEM_TIMEZONES 64
static const char *opt_system_type_values[]=
- {"all", "users", "plugins", "udfs", "servers", "stats", "timezones"};
+ {"all", "users", "plugins", "udfs", "servers", "stats", "timezones", NullS};
static TYPELIB opt_system_types=CREATE_TYPELIB_FOR(opt_system_type_values);
static ulonglong opt_system= 0ULL;
static my_bool insert_pat_inited= 0, debug_info_flag= 0, debug_check_flag= 0,
@@ -327,8 +327,14 @@ static struct my_option my_long_options[] =
"Include all MariaDB specific create options.",
&create_options, &create_options, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
{"databases", 'B',
- "Dump several databases. Note the difference in usage; in this case no tables are given. All name arguments are regarded as database names. 'USE db_name;' will be included in the output.",
+ "Dump several databases. Note the difference in usage; in this case no "
+ "tables are given. All name arguments are regarded as database names. "
+ "'USE db_name;' will be included in the output.",
&opt_databases, &opt_databases, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"wildcards", 'L', "Usage of wildcards in the table/database name. Without "
+ "option \"databases\" wildcards are only recognized in table names. "
+ "With the \"databases\" option - in databases names.",
+ &opt_wildcards, &opt_wildcards, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
#ifdef DBUG_OFF
{"debug", '#', "This is a non-debug version. Catch this and exit.",
0,0, 0, GET_DISABLED, OPT_ARG, 0, 0, 0, 0, 0, 0},
@@ -441,7 +447,7 @@ static struct my_option my_long_options[] =
{"ignore-database", OPT_IGNORE_DATABASE,
"Do not dump the specified database. To specify more than one database to ignore, "
"use the directive multiple times, once for each database. Only takes effect "
- "when used together with --all-databases|-A",
+ "when used together with --all-databases or --wildcards --databases.",
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"ignore-table-data", OPT_IGNORE_DATA,
"Do not dump the specified table data. To specify more than one table "
@@ -492,7 +498,7 @@ static struct my_option my_long_options[] =
{"max_allowed_packet", 0,
"The maximum packet length to send to or receive from server.",
&opt_max_allowed_packet, &opt_max_allowed_packet, 0,
- GET_ULONG, REQUIRED_ARG, 24*1024*1024, 4096,
+ GET_ULONG, REQUIRED_ARG, 1024LL*1024*1024, 4096,
(longlong) 2L*1024L*1024L*1024L, 0, 1024, 0},
{"max-statement-time", 0,
"Max statement execution time. If unset, overrides server default with 0.",
@@ -1344,10 +1350,11 @@ static int get_options(int *argc, char ***argv)
my_progname_short);
return(EX_USAGE);
}
- if (ignore_database.records && !opt_alldbs)
+ if (ignore_database.records && !opt_alldbs && !(opt_wildcards && opt_databases))
{
fprintf(stderr,
- "%s: --ignore-database can only be used together with --all-databases.\n",
+ "%s: --ignore-database can only be used together with --all-databases"
+ " or --wildcards --databases.\n",
my_progname_short);
return(EX_USAGE);
}
@@ -1942,6 +1949,40 @@ static char *cover_definer_clause(const char *stmt_str,
return query_str;
}
+
+static char *format_fs_safe_filename(const char *from, char *to, size_t to_size)
+{
+ if (check_if_legal_tablename(from))
+ strxnmov(to, to_size - 1, from , "@@@", NULL);
+ else
+ {
+ uint errors, len;
+ len= my_convert(to, (uint32)(to_size - 1), &my_charset_filename,
+ from, (uint32) strlen(from), charset_info, &errors);
+ to[len]= 0;
+ }
+ return to;
+}
+
+static void format_fs_safe_output_dir(const char *db, char *out_dir, size_t out_size)
+{
+ DBUG_ASSERT(opt_dir);
+ char fs_safe_db[FN_REFLEN];
+ format_fs_safe_filename(db, fs_safe_db, sizeof(fs_safe_db));
+ my_snprintf(out_dir, out_size, "%s/%s", opt_dir, fs_safe_db);
+}
+
+static const char* build_path_for_table(char *to, const char *dir,
+ const char *table, const char *ext)
+{
+ char filename[FN_REFLEN], tmp_path[FN_REFLEN];
+ convert_dirname(tmp_path, dir, NULL);
+ my_load_path(tmp_path, tmp_path, NULL);
+ format_fs_safe_filename(table, filename, sizeof(filename));
+ return fn_format(to, filename, tmp_path, ext, MYF(MY_UNPACK_FILENAME));
+}
+
+
/*
Open a new .sql file to dump the table or view into
@@ -1957,18 +1998,17 @@ static char *cover_definer_clause(const char *stmt_str,
static FILE* open_sql_file_for_table(const char *db, const char* table, int flags)
{
FILE* res;
- char filename[FN_REFLEN], tmp_path[FN_REFLEN];
+ char filename[FN_REFLEN];
char out_dir_buf[FN_REFLEN];
char *out_dir= path;
if (opt_dir)
{
out_dir= out_dir_buf;
- my_snprintf(out_dir_buf, sizeof(out_dir_buf), "%s/%s", opt_dir, db);
+ format_fs_safe_output_dir(db, out_dir_buf, sizeof(out_dir_buf));
}
- convert_dirname(tmp_path, out_dir, NullS);
- res= my_fopen(fn_format(filename, table, tmp_path, ".sql", 4),
+ res= my_fopen(build_path_for_table(filename, out_dir, table, ".sql"),
flags, MYF(MY_WME));
return res;
}
@@ -2155,11 +2195,9 @@ static void unescape(FILE *file,char *pos, size_t length)
static my_bool test_if_special_chars(const char *str)
{
-#if MYSQL_VERSION_ID >= 32300
for ( ; *str ; str++)
if (!my_isvar(charset_info,*str) && *str != '$')
return 1;
-#endif
return 0;
} /* test_if_special_chars */
@@ -4290,12 +4328,12 @@ static void dump_table(const char *table, const char *db, const uchar *hash_key,
if (multi_file_output)
{
- char filename[FN_REFLEN], tmp_path[FN_REFLEN];
+ char filename[FN_REFLEN];
char out_dir_buf[FN_REFLEN];
char *out_dir= path;
if (!out_dir)
{
- my_snprintf(out_dir_buf, sizeof(out_dir_buf), "%s/%s", opt_dir, db);
+ format_fs_safe_output_dir(db, out_dir_buf, sizeof(out_dir_buf));
out_dir= out_dir_buf;
}
@@ -4303,9 +4341,7 @@ static void dump_table(const char *table, const char *db, const uchar *hash_key,
Convert the path to native os format
and resolve to the full filepath.
*/
- convert_dirname(tmp_path,out_dir,NullS);
- my_load_path(tmp_path, tmp_path, NULL);
- fn_format(filename, table, tmp_path, ".txt", MYF(MY_UNPACK_FILENAME));
+ build_path_for_table(filename, out_dir, table, ".txt");
/* Must delete the file that 'INTO OUTFILE' will write to */
my_delete(filename, MYF(0));
@@ -4314,7 +4350,6 @@ static void dump_table(const char *table, const char *db, const uchar *hash_key,
to_unix_path(filename);
/* now build the query string */
-
dynstr_append_checked(&query_string, "SELECT /*!40001 SQL_NO_CACHE */ ");
dynstr_append_checked(&query_string, select_field_names.str);
dynstr_append_checked(&query_string, " INTO OUTFILE '");
@@ -4459,6 +4494,11 @@ static void dump_table(const char *table, const char *db, const uchar *hash_key,
fprintf(md_result_file,"/*M!101100 SET @old_system_versioning_insert_history=@@session.system_versioning_insert_history, @@session.system_versioning_insert_history=1 */;\n");
check_io(md_result_file);
}
+ if (no_autocommit)
+ {
+ fprintf(md_result_file, "SET @OLD_AUTOCOMMIT=@@AUTOCOMMIT, @@AUTOCOMMIT=0;\n");
+ check_io(md_result_file);
+ }
if (opt_lock)
{
fprintf(md_result_file,"LOCK TABLES %s WRITE;\n", opt_quoted_table);
@@ -4479,11 +4519,6 @@ static void dump_table(const char *table, const char *db, const uchar *hash_key,
if (opt_xml)
print_xml_tag(md_result_file, "\t", "\n", "table_data", "name=", table,
NullS);
- if (no_autocommit)
- {
- fprintf(md_result_file, "set autocommit=0;\n");
- check_io(md_result_file);
- }
while ((row= mysql_fetch_row(res)))
{
@@ -4755,7 +4790,7 @@ static void dump_table(const char *table, const char *db, const uchar *hash_key,
}
if (no_autocommit)
{
- fprintf(md_result_file, "commit;\n");
+ fprintf(md_result_file, "COMMIT;\nSET AUTOCOMMIT=@OLD_AUTOCOMMIT;\n");
check_io(md_result_file);
}
if (versioned && !opt_xml && opt_dump_history)
@@ -5532,6 +5567,29 @@ static my_bool include_database(const char *hash_key)
}
+/* check database name if it's INFORMATION_SCHEMA or PERFORMANCE_SCHEMA. */
+static bool is_IS_or_PS(const char *schema_name)
+{
+ if (mysql_get_server_version(mysql) >= FIRST_INFORMATION_SCHEMA_VERSION &&
+ !cmp_database(schema_name, INFORMATION_SCHEMA_DB_NAME))
+ return TRUE;
+
+ if (mysql_get_server_version(mysql) >= FIRST_PERFORMANCE_SCHEMA_VERSION &&
+ !cmp_database(schema_name, PERFORMANCE_SCHEMA_DB_NAME))
+ return TRUE;
+
+ return FALSE;
+}
+
+
+/* check database name if it's SYS_SCHEMA. */
+static bool is_SyS(const char *schema_name)
+{
+ return (mysql_get_server_version(mysql) >= FIRST_SYS_SCHEMA_VERSION &&
+ !cmp_database(schema_name, SYS_SCHEMA_DB_NAME));
+}
+
+
static int dump_all_databases()
{
MYSQL_ROW row;
@@ -5542,18 +5600,9 @@ static int dump_all_databases()
return 1;
while ((row= mysql_fetch_row(tableres)))
{
- if (mysql_get_server_version(mysql) >= FIRST_INFORMATION_SCHEMA_VERSION &&
- !cmp_database(row[0], INFORMATION_SCHEMA_DB_NAME))
- continue;
-
- if (mysql_get_server_version(mysql) >= FIRST_PERFORMANCE_SCHEMA_VERSION &&
- !cmp_database(row[0], PERFORMANCE_SCHEMA_DB_NAME))
+ if (is_IS_or_PS(row[0]) || is_SyS(row[0]))
continue;
- if (mysql_get_server_version(mysql) >= FIRST_SYS_SCHEMA_VERSION &&
- !cmp_database(row[0], SYS_SCHEMA_DB_NAME))
- continue;
-
if (include_database(row[0]))
if (dump_all_tables_in_db(row[0]))
result=1;
@@ -5570,16 +5619,7 @@ static int dump_all_databases()
}
while ((row= mysql_fetch_row(tableres)))
{
- if (mysql_get_server_version(mysql) >= FIRST_INFORMATION_SCHEMA_VERSION &&
- !cmp_database(row[0], INFORMATION_SCHEMA_DB_NAME))
- continue;
-
- if (mysql_get_server_version(mysql) >= FIRST_PERFORMANCE_SCHEMA_VERSION &&
- !cmp_database(row[0], PERFORMANCE_SCHEMA_DB_NAME))
- continue;
-
- if (mysql_get_server_version(mysql) >= FIRST_SYS_SCHEMA_VERSION &&
- !cmp_database(row[0], SYS_SCHEMA_DB_NAME))
+ if (is_IS_or_PS(row[0]) || is_SyS(row[0]))
continue;
if (include_database(row[0]))
@@ -6187,11 +6227,7 @@ static int dump_selected_tables(char *db, char **table_names, int tables)
end= pos;
/* Can't LOCK TABLES in I_S / P_S, so don't try. */
- if (lock_tables &&
- !(mysql_get_server_version(mysql) >= FIRST_INFORMATION_SCHEMA_VERSION &&
- !cmp_database(db, INFORMATION_SCHEMA_DB_NAME)) &&
- !(mysql_get_server_version(mysql) >= FIRST_PERFORMANCE_SCHEMA_VERSION &&
- !cmp_database(db, PERFORMANCE_SCHEMA_DB_NAME)))
+ if (lock_tables && !is_IS_or_PS(db))
{
if (mysql_real_query(mysql, lock_tables_query.str,
(ulong)lock_tables_query.length-1))
@@ -6328,7 +6364,7 @@ const char fmt_gtid_pos[]= "%sSET GLOBAL gtid_slave_pos='%s';\n";
static int do_show_master_status(MYSQL *mysql_con, int consistent_binlog_pos,
int have_mariadb_gtid, int use_gtid,
- char *set_gtid_pos)
+ char *set_gtid_pos, size_t set_gtid_pos_size)
{
MYSQL_ROW row;
MYSQL_RES *UNINIT_VAR(master);
@@ -6403,7 +6439,7 @@ static int do_show_master_status(MYSQL *mysql_con, int consistent_binlog_pos,
"CHANGE-MASTER settings to the slave gtid state is printed "
"later in the file.\n");
}
- sprintf(set_gtid_pos, fmt_gtid_pos,
+ snprintf(set_gtid_pos, set_gtid_pos_size, fmt_gtid_pos,
(!use_gtid ? "-- " : comment_prefix), gtid_pos);
}
@@ -6455,7 +6491,7 @@ static int do_stop_slave_sql(MYSQL *mysql_con)
{
char query[160];
if (multi_source)
- sprintf(query, "STOP SLAVE '%.80s' SQL_THREAD", row[0]);
+ snprintf(query, sizeof(query), "STOP SLAVE '%.80s' SQL_THREAD", row[0]);
else
strmov(query, "STOP SLAVE SQL_THREAD");
@@ -6494,7 +6530,8 @@ static int add_slave_statements(void)
}
static int do_show_slave_status(MYSQL *mysql_con, int have_mariadb_gtid,
- int use_gtid, char* set_gtid_pos)
+ int use_gtid, char* set_gtid_pos,
+ size_t set_gtid_pos_size)
{
MYSQL_RES *UNINIT_VAR(slave);
MYSQL_ROW row;
@@ -6539,7 +6576,8 @@ static int do_show_slave_status(MYSQL *mysql_con, int have_mariadb_gtid,
"\n-- A corresponding to the below dump-slave "
"CHANGE-MASTER settings to the slave gtid state is printed "
"later in the file.\n");
- sprintf(set_gtid_pos, fmt_gtid_pos, gtid_comment_prefix, gtid_pos);
+ snprintf(set_gtid_pos, set_gtid_pos_size,
+ fmt_gtid_pos, gtid_comment_prefix, gtid_pos);
}
if (use_gtid)
print_comment(md_result_file, 0,
@@ -6615,7 +6653,8 @@ static int do_start_slave_sql(MYSQL *mysql_con)
{
char query[160];
if (multi_source)
- sprintf(query, "START SLAVE '%.80s' SQL_THREAD", row[0]);
+ snprintf(query, sizeof(query),
+ "START SLAVE '%.80s' SQL_THREAD", row[0]);
else
strmov(query, "START SLAVE SQL_THREAD");
@@ -7287,6 +7326,85 @@ static void init_connection_pool(uint n_connections)
connection_pool.init(conn, n_connections);
}
+/*
+ Fix permissions and ownership of given directory to be the same
+ as the root output directory.
+
+ The function is used for newly created database directories,
+ together with --dir option
+
+ This function is not thread-safe, nor does it need to be, because
+ it is called from the main thread only.
+
+ chmod/chown errors are ignored after the first one, with a warning printed,
+ so it is really the best effort attempt. We might see an error later
+ if the server can't write into the directory, and this will be the
+ real error.
+
+ On Windows, this function does nothing, because the permissions are
+ inherited from the parent directory anyway.
+
+ @param dirpath Directory path
+*/
+static void fix_permissions_and_owner(const char *dirpath)
+{
+#ifndef _WIN32
+ // Permissions and ownership of output directory (--dir)
+ static struct stat st_out_dir;
+
+ static bool fix_perms= true; // Try fixing permission bits
+ static bool fix_ownership_uid= true; // Try fixing user+group ownership
+ static bool fix_ownership_gid= false; // Try fixing group ownership only
+
+ static bool first_time= true;
+ if (first_time)
+ {
+ /* Find out permissions and ownership of output directory */
+ first_time= false;
+ if (stat(opt_dir, &st_out_dir) != 0)
+ {
+ die(EX_CONSCHECK, "Error: cannot stat output directory %s, errno %d",
+ opt_dir, errno);
+ }
+ }
+
+ /* Change permissions to be the same as for the output directory*/
+ if (fix_perms &&
+ chmod(dirpath, st_out_dir.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO)))
+ {
+ fprintf(stderr,
+ "Warning: cannot set permissions on directory %s, errno %d\n",
+ dirpath, errno);
+ fix_perms= false;
+ }
+
+ /*
+ Change ownership to be the same as backup root dir.
+ If user can't be changed, try changing owner group only.
+ */
+ if (fix_ownership_uid &&
+ chown(dirpath, st_out_dir.st_uid, st_out_dir.st_gid))
+ {
+ // No warning, error is expected, unless current user is root.
+ fix_ownership_uid= false;
+ fix_ownership_gid= true;
+ }
+
+ if (fix_ownership_gid && chown(dirpath, -1, st_out_dir.st_gid))
+ {
+ if (!(st_out_dir.st_mode & S_IWOTH))
+ {
+ /* Only warn if directory is not world-writable (group ownership
+ matters more in this case), to avoid spamming stderr.*/
+ fprintf(stderr,
+ "Warning: cannot set group ownership on directory %s, errno %d\n",
+ dirpath, errno);
+ }
+ fix_ownership_gid= false;
+ }
+#endif
+}
+
/*
If --dir option is in use, ensure that output directory for given db
exists.
@@ -7295,7 +7413,7 @@ static void ensure_out_dir_exists(const char *db)
{
DBUG_ASSERT(opt_dir);
char outdir[FN_REFLEN];
- my_snprintf(outdir, sizeof(outdir), "%s/%s", opt_dir, db);
+ format_fs_safe_output_dir(db, outdir, sizeof(outdir));
struct stat st;
if (stat(outdir, &st) == 0)
{
@@ -7306,6 +7424,7 @@ static void ensure_out_dir_exists(const char *db)
}
if (my_mkdir(outdir, 0777, MYF(MY_WME)))
die(EX_MYSQLERR, "Error creating directory %s", outdir);
+ fix_permissions_and_owner(outdir);
}
@@ -7338,6 +7457,175 @@ static void do_print_set_gtid_slave_pos(const char *set_gtid_pos,
fprintf(md_result_file, "%s", set_gtid_pos);
}
+void dump_tables_for_database_wild(const char *db,
+ int n_patterns, char **patterns)
+{
+ int num;
+ int number_of_tables= 0;
+ MYSQL_ROW row;
+ char *buff, quoted_buf[NAME_LEN*2+3];
+ MYSQL_RES *dbinfo;
+ char **tables_to_dump;
+ /* dbcopy - unquoted db; */
+ char dbcopy[2 * NAME_LEN + 30];
+ char hash_key[2*NAME_LEN+2]; /* "db.tablename" */
+ char *afterdot;
+ size_t len;
+ size_t buff_size= 108 + (NAME_LEN + 30)*n_patterns;
+
+ DBUG_ENTER("dump_tables_for_database_wild");
+ DBUG_ASSERT(n_patterns > 0);
+
+
+ if (*db == '`')
+ {
+ len= strlen(db);
+ memcpy(dbcopy, db + 1, len - 2);
+ dbcopy[len - 2] = 0;
+ }
+ else
+ {
+ strncpy(dbcopy, db, NAME_LEN + 1);
+ }
+
+ afterdot= strmov(hash_key, dbcopy);
+ *afterdot++= '.';
+
+ if (!(buff=(char*) my_malloc(PSI_NOT_INSTRUMENTED, buff_size, MYF(MY_WME))))
+ die(EX_MYSQLERR, "Couldn't allocate memory");
+
+ len= my_snprintf(buff, buff_size,
+ "SELECT table_name FROM INFORMATION_SCHEMA.TABLES"
+ " WHERE table_schema=%s", quote_for_equal(dbcopy, quoted_buf));
+
+ mysql_real_escape_string(mysql, quoted_buf,
+ patterns[0], (ulong)strlen(patterns[0]));
+
+ len+= my_snprintf(buff+len, buff_size,
+ " AND (table_name LIKE '%s'", quoted_buf);
+
+ for (num=1; numrow_count + (int) 1) * sizeof(char *), MYF(MY_WME))))
+ die(EX_MYSQLERR, "Couldn't allocate memory");
+ while ((row= mysql_fetch_row(dbinfo)))
+ {
+ char *end= strmov(afterdot, row[0]);
+ if (include_table((uchar*) hash_key,end - hash_key))
+ {
+ tables_to_dump[number_of_tables++]= row[0];
+ }
+ }
+ tables_to_dump[number_of_tables]= NULL;
+ if (number_of_tables > 0)
+ {
+ if (!opt_alltspcs && !opt_notspcs)
+ dump_tablespaces_for_tables(dbcopy, tables_to_dump, number_of_tables);
+ dump_selected_tables(dbcopy, tables_to_dump, number_of_tables);
+ }
+ mysql_free_result(dbinfo);
+ my_free(tables_to_dump);
+
+free_buf_and_exit:
+ my_free(buff);
+ DBUG_VOID_RETURN;
+}
+
+
+/* pattern should be unquoted */
+void dump_databases_wild(int n_patterns, char **db_patterns)
+{
+ MYSQL_RES *dbinfo;
+ char *qwe_buff;
+ size_t qwe_buff_size= (NAME_LEN + 30)*n_patterns + 40;
+ size_t qwe_len;
+ MYSQL_ROW row;
+ int i;
+ char **databases_to_dump;
+ DBUG_ENTER("dump_databases_wild");
+ DBUG_ASSERT(n_patterns > 0);
+
+ if (!(qwe_buff= (char *) my_malloc(PSI_NOT_INSTRUMENTED,
+ qwe_buff_size, MYF(MY_WME))))
+ die(EX_MYSQLERR, "Couldn't allocate memory");
+
+
+ qwe_len= my_snprintf(qwe_buff, qwe_buff_size,
+ "SHOW DATABASES WHERE Database LIKE '%s'", db_patterns[0]);
+ for (i=1; irow_count + (int) 1) * sizeof(char *), MYF(MY_WME))))
+ die(EX_MYSQLERR, "Couldn't allocate memory");
+
+ i= 0;
+ while ((row= mysql_fetch_row(dbinfo)))
+ {
+ if (is_IS_or_PS(row[0]) || is_SyS(row[0]) || !include_database(row[0]))
+ continue;
+
+ databases_to_dump[i++]= row[0];
+ }
+
+ if (i == 0) /* No database found to dump. */
+ {
+ fprintf(stderr, "%s: Error: no databases matching the ", my_progname_short);
+
+ if (n_patterns > 1)
+ {
+ fprintf(stderr, "patterns ['%s'", db_patterns[0]);
+ for (i=1; i 1 && !opt_databases)
+ if (opt_wildcards &&(opt_databases || argc > 1))
{
- /* Only one database and selected table(s) */
- if (!opt_alltspcs && !opt_notspcs)
- dump_tablespaces_for_tables(*argv, (argv + 1), (argc - 1));
- dump_selected_tables(*argv, (argv + 1), (argc - 1));
+ if (argc > 1 && !opt_databases)
+ /* One database, tables matching the wildcard. */
+ dump_tables_for_database_wild(argv[0], argc-1, argv+1);
+ else if (argc > 0)
+ /* Databases matching the wildcards. */
+ dump_databases_wild(argc, argv);
+ else
+ die(EX_CONSCHECK,
+ "Incorrect usage of patterns \n");
}
- else if (argc > 0)
+ else
{
- /* One or more databases, all tables */
- if (!opt_alltspcs && !opt_notspcs)
- dump_tablespaces_for_databases(argv);
- dump_databases(argv);
+ if (argc > 1 && !opt_databases)
+ {
+ /* Only one database and selected table(s) */
+ if (!opt_alltspcs && !opt_notspcs)
+ dump_tablespaces_for_tables(*argv, (argv + 1), (argc - 1));
+ dump_selected_tables(*argv, (argv + 1), (argc - 1));
+ }
+ else if (argc > 0)
+ {
+ /* One or more databases, all tables */
+ if (!opt_alltspcs && !opt_notspcs)
+ dump_tablespaces_for_databases(argv);
+ dump_databases(argv);
+ }
}
}
diff --git a/client/mysqlimport.cc b/client/mysqlimport.cc
index 01259e95ef8a8..c6af8d5091cb6 100644
--- a/client/mysqlimport.cc
+++ b/client/mysqlimport.cc
@@ -50,7 +50,7 @@ static std::vector all_tp_connections;
std::atomic aborting{false};
static void kill_tp_connections(MYSQL *mysql);
-static void db_error_with_table(MYSQL *mysql, char *table);
+static void db_error_with_table(MYSQL *mysql, const char *table);
static void db_error(MYSQL *mysql);
static char *field_escape(char *to,const char *from,uint length);
static char *add_load_option(char *ptr,const char *object,
@@ -82,12 +82,36 @@ static char **argv_to_free;
static void safe_exit(int error, MYSQL *mysql);
static void set_exitcode(int code);
+/*
+ Try to convert from filesystem-safe name escaping to string
+ in default character set.
+
+ @param name Name to unescape
+ @param buf Buffer to store result
+ @param sz Size of buffer
+ @return length of result string, or 0 on error or decodin
+ not needed
+*/
+static uint decode_fs_safe_name(const char *name, char *buf, size_t sz)
+{
+ if (!strchr(name, '@'))
+ return 0;
+ uint errors, len;
+ len= my_convert(buf, (uint32)(sz - 1), default_charset_info, name, (uint32) strlen(name),
+ &my_charset_filename, &errors);
+ if (errors || !len)
+ return 0;
+ buf[len]= 0;
+ return len;
+}
+
struct table_load_params
{
std::string data_file; /* name of the file to load with LOAD DATA INFILE */
std::string sql_file; /* name of the file that contains CREATE TABLE or
CREATE VIEW */
std::string dbname; /* name of the database */
+ std::string tablename; /* name of the table */
bool tz_utc= false; /* true if the script sets the timezone to UTC */
bool is_view= false; /* true if the script is for a VIEW */
std::vector triggers; /* CREATE TRIGGER statements */
@@ -98,12 +122,21 @@ struct table_load_params
table_load_params(const char* dfile, const char* sqlfile,
const char* db, ulonglong data_size)
: data_file(dfile), sql_file(sqlfile),
- dbname(db), triggers(),
+ triggers(),
size(data_size),
sql_text(parse_sql_script(sqlfile, &tz_utc, &triggers)),
ddl_info(sql_text)
{
is_view= ddl_info.table_name.empty();
+ /* Convert dbname from FS safe encoding if needed. */
+ char decoded_name[FN_REFLEN];
+ uint len= decode_fs_safe_name(db, decoded_name, sizeof(decoded_name));
+ dbname= len ? std::string(decoded_name, len) : std::string(db);
+
+ char raw_tblname[FN_REFLEN];
+ fn_format(raw_tblname, dfile, "", "", MY_REPLACE_DIR | MY_REPLACE_EXT);
+ len= decode_fs_safe_name(raw_tblname, decoded_name, sizeof(decoded_name));
+ tablename= len ? std::string(decoded_name, len) : std::string(raw_tblname);
}
int create_table_or_view(MYSQL *);
int load_data(MYSQL *);
@@ -646,7 +679,7 @@ int table_load_params::create_table_or_view(MYSQL* mysql)
int table_load_params::load_data(MYSQL *mysql)
{
- char tablename[FN_REFLEN], hard_path[FN_REFLEN],
+ char hard_path[FN_REFLEN],
escaped_name[FN_REFLEN * 2 + 1],
sql_statement[FN_REFLEN*16+256], *end;
DBUG_ENTER("table_load_params::load");
@@ -666,13 +699,10 @@ int table_load_params::load_data(MYSQL *mysql)
}
const char *filename= data_file.c_str();
-
- fn_format(tablename, filename, "", "", 1 | 2); /* removes path & ext. */
-
const char *db= current_db ? current_db : dbname.c_str();
std::string full_tablename= quote_identifier(db);
full_tablename+= ".";
- full_tablename+= quote_identifier(tablename);
+ full_tablename+= quote_identifier(tablename.c_str());
if (tz_utc && exec_sql(mysql, "SET TIME_ZONE='+00:00';"))
DBUG_RETURN(1);
@@ -688,7 +718,7 @@ int table_load_params::load_data(MYSQL *mysql)
if (opt_delete)
{
if (verbose)
- fprintf(stdout, "Deleting the old data from table %s\n", tablename);
+ fprintf(stdout, "Deleting the old data from table %s\n", tablename.c_str());
snprintf(sql_statement, FN_REFLEN * 16 + 256, "DELETE FROM %s",
full_tablename.c_str());
if (exec_sql(mysql, sql_statement))
@@ -713,11 +743,12 @@ int table_load_params::load_data(MYSQL *mysql)
if (verbose)
{
fprintf(stdout, "Loading data from %s file: %s into %s\n",
- (opt_local_file) ? "LOCAL" : "SERVER", hard_path, tablename);
+ (opt_local_file) ? "LOCAL" : "SERVER", hard_path, tablename.c_str());
}
mysql_real_escape_string(mysql, escaped_name, hard_path,
(unsigned long) strlen(hard_path));
- sprintf(sql_statement, "LOAD DATA %s %s INFILE '%s'",
+ snprintf(sql_statement, sizeof(sql_statement),
+ "LOAD DATA %s %s INFILE '%s'",
opt_low_priority ? "LOW_PRIORITY" : "",
opt_local_file ? "LOCAL" : "", escaped_name);
@@ -747,14 +778,14 @@ int table_load_params::load_data(MYSQL *mysql)
if (mysql_query(mysql, sql_statement))
{
- db_error_with_table(mysql, tablename);
+ db_error_with_table(mysql, tablename.c_str());
DBUG_RETURN(1);
}
if (!silent)
{
const char *info= mysql_info(mysql);
if (info) /* If NULL-pointer, print nothing */
- fprintf(stdout, "%s.%s: %s\n", db, tablename, info);
+ fprintf(stdout, "%s.%s: %s\n", db, tablename.c_str(), info);
}
@@ -869,10 +900,7 @@ static MYSQL *db_connect(char *host, char *database,
if (opt_default_auth && *opt_default_auth)
mysql_options(mysql, MYSQL_DEFAULT_AUTH, opt_default_auth);
- if (!strcmp(default_charset,MYSQL_AUTODETECT_CHARSET_NAME))
- default_charset= (char *)my_default_csname();
- my_set_console_cp(default_charset);
- mysql_options(mysql, MYSQL_SET_CHARSET_NAME, my_default_csname());
+ mysql_options(mysql, MYSQL_SET_CHARSET_NAME, default_charset);
mysql_options(mysql, MYSQL_OPT_CONNECT_ATTR_RESET, 0);
mysql_options4(mysql, MYSQL_OPT_CONNECT_ATTR_ADD,
"program_name", "mysqlimport");
@@ -961,7 +989,7 @@ static void safe_exit(int error, MYSQL *mysql)
-static void db_error_with_table(MYSQL *mysql, char *table)
+static void db_error_with_table(MYSQL *mysql, const char *table)
{
if (aborting)
return;
@@ -1263,6 +1291,12 @@ int main(int argc, char **argv)
free_defaults(argv_to_free);
return(1);
}
+
+ if (!strcmp(default_charset, MYSQL_AUTODETECT_CHARSET_NAME))
+ default_charset= (char *) my_default_csname();
+ my_set_console_cp(default_charset);
+ default_charset_info= get_charset_by_csname(default_charset, MY_CS_PRIMARY, 0);
+
if (opt_use_threads > MAX_THREADS)
{
fatal_error("Too many connections, max value for --parallel is %d\n",
diff --git a/client/mysqltest.cc b/client/mysqltest.cc
index 637f48c559eb4..b54bdcf4c78dc 100644
--- a/client/mysqltest.cc
+++ b/client/mysqltest.cc
@@ -55,6 +55,7 @@
#endif
#include
#include
+#include
#include // ORACLE_WELCOME_COPYRIGHT_NOTICE
@@ -78,7 +79,7 @@ static my_bool non_blocking_api_enabled= 0;
#define MAX_DELIMITER_LENGTH 16
#define DEFAULT_MAX_CONN 64
-#define DIE_BUFF_SIZE 15*1024
+#define DIE_BUFF_SIZE 64*1024
#define RESULT_STRING_INIT_MEM 2048
#define RESULT_STRING_INCREMENT_MEM 2048
@@ -308,6 +309,7 @@ struct Parser
struct MasterPos
{
char file[FN_REFLEN];
+ char gtid[256];
ulong pos;
} master_pos;
@@ -697,6 +699,320 @@ void display_optimizer_trace(struct st_connection *con,
static void append_session_track_info(DYNAMIC_STRING *ds, MYSQL *mysql);
+
+/*
+ ========================================================================
+ EXPRESSION PARSER AND EVALUATOR FOR MYSQLTEST
+ ========================================================================
+
+ DESCRIPTION
+ This module implements a complete recursive descent parser for mathematical
+ and logical expressions used in mysqltest scripts. The parser supports:
+
+ OPERATOR PRECEDENCE (from highest to lowest):
+ - Primary expressions (parentheses, literals, functions)
+ - Unary operators (!, -, ~)
+ - Bitwise XOR (^)
+ - Multiplication/Division (*, /, %)
+ - Arithmetic (+, -)
+ - Bitwise Shift (<<, >>)
+ - Bitwise AND (&)
+ - Bitwise OR (|)
+ - Comparison (<, <=, >, >=)
+ - Equality (==, !=)
+ - Logical AND (&&)
+ - Logical OR (||)
+
+ SUPPORTED DATA TYPES:
+ - Integers (decimal, hexadecimal (0x), binary (0b))
+ - Booleans
+ - Strings
+ - NULL values
+
+ BUILT-IN FUNCTIONS:
+ String functions: substr/substring, locate, length, hex, oct, bin,
+ ltrim, rtrim, trim, upper/ucase, lower/lcase,
+ reverse, replace, concat, concat_ws, repeat,
+ insert, instr, lpad, rpad, substring_index
+ Regex functions: regexp_instr, regexp_replace, regexp_substr
+ Numeric functions: abs, conv
+ Comparison functions: greatest, least
+ Conditional: ifnull, nullif, coalesce
+
+ SYNTAX:
+ Expressions are enclosed in $() and can contain:
+ - Variables: $var_name
+ - Literals: numbers, strings, booleans, null
+ - Operators: all standard mathematical and logical operators
+ - Functions: built-in function calls with arguments
+ - Parentheses for grouping
+
+ EXAMPLES:
+ $(1 + 2 * 3) # Arithmetic
+ $($var1 > $var2) # Comparison
+ $(substr("hello", 1, 3)) # Function call
+ $($flag && ($count > 0)) # Logical operations
+ $(1 << 2 | 3) # Bitwise operations
+
+ let $x = $(10 + 2);
+ echo $(1 + 2);
+ if ($($x > 10))
+ {
+ echo "x is greater than 10";
+ }
+ while ($($x < 20))
+ {
+ echo $($x);
+ let $x = $($x + 1);
+ }
+
+ ENTRY POINT:
+ Main parsing starts with expr() function which is called from do_eval().
+
+ ERROR HANDLING:
+ Parser dies with descriptive error messages on syntax errors or
+ type mismatches. All errors are fatal to ensure test reliability.
+*/
+
+typedef String My_string;
+
+enum Expression_value_type
+{
+ EXPR_INT,
+ EXPR_STRING,
+ EXPR_NULL
+};
+
+
+/*
+ Expression value container for mysqltest expression parser
+ This structure holds the result of parsed expressions and provides
+ type conversion methods. It supports multiple data types with
+ the ability to convert between them.
+*/
+
+struct Expression_value
+{
+ Expression_value_type type;
+ unsigned long long int_val;
+ bool is_numeric;
+ bool is_unsigned;
+ My_string str_val;
+
+
+ Expression_value()
+ {
+ type= EXPR_NULL;
+ is_numeric= false;
+ is_unsigned= false;
+ }
+
+
+ void set_int(long long value)
+ {
+ type= EXPR_INT;
+ is_numeric= true;
+ is_unsigned= false;
+ int_val= value;
+ }
+
+
+ void set_uint(unsigned long long value)
+ {
+ type= EXPR_INT;
+ is_numeric= true;
+ is_unsigned= true;
+ int_val= value;
+ }
+
+
+ void set_string(const char *value, size_t len)
+ {
+ type= EXPR_STRING;
+ is_numeric= false;
+ str_val.copy(value, len, charset_info);
+ }
+
+
+ void set_bool(bool value)
+ {
+ type= EXPR_INT;
+ is_numeric= true;
+ is_unsigned= false;
+ int_val= value ? 1 : 0;
+ }
+
+
+ long long to_int() const
+ {
+ if (is_numeric)
+ return (long long)int_val;
+ errno= 0;
+ long long val= strtoll(str_val.ptr(), NULL, 10);
+ if (errno == ERANGE)
+ die("Range error: %.*s value out of range for Integer type",
+ (int)str_val.length(), str_val.ptr());
+ return val;
+ }
+
+
+ unsigned long long to_uint() const
+ {
+ if (is_numeric)
+ return int_val;
+ errno= 0;
+ unsigned long long val= strtoull(str_val.ptr(), NULL, 10);
+ if (errno == ERANGE)
+ die("Range error: %.*s value out of range for Integer type",
+ (int)str_val.length(), str_val.ptr());
+ return val;
+ }
+
+
+ bool to_bool() const
+ {
+ return (bool)to_int();
+ }
+
+
+ My_string to_string() const
+ {
+ My_string buffer;
+
+ if (type == EXPR_NULL)
+ {
+ buffer.set("", 0, charset_info);
+ return buffer;
+ }
+
+ if (is_numeric)
+ {
+ buffer.set_int(int_val, is_unsigned, charset_info);
+ return buffer;
+ }
+
+ if (type == EXPR_STRING)
+ {
+ buffer.copy(str_val);
+ return buffer;
+ }
+
+ buffer.set("", 0, charset_info);
+ return buffer;
+ }
+
+
+ Expression_value& operator=(const Expression_value& other)
+ {
+ if (this != &other)
+ {
+ type= other.type;
+ int_val= other.int_val;
+ is_numeric= other.is_numeric;
+ is_unsigned= other.is_unsigned;
+ if (other.type == EXPR_STRING)
+ {
+ str_val.copy(other.str_val);
+ }
+ }
+ return *this;
+ }
+
+
+ void reset()
+ {
+ // My_string memory is kept allocated for reuse
+ type= EXPR_NULL;
+ is_numeric= false;
+ is_unsigned= false;
+ }
+
+
+/**
+ Parses a token string and initializes the Expression_value with the
+ appropriate type and value.
+
+ Type selection logic:
+ - Hex/binary numbers, or values > LLONG_MAX → unsigned integer
+ - Decimal numbers ≤ LLONG_MAX → signed integer
+ - Boolean literals → boolean type
+ - "null" → null type
+ - Everything else → string type
+*/
+
+ void init(const char* token_start, size_t token_len)
+ {
+ char *endptr;
+ unsigned long long parsed_int;
+ int base= 10;
+
+ // Check for boolean literals (case insensitive)
+ if (token_len == 4 && strncasecmp(token_start, "true", 4) == 0)
+ {
+ set_bool(true);
+ return;
+ }
+
+ if (token_len == 5 && strncasecmp(token_start, "false", 5) == 0)
+ {
+ set_bool(false);
+ return;
+ }
+
+ if(token_len == 4 && strncasecmp(token_start, "null", 4) == 0)
+ {
+ reset();
+ return;
+ }
+
+ // Check for special prefixes (0x, 0b)
+ if (token_len >= 3 && token_start[0] == '0')
+ {
+ if (token_start[1] == 'x')
+ {
+ base= 16;
+ }
+ else if (token_start[1] == 'b')
+ {
+ base= 2;
+ token_start+= 2; // Skip "0b" prefix for strtol
+ token_len-= 2;
+ }
+ }
+
+ errno= 0;
+ parsed_int= strtoull(token_start, &endptr, base);
+ if (errno == ERANGE)
+ die("Range error: %.*s value out of range for Integer type",
+ (int)token_len, token_start);
+
+ // If the entire token was parsed as an integer, set the type to integer
+ if (endptr == token_start + token_len)
+ {
+ if (base == 16 || base == 2 || parsed_int > LLONG_MAX)
+ set_uint(parsed_int);
+ else
+ set_int((long long)parsed_int);
+ return;
+ }
+
+ set_string(token_start, token_len);
+ }
+};
+
+
+/* Core expression parsing functions */
+static void expr(Expression_value *result, const char **s);
+static void logical_or(Expression_value *result, const char **s);
+static void logical_and(Expression_value *result, const char **s);
+static void equality(Expression_value *result, const char **s);
+static void comparison(Expression_value *result, const char **s);
+static void term(Expression_value *result, const char **s);
+static void factor(Expression_value *result, const char **s);
+static void unary(Expression_value *result, const char **s);
+static void primary(Expression_value *result, const char **s);
+
+
class LogFile {
FILE* m_file;
char m_file_name[FN_REFLEN];
@@ -1172,6 +1488,60 @@ void do_eval(DYNAMIC_STRING *query_eval, const char *query,
escaped= 0;
dynstr_append_mem(query_eval, p, 1);
}
+ else if (p < query_end && *(p + 1) == '(')
+ {
+ const char* expr_start= p + 2;
+ int paren_level= 1;
+ const char* expr_end= expr_start;
+ char in_quote= 0;
+ bool escaped= false;
+
+ // Find the matching closing parenthesis
+ while (*expr_end && paren_level > 0)
+ {
+ if (!in_quote)
+ {
+ // Not inside quotes - handle parentheses normally
+ if (*expr_end == '(') paren_level++;
+ else if (*expr_end == ')') paren_level--;
+ else if (*expr_end == '\'' || *expr_end == '"')
+ in_quote= *expr_end; // Start of quoted string
+ }
+ else
+ {
+ // Inside quotes - only look for closing quote
+ if (!escaped && *expr_end == in_quote)
+ in_quote= 0; // End of quoted string
+ }
+ escaped= (!escaped && *expr_end == '\\');
+ expr_end++;
+ }
+
+ if (paren_level != 0)
+ die("Unmatched parenthesis in expression starting at '%.*s'", 10, p);
+ expr_end--; // Go back to the ')'
+
+ // Recursively evaluate the content of the expression
+ DYNAMIC_STRING sub_expr_eval;
+ init_dynamic_string(&sub_expr_eval, "", 256, 1024);
+ do_eval(&sub_expr_eval, expr_start, expr_end, FALSE);
+
+ const char* eval_ptr= sub_expr_eval.str;
+ Expression_value result_val;
+ expr(&result_val, &eval_ptr);
+
+ while(*eval_ptr && my_isspace(charset_info, *eval_ptr))
+ eval_ptr++;
+
+ if (*eval_ptr != '\0')
+ die("Syntax error in sub-expression '%.*s'", (int)sub_expr_eval.length, sub_expr_eval.str);
+
+ My_string result_buf= result_val.to_string();
+ dynstr_append_mem(query_eval, result_buf.c_ptr(), result_buf.length());
+
+ dynstr_free(&sub_expr_eval);
+ p= expr_end;
+ }
else
{
if (!(v= var_get(p, &p, 0, 0)))
@@ -1631,6 +2001,8 @@ static void make_error_message(char *buf, size_t len, const char *fmt, va_list a
s+= my_snprintf(s, end -s, "\n");
}
+PRAGMA_DISABLE_CHECK_STACK_FRAME
+
static void die(const char *fmt, ...)
{
char buff[DIE_BUFF_SIZE];
@@ -1642,6 +2014,8 @@ static void die(const char *fmt, ...)
really_die(buff);
}
+PRAGMA_REENABLE_CHECK_STACK_FRAME
+
static void really_die(const char *msg)
{
static int dying= 0;
@@ -1670,6 +2044,8 @@ static void really_die(const char *msg)
cleanup_and_exit(1, 1);
}
+PRAGMA_DISABLE_CHECK_STACK_FRAME
+
void report_or_die(const char *fmt, ...)
{
va_list args;
@@ -1724,6 +2100,7 @@ void abort_not_supported_test(const char *fmt, ...)
cleanup_and_exit(62, 0);
}
+PRAGMA_REENABLE_CHECK_STACK_FRAME
void abort_not_in_this_version()
{
@@ -4663,6 +5040,24 @@ void do_change_user(struct st_command *command)
dynstr_set(&ds_db, mysql->db);
}
+ /* Connection logging if enabled */
+ if (!disable_query_log)
+ {
+ DYNAMIC_STRING *ds= &ds_res;
+
+ dynstr_append_mem(ds, STRING_WITH_LEN("change_user "));
+ replace_dynstr_append(ds, ds_user.str);
+ dynstr_append_mem(ds, STRING_WITH_LEN(","));
+
+ if (ds_passwd.length)
+ replace_dynstr_append(ds, ds_passwd.str);
+ dynstr_append_mem(ds, STRING_WITH_LEN(","));
+
+ if (ds_db.length)
+ replace_dynstr_append(ds, ds_db.str);
+ dynstr_append_mem(ds, STRING_WITH_LEN(";\n"));
+ }
+
DBUG_PRINT("info",("connection: '%s' user: '%s' password: '%s' database: '%s'",
cur_con->name, ds_user.str, ds_passwd.str, ds_db.str));
@@ -4865,161 +5260,2552 @@ void do_wait_for_slave_to_stop(struct st_command *c __attribute__((unused)))
break;
my_sleep(SLAVE_POLL_INTERVAL);
}
- return;
+ return;
+}
+
+static const char *get_col_value(MYSQL_RES *res, MYSQL_ROW row, const char *name)
+{
+ uint num_fields= mysql_num_fields(res);
+ MYSQL_FIELD *fields= mysql_fetch_fields(res);
+
+ for (uint i= 0; i < num_fields; i++)
+ {
+ if (strcmp(fields[i].name, name) == 0)
+ return row[i];
+ }
+ return "NULL";
+}
+
+
+void do_sync_with_master2(struct st_command *command, long offset,
+ const char *connection_name)
+{
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ MYSQL *mysql= cur_con->mysql;
+ char query_buf[FN_REFLEN+128], query_buf2[256];
+ int timeout= opt_wait_for_pos_timeout;
+
+ if (!master_pos.file[0])
+ die("Calling 'sync_with_master' without calling 'save_master_pos'");
+
+ sprintf(query_buf, "select master_pos_wait('%s', %ld, %d, '%s')",
+ master_pos.file, master_pos.pos + offset, timeout,
+ connection_name);
+
+ if (mysql_query(mysql, query_buf))
+ die("failed in '%s': %d: %s", query_buf, mysql_errno(mysql),
+ mysql_error(mysql));
+
+ if (!(res= mysql_store_result(mysql)))
+ die("mysql_store_result() returned NULL for '%s'", query_buf);
+ if (!(row= mysql_fetch_row(res)))
+ {
+ mysql_free_result(res);
+ die("empty result in %s", query_buf);
+ }
+
+ int result= -99;
+ const char* result_str= row[0];
+ if (result_str)
+ result= atoi(result_str);
+
+ mysql_free_result(res);
+
+ if (!result_str || result < 0)
+ {
+ /* master_pos_wait returned NULL or < 0 */
+ fprintf(stderr, "analyze: sync_with_master\n");
+
+ snprintf(query_buf2, sizeof(query_buf2)-1,
+ "select Relay_Master_Log_File, Read_Master_Log_Pos, Gtid_IO_Pos, "
+ "Gtid_Slave_Pos from information_schema.slave_status where "
+ "Connection_name='%.64s'", connection_name);
+
+ /* purify begin tested */
+ if (!mysql_query(mysql, query_buf2))
+ {
+ if ((res= mysql_store_result(mysql)))
+ {
+ if ((row= mysql_fetch_row(res)))
+ {
+ fprintf(stderr, "Slave position: file: %s position: %s "
+ "Gtid_Slave_Pos: %s Gtid_IO_Pos: %s\n",
+ get_col_value(res, row, "Relay_Master_Log_File"),
+ get_col_value(res, row, "Read_Master_Log_Pos"),
+ get_col_value(res, row, "Gtid_Slave_Pos"),
+ get_col_value(res, row, "Gtid_IO_Pos"));
+ fprintf(stderr, "Master position: file: %s position: %lld "
+ "Gtid_Master_Pos: %s\n",
+ master_pos.file, (longlong) (master_pos.pos + offset),
+ master_pos.gtid);
+ }
+ mysql_free_result(res);
+ }
+ }
+ /* purify end tested */
+
+ if (!result_str)
+ {
+ /*
+ master_pos_wait returned NULL. This indicates that
+ slave SQL thread is not started, the slave's master
+ information is not initialized, the arguments are
+ incorrect, or an error has occurred
+ */
+ die("%.*sB failed: '%s' returned NULL " \
+ "indicating slave SQL thread failure",
+ command->first_word_len, command->query, query_buf);
+ }
+
+ if (result == -1)
+ die("%.*sB failed: '%s' returned -1 " \
+ "indicating timeout after %d seconds",
+ command->first_word_len, command->query, query_buf, timeout);
+ else
+ die("%.*sB failed: '%s' returned unknown result :%d",
+ command->first_word_len, command->query, query_buf, result);
+ }
+
+ return;
+}
+
+void do_sync_with_master(struct st_command *command)
+{
+ long offset= 0;
+ char *p= command->first_argument;
+ const char *offset_start= p;
+ char *start, *buff= 0;
+ start= const_cast("");
+
+ if (*offset_start)
+ {
+ for (; my_isdigit(charset_info, *p); p++)
+ offset = offset * 10 + *p - '0';
+
+ if (*p && !my_isspace(charset_info, *p) && *p != ',')
+ die("Invalid integer argument \"%s\"", offset_start);
+
+ while (*p && my_isspace(charset_info, *p))
+ p++;
+ if (*p == ',')
+ {
+ p++;
+ while (*p && my_isspace(charset_info, *p))
+ p++;
+ start= buff= (char*)my_malloc(PSI_NOT_INSTRUMENTED, strlen(p)+1,
+ MYF(MY_WME|MY_FAE));
+ get_string(&buff, &p, command);
+ }
+ command->last_argument= p;
+ }
+ do_sync_with_master2(command, offset, start);
+ if (buff)
+ my_free(start);
+ return;
+}
+
+
+int do_save_master_pos()
+{
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ MYSQL *mysql = cur_con->mysql;
+ const char *query;
+ DBUG_ENTER("do_save_master_pos");
+
+ if (mysql_query(mysql, query= "show master status"))
+ die("failed in 'show master status': %d %s",
+ mysql_errno(mysql), mysql_error(mysql));
+
+ if (!(res = mysql_store_result(mysql)))
+ die("mysql_store_result() returned NULL for '%s'", query);
+ if (!(row = mysql_fetch_row(res)))
+ die("empty result in show master status");
+ strmake(master_pos.file, row[0], sizeof(master_pos.file)-1);
+ master_pos.pos= strtoul(row[1], (char**) 0, 10);
+ strmake(master_pos.gtid, row[4], sizeof(master_pos.gtid)-1);
+ mysql_free_result(res);
+ DBUG_RETURN(0);
+}
+
+
+/* Built-in functions available in expressions */
+enum func_type
+{
+ // Numeric functions
+ FUNC_ABS,
+ FUNC_BIN,
+ FUNC_CONV,
+ FUNC_HEX,
+ FUNC_OCT,
+ // String functions
+ FUNC_CONCAT,
+ FUNC_CONCAT_WS,
+ FUNC_GREATEST,
+ FUNC_INSERT,
+ FUNC_INSTR,
+ FUNC_LPAD,
+ FUNC_LEAST,
+ FUNC_LENGTH,
+ FUNC_LOCATE,
+ FUNC_LOWER,
+ FUNC_LTRIM,
+ FUNC_REPEAT,
+ FUNC_REPLACE,
+ FUNC_REVERSE,
+ FUNC_RPAD,
+ FUNC_RTRIM,
+ FUNC_SUBSTR,
+ FUNC_SUBSTR_IDX,
+ FUNC_TRIM,
+ FUNC_UPPER,
+ // Regexp functions
+ FUNC_REGEXP_INSTR,
+ FUNC_REGEXP_REPLACE,
+ FUNC_REGEXP_SUBSTR,
+ // Null functions
+ FUNC_COALESCE,
+ FUNC_IFNULL,
+ FUNC_NULLIF,
+
+ FUNC_UNKNOWN
+};
+
+
+enum func_type get_expr_function_type(const char *name, size_t len);
+void handle_expr_function_call(enum func_type func_type,
+ Expression_value *result, const char **s);
+
+
+static int match(const char **s, const char *op)
+{
+ while (my_isspace(charset_info, **s)) (*s)++;
+ size_t len= strlen(op);
+ if (strncmp(*s, op, len) == 0)
+ {
+ // check for ambiguous operators (e.g., distinguish | from ||)
+ if (len == 1 && strchr("&|", **s))
+ {
+ char next_char= *(*s + 1);
+ if (next_char == op[0])
+ return 0; // don't match single & or | when && or || follows
+ }
+ *s += len;
+ return 1;
+ }
+ return 0;
+}
+
+
+/**
+ @brief Check if character is an operator
+ @param[in] c Character to check
+
+ @details
+ Used to separate tokens during parsing of unquoted string literals.
+ Operator characters: ! * % / + - < > = & | ^ ~ ( ) ,
+
+ @return
+ TRUE if character is an operator
+ FALSE otherwise
+*/
+
+static bool is_operator_char(char c)
+{
+ return strchr("!*%/+-<>=&|^~(),", c) != NULL;
+}
+
+
+/**
+ @brief Compare two Expression_value operands numerically
+ @param[in] left Left operand
+ @param[in] right Right operand
+
+ @details
+ Compares two numeric Expression_value objects handling signed vs unsigned
+ comparison correctly. Handles the edge cases where comparing signed negative
+ values with unsigned values.
+
+ @return
+ -1 left < right
+ 0 left == right
+ 1 left > right
+ -2 left or right is null
+*/
+
+static int cmp_numeric(const Expression_value &left, const Expression_value &right)
+{
+ // Handle null values first
+ if (left.type == EXPR_NULL || right.type == EXPR_NULL)
+ return -2;
+
+ if (!left.is_numeric || !right.is_numeric)
+ die("Evaluation error: cmp_numeric called with non-numeric operands");
+
+ // Both unsigned
+ if (left.is_unsigned && right.is_unsigned)
+ return (left.to_uint() > right.to_uint()) - (left.to_uint() < right.to_uint());
+
+ // Both signed
+ if (!left.is_unsigned && !right.is_unsigned)
+ return (left.to_int() > right.to_int()) - (left.to_int() < right.to_int());
+
+ // Mixed signed/unsigned
+ if (left.is_unsigned)
+ {
+ // left is unsigned, right is signed
+ long long right_val= right.to_int();
+ if (right_val < 0)
+ return 1; // unsigned > negative
+ else
+ {
+ unsigned long long left_val= left.to_uint();
+ unsigned long long right_unsigned= (unsigned long long)right_val;
+ return (left_val > right_unsigned) - (left_val < right_unsigned);
+ }
+ }
+ else
+ {
+ // left is signed, right is unsigned
+ long long left_val= left.to_int();
+ if (left_val < 0)
+ return -1; // negative < unsigned
+ else
+ {
+ unsigned long long left_unsigned= (unsigned long long)left_val;
+ unsigned long long right_val= right.to_uint();
+ return (left_unsigned > right_val) - (left_unsigned < right_val);
+ }
+ }
+}
+
+
+/**
+ @brief Parse primary expressions (literals, functions)
+ @param[out] result Expression_value to store result
+ @param[in] s Pointer to string pointer containing the expression to parse
+
+ @details
+ Handles the lowest level of expression parsing:
+ - String literals: 'text' or "text"
+ - Function calls: func_name(args...)
+ - Numeric literals: integers in decimal/hex/binary format
+ - Boolean literals: true/false (case-insensitive)
+ - Null literal: null (case-insensitive)
+ - Unquoted string tokens (treated as strings) as long as they are not operators,
+ literals, or function calls.
+
+ For function calls, validates function name against function_table[]
+ and delegates to handle_expr_function_call().
+
+ @note Dies on syntax errors or unknown functions
+*/
+
+static void primary(Expression_value *result, const char **s)
+{
+ while (my_isspace(charset_info, **s)) (*s)++;
+
+ if (match(s, "("))
+ {
+ expr(result, s);
+ if (!match(s, ")"))
+ die("Syntax error: Expected ')' in expression");
+ return;
+ }
+
+ const char *start= *s;
+ const char *end= start;
+ char quote_char= 0;
+
+ // check if this is a quoted string literal
+ if (*start == '\'' || *start == '"')
+ {
+ quote_char= *start;
+ start++;
+ end= start;
+ while (*end)
+ {
+ if (*end == '\\' && *(end + 1))
+ end++;
+ else if (*end == quote_char)
+ break;
+ end++;
+ }
+
+ if (*end != quote_char)
+ die("Syntax error: Unmatched quote in expression");
+
+ result->set_string(start, end - start);
+ *s= end + 1;
+ return;
+ }
+
+ /*
+ function name is a sequence of alphanumeric characters or underscores
+ followed by a '('
+ */
+ while (*end && (my_isalnum(charset_info, *end) || *end == '_'))
+ end++;
+
+ if (*end == '(')
+ {
+ enum func_type func_type= get_expr_function_type(start,
+ end - start);
+ if (func_type == FUNC_UNKNOWN)
+ die("Syntax error: Unknown function");
+
+ *s= end + 1; // skip '('
+ handle_expr_function_call(func_type, result, s);
+ }
+ else
+ {
+ // treat unquoted string literals as strings
+ end= start;
+ while (*end && !is_operator_char(*end))
+ end++;
+
+ while (start < end && my_isspace(charset_info, *(end - 1)))
+ end--;
+
+ if (end == start)
+ die("Syntax error: invalid expression");
+
+ result->init(start, end - start);
+ *s= end;
+ }
+}
+
+
+static void unary(Expression_value *result, const char **s)
+{
+ if (match(s, "!"))
+ {
+ unary(result, s);
+ if (!result->is_numeric)
+ die("Type error: logical NOT requires an integer operand");
+ result->set_bool(!result->to_int());
+ return;
+ }
+ if (match(s, "-"))
+ {
+ unary(result, s);
+ if (!result->is_numeric)
+ die("Type error: unary minus requires an integer operand");
+ result->set_int(-result->to_int());
+ return;
+ }
+ if (match(s, "~"))
+ {
+ unary(result, s);
+ if (!result->is_numeric)
+ die("Type error: bitwise NOT requires an integer operand");
+ result->set_uint(~result->to_uint());
+ return;
+ }
+ primary(result, s);
+}
+
+
+static void bitwise_xor(Expression_value *result, const char **s)
+{
+ Expression_value rhs;
+
+ unary(result, s);
+ while (true)
+ {
+ if (match(s, "^"))
+ {
+ rhs.reset();
+ unary(&rhs, s);
+ if (!result->is_numeric || !rhs.is_numeric)
+ die("Type error: operator '^' requires integer operands");
+ result->set_uint(result->to_uint() ^ rhs.to_uint());
+ }
+ else
+ break;
+ }
+}
+
+
+static void factor(Expression_value *result, const char **s)
+{
+ Expression_value rhs;
+
+ bitwise_xor(result, s);
+ while (true)
+ {
+ if (match(s, "*"))
+ {
+ rhs.reset();
+ bitwise_xor(&rhs, s);
+ if (!result->is_numeric || !rhs.is_numeric)
+ die("Type error: operator '*' requires integer operands");
+ if (result->is_unsigned || rhs.is_unsigned)
+ result->set_uint(result->to_uint() * rhs.to_uint());
+ else
+ result->set_int(result->to_int() * rhs.to_int());
+ }
+ else if (match(s, "/"))
+ {
+ rhs.reset();
+ bitwise_xor(&rhs, s);
+ if (!result->is_numeric || !rhs.is_numeric)
+ die("Type error: operator '/' requires integer operands");
+ if (rhs.to_int() == 0)
+ die("Evaluation error: Division by zero");
+ if (result->is_unsigned || rhs.is_unsigned)
+ result->set_uint(result->to_uint() / rhs.to_uint());
+ else
+ {
+ long long nominator= result->to_int();
+ long long denominator= rhs.to_int();
+ // Prevent fatal integer overflow from LLONG_MIN / -1, which causes a crash
+ if (nominator == LLONG_MIN && denominator == -1)
+ result->set_int(nominator);
+ else
+ result->set_int(nominator / denominator);
+ }
+ }
+ else if (match(s, "%"))
+ {
+ rhs.reset();
+ bitwise_xor(&rhs, s);
+ if (!result->is_numeric || !rhs.is_numeric)
+ die("Type error: operator '%%' requires integer operands");
+ if (rhs.to_int() == 0)
+ die("Evaluation error: Modulo by zero");
+ if (result->is_unsigned || rhs.is_unsigned)
+ result->set_uint(result->to_uint() % rhs.to_uint());
+ else
+ {
+ long long nominator= result->to_int();
+ long long denominator= rhs.to_int();
+ // Prevent fatal integer overflow from LLONG_MIN % -1, which causes a crash
+ if (nominator == LLONG_MIN && denominator == -1)
+ result->set_int(0);
+ else
+ result->set_int(nominator % denominator);
+ }
+ }
+ else
+ break;
+ }
+}
+
+
+static void term(Expression_value *result, const char **s)
+{
+ Expression_value rhs;
+
+ factor(result, s);
+ while (true)
+ {
+ if (match(s, "+"))
+ {
+ rhs.reset();
+ factor(&rhs, s);
+ if (!result->is_numeric || !rhs.is_numeric)
+ die("Type error: operator '+' requires integer operands");
+ if (result->is_unsigned || rhs.is_unsigned)
+ result->set_uint(result->to_uint() + rhs.to_uint());
+ else
+ result->set_int(result->to_int() + rhs.to_int());
+ }
+ else if (match(s, "-"))
+ {
+ rhs.reset();
+ factor(&rhs, s);
+ if (!result->is_numeric || !rhs.is_numeric)
+ die("Type error: operator '-' requires integer operands");
+ if (result->is_unsigned || rhs.is_unsigned)
+ result->set_uint(result->to_uint() - rhs.to_uint());
+ else
+ result->set_int(result->to_int() - rhs.to_int());
+ }
+ else
+ break;
+ }
+}
+
+
+static void bitwise_shift(Expression_value *result, const char **s)
+{
+ Expression_value rhs;
+
+ term(result, s);
+ while (true)
+ {
+ if (match(s, "<<"))
+ {
+ rhs.reset();
+ term(&rhs, s);
+ if (!result->is_numeric || !rhs.is_numeric)
+ die("Type error: operator '<<' requires integer operands");
+ if (rhs.to_int() < 0 || rhs.to_int() >= 64)
+ die("Evaluation error: Invalid shift amount");
+ result->set_uint(result->to_uint() << rhs.to_int());
+ }
+ else if (match(s, ">>"))
+ {
+ rhs.reset();
+ term(&rhs, s);
+ if (!result->is_numeric || !rhs.is_numeric)
+ die("Type error: operator '>>' requires integer operands");
+ if (rhs.to_int() < 0 || rhs.to_int() >= 64)
+ die("Evaluation error: Invalid shift amount");
+ result->set_uint(result->to_uint() >> rhs.to_int());
+ }
+ else
+ break;
+ }
+}
+
+
+static void bitwise_and(Expression_value *result, const char **s)
+{
+ Expression_value rhs;
+
+ bitwise_shift(result, s);
+ while (true)
+ {
+ if (match(s, "&") && !match(s, "&&"))
+ {
+ rhs.reset();
+ bitwise_shift(&rhs, s);
+ if (!result->is_numeric || !rhs.is_numeric)
+ die("Type error: operator '&' requires integer operands");
+ result->set_uint(result->to_uint() & rhs.to_uint());
+ }
+ else
+ break;
+ }
+}
+
+
+static void bitwise_or(Expression_value *result, const char **s)
+{
+ Expression_value rhs;
+
+ bitwise_and(result, s);
+ while (true)
+ {
+ if (match(s, "|") && !match(s, "||"))
+ {
+ rhs.reset();
+ bitwise_and(&rhs, s);
+ if (!result->is_numeric || !rhs.is_numeric)
+ die("Type error: operator '|' requires integer operands");
+ result->set_uint(result->to_uint() | rhs.to_uint());
+ }
+ else
+ break;
+ }
+}
+
+
+static void comparison(Expression_value *result, const char **s)
+{
+ Expression_value rhs;
+
+ bitwise_or(result, s);
+ while (true)
+ {
+ if (match(s, "<="))
+ {
+ rhs.reset();
+ bitwise_or(&rhs, s);
+ if (result->type == EXPR_NULL || rhs.type == EXPR_NULL)
+ result->reset();
+ else if (!result->is_numeric || !rhs.is_numeric)
+ die("Type error: operator '<=' requires integer operands");
+ else
+ result->set_bool(cmp_numeric(*result, rhs) <= 0);
+ }
+ else if (match(s, ">="))
+ {
+ rhs.reset();
+ bitwise_or(&rhs, s);
+ if (result->type == EXPR_NULL || rhs.type == EXPR_NULL)
+ result->reset();
+ else if (!result->is_numeric || !rhs.is_numeric)
+ die("Type error: operator '>=' requires integer operands");
+ else
+ result->set_bool(cmp_numeric(*result, rhs) >= 0);
+ }
+ else if (match(s, "<"))
+ {
+ rhs.reset();
+ bitwise_or(&rhs, s);
+ if (result->type == EXPR_NULL || rhs.type == EXPR_NULL)
+ result->reset();
+ else if (!result->is_numeric || !rhs.is_numeric)
+ die("Type error: operator '<' requires integer operands");
+ else
+ result->set_bool(cmp_numeric(*result, rhs) < 0);
+ }
+ else if (match(s, ">"))
+ {
+ rhs.reset();
+ bitwise_or(&rhs, s);
+ if (result->type == EXPR_NULL || rhs.type == EXPR_NULL)
+ result->reset();
+ else if (!result->is_numeric || !rhs.is_numeric)
+ die("Type error: operator '>' requires integer operands");
+ else
+ result->set_bool(cmp_numeric(*result, rhs) > 0);
+ }
+ else
+ break;
+ }
+}
+
+
+static void equality(Expression_value *result, const char **s)
+{
+ Expression_value rhs;
+
+ comparison(result, s);
+ while (true)
+ {
+ if (match(s, "=="))
+ {
+ rhs.reset();
+ comparison(&rhs, s);
+
+ if (result->type == EXPR_NULL || rhs.type == EXPR_NULL)
+ {
+ result->reset();
+ }
+ else if (result->is_numeric && rhs.is_numeric)
+ {
+ result->set_bool(cmp_numeric(*result, rhs) == 0);
+ }
+ else if (result->type == EXPR_STRING && rhs.type == EXPR_STRING)
+ {
+ result->set_bool(!strcmp(result->str_val.c_ptr(), rhs.str_val.c_ptr()));
+ }
+ else
+ {
+ result->set_bool(false); // different types are not equal
+ }
+ }
+ else if (match(s, "!="))
+ {
+ rhs.reset();
+ comparison(&rhs, s);
+
+ if (result->type == EXPR_NULL || rhs.type == EXPR_NULL)
+ {
+ result->reset();
+ }
+ else if (result->is_numeric && rhs.is_numeric)
+ {
+ result->set_bool(cmp_numeric(*result, rhs) != 0);
+ }
+ else if (result->type == EXPR_STRING && rhs.type == EXPR_STRING)
+ {
+ result->set_bool(strcmp(result->str_val.c_ptr(), rhs.str_val.c_ptr()) != 0);
+ }
+ else
+ {
+ result->set_bool(true); // different types are not equal
+ }
+ }
+ else
+ break;
+ }
+}
+
+
+static void logical_and(Expression_value *result, const char **s)
+{
+ Expression_value rhs;
+
+ equality(result, s);
+ while (match(s, "&&"))
+ {
+ rhs.reset();
+ equality(&rhs, s);
+ if (!result->is_numeric || !rhs.is_numeric)
+ die("Type error: operator '&&' requires integer operands");
+ result->set_bool(result->to_int() && rhs.to_int());
+ }
+}
+
+
+static void logical_or(Expression_value *result, const char **s)
+{
+ Expression_value rhs;
+
+ logical_and(result, s);
+ while (match(s, "||"))
+ {
+ rhs.reset();
+ logical_and(&rhs, s);
+ if (!result->is_numeric || !rhs.is_numeric)
+ die("Type error: operator '||' requires integer operands");
+ result->set_bool(result->to_int() || rhs.to_int());
+ }
+}
+
+
+/**
+ @brief Parse and evaluate a mathematical/logical expression
+ @param[out] result Pointer to Expression_value structure to store the result
+ @param[in] s Pointer to string pointer containing the expression to parse
+
+ @details
+ This is the main entry point for the recursive descent expression parser.
+ It parses expressions with the following grammar hierarchy (by precedence):
+
+ expr -> logical_or
+ logical_or -> logical_and (||)
+ logical_and -> equality (&&)
+ equality -> comparison (==, !=)
+ comparison -> bitwise_or (<, >, <=, >=)
+ bitwise_or -> bitwise_and (|)
+ bitwise_and -> bitwise_shift (&)
+ bitwise_shift -> term (<<, >>)
+ term -> factor (+, -)
+ factor -> bitwise_xor (*, /, %)
+ bitwise_xor -> unary (^)
+ unary -> primary (!, -, ~)
+ primary -> literals, functions, parentheses
+
+ Supported data types:
+ - INTEGERS: signed/unsigned integers (decimal, hex 0x, binary 0b)
+ - BOOLEAN: boolean values (true, false)
+ - STRINGS: quoted or unquoted string literals
+ - NULL: null values
+
+ The parser advances the string pointer *s as it consumes tokens.
+
+ @note
+ The parser does not handle overflow/underflow of large numbers after
+ the initial parsing. It is the responsibility of the caller to ensure that
+ the result of the operations is within the range of the data type (2^64-1).
+
+ @note Dies with error message if syntax error or type mismatch detected
+*/
+
+static void expr(Expression_value *result, const char **s)
+{
+ logical_or(result, s);
+}
+
+
+/* Expression function handling */
+#define MAX_FUNC_ARGS 100
+
+static struct {
+ const char *name;
+ enum func_type type;
+} function_table[]= {
+ // Numeric functions
+ {"abs", FUNC_ABS},
+ {"bin", FUNC_BIN},
+ {"conv", FUNC_CONV},
+ {"hex", FUNC_HEX},
+ {"oct", FUNC_OCT},
+ // String functions
+ {"concat", FUNC_CONCAT},
+ {"concat_ws", FUNC_CONCAT_WS},
+ {"greatest", FUNC_GREATEST},
+ {"insert", FUNC_INSERT},
+ {"instr", FUNC_INSTR},
+ {"lcase", FUNC_LOWER},
+ {"least", FUNC_LEAST},
+ {"length", FUNC_LENGTH},
+ {"locate", FUNC_LOCATE},
+ {"lower", FUNC_LOWER},
+ {"lpad", FUNC_LPAD},
+ {"ltrim", FUNC_LTRIM},
+ {"repeat", FUNC_REPEAT},
+ {"replace", FUNC_REPLACE},
+ {"reverse", FUNC_REVERSE},
+ {"rpad", FUNC_RPAD},
+ {"rtrim", FUNC_RTRIM},
+ {"substr", FUNC_SUBSTR},
+ {"substring", FUNC_SUBSTR},
+ {"substring_index", FUNC_SUBSTR_IDX},
+ {"trim", FUNC_TRIM},
+ {"ucase", FUNC_UPPER},
+ {"upper", FUNC_UPPER},
+ // Regexp functions
+ {"regexp_instr", FUNC_REGEXP_INSTR},
+ {"regexp_replace", FUNC_REGEXP_REPLACE},
+ {"regexp_substr", FUNC_REGEXP_SUBSTR},
+ // Null functions
+ {"coalesce", FUNC_COALESCE},
+ {"ifnull", FUNC_IFNULL},
+ {"nullif", FUNC_NULLIF},
+ {NULL, FUNC_UNKNOWN}
+};
+
+
+static void convert_base_helper(const My_string &str, int from_base, int to_base,
+ Expression_value *value)
+{
+ char temp_buffer[66]; // should be enough for any base
+ long long result;
+ char *endptr;
+ int err;
+ size_t str_len= str.length();
+
+ if (from_base < 0) // Negative base = treat input as SIGNED
+ result= my_strntoll_8bit(charset_info, str.ptr(), str_len, -from_base,
+ &endptr, &err);
+ else // Positive base = treat input as UNSIGNED
+ result= (long long) my_strntoull_8bit(charset_info, str.ptr(), str_len,
+ from_base, &endptr, &err);
+
+ if (err == ERANGE)
+ die("Range error: value out of range for Integer type");
+
+ if (err != 0 || endptr != str.ptr() + str_len)
+ die("invalid number '%.*s' for base %d", (int)str_len, str.ptr(), from_base);
+
+ endptr= longlong2str(result, temp_buffer, to_base);
+ if (!endptr)
+ die("could not convert number '%.*s' for base %d",
+ (int)str_len, str.ptr(), to_base);
+
+ value->set_string(temp_buffer, endptr - temp_buffer);
+}
+
+
+/**
+ @brief Compare two decimal strings numerically
+ @param[in] a First decimal string
+ @param[in] b Second decimal string
+
+ @details
+ Compares two decimal number strings treating them as numeric values.
+ Handles leading/trailing whitespace, signs, and leading zeros properly.
+
+ @return
+ -1 a < b
+ 0 a == b
+ 1 a > b
+*/
+
+static int cmp_decimal(const My_string &a, const My_string &b)
+{
+ const char *a_ptr= a.ptr();
+ const char *b_ptr= b.ptr();
+ size_t a_len= a.length();
+ size_t b_len= b.length();
+
+ // Skip leading whitespace
+ while (a_len > 0 && isspace(*a_ptr))
+ a_ptr++, a_len--;
+ while (b_len > 0 && isspace(*b_ptr))
+ b_ptr++, b_len--;
+
+ // Handle empty strings (treat as 0)
+ if (a_len == 0 && b_len == 0) return 0;
+ if (a_len == 0) return b_ptr[0] == '-' ? 1 : -1;
+ if (b_len == 0) return a_ptr[0] == '-' ? -1 : 1;
+
+ // Extract signs
+ bool a_negative= false, b_negative= false;
+ if (*a_ptr == '-') a_negative= true, a_ptr++, a_len--;
+ else if (*a_ptr == '+') a_ptr++, a_len--;
+
+ if (*b_ptr == '-') b_negative= true, b_ptr++, b_len--;
+ else if (*b_ptr == '+') b_ptr++, b_len--;
+
+ // Skip leading zeros
+ while (a_len > 0 && *a_ptr == '0') a_ptr++, a_len--;
+ while (b_len > 0 && *b_ptr == '0') b_ptr++, b_len--;
+
+ // Find actual numeric length (digits only)
+ size_t a_digits= 0, b_digits= 0;
+ for (size_t i= 0; i < a_len && isdigit(a_ptr[i]); i++) a_digits++;
+ for (size_t i= 0; i < b_len && isdigit(b_ptr[i]); i++) b_digits++;
+
+ // Handle zero cases after removing leading zeros
+ bool a_is_zero= (a_digits == 0);
+ bool b_is_zero= (b_digits == 0);
+
+ if (a_is_zero && b_is_zero) return 0;
+ if (a_is_zero) return b_negative ? 1 : -1;
+ if (b_is_zero) return a_negative ? -1 : 1;
+
+ // Different signs: negative < positive
+ if (a_negative && !b_negative) return -1;
+ if (!a_negative && b_negative) return 1;
+
+ // Same sign: compare absolute values
+ int abs_cmp= 0;
+
+ // First compare by number of digits
+ if (a_digits != b_digits)
+ {
+ abs_cmp= (a_digits > b_digits) ? 1 : -1;
+ }
+ else
+ {
+ // Same number of digits: compare digit by digit
+ for (size_t i= 0; i < a_digits; i++)
+ {
+ if (a_ptr[i] != b_ptr[i])
+ {
+ abs_cmp= (a_ptr[i] > b_ptr[i]) ? 1 : -1;
+ break;
+ }
+ }
+ }
+
+ // If both negative, reverse the comparison result
+ return a_negative ? -abs_cmp : abs_cmp;
+}
+
+
+/* Expression Built-in Function Implementations */
+
+
+/**
+ @brief Absolute value function
+ @param[in] args Array of function arguments
+ @param[in] count Number of arguments
+ @param[out] result Expression_value to store result
+
+ @details
+ ABS(X) returns the absolute (positive) value of X.
+
+ @note Dies if argument count != 1 or argument is not numeric
+*/
+
+void func_abs(Expression_value args[], int count, Expression_value *result)
+{
+ if (count != 1)
+ die("abs() expects 1 argument, got %d", count);
+
+ if (!args[0].is_numeric)
+ die("abs() requires numeric argument");
+
+ result->set_int(abs(args[0].to_int()));
+}
+
+
+/**
+ @brief Base conversion function
+ @param[in] args Array of function arguments
+ @param[in] count Number of arguments
+ @param[out] result Expression_value to store result
+
+ @details
+ Converts numbers between different bases.
+ CONV(N, from_base, to_base) converts number N from base from_base to base to_base.
+ Bases can be from 2 to 62. Negative bases treat input as signed.
+
+ @note Dies if argument count != 3, bases not numeric, or bases out of range
+*/
+
+void func_conv(Expression_value args[], int count, Expression_value *result)
+{
+ int from_base;
+ int to_base;
+
+ if (count != 3)
+ die("conv() expects 3 arguments (N, from_base, to_base), got %d", count);
+
+ from_base= (int)args[1].to_int();
+ to_base= (int)args[2].to_int();
+
+ if (!args[1].is_numeric || !args[2].is_numeric)
+ die("conv() bases must be numeric");
+
+ if (abs(from_base) < 2 || abs(from_base) > 62)
+ die("conv() from_base must be between 2 and 62, got %d", from_base);
+ if (abs(to_base) < 2 || abs(to_base) > 62)
+ die("conv() to_base must be between 2 and 62, got %d", to_base);
+
+ convert_base_helper(args[0].to_string(), from_base, to_base, result);
+}
+
+
+/**
+ @brief Binary conversion function
+ @param[in] args Array of function arguments
+ @param[in] count Number of arguments
+ @param[out] result Expression_value to store result
+
+ @details
+ Converts a number to binary representation.
+ BIN(N) returns a string representation of the binary value of N.
+ This is equivalent to CONV(N, 10, 2).
+
+ @note Dies if argument count != 1
+*/
+
+void func_bin(Expression_value args[], int count, Expression_value *result)
+{
+ if (count != 1)
+ die("bin() expects 1 argument, got %d", count);
+
+ convert_base_helper(args[0].to_string(), 10, 2, result);
+}
+
+
+/**
+ @brief Octal conversion function
+ @param[in] args Array of function arguments
+ @param[in] count Number of arguments
+ @param[out] result Expression_value to store result
+
+ @details
+ Converts a number to octal representation.
+ OCT(N) returns a string representation of the octal value of N.
+ This is equivalent to CONV(N, 10, 8).
+
+ @note Dies if argument count != 1
+*/
+
+void func_oct(Expression_value args[], int count, Expression_value *result)
+{
+ if (count != 1)
+ die("oct() expects 1 argument, got %d", count);
+
+ convert_base_helper(args[0].to_string(), 10, 8, result);
+}
+
+
+/**
+ @brief Hexadecimal conversion function
+ @param[in] args Array of function arguments
+ @param[in] count Number of arguments
+ @param[out] result Expression_value to store result
+
+ @details
+ Converts a number to hexadecimal representation.
+ HEX(N) returns a string representation of the hexadecimal value of N.
+ This is equivalent to CONV(N, 10, 16).
+
+ @note Dies if argument count != 1
+*/
+
+void func_hex(Expression_value args[], int count, Expression_value *result)
+{
+ if (count != 1)
+ die("hex() expects 1 argument, got %d", count);
+
+ convert_base_helper(args[0].to_string(), 10, 16, result);
+}
+
+
+/**
+ @brief String search function
+ @param[in] args Array of function arguments
+ @param[in] count Number of arguments
+ @param[out] result Expression_value to store result
+
+ @details
+ INSTR(str, substr) returns position of first occurrence of substr in str.
+ Returns 0 if not found. Positions start at 1. Performs a case-insensitive
+ search.
+
+ @note Dies if less than 2 arguments
+*/
+
+void func_instr(Expression_value args[], int count, Expression_value *result)
+{
+ if (count < 2)
+ die("instr() expects 2 arguments (str, substr), got %d", count);
+
+ my_match_t match;
+ My_string str= args[0].to_string();
+ My_string substr= args[1].to_string();
+
+ if (charset_info->coll->instr(charset_info, str.ptr(), str.length(),
+ substr.ptr(), substr.length(), &match, 1))
+ result->set_int(match.mb_len + 1);
+ else
+ result->set_int(0);
+}
+
+
+/**
+ @brief Locate substring function
+ @param[in] args Array of function arguments
+ @param[in] count Number of arguments
+ @param[out] result Expression_value to store result
+
+ @details
+ LOCATE(substr, str [, start]) returns position of substr in str starting from
+ start (default 1). Returns 0 if substr is not in str. Positions start at 1.
+ Performs a case-insensitive search.
+
+ @note Dies if wrong argument count or non-numeric start position
+*/
+
+void func_locate(Expression_value args[], int count, Expression_value *result)
+{
+ if (count < 2 || count > 3)
+ die("locate() expects 2 or 3 arguments (substr, str [, start]), got %d", count);
+
+ if (count == 3 && !args[2].is_numeric)
+ die("locate() start position must be numeric");
+
+ My_string substr= args[0].to_string();
+ My_string str= args[1].to_string();
+
+ long long start= 0;
+ long long start0= 0;
+ my_match_t match;
+
+ if (count == 3)
+ {
+ start0= start= args[2].to_int() - 1;
+
+ if (start < 0 || start > (longlong)str.length())
+ {
+ result->set_int(0);
+ return;
+ }
+
+ start= str.charpos((int) start);
+
+ // Substring is longer than str at start position.
+ if (start + substr.length() > str.length())
+ {
+ result->set_int(0);
+ return;
+ }
+ }
+
+ if (!substr.length())
+ {
+ result->set_int(start + 1);
+ return;
+ }
+
+ if (charset_info->coll->instr(charset_info, str.ptr() + start,
+ (uint)(str.length() - start),
+ substr.ptr(), substr.length(), &match, 1))
+ result->set_int((longlong)match.mb_len + start0 + 1);
+ else
+ result->set_int(0);
+}
+
+
+/**
+ @brief String replacement function
+ @param[in] args Array of function arguments
+ @param[in] count Number of arguments
+ @param[out] result Expression_value to store result
+
+ @details
+ REPLACE(str, from_str, to_str) replaces all occurrences of from_str with
+ to_str. Performs a case-sensitive match when searching for from_str.
+
+ @note Dies if argument count != 3 or arguments are numeric
+*/
+
+void func_replace(Expression_value args[], int count, Expression_value *result)
+{
+ if (count != 3)
+ die("replace() expects 3 arguments (str, from, to), got %d", count);
+
+ if (args[0].is_numeric || args[1].is_numeric || args[2].is_numeric)
+ die("replace() arguments must be strings");
+
+ My_string str= args[0].to_string();
+ My_string from_str= args[1].to_string();
+ My_string to_str= args[2].to_string();
+
+ if (from_str.length() == 0)
+ {
+ result->set_string(str.ptr(), str.length());
+ return;
+ }
+
+ My_string result_str;
+ result_str.copy(str);
+
+ int pos= 0;
+ while ((pos= result_str.strstr(from_str, pos)) >= 0)
+ {
+ result_str.replace(pos, from_str.length(), to_str.ptr(), to_str.length());
+ pos += to_str.length();
+ }
+
+ result->set_string(result_str.ptr(), result_str.length());
+}
+
+
+/**
+ @brief Substring extraction function
+ @param[in] args Array of function arguments
+ @param[in] count Number of arguments
+ @param[out] result Expression_value to store result
+
+ @details
+ SUBSTR(str, pos [, len]) returns substring starting at position pos.
+ Positions start at 1. Negative positions count from end.
+
+ @note Dies if wrong argument count or non-numeric position/length
+*/
+
+void func_substr(Expression_value args[], int count, Expression_value *result)
+{
+ if (count < 2 || count > 3)
+ die("substr() expects 2 or 3 arguments (str, start [, length]), got %d", count);
+
+ if (args[0].is_numeric)
+ die("substr() first argument must be a string");
+
+ if (!args[1].is_numeric)
+ die("substr() start position must be numeric");
+
+ if (count == 3 && !args[2].is_numeric)
+ die("substr() length must be numeric");
+
+ My_string str= args[0].to_string();
+ int start= (int)args[1].to_int();
+ int length= count == 3 ? (int)args[2].to_int() : str.length();
+
+ if (start == 0 || start > (int)str.length() || length <= 0)
+ {
+ result->set_string("", 0);
+ return;
+ }
+
+ if (start < 0)
+ start= str.length() + start;
+ else
+ start--;
+
+ int end= str.length();
+ if (count == 3)
+ {
+ end= start + length;
+ if (end > (int)str.length())
+ end= str.length();
+ }
+
+ if (start >= end || start >= (int)str.length() || start < 0)
+ {
+ result->set_string("", 0);
+ return;
+ }
+
+ result->set_string(str.ptr() + start, end - start);
+}
+
+
+/**
+ @brief String concatenation function
+ @param[in] args Array of function arguments
+ @param[in] count Number of arguments
+ @param[out] result Expression_value to store result
+
+ @details
+ CONCAT(str1, str2, ...) returns the string that results from concatenating
+ arguments.
+
+ @note Dies if no arguments provided
+*/
+
+void func_concat(Expression_value args[], int count, Expression_value *result)
+{
+ if (count == 0)
+ die("concat() expects at least 1 argument");
+
+ My_string result_str= args[0].to_string();
+
+ for (int i= 1; i < count; ++i)
+ {
+ result_str.append(args[i].to_string());
+ }
+
+ result->set_string(result_str.ptr(), result_str.length());
+}
+
+
+/**
+ @brief String concatenation with separator function
+ @param[in] args Array of function arguments
+ @param[in] count Number of arguments
+ @param[out] result Expression_value to store result
+
+ @details
+ CONCAT_WS(separator, str1, str2, ...) concatenates strings using separator.
+ If separator is NULL, returns NULL; all other NULL values are skipped.
+
+ @note Dies if less than 2 arguments provided
+*/
+
+void func_concat_ws(Expression_value args[], int count, Expression_value *result)
+{
+ if (count < 2)
+ die("concat_ws() expects at least 2 arguments");
+
+ if (args[0].type == EXPR_NULL)
+ {
+ result->reset();
+ return;
+ }
+
+ My_string separator= args[0].to_string();
+ My_string result_str= args[1].to_string();
+
+ for (int i= 2; i < count; ++i)
+ {
+ if (args[i].type == EXPR_NULL)
+ continue;
+ result_str.append(separator);
+ result_str.append(args[i].to_string());
+ }
+
+ result->set_string(result_str.ptr(), result_str.length());
+}
+
+
+/**
+ @brief String case conversion to lowercase
+ @param[in] args Array of function arguments
+ @param[in] count Number of arguments
+ @param[out] result Expression_value to store result
+
+ @details
+ LOWER(str) returns string str with all characters converted to lowercase.
+ LCASE(str) is an alias for LOWER(str).
+
+ @note Dies if argument count != 1
+*/
+
+void func_lower(Expression_value args[], int count, Expression_value *result)
+{
+ if (count != 1)
+ die("lower() expects 1 argument, got %d", count);
+
+ My_string result_str;
+ result_str.copy_casedn(charset_info, args[0].to_string().to_lex_cstring());
+
+ result->set_string(result_str.ptr(), result_str.length());
+}
+
+
+/**
+ @brief String case conversion to uppercase
+ @param[in] args Array of function arguments
+ @param[in] count Number of arguments
+ @param[out] result Expression_value to store result
+
+ @details
+ UPPER(str) returns string str with all characters converted to uppercase.
+ UCASE(str) is an alias for UPPER(str).
+
+ @note Dies if argument count != 1
+*/
+
+void func_upper(Expression_value args[], int count, Expression_value *result)
+{
+ if (count != 1)
+ die("upper() expects 1 argument, got %d", count);
+
+ My_string result_str;
+ result_str.copy_caseup(charset_info, args[0].to_string().to_lex_cstring());
+
+ result->set_string(result_str.ptr(), result_str.length());
+}
+
+
+/**
+ @brief String reversal function
+ @param[in] args Array of function arguments
+ @param[in] count Number of arguments
+ @param[out] result Expression_value to store result
+
+ @details
+ REVERSE(str) returns the string str with the order of the characters reversed.
+
+ @note Dies if argument count != 1
+*/
+
+void func_reverse(Expression_value args[], int count, Expression_value *result)
+{
+ if (count != 1)
+ die("reverse() expects 1 argument, got %d", count);
+
+ My_string str= args[0].to_string();
+
+ size_t len= str.length();
+ for (size_t i= 0; i < len / 2; ++i)
+ {
+ char temp= str.c_ptr()[i];
+ str.c_ptr()[i]= str.c_ptr()[len - 1 - i];
+ str.c_ptr()[len - 1 - i]= temp;
+ }
+
+ result->set_string(str.ptr(), str.length());
+}
+
+
+/**
+ @brief String trimming function
+ @param[in] args Array of function arguments
+ @param[in] count Number of arguments
+ @param[out] result Expression_value to store result
+
+ @details
+ TRIM(str) returns string str with leading and trailing space removed.
+
+ @note Dies if argument count != 1
+*/
+
+void func_trim(Expression_value args[], int count, Expression_value *result)
+{
+ if (count != 1)
+ die("trim() expects 1 argument, got %d", count);
+
+ My_string str= args[0].to_string();
+
+ int start= 0;
+ while (start < (int)str.length() && my_isspace(charset_info, str.ptr()[start]))
+ start++;
+
+ int end= (int)str.length();
+ while (end > start && my_isspace(charset_info, str.ptr()[end - 1]))
+ end--;
+
+ result->set_string(str.ptr() + start, end - start);
+}
+
+
+/**
+ @brief Left string trimming function
+ @param[in] args Array of function arguments
+ @param[in] count Number of arguments
+ @param[out] result Expression_value to store result
+
+ @details
+ LTRIM(str) returns string str with leading space removed.
+
+ @note Dies if argument count != 1
+*/
+
+void func_ltrim(Expression_value args[], int count, Expression_value *result)
+{
+ if (count != 1)
+ die("ltrim() expects 1 argument, got %d", count);
+
+ My_string str= args[0].to_string();
+
+ int start= 0;
+ while (start < (int)str.length() && my_isspace(charset_info, str.ptr()[start]))
+ start++;
+
+ result->set_string(str.ptr() + start, (int)str.length() - start);
+}
+
+
+/**
+ @brief Right string trimming function
+ @param[in] args Array of function arguments
+ @param[in] count Number of arguments
+ @param[out] result Expression_value to store result
+
+ @details
+ RTRIM(str) returns string str with trailing space removed.
+
+ @note Dies if argument count != 1
+*/
+
+void func_rtrim(Expression_value args[], int count, Expression_value *result)
+{
+ if (count != 1)
+ die("rtrim() expects 1 argument, got %d", count);
+
+ My_string str= args[0].to_string();
+
+ int end= (int)str.length();
+ while (end > 0 && my_isspace(charset_info, str.ptr()[end - 1]))
+ end--;
+
+ result->set_string(str.ptr(), end);
+}
+
+
+/**
+ @brief Left padding function
+ @param[in] args Array of function arguments
+ @param[in] count Number of arguments
+ @param[out] result Expression_value to store result
+
+ @details
+ LPAD(str, len [, padstr]) returns the string str, left-padded with the
+ string padstr to a length of len characters. If str is longer than len,
+ the return value is shortened to len characters. If padstr is omitted,
+ the LPAD function pads spaces.
+
+ @note Dies if wrong argument count, non-numeric length, or negative length
+*/
+
+void func_lpad(Expression_value args[], int count, Expression_value *result)
+{
+ if (count != 2 && count != 3)
+ die("lpad() expects 2 or 3 arguments (str, length [, padstr]), got %d", count);
+
+ if (!args[1].is_numeric)
+ die("lpad() length must be numeric");
+
+ My_string str= args[0].to_string();
+ int length= (int)args[1].to_int();
+ My_string padstr= count == 3 ? args[2].to_string() : My_string();
+ My_string result_str;
+
+ if (length < 0)
+ die("lpad() length cannot be negative");
+
+ if (count == 3 && padstr.is_empty())
+ {
+ result->set_string("", 0);
+ return;
+ }
+
+ if (length <= (int) str.length())
+ {
+ result->set_string(str.ptr(), length);
+ return;
+ }
+
+ int padding_needed= length - (int)str.length();
+ if (count == 2)
+ {
+ for (int i= 0; i < padding_needed; ++i)
+ result_str.append(" ", 1);
+ }
+ else
+ {
+ for (int i= 0; i < padding_needed; ++i)
+ result_str.append(&padstr.ptr()[i % padstr.length()], 1);
+ }
+
+ result_str.append(str.ptr(), str.length());
+ result->set_string(result_str.ptr(), result_str.length());
+}
+
+
+/**
+ @brief Right padding function
+ @param[in] args Array of function arguments
+ @param[in] count Number of arguments
+ @param[out] result Expression_value to store result
+
+ @details
+ RPAD(str, len [, padstr]) returns the string str, right-padded with the
+ string padstr to a length of len characters. If str is longer than len,
+ the return value is shortened to len characters. If padstr is omitted,
+ the RPAD function pads spaces.
+
+ @note Dies if wrong argument count, non-numeric length, or negative length
+*/
+
+void func_rpad(Expression_value args[], int count, Expression_value *result)
+{
+ if (count != 2 && count != 3)
+ die("rpad() expects 2 or 3 arguments (str, length [, padstr]), got %d", count);
+
+ if (!args[1].is_numeric)
+ die("rpad() length must be numeric");
+
+ My_string str= args[0].to_string();
+ int length= (int)args[1].to_int();
+ My_string padstr= count == 3 ? args[2].to_string() : My_string();
+
+ if (length < 0)
+ die("rpad() length cannot be negative");
+
+ if (count == 3 && padstr.is_empty())
+ {
+ result->set_string("", 0);
+ return;
+ }
+
+ if (length <= (int)str.length())
+ {
+ result->set_string(str.ptr(), length);
+ return;
+ }
+
+ int padding_needed= length - (int)str.length();
+
+ if (count == 2)
+ {
+ for (int i= 0; i < padding_needed; ++i)
+ str.append(" ", 1);
+ }
+ else
+ {
+ for (int i= 0; i < padding_needed; ++i)
+ str.append(&padstr.ptr()[i % padstr.length()], 1);
+ }
+
+ result->set_string(str.ptr(), str.length());
+}
+
+
+/**
+ @brief String length function
+ @param[in] args Array of function arguments
+ @param[in] count Number of arguments
+ @param[out] result Expression_value to store result
+
+ @details
+ LENGTH(str) returns the length of the string str.
+
+ @note Dies if argument count != 1
+*/
+
+void func_length(Expression_value args[], int count, Expression_value *result)
+{
+ if (count != 1)
+ die("length() expects 1 argument, got %d", count);
+
+ result->set_int((long long) args[0].to_string().length());
+}
+
+
+/**
+ @brief Substring index function
+ @param[in] args Array of function arguments
+ @param[in] count Number of arguments
+ @param[out] result Expression_value to store result
+
+ @details
+ SUBSTRING_INDEX(str, delim, count) returns substring before count occurrences
+ of delim (counting from the left). If count is negative, returns substring
+ after count occurrences from end (counting from the right). Performs a
+ case-sensitive match when searching for delim.
+
+ @note Dies if argument count != 3 or count is not numeric
+*/
+
+void func_substring_index(Expression_value args[], int count,
+ Expression_value *result)
+{
+ if (count != 3)
+ die("substring_index() expects 3 arguments (str, delimiter, count), got %d", count);
+
+ if (!args[2].is_numeric)
+ die("substring_index() count must be numeric");
+
+ My_string str= args[0].to_string();
+ My_string delimiter= args[1].to_string();
+ int count_val= (int)args[2].to_int();
+
+ if (str.is_empty() || delimiter.is_empty() || !count_val)
+ {
+ result->set_string("", 0);
+ return;
+ }
+
+ const char *str_ptr= str.ptr();
+ const char *str_end= str.end();
+ const char *delim_ptr= delimiter.ptr();
+ int delim_len= (int)delimiter.length();
+
+ if (count_val > 0)
+ {
+ const char *current_pos= str_ptr;
+ int found_count= 0;
+
+ while (current_pos < str_end && found_count < count_val)
+ {
+ const char *found= strstr(current_pos, delim_ptr);
+ if (!found)
+ break;
+
+ found_count++;
+ if (found_count < count_val)
+ current_pos= found + delim_len;
+ else
+ current_pos= found;
+ }
+
+ if (found_count < count_val)
+ result->set_string(str.ptr(), str.length());
+ else
+ result->set_string(str.ptr(), current_pos - str_ptr);
+ }
+ else
+ {
+ count_val= -count_val;
+ const char *current_pos= str_end;
+ int found_count= 0;
+
+ while (current_pos > str_ptr && found_count < count_val)
+ {
+ const char *found= NULL;
+ const char *search_pos= str_ptr;
+
+ while (search_pos < current_pos)
+ {
+ const char *temp_found= strstr(search_pos, delim_ptr);
+ if (!temp_found || temp_found >= current_pos)
+ break;
+ found= temp_found;
+ search_pos= temp_found + delim_len;
+ }
+
+ if (!found)
+ break;
+
+ found_count++;
+ if (found_count < count_val)
+ current_pos= found;
+ else
+ current_pos= found + delim_len;
+ }
+
+ if (found_count < count_val)
+ result->set_string(str.ptr(), str.length());
+ else
+ result->set_string(current_pos, str_end - current_pos);
+ }
+}
+
+
+/**
+ @brief String repetition function
+ @param[in] args Array of function arguments
+ @param[in] count Number of arguments
+ @param[out] result Expression_value to store result
+
+ @details
+ REPEAT(str, count) returns string consisting of str repeated count times.
+ If count is less than 1, returns an empty string.
+
+ @note Dies if argument count != 2 or count is not numeric
+*/
+
+void func_repeat(Expression_value args[], int count, Expression_value *result)
+{
+ if (count != 2)
+ die("repeat() expects 2 arguments (str, count), got %d", count);
+
+ if (!args[1].is_numeric)
+ die("repeat() count must be numeric");
+
+ My_string result_str;
+ My_string str= args[0].to_string();
+ int repeat_count= (int)args[1].to_int();
+
+ if (repeat_count <= 0 || str.is_empty())
+ {
+ result->set_string("", 0);
+ return;
+ }
+
+ if ((ulonglong) repeat_count > INT_MAX32)
+ repeat_count= INT_MAX32;
+
+ for (int i= 0; i < repeat_count; ++i)
+ {
+ result_str.append(str.ptr(), str.length());
+ }
+
+ result->set_string(result_str.ptr(), result_str.length());
+}
+
+
+/**
+ @brief String insertion function
+ @param[in] args Array of function arguments
+ @param[in] count Number of arguments
+ @param[out] result Expression_value to store result
+
+ @details
+ INSERT(str, pos, len, newstr) replaces len characters starting at pos with
+ newstr. Returns the original string if pos is not within the length of the string.
+ Replaces the rest of the string from position pos if len is not
+ within the length of the rest of the string.
+
+ @note Dies if argument count != 4 or position/length not numeric
+*/
+
+void func_insert(Expression_value args[], int count, Expression_value *result)
+{
+ if (count != 4)
+ die("insert() expects 4 arguments (str, pos, len, newstr), got %d", count);
+
+ if (!args[1].is_numeric)
+ die("insert() position must be numeric");
+
+ if (!args[2].is_numeric)
+ die("insert() length must be numeric");
+
+ My_string str= args[0].to_string();
+ int pos= (int)args[1].to_int();
+ int len= (int)args[2].to_int();
+ My_string newstr= args[3].to_string();
+ My_string result_str;
+
+
+ if (pos <= 0 || pos > (int)str.length())
+ {
+ result->set_string(str.ptr(), str.length());
+ return;
+ }
+
+ pos--;
+
+ int end_pos;
+ if (len < 0)
+ {
+ end_pos= str.length();
+ }
+ else
+ {
+ end_pos= pos + len;
+ if (end_pos > (int)str.length())
+ end_pos= str.length();
+ }
+
+ if (pos > 0)
+ result_str.append(str.ptr(), pos);
+
+ result_str.append(newstr.ptr(), newstr.length());
+
+ if (end_pos < (int)str.length())
+ result_str.append(str.ptr() + end_pos, str.length() - end_pos);
+
+ result->set_string(result_str.ptr(), result_str.length());
+}
+
+
+/**
+ @brief Regular expression position function
+ @param[in] args Array of function arguments
+ @param[in] count Number of arguments
+ @param[out] result Expression_value to store result
+
+ @details
+ REGEXP_INSTR(subject, pattern) returns position of first match of pattern in
+ subject. Uses POSIX extended regular expressions with case-insensitive
+ matching.
+
+ @note
+ The collation case sensitivity can be overwritten using the (?i) and (?-i) PCRE flags.
+
+ @note
+ The $ literal is used as a special character for variable replacement.
+
+ To use it as a regex End of Line/String Anchor, escape it with a backslash.
+ @code
+ $(regexp_instr('ABCC','C\$')) -> 4
+ @endcode
+
+ To use it as a literal, escape it with three backslashes.
+ @code
+ $(regexp_instr('ABC\$DE','\\\$')) -> 4
+ @endcode
+
+ @note Dies if argument count != 2 or regex compilation fails
+*/
+
+void func_regexp_instr(Expression_value args[], int count, Expression_value *result)
+{
+ if (count != 2)
+ die("regexp_instr() expects 2 arguments (subject, pattern), got %d", count);
+
+ regex_t regex;
+ regmatch_t match;
+ int err_code;
+ int cflags= REG_EXTENDED | REG_DOTALL | REG_ICASE;
+ My_string subject= args[0].to_string();
+ My_string pattern= args[1].to_string();
+
+ if (pattern.is_empty())
+ {
+ result->set_int(1);
+ return;
+ }
+
+ if (subject.is_empty())
+ {
+ result->set_int(0);
+ return;
+ }
+
+ if ((err_code= regcomp(®ex, pattern.ptr(), cflags)))
+ {
+ char err_buf[1024];
+ regerror(err_code, ®ex, err_buf, sizeof(err_buf));
+ die("Regex error: %s\n", err_buf);
+ }
+
+ err_code= regexec(®ex, subject.ptr(), 1, &match, 0);
+ regfree(®ex);
+
+ result->set_int(err_code ? 0 : (int)(match.rm_so + 1));
+}
+
+
+/**
+ @brief Regular expression substring extraction function
+ @param[in] args Array of function arguments
+ @param[in] count Number of arguments
+ @param[out] result Expression_value to store result
+
+ @details
+ REGEXP_SUBSTR(subject, pattern) returns substring that matches pattern.
+ Uses POSIX extended regular expressions with case-insensitive matching.
+
+ @note
+ The collation case sensitivity can be overwritten using the (?i) and (?-i) PCRE flags.
+
+ @note
+ The $ literal is used as a special character for variable replacement.
+
+ To use it as a regex End of Line/String Anchor, escape it with a backslash.
+ @code
+ $(regexp_substr('ABCC','C\$')) -> C
+ @endcode
+
+ To use it as a literal, escape it with three backslashes.
+ @code
+ $(regexp_substr('ABC\$','\\\$')) -> $
+ @endcode
+
+ @note Dies if argument count != 2 or regex compilation fails
+*/
+
+void func_regexp_substr(Expression_value args[], int count, Expression_value *result)
+{
+ if (count != 2)
+ die("regexp_substr() expects 2 arguments (subject, pattern), got %d", count);
+
+ regex_t regex;
+ regmatch_t matches[1];
+ int err_code;
+ int cflags= REG_EXTENDED | REG_DOTALL | REG_ICASE;
+ My_string subject= args[0].to_string();
+ My_string pattern= args[1].to_string();
+
+ if (subject.is_empty())
+ {
+ result->set_string("", 0);
+ return;
+ }
+
+ if ((err_code= regcomp(®ex, pattern.ptr(), cflags)))
+ {
+ char err_buf[1024];
+ regerror(err_code, ®ex, err_buf, sizeof(err_buf));
+ die("Regex error: %s\n", err_buf);
+ }
+
+ err_code= regexec(®ex, subject.ptr(), 1, matches, 0);
+ regfree(®ex);
+
+ if (err_code)
+ {
+ result->set_string("", 0);
+ }
+ else
+ {
+ regoff_t start= matches[0].rm_so;
+ regoff_t end= matches[0].rm_eo;
+ result->set_string(subject.ptr() + start, end - start);
+ }
+}
+
+
+/**
+ @brief Regular expression replacement function
+ @param[in] args Array of function arguments
+ @param[in] count Number of arguments
+ @param[out] result Expression_value to store result
+
+ @details
+ REGEXP_REPLACE(subject, pattern, replace) replaces all matches of pattern
+ with replace. Supports backreferences \0-\9 in replace string. Uses
+ POSIX extended regex.
+
+ @note
+ The collation case sensitivity can be overwritten using the (?i) and (?-i) PCRE flags.
+
+ @note
+ The $ literal is used as a special character for variable replacement.
+
+ To use it as a regex End of Line/String Anchor, escape it with a backslash.
+ @code
+ $(regexp_replace('ABCC','C\$','D')) -> ABCD
+ @endcode
+
+ To use it as a literal, escape it with three backslashes.
+ @code
+ $(regexp_replace('ABC\$','\\\$','D')) -> ABCD
+ @endcode
+
+ @note Dies if argument count != 3 or regex compilation fails
+*/
+
+void func_regexp_replace(Expression_value args[], int count,
+ Expression_value *result)
+{
+ if (count != 3)
+ die("regexp_replace() expects 3 arguments (subject, pattern, replace), got %d", count);
+
+ regex_t regex;
+ regmatch_t matches[10]; // Array to store up to 10 matches (0=full match, 1-9=capture groups)
+ int err_code;
+ int cflags= REG_EXTENDED | REG_DOTALL | REG_ICASE;
+ My_string result_str;
+ My_string subject= args[0].to_string();
+ My_string pattern= args[1].to_string();
+ My_string replace= args[2].to_string();
+ const char *current_pos= subject.ptr();
+ const char *end_pos= subject.end();
+ const char *replace_ptr;
+ const char *replace_end;
+
+ if (pattern.is_empty())
+ {
+ result->set_string(subject.ptr(), subject.length());
+ return;
+ }
+
+ if ((err_code= regcomp(®ex, pattern.ptr(), cflags)))
+ {
+ char err_buf[1024];
+ regerror(err_code, ®ex, err_buf, sizeof(err_buf));
+ die("Regex error: %s\n", err_buf);
+ }
+
+ while (current_pos < end_pos)
+ {
+ err_code= regexec(®ex, current_pos, 10, matches, 0);
+ if (err_code)
+ {
+ result_str.append(current_pos, end_pos - current_pos);
+ break;
+ }
+
+ // Append the text before the match
+ if (matches[0].rm_so > 0)
+ result_str.append(current_pos, matches[0].rm_so);
+
+ // Process replacement string with backreferences
+ replace_ptr= replace.ptr();
+ replace_end= replace.end();
+
+ while (replace_ptr < replace_end)
+ {
+ if (*replace_ptr == '\\' && replace_ptr + 1 < replace_end)
+ {
+ int back_ref_num= (int) (*(replace_ptr + 1) - '0');
+ regoff_t start_off, end_off;
+ if (back_ref_num >= 0 && back_ref_num <= 9 &&
+ (start_off=matches[back_ref_num].rm_so) > -1 &&
+ (end_off=matches[back_ref_num].rm_eo) > -1)
+ {
+ result_str.append(current_pos + start_off, end_off - start_off);
+ }
+ else
+ {
+ result_str.append(replace_ptr, 2);
+ }
+ replace_ptr+= 2;
+ continue;
+ }
+ result_str.append(replace_ptr, 1);
+ replace_ptr++;
+ }
+
+ current_pos+= matches[0].rm_eo;
+
+ if (matches[0].rm_so == matches[0].rm_eo)
+ current_pos++;
+ }
+
+ regfree(®ex);
+ result->set_string(result_str.ptr(), result_str.length());
}
-static const char *get_col_value(MYSQL_RES *res, MYSQL_ROW row, const char *name)
+
+/**
+ @brief NULL-aware conditional function
+ @param[in] args Array of function arguments
+ @param[in] count Number of arguments
+ @param[out] result Expression_value to store result
+
+ @details
+ IFNULL(expr1, expr2) returns expr1 if it is not NULL, otherwise returns expr2.
+ Returns first non-NULL value.
+
+ @note Dies if argument count != 2
+*/
+
+void func_ifnull(Expression_value args[], int count, Expression_value *result)
{
- uint num_fields= mysql_num_fields(res);
- MYSQL_FIELD *fields= mysql_fetch_fields(res);
+ if (count != 2)
+ die("ifnull() expects 2 arguments, got %d", count);
- for (uint i= 0; i < num_fields; i++)
+ if (args[0].type == EXPR_NULL)
{
- if (strcmp(fields[i].name, name) == 0)
- return row[i];
+ *result= args[1];
+ return;
}
- return "NULL";
+ *result= args[0];
}
-void do_sync_with_master2(struct st_command *command, long offset,
- const char *connection_name)
-{
- MYSQL_RES *res;
- MYSQL_ROW row;
- MYSQL *mysql= cur_con->mysql;
- char query_buf[FN_REFLEN+128], query_buf2[120];
- int timeout= opt_wait_for_pos_timeout;
+/**
+ @brief NULL-if-equal function
+ @param[in] args Array of function arguments
+ @param[in] count Number of arguments
+ @param[out] result Expression_value to store result
- if (!master_pos.file[0])
- die("Calling 'sync_with_master' without calling 'save_master_pos'");
+ @details
+ NULLIF(expr1, expr2) returns NULL if expr1 = expr2, otherwise returns expr1.
+ This is the same as `CASE WHEN expr1 = expr2 THEN NULL ELSE expr1 END`.
- sprintf(query_buf, "select master_pos_wait('%s', %ld, %d, '%s')",
- master_pos.file, master_pos.pos + offset, timeout,
- connection_name);
+ @note Dies if argument count != 2
+*/
- if (mysql_query(mysql, query_buf))
- die("failed in '%s': %d: %s", query_buf, mysql_errno(mysql),
- mysql_error(mysql));
+void func_nullif(Expression_value args[], int count, Expression_value *result)
+{
+ if (count != 2)
+ die("nullif() expects 2 arguments, got %d", count);
- if (!(res= mysql_store_result(mysql)))
- die("mysql_store_result() returned NULL for '%s'", query_buf);
- if (!(row= mysql_fetch_row(res)))
+ /* If first is NULL, result is NULL (returns expr1) */
+ if (args[0].type == EXPR_NULL)
{
- mysql_free_result(res);
- die("empty result in %s", query_buf);
+ result->reset();
+ return;
}
- int result= -99;
- const char* result_str= row[0];
- if (result_str)
- result= atoi(result_str);
+ bool equal= false;
+ if (args[0].is_numeric && args[1].is_numeric)
+ {
+ if (args[0].is_unsigned || args[1].is_unsigned)
+ equal= (args[0].to_uint() == args[1].to_uint());
+ else
+ equal= (args[0].to_int() == args[1].to_int());
+ }
+ else
+ {
+ equal= !(strcmp(args[0].to_string().c_ptr(), args[1].to_string().c_ptr()));
+ }
- mysql_free_result(res);
+ if (equal)
+ result->reset();
+ else
+ *result= args[0];
+}
- if (!result_str || result < 0)
- {
- /* master_pos_wait returned NULL or < 0 */
- fprintf(stderr, "analyze: sync_with_master\n");
- sprintf(query_buf2, "show slave \"%s\" status", connection_name);
+/**
+ @brief First non-NULL value function
+ @param[in] args Array of function arguments
+ @param[in] count Number of arguments
+ @param[out] result Expression_value to store result
- if (!mysql_query(mysql, query_buf2))
+ @details
+ COALESCE(value1, value2, ...) returns first non-NULL value in list.
+ Returns NULL if all values are NULL.
+
+ @note Dies if no arguments provided
+*/
+
+void func_coalesce(Expression_value args[], int count, Expression_value *result)
+{
+ if (count < 1)
+ die("coalesce() expects at least 1 argument");
+
+ for (int i= 0; i < count; ++i)
+ {
+ if (args[i].type != EXPR_NULL)
{
- if ((res= mysql_store_result(mysql)))
- {
- if ((row= mysql_fetch_row(res)))
- {
- fprintf(stderr, "Slave position: file: %s position: %s\n",
- get_col_value(res, row, "Relay_Master_Log_File"),
- get_col_value(res, row, "Read_Master_Log_Pos"));
- fprintf(stderr, "Master position: file: %s position: %lld\n",
- master_pos.file, (longlong) (master_pos.pos + offset));
- }
- mysql_free_result(res);
- }
+ *result= args[i];
+ return;
}
- if (!result_str)
+ }
+ result->reset();
+}
+
+
+/**
+ @brief Least value function
+ @param[in] args Array of function arguments
+ @param[in] count Number of arguments
+ @param[out] result Expression_value to store result
+
+ @details
+ LEAST(value1, value2, ...) returns the minimum value among arguments.
+ For numeric values, performs numeric comparison. For strings, performs
+ string comparison.
+
+ @note
+ If mixed numeric and string values are provided, the string values are
+ converted to numbers and the numeric comparison is performed. Be careful
+ with this, as a string could contain a number that is larger than 2^64-1.
+
+ @note Dies if less than 2 arguments provided.
+*/
+
+void func_least(Expression_value args[], int count, Expression_value *result)
+{
+ if (count < 2)
+ die("least() expects at least 2 arguments");
+
+ // Numeric mode if any arg is numeric
+ bool any_numeric= false;
+ for (int i= 0; i < count; ++i)
+ if (args[i].is_numeric) { any_numeric= true; break; }
+
+ if (any_numeric)
+ {
+ int best_idx= 0;
+ for (int i= 1; i < count; ++i)
{
- /*
- master_pos_wait returned NULL. This indicates that
- slave SQL thread is not started, the slave's master
- information is not initialized, the arguments are
- incorrect, or an error has occurred
- */
- die("%.*sB failed: '%s' returned NULL " \
- "indicating slave SQL thread failure",
- command->first_word_len, command->query, query_buf);
+ if (cmp_decimal(args[i].to_string(), args[best_idx].to_string()) < 0)
+ best_idx= i;
}
-
- if (result == -1)
- die("%.*sB failed: '%s' returned -1 " \
- "indicating timeout after %d seconds",
- command->first_word_len, command->query, query_buf, timeout);
+ if(args[best_idx].is_unsigned)
+ result->set_uint(args[best_idx].to_uint());
else
- die("%.*sB failed: '%s' returned unknown result :%d",
- command->first_word_len, command->query, query_buf, result);
+ result->set_int(args[best_idx].to_int());
+ return;
}
- return;
+ // String mode: collation-aware
+ int best_idx= 0;
+ for (int i= 1; i < count; ++i)
+ {
+ My_string cur= args[i].to_string();
+ My_string best= args[best_idx].to_string();
+ if (sortcmp(&best, &cur, charset_info) > 0)
+ best_idx= i;
+ }
+ *result= args[best_idx];
}
-void do_sync_with_master(struct st_command *command)
-{
- long offset= 0;
- char *p= command->first_argument;
- const char *offset_start= p;
- char *start, *buff= 0;
- start= const_cast("");
- if (*offset_start)
- {
- for (; my_isdigit(charset_info, *p); p++)
- offset = offset * 10 + *p - '0';
+/**
+ @brief Greatest value function
+ @param[in] args Array of function arguments
+ @param[in] count Number of arguments
+ @param[out] result Expression_value to store result
+
+ @details
+ GREATEST(value1, value2, ...) returns the maximum value among arguments.
+ For numeric values, performs numeric comparison. For strings, performs
+ string comparison.
+
+ @note
+ If mixed numeric and string values are provided, the string values are
+ converted to numbers and the numeric comparison is performed. Be careful
+ with this, as a string could contain a number that is larger than 2^64-1.
+
+ @note Dies if less than 2 arguments provided.
+*/
- if (*p && !my_isspace(charset_info, *p) && *p != ',')
- die("Invalid integer argument \"%s\"", offset_start);
+void func_greatest(Expression_value args[], int count, Expression_value *result)
+{
+ if (count < 2)
+ die("greatest() expects at least 2 arguments");
- while (*p && my_isspace(charset_info, *p))
- p++;
- if (*p == ',')
+ bool any_numeric= false;
+ for (int i= 0; i < count; ++i)
+ if (args[i].is_numeric) { any_numeric= true; break; }
+
+ if (any_numeric)
+ {
+ int best_idx= 0;
+ for (int i= 1; i < count; ++i)
{
- p++;
- while (*p && my_isspace(charset_info, *p))
- p++;
- start= buff= (char*)my_malloc(PSI_NOT_INSTRUMENTED, strlen(p)+1,
- MYF(MY_WME|MY_FAE));
- get_string(&buff, &p, command);
+ if (cmp_decimal(args[i].to_string(), args[best_idx].to_string()) > 0)
+ best_idx= i;
}
- command->last_argument= p;
+ if(args[best_idx].is_unsigned)
+ result->set_uint(args[best_idx].to_uint());
+ else
+ result->set_int(args[best_idx].to_int());
+ return;
}
- do_sync_with_master2(command, offset, start);
- if (buff)
- my_free(start);
- return;
+
+ // String mode: collation-aware
+ int best_idx= 0;
+ for (int i= 1; i < count; ++i)
+ {
+ My_string best= args[best_idx].to_string();
+ My_string cur= args[i].to_string();
+ if (sortcmp(&best, &cur, charset_info) < 0)
+ best_idx= i;
+ }
+ *result= args[best_idx];
}
-int do_save_master_pos()
+enum func_type get_expr_function_type(const char *name, size_t len)
{
- MYSQL_RES *res;
- MYSQL_ROW row;
- MYSQL *mysql = cur_con->mysql;
- const char *query;
- DBUG_ENTER("do_save_master_pos");
+ for (int i= 0; function_table[i].name; ++i)
+ {
+ if (!strncasecmp(function_table[i].name, name, len))
+ return function_table[i].type;
+ }
+ return FUNC_UNKNOWN;
+}
- if (mysql_query(mysql, query= "show master status"))
- die("failed in 'show master status': %d %s",
- mysql_errno(mysql), mysql_error(mysql));
- if (!(res = mysql_store_result(mysql)))
- die("mysql_store_result() returned NULL for '%s'", query);
- if (!(row = mysql_fetch_row(res)))
- die("empty result in show master status");
- strnmov(master_pos.file, row[0], sizeof(master_pos.file)-1);
- master_pos.pos = strtoul(row[1], (char**) 0, 10);
- mysql_free_result(res);
- DBUG_RETURN(0);
+/**
+ @brief Execute built-in function call during expression parsing
+ @param[in] func_type Type of function to execute (from func_type enum)
+ @param[out] result Expression_value to store function result
+ @param[in] s Pointer to string pointer containing expression
+
+ @details
+ Parses function arguments and executes the specified built-in function.
+ Each argument is recursively evaluated as a full expression.
+ Then delegates to the appropriate func_* implementation based on func_type.
+
+ @note Dies on syntax errors or argument count mismatches
+*/
+
+void handle_expr_function_call(enum func_type func_type,
+ Expression_value *result, const char **s)
+{
+ Expression_value args[MAX_FUNC_ARGS];
+ int arg_count= 0;
+
+ while (!match(s, ")"))
+ {
+ if (arg_count >= MAX_FUNC_ARGS)
+ die("Too many function arguments (max %d)", MAX_FUNC_ARGS);
+
+ expr(&args[arg_count], s);
+ arg_count++;
+
+ /* if the next character is a comma, skip it */
+ if (match(s, ","))
+ continue;
+
+ if (match(s, ")"))
+ break;
+
+ die("Syntax error: Expected ',' or ')' in function call");
+ }
+
+ /* generic NULL propagation, except for IFNULL/NULLIF/COALESCE/CONCAT_WS */
+ if (func_type != FUNC_IFNULL && func_type != FUNC_NULLIF &&
+ func_type != FUNC_COALESCE && func_type != FUNC_CONCAT_WS)
+ {
+ for (int i= 0; i < arg_count; i++)
+ {
+ if (args[i].type == EXPR_NULL)
+ {
+ result->reset();
+ return;
+ }
+ }
+ }
+
+ switch (func_type) {
+ case FUNC_ABS:
+ func_abs(args, arg_count, result);
+ break;
+ case FUNC_CONV:
+ func_conv(args, arg_count, result);
+ break;
+ case FUNC_BIN:
+ func_bin(args, arg_count, result);
+ break;
+ case FUNC_OCT:
+ func_oct(args, arg_count, result);
+ break;
+ case FUNC_HEX:
+ func_hex(args, arg_count, result);
+ break;
+ case FUNC_INSTR:
+ func_instr(args, arg_count, result);
+ break;
+ case FUNC_LOCATE:
+ func_locate(args, arg_count, result);
+ break;
+ case FUNC_REPLACE:
+ func_replace(args, arg_count, result);
+ break;
+ case FUNC_SUBSTR:
+ func_substr(args, arg_count, result);
+ break;
+ case FUNC_CONCAT:
+ func_concat(args, arg_count, result);
+ break;
+ case FUNC_CONCAT_WS:
+ func_concat_ws(args, arg_count, result);
+ break;
+ case FUNC_LOWER:
+ func_lower(args, arg_count, result);
+ break;
+ case FUNC_UPPER:
+ func_upper(args, arg_count, result);
+ break;
+ case FUNC_REVERSE:
+ func_reverse(args, arg_count, result);
+ break;
+ case FUNC_TRIM:
+ func_trim(args, arg_count, result);
+ break;
+ case FUNC_LTRIM:
+ func_ltrim(args, arg_count, result);
+ break;
+ case FUNC_RTRIM:
+ func_rtrim(args, arg_count, result);
+ break;
+ case FUNC_LPAD:
+ func_lpad(args, arg_count, result);
+ break;
+ case FUNC_RPAD:
+ func_rpad(args, arg_count, result);
+ break;
+ case FUNC_LENGTH:
+ func_length(args, arg_count, result);
+ break;
+ case FUNC_SUBSTR_IDX:
+ func_substring_index(args, arg_count, result);
+ break;
+ case FUNC_REPEAT:
+ func_repeat(args, arg_count, result);
+ break;
+ case FUNC_INSERT:
+ func_insert(args, arg_count, result);
+ break;
+ case FUNC_LEAST:
+ func_least(args, arg_count, result);
+ break;
+ case FUNC_GREATEST:
+ func_greatest(args, arg_count, result);
+ break;
+ case FUNC_REGEXP_INSTR:
+ func_regexp_instr(args, arg_count, result);
+ break;
+ case FUNC_REGEXP_SUBSTR:
+ func_regexp_substr(args, arg_count, result);
+ break;
+ case FUNC_REGEXP_REPLACE:
+ func_regexp_replace(args, arg_count, result);
+ break;
+ case FUNC_IFNULL:
+ func_ifnull(args, arg_count, result);
+ break;
+ case FUNC_NULLIF:
+ func_nullif(args, arg_count, result);
+ break;
+ case FUNC_COALESCE:
+ func_coalesce(args, arg_count, result);
+ break;
+ case FUNC_UNKNOWN:
+ default:
+ die("Unknown function");
+ break;
+ }
}
@@ -5811,8 +8597,12 @@ void do_close_connection(struct st_command *command)
DBUG_PRINT("info", ("Closing connection %s", con->name));
#ifndef EMBEDDED_LIBRARY
if (command->type == Q_DIRTY_CLOSE)
- {
mariadb_cancel(con->mysql);
+ else
+ {
+ simple_command(con->mysql,COM_QUIT,0,0,0);
+ if (con->util_mysql)
+ simple_command(con->util_mysql,COM_QUIT,0,0,0);
}
#endif /*!EMBEDDED_LIBRARY*/
if (con->stmt)
@@ -6559,6 +9349,84 @@ void do_block(enum block_cmd cmd, struct st_command* command)
if (*p && *p != '{')
die("Missing '{' after %s. Found \"%s\"", cmd_name, p);
+ if (*expr_start == '$' && *(expr_start + 1) == '(')
+ {
+ const char *scanner= expr_start + 2;
+ int paren_level= 1;
+ char in_quote= 0; // Track quote state
+ bool escaped= false; // Track if the current character is escaped
+
+ while (*scanner && paren_level > 0)
+ {
+ if (!in_quote)
+ {
+ // Not inside quotes - handle parentheses normally
+ if (*scanner == '(') paren_level++;
+ else if (*scanner == ')') paren_level--;
+ else if (*scanner == '\'' || *scanner == '"')
+ in_quote= *scanner; // Start of quoted string
+ }
+ else
+ {
+ // Inside quotes - only look for closing quote
+ if (!escaped && *scanner == in_quote)
+ in_quote= 0; // End of quoted string
+ }
+ escaped= (!escaped && *scanner == '\\');
+ scanner++;
+ }
+
+ const char *end_ptr= expr_end;
+ while(end_ptr > expr_start && my_isspace(charset_info, *(end_ptr - 1)))
+ end_ptr--;
+
+ // if the $(...) is the entire condition, evaluate it
+ if (scanner == end_ptr)
+ {
+ DYNAMIC_STRING evaluated_expr;
+ init_dynamic_string(&evaluated_expr, "", 64, 256);
+
+ do_eval(&evaluated_expr, expr_start, expr_end, FALSE);
+
+ char* result_str= evaluated_expr.str;
+ while (*result_str && my_isspace(charset_info, *result_str))
+ result_str++;
+
+ /*
+ Setup the next block on the stack
+ This logic is borrowed from the end of this function
+ Any non-empty string which does not begin with 0 is TRUE
+ */
+ cur_block++;
+ cur_block->cmd= cmd;
+ cur_block->ok= (*result_str && *result_str != '0');
+
+ if (not_expr)
+ cur_block->ok= !cur_block->ok;
+
+ if (cur_block->ok)
+ {
+ cur_block->delim[0]= '\0';
+ }
+ else
+ {
+ /* Remember "old" delimiter if entering a false if block */
+ if (safe_strcpy_truncated(cur_block->delim, sizeof cur_block->delim,
+ delimiter))
+ die("Delimiter too long, truncated");
+ }
+
+ DBUG_PRINT("info", ("OK: %d", cur_block->ok));
+
+ dynstr_free(&evaluated_expr);
+ DBUG_VOID_RETURN;
+ }
+ else
+ {
+ die("Expression evaluator $(...) must be the entire condition");
+ }
+ }
+
var_init(&v,0,0,0,0);
/* If expression starts with a variable, it may be a compare condition */
@@ -9023,7 +11891,6 @@ void run_query_stmt(struct st_connection *cn, struct st_command *command,
var_set_errno(mysql_stmt_errno(stmt));
display_optimizer_trace(cn, ds);
- #if MYSQL_VERSION_ID >= 50000
if (cursor_protocol_enabled)
{
ulong type= CURSOR_TYPE_NO_CURSOR;
@@ -9031,7 +11898,6 @@ void run_query_stmt(struct st_connection *cn, struct st_command *command,
die("mysql_stmt_attr_set(STMT_ATTR_CURSOR_TYPE) failed': %d %s",
mysql_stmt_errno(stmt), mysql_stmt_error(stmt));
}
- #endif
revert_properties();
@@ -9248,7 +12114,6 @@ void run_execute_stmt(struct st_connection *cn, struct st_command *command,
init_dynamic_string(&ds_execute_warnings, NULL, 0, 256);
}
-#if MYSQL_VERSION_ID >= 50000
if (cursor_protocol_enabled)
{
/*
@@ -9259,7 +12124,6 @@ void run_execute_stmt(struct st_connection *cn, struct st_command *command,
die("mysql_stmt_attr_set(STMT_ATTR_CURSOR_TYPE) failed': %d %s",
mysql_stmt_errno(stmt), mysql_stmt_error(stmt));
}
-#endif
/*
Execute the query
@@ -9494,6 +12358,7 @@ int util_query(MYSQL* org_mysql, const char* query){
/* enable local infile, in non-binary builds often disabled by default */
mysql_options(mysql, MYSQL_OPT_LOCAL_INFILE, 0);
mysql_options(mysql, MYSQL_OPT_NONBLOCK, 0);
+ mysql_options(mysql,MYSQL_OPT_PROTOCOL,(char*)&(org_mysql->options.protocol));
SET_SSL_OPTS(mysql);
safe_connect(mysql, "util", org_mysql->host, org_mysql->user,
org_mysql->passwd, org_mysql->db, org_mysql->port,
@@ -9615,7 +12480,7 @@ void run_query(struct st_connection *cn, struct st_command *command, int flags)
dynstr_set(&ds_res, 0);
if (view_protocol_enabled && mysql &&
- complete_query &&
+ complete_query && !(mysql->server_status & SERVER_STATUS_IN_TRANS) &&
match_re(&view_re, query))
{
/*
diff --git a/client/readline.cc b/client/readline.cc
index e4014658c0822..f88a942f012a4 100644
--- a/client/readline.cc
+++ b/client/readline.cc
@@ -23,38 +23,11 @@
#include
#include "my_readline.h"
-static bool init_line_buffer(LINE_BUFFER *buffer,File file,ulong size,
- ulong max_size);
static bool init_line_buffer_from_string(LINE_BUFFER *buffer,char * str);
static size_t fill_buffer(LINE_BUFFER *buffer);
static char *intern_read_line(LINE_BUFFER *buffer, ulong *out_length);
-LINE_BUFFER *batch_readline_init(ulong max_size,FILE *file)
-{
- LINE_BUFFER *line_buff;
-
-#ifndef _WIN32
- MY_STAT input_file_stat;
- if (my_fstat(fileno(file), &input_file_stat, MYF(MY_WME)) ||
- MY_S_ISDIR(input_file_stat.st_mode) ||
- MY_S_ISBLK(input_file_stat.st_mode))
- return 0;
-#endif
-
- if (!(line_buff=(LINE_BUFFER*)
- my_malloc(PSI_NOT_INSTRUMENTED, sizeof(*line_buff),
- MYF(MY_WME | MY_ZEROFILL))))
- return 0;
- if (init_line_buffer(line_buff,my_fileno(file),IO_SIZE,max_size))
- {
- my_free(line_buff);
- return 0;
- }
- return line_buff;
-}
-
-
char *batch_readline(LINE_BUFFER *line_buff, bool binary_mode)
{
char *pos;
@@ -105,8 +78,7 @@ LINE_BUFFER *batch_readline_command(LINE_BUFFER *line_buff, char * str)
Functions to handle buffered readings of lines from a stream
******************************************************************************/
-static bool
-init_line_buffer(LINE_BUFFER *buffer,File file,ulong size,ulong max_buffer)
+bool init_line_buffer(LINE_BUFFER *buffer,File file,ulong size,ulong max_buffer)
{
buffer->file=file;
buffer->bufread=size;
diff --git a/cmake/build_configurations/mysql_release.cmake b/cmake/build_configurations/mysql_release.cmake
index 6b7b4d698b117..8c120642fe50f 100644
--- a/cmake/build_configurations/mysql_release.cmake
+++ b/cmake/build_configurations/mysql_release.cmake
@@ -120,8 +120,8 @@ ELSEIF(DEB)
SET(WITH_ZLIB system CACHE STRING "")
SET(WITH_LIBWRAP ON)
SET(HAVE_EMBEDDED_PRIVILEGE_CONTROL ON)
- # No hurd implementation
- IF(NOT CMAKE_SYSTEM_PROCESSOR STREQUAL "i686-AT386")
+ # On Hurd systems (GNU) there is no auth socket implementation
+ IF(NOT CMAKE_SYSTEM_NAME STREQUAL "GNU")
SET(PLUGIN_AUTH_SOCKET YES CACHE STRING "")
ENDIF()
SET(WITH_EMBEDDED_SERVER ON CACHE BOOL "")
diff --git a/cmake/build_depends.cmake b/cmake/build_depends.cmake
index 5adaee337403c..758ba184628bd 100644
--- a/cmake/build_depends.cmake
+++ b/cmake/build_depends.cmake
@@ -32,7 +32,7 @@ IF(RPM)
GET_PROPERTY(T CACHE ${V} PROPERTY TYPE)
IF ((T STREQUAL FILEPATH OR V MATCHES "^CMAKE_COMMAND$") AND ${V} MATCHES "^/")
IF (RPM)
- FIND_DEP(${V} rpm -q --qf "%{NAME}" -f ${${V}})
+ FIND_DEP(${V} rpm -q --qf "%{NAME} " -f ${${V}})
ELSE() # must be DEB
MESSAGE(FATAL_ERROR "Not implemented")
ENDIF ()
diff --git a/cmake/cpack_rpm.cmake b/cmake/cpack_rpm.cmake
index 72595e358bd0a..55645b69d2d04 100644
--- a/cmake/cpack_rpm.cmake
+++ b/cmake/cpack_rpm.cmake
@@ -229,6 +229,10 @@ SETA(CPACK_RPM_client_PACKAGE_REQUIRES
SETA(CPACK_RPM_common_PACKAGE_CONFLICTS
"MariaDB-server < 10.6.1")
+SETA(CPACK_RPM_common_PACKAGE_OBSOLETES
+ "mysql-common")
+SETA(CPACK_RPM_common_PACKAGE_PROVIDES
+ "mysql-common")
SETA(CPACK_RPM_devel_PACKAGE_OBSOLETES
"MySQL-devel")
@@ -259,14 +263,6 @@ SETA(CPACK_RPM_server_PACKAGE_REQUIRES
"MariaDB-common >= 10.6.1"
"MariaDB-client >= 11.0.0")
-IF(WITH_WSREP)
- SETA(CPACK_RPM_server_PACKAGE_REQUIRES
- "galera-4" "rsync" "grep" "gawk" "iproute"
- "coreutils" "findutils" "tar")
- SETA(CPACK_RPM_server_PACKAGE_RECOMMENDS "lsof" "socat" "pv")
- SETA(CPACK_RPM_test_PACKAGE_REQUIRES "${CPACK_RPM_PACKAGE_REQUIRES}" "socat")
-ENDIF()
-
SET(CPACK_RPM_server_PRE_INSTALL_SCRIPT_FILE ${CMAKE_SOURCE_DIR}/support-files/rpm/server-prein.sh)
SET(CPACK_RPM_server_PRE_UNINSTALL_SCRIPT_FILE ${CMAKE_SOURCE_DIR}/support-files/rpm/server-preun.sh)
SET(CPACK_RPM_server_POST_INSTALL_SCRIPT_FILE ${CMAKE_SOURCE_DIR}/support-files/rpm/server-postin.sh)
@@ -322,8 +318,6 @@ ELSEIF(RPM MATCHES "(rhel|centos|rocky)")
ALTERNATIVE_NAME("shared" "mariadb-connector-c" ${MARIADB_CONNECTOR_C_VERSION}-1)
ALTERNATIVE_NAME("shared" "mariadb-connector-c-config" ${MARIADB_CONNECTOR_C_VERSION}-1)
ALTERNATIVE_NAME("devel" "mariadb-connector-c-devel" ${MARIADB_CONNECTOR_C_VERSION}-1)
- SETA(CPACK_RPM_client_PACKAGE_PROVIDES "mariadb-galera = 3:%{version}-%{release}")
- SETA(CPACK_RPM_common_PACKAGE_PROVIDES "mariadb-galera-common = 3:%{version}-%{release}")
SETA(CPACK_RPM_common_PACKAGE_REQUIRES "MariaDB-shared")
ELSEIF(RPM MATCHES "sles")
ALTERNATIVE_NAME("server" "mariadb")
@@ -341,6 +335,9 @@ IF(RPM MATCHES "fedora")
ALTERNATIVE_NAME("shared" "mariadb-connector-c" ${MARIADB_CONNECTOR_C_VERSION}-1)
ENDIF()
+IF(RPM MATCHES "fedora|rhel|centos" AND NOT RPM MATCHES "rhel[78]")
+ SETA(CPACK_RPM_server_PACKAGE_REQUIRES "(mysql-selinux >= 1.0.14 if selinux-policy-targeted)")
+ENDIF()
SET(PYTHON_SHEBANG "/usr/bin/python3" CACHE STRING "python shebang")
################
diff --git a/cmake/info_bin.cmake b/cmake/info_bin.cmake
deleted file mode 100644
index d59b512bcec24..0000000000000
--- a/cmake/info_bin.cmake
+++ /dev/null
@@ -1,30 +0,0 @@
-# Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
-#
-# 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
-
-
-# The sole purpose of this cmake control file is to create the "INFO_BIN" file.
-
-# By having a separate cmake file for this, it is ensured this happens
-# only in the build (Unix: "make") phase, not when cmake runs.
-# This, in turn, avoids creating stuff in the source directory -
-# it should get into the binary directory only.
-
-
-# Get the macros which the "INFO_*" files.
-INCLUDE(${CMAKE_BINARY_DIR}/info_macros.cmake)
-
-# Here is where the action is.
-CREATE_INFO_BIN()
-
diff --git a/cmake/info_macros.cmake.in b/cmake/info_macros.cmake.in
deleted file mode 100644
index 89ca1ec79dc33..0000000000000
--- a/cmake/info_macros.cmake.in
+++ /dev/null
@@ -1,161 +0,0 @@
-# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
-#
-# 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
-
-
-# Handle/create the "INFO_*" files describing a MariaDB (server) binary.
-# This is part of the fix for bug#42969.
-
-
-# Several of cmake's variables need to be translated from '@' notation
-# to '${}', this is done by the "configure" call in top level "CMakeLists.txt".
-# If further variables are used in this file, add them to this list.
-
-SET(VERSION "@VERSION@")
-SET(MAJOR_VERSION "@MAJOR_VERSION@")
-SET(MINOR_VERSION "@MINOR_VERSION@")
-SET(PATCH_VERSION "@PATCH_VERSION@")
-SET(CMAKE_SOURCE_DIR "@CMAKE_SOURCE_DIR@")
-SET(CMAKE_BINARY_DIR "@CMAKE_BINARY_DIR@")
-SET(CMAKE_GENERATOR "@CMAKE_GENERATOR@")
-SET(CMAKE_SIZEOF_VOID_P "@CMAKE_SIZEOF_VOID_P@")
-SET(GIT_EXECUTABLE "@GIT_EXECUTABLE@")
-SET(CMAKE_CROSSCOMPILING "@CMAKE_CROSSCOMPILING@")
-SET(CMAKE_HOST_SYSTEM "@CMAKE_HOST_SYSTEM@")
-SET(CMAKE_HOST_SYSTEM_PROCESSOR "@CMAKE_HOST_SYSTEM_PROCESSOR@")
-SET(CMAKE_SYSTEM "@CMAKE_SYSTEM@")
-SET(CMAKE_SYSTEM_PROCESSOR "@CMAKE_SYSTEM_PROCESSOR@")
-
-
-# Create an "INFO_SRC" file with information about the source (only).
-# We use "git log", if possible, and the "VERSION" contents.
-#
-# Outside development (git tree), the "INFO_SRC" file will not be modified
-# provided it exists (from "make dist" or a source tarball creation).
-
-MACRO(CREATE_INFO_SRC target_dir)
- SET(INFO_SRC "${target_dir}/INFO_SRC")
-
- SET(PERLSCRIPT
- "use warnings; use POSIX qw(strftime); "
- "print strftime \"%F %T %z\", localtime;")
- EXECUTE_PROCESS(
- COMMAND perl -e "${PERLSCRIPT}"
- RESULT_VARIABLE result
- OUTPUT_VARIABLE bdate
- ERROR_VARIABLE error
- )
- IF(error)
- MESSAGE(STATUS "Could not determine build-date: <${error}>")
- ENDIF()
-
- IF(GIT_EXECUTABLE AND EXISTS ${CMAKE_SOURCE_DIR}/.git)
- # Sources are in a GIT repository: Always update.
- EXECUTE_PROCESS(
- COMMAND ${GIT_EXECUTABLE} rev-parse --abbrev-ref HEAD
- WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
- OUTPUT_VARIABLE bname
- )
-
- EXECUTE_PROCESS(
- COMMAND ${GIT_EXECUTABLE} log -1
- --pretty="commit: %H%ndate: %ci%nbuild-date: ${bdate} %nshort: %h%nbranch: ${bname}"
- WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
- OUTPUT_VARIABLE VERSION_INFO
- )
-
- ## Output from git is quoted with "", remove them.
- STRING(REPLACE "\"" "" VERSION_INFO "${VERSION_INFO}")
- FILE(WRITE ${INFO_SRC} "${VERSION_INFO}\n")
- # to debug, add: FILE(APPEND ${INFO_SRC} "\nResult ${RESULT}\n")
- # For better readability ...
- FILE(APPEND ${INFO_SRC}
- "MariaDB source ${MAJOR_VERSION}.${MINOR_VERSION}.${PATCH_VERSION}\n")
- ELSEIF(EXISTS ${INFO_SRC})
- # Outside a git tree, there is no need to change an existing "INFO_SRC",
- # it cannot be improved.
- ELSEIF(EXISTS ${CMAKE_SOURCE_DIR}/Docs/INFO_SRC)
- # If we are building from a source distribution, it also contains "INFO_SRC".
- # Similar, the export used for a release build already has the file.
- FILE(READ ${CMAKE_SOURCE_DIR}/Docs/INFO_SRC SOURCE_INFO)
- FILE(WRITE ${INFO_SRC} "${SOURCE_INFO}\n")
- ELSEIF(EXISTS ${CMAKE_SOURCE_DIR}/INFO_SRC)
- # This is not the proper location, but who knows ...
- FILE(READ ${CMAKE_SOURCE_DIR}/INFO_SRC SOURCE_INFO)
- FILE(WRITE ${INFO_SRC} "${SOURCE_INFO}\n")
- ELSE()
- # This is a fall-back.
- FILE(WRITE ${INFO_SRC} "\nMariaDB source ${VERSION}\n")
- ENDIF()
-ENDMACRO(CREATE_INFO_SRC)
-
-
-# This is for the "real" build, must be run again with each cmake run
-# to make sure we report the current flags (not those of some previous run).
-
-MACRO(CREATE_INFO_BIN)
- SET(INFO_BIN "Docs/INFO_BIN")
-
- FILE(WRITE ${INFO_BIN} "===== Information about the build process: =====\n")
- IF (WIN32)
- EXECUTE_PROCESS(COMMAND cmd /c date /T
- OUTPUT_VARIABLE TMP_DATE OUTPUT_STRIP_TRAILING_WHITESPACE)
- ELSEIF(UNIX)
- EXECUTE_PROCESS(COMMAND date "+%Y-%m-%d %H:%M:%S"
- OUTPUT_VARIABLE TMP_DATE OUTPUT_STRIP_TRAILING_WHITESPACE)
- ELSE()
- SET(TMP_DATE "(no date command known for this platform)")
- ENDIF()
- SITE_NAME(HOSTNAME)
- FILE(APPEND ${INFO_BIN} "Build was run at ${TMP_DATE} on host '${HOSTNAME}'\n\n")
-
- # According to the cmake docs, these variables should always be set.
- # However, they are empty in my tests, using cmake 2.6.4 on Linux, various Unix, and Windows.
- # Still, include this code, so we will profit if a build environment does provide that info.
- IF(CMAKE_HOST_SYSTEM)
- FILE(APPEND ${INFO_BIN} "Build was done on ${CMAKE_HOST_SYSTEM} using ${CMAKE_HOST_SYSTEM_PROCESSOR}\n")
- ENDIF()
- IF(CMAKE_CROSSCOMPILING)
- FILE(APPEND ${INFO_BIN} "Build was done for ${CMAKE_SYSTEM} using ${CMAKE_SYSTEM_PROCESSOR}\n")
- ENDIF()
-
- # ${CMAKE_VERSION} doesn't work in 2.6.0, use the separate components.
- FILE(APPEND ${INFO_BIN} "Build was done using cmake ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION} \n\n")
-
- IF (WIN32)
- FILE(APPEND ${INFO_BIN} "===== Compiler / generator used: =====\n")
- FILE(APPEND ${INFO_BIN} ${CMAKE_GENERATOR} "\n\n")
- ELSEIF(UNIX)
- FILE(APPEND ${INFO_BIN} "===== Compiler flags used (from the 'sql/' subdirectory): =====\n")
- IF(EXISTS sql/CMakeFiles/sql.dir/flags.make)
- EXECUTE_PROCESS(COMMAND egrep "^# compile|^C_|^CXX_" sql/CMakeFiles/sql.dir/flags.make OUTPUT_VARIABLE COMPILE_FLAGS)
- FILE(APPEND ${INFO_BIN} ${COMPILE_FLAGS} "\n")
- ELSE()
- FILE(APPEND ${INFO_BIN} "File 'sql/CMakeFiles/sql.dir/flags.make' is not yet found.\n\n")
- ENDIF()
- ENDIF()
- FILE(APPEND ${INFO_BIN} "Pointer size: ${CMAKE_SIZEOF_VOID_P}\n\n")
-
- FILE(APPEND ${INFO_BIN} "===== Feature flags used: =====\n")
- IF(EXISTS ${CMAKE_BINARY_DIR}/CMakeCache.txt)
- # Attention: "-N" prevents cmake from entering a recursion, and it must be a separate flag from "-L".
- EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -N -L ${CMAKE_BINARY_DIR} OUTPUT_VARIABLE FEATURE_FLAGS)
- FILE(APPEND ${INFO_BIN} ${FEATURE_FLAGS} "\n")
- ELSE()
- FILE(APPEND ${INFO_BIN} "File 'CMakeCache.txt' is not yet found.\n\n")
- ENDIF()
-
- FILE(APPEND ${INFO_BIN} "===== EOF =====\n")
-ENDMACRO(CREATE_INFO_BIN)
-
diff --git a/cmake/info_src.cmake b/cmake/info_src.cmake
deleted file mode 100644
index df6249f111e1c..0000000000000
--- a/cmake/info_src.cmake
+++ /dev/null
@@ -1,31 +0,0 @@
-# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
-#
-# 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
-
-
-# The sole purpose of this cmake control file is to create the "INFO_SRC" file.
-
-# As long as and "git pull" (or "git commit") is followed by a "cmake",
-# the call in top level "CMakeLists.txt" is sufficient.
-# This file is to provide a separate target for the "make" phase,
-# to ensure the git commit hash is correct even after a sequence
-# cmake ; make ; git pull ; make
-
-
-# Get the macros which handle the "INFO_*" files.
-INCLUDE(${CMAKE_BINARY_DIR}/info_macros.cmake)
-
-# Here is where the action is.
-CREATE_INFO_SRC(${CMAKE_BINARY_DIR}/Docs)
-
diff --git a/cmake/install_layout.cmake b/cmake/install_layout.cmake
index eb969679bf786..55e960a3c1572 100644
--- a/cmake/install_layout.cmake
+++ b/cmake/install_layout.cmake
@@ -163,6 +163,7 @@ SET(INSTALL_UNIX_ADDRDIR_RPM "${INSTALL_MYSQLDATADIR_RPM}/mysql.sock"
SET(INSTALL_SYSTEMD_UNITDIR_RPM "/usr/lib/systemd/system")
SET(INSTALL_SYSTEMD_SYSUSERSDIR_RPM "/usr/lib/sysusers.d")
SET(INSTALL_SYSTEMD_TMPFILESDIR_RPM "/usr/lib/tmpfiles.d")
+SET(INSTALL_RUNDATADIR_RPM "/run/mariadb")
SET(INSTALL_PAMDIR_RPM "/${INSTALL_LIBDIR_RPM}/security")
SET(INSTALL_PAMDATADIR_RPM "/etc/security")
@@ -193,7 +194,8 @@ SET(INSTALL_SUPPORTFILESDIR_DEB "share/mariadb")
#
SET(INSTALL_MYSQLDATADIR_DEB "/var/lib/mysql")
-SET(INSTALL_UNIX_ADDRDIR_DEB "/run/mysqld/mysqld.sock")
+SET(INSTALL_RUNDATADIR_DEB "/run/mysqld")
+SET(INSTALL_UNIX_ADDRDIR_DEB "${INSTALL_RUNDATADIR_DEB}/mysqld.sock")
SET(INSTALL_SYSTEMD_UNITDIR_DEB "/lib/systemd/system")
SET(INSTALL_SYSTEMD_SYSUSERSDIR_DEB "/usr/lib/sysusers.d")
SET(INSTALL_SYSTEMD_TMPFILESDIR_DEB "/usr/lib/tmpfiles.d")
@@ -257,3 +259,7 @@ IF(NOT MYSQL_UNIX_ADDR)
SET(MYSQL_UNIX_ADDR ${INSTALL_UNIX_ADDRDIR})
ENDIF()
+IF(NOT INSTALL_RUNDATADIR)
+ get_filename_component(MYSQL_UNIX_DIR ${MYSQL_UNIX_ADDR} DIRECTORY)
+ SET(INSTALL_RUNDATADIR "${MYSQL_UNIX_DIR}" CACHE FILEPATH "Rundata installation directory" ${FORCE})
+ENDIF()
diff --git a/cmake/install_macros.cmake b/cmake/install_macros.cmake
index cad94a641930f..282800a3285e8 100644
--- a/cmake/install_macros.cmake
+++ b/cmake/install_macros.cmake
@@ -286,6 +286,7 @@ FUNCTION(INSTALL_RUNTIME_DEPS)
POST_EXCLUDE_REGEXES
".*system32/.*\\.dll" # Windows stuff
POST_INCLUDE_REGEXES
+ "libssl" "libcrypto" # Account for OpenSSL libraries in system32
DIRECTORIES
$<$:${VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/bin
$<$,$>:${VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/debug/bin>
diff --git a/cmake/libfmt.cmake b/cmake/libfmt.cmake
index 47f2e00bae164..bdd7d8c0be958 100644
--- a/cmake/libfmt.cmake
+++ b/cmake/libfmt.cmake
@@ -15,8 +15,8 @@ MACRO(BUNDLE_LIBFMT)
ExternalProject_Add(
libfmt
PREFIX "${dir}"
- URL "https://github.com/fmtlib/fmt/releases/download/11.1.4/fmt-11.1.4.zip"
- URL_MD5 ad6a56b15cddf4aad2a234e7cfc9e8c9
+ URL "https://github.com/fmtlib/fmt/releases/download/12.1.0/fmt-12.1.0.zip"
+ URL_MD5 028c6979cad96a4260154f091885171a
INSTALL_COMMAND ""
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
diff --git a/cmake/maintainer.cmake b/cmake/maintainer.cmake
index ce183d5d238f0..d454f10e86695 100644
--- a/cmake/maintainer.cmake
+++ b/cmake/maintainer.cmake
@@ -67,6 +67,14 @@ IF(CMAKE_C_COMPILER_ID STREQUAL "GNU" AND CMAKE_C_COMPILER_VERSION VERSION_LESS
SET(MY_ERROR_FLAGS ${MY_ERROR_FLAGS} -Wno-error=non-virtual-dtor) # gcc bug 7302
ENDIF()
+FOREACH(LANG C CXX)
+ IF(CMAKE_${LANG}_COMPILER_ID MATCHES "Clang")
+ MY_CHECK_AND_SET_COMPILER_FLAG(-Werror=uninitialized-explicit-init)
+ MY_CHECK_AND_SET_COMPILER_FLAG(-Werror=uninitialized-const-reference)
+ SET(CMAKE_${LANG}_FLAGS "${CMAKE_${LANG}_FLAGS} -Werror=uninitialized")
+ ENDIF()
+ENDFOREACH()
+
IF(MYSQL_MAINTAINER_MODE MATCHES "OFF|WARN")
RETURN()
ELSEIF(MYSQL_MAINTAINER_MODE MATCHES "AUTO")
diff --git a/cmake/make_dist.cmake.in b/cmake/make_dist.cmake.in
index 8a219ac7ddc27..4a19486a1417c 100644
--- a/cmake/make_dist.cmake.in
+++ b/cmake/make_dist.cmake.in
@@ -141,12 +141,6 @@ IF(MYSQL_DOCS_LOCATION)
EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E copy_directory "${MYSQL_DOCS_LOCATION}" "${PACKAGE_DIR}")
ENDIF()
-# Ensure there is an "INFO_SRC" file.
-INCLUDE(${CMAKE_BINARY_DIR}/info_macros.cmake)
-IF(NOT EXISTS ${PACKAGE_DIR}/Docs/INFO_SRC)
- CREATE_INFO_SRC(${PACKAGE_DIR}/Docs)
-ENDIF()
-
INCLUDE(${CMAKE_SOURCE_DIR}/cmake/generate_submodule_info.cmake)
GENERATE_SUBMODULE_INFO(${PACKAGE_DIR}/cmake/submodule_info.cmake)
diff --git a/cmake/mariadb_connector_c.cmake b/cmake/mariadb_connector_c.cmake
index 86e7d5612e20e..859f96a8dcccc 100644
--- a/cmake/mariadb_connector_c.cmake
+++ b/cmake/mariadb_connector_c.cmake
@@ -7,12 +7,7 @@ ENDIF()
SET(CONC_WITH_SIGNCODE ${SIGNCODE})
SET(SIGN_OPTIONS ${SIGNTOOL_PARAMETERS})
SET(CONC_WITH_EXTERNAL_ZLIB ON)
-SET(CLIENT_PLUGIN_PARSEC OFF)
-CHECK_INCLUDE_FILES (threads.h HAVE_THREADS_H)
-IF(HAVE_THREADS_H)
-SET(CLIENT_PLUGIN_PARSEC DYNAMIC)
-ENDIF()
IF(NOT CONC_WITH_SSL)
IF(SSL_DEFINES MATCHES "WOLFSSL")
diff --git a/cmake/pcre.cmake b/cmake/pcre.cmake
index 08353e9236ad3..9ebab4e66fee0 100644
--- a/cmake/pcre.cmake
+++ b/cmake/pcre.cmake
@@ -8,7 +8,6 @@ MACRO(BUNDLE_PCRE2)
"Which pcre to use (possible values are 'bundled', 'system', or 'auto')")
SET(dir "${CMAKE_BINARY_DIR}/extra/pcre2")
- SET(PCRE_INCLUDE_DIRS ${dir}/src/pcre2-build ${dir}/src/pcre2/src)
MESSAGE(STATUS "Will download and bundle pcre2")
SET(byproducts)
FOREACH(lib pcre2-posix pcre2-8)
@@ -43,6 +42,8 @@ MACRO(BUNDLE_PCRE2)
ENDIF()
SET(byproducts ${byproducts} BUILD_BYPRODUCTS ${file} ${file_d})
SET_TARGET_PROPERTIES(${lib} PROPERTIES IMPORTED_LOCATION ${file})
+ MAKE_DIRECTORY(${dir}/src/pcre2-build/interface)
+ TARGET_INCLUDE_DIRECTORIES(${lib} INTERFACE ${dir}/src/pcre2-build/interface)
ENDFOREACH()
FOREACH(v "" "_DEBUG" "_RELWITHDEBINFO" "_RELEASE" "_MINSIZEREL")
@@ -64,8 +65,8 @@ MACRO(BUNDLE_PCRE2)
ExternalProject_Add(
pcre2
PREFIX "${dir}"
- URL "https://github.com/PCRE2Project/pcre2/releases/download/pcre2-10.45/pcre2-10.45.zip"
- URL_MD5 873da56c6469ec207ca5c5ae9688b83a
+ URL "https://github.com/PCRE2Project/pcre2/releases/download/pcre2-10.47/pcre2-10.47.zip"
+ URL_MD5 7906aec38f872b74f1b925122dde9069
INSTALL_COMMAND ""
CMAKE_ARGS
"-DCMAKE_WARN_DEPRECATED=FALSE"
diff --git a/cmake/ssl.cmake b/cmake/ssl.cmake
index b72f959828ff3..6d6e0de4f873a 100644
--- a/cmake/ssl.cmake
+++ b/cmake/ssl.cmake
@@ -53,7 +53,6 @@ MACRO (MYSQL_USE_BUNDLED_SSL)
SET(HAVE_ERR_remove_thread_state ON CACHE INTERNAL "wolfssl doesn't have ERR_remove_thread_state")
SET(HAVE_EncryptAes128Ctr ON CACHE INTERNAL "wolfssl does support AES-CTR")
SET(HAVE_EncryptAes128Gcm OFF CACHE INTERNAL "wolfssl does not support AES-GCM")
- SET(HAVE_des ON CACHE INTERNAL "wolfssl does support DES API")
SET(HAVE_evp_pkey ON CACHE INTERNAL "wolfssl does support EVP_PKEY API")
SET(HAVE_hkdf ON CACHE INTERNAL "wolfssl does support EVP_PKEY_HKDF API")
CHANGE_SSL_SETTINGS("bundled")
@@ -136,8 +135,6 @@ MACRO (MYSQL_CHECK_SSL)
HAVE_EncryptAes128Ctr)
CHECK_SYMBOL_EXISTS(EVP_aes_128_gcm "openssl/evp.h"
HAVE_EncryptAes128Gcm)
- CHECK_SYMBOL_EXISTS(DES_set_key_unchecked "openssl/des.h"
- HAVE_des)
CHECK_SYMBOL_EXISTS(EVP_PKEY_get_raw_public_key "openssl/evp.h"
HAVE_evp_pkey)
CHECK_SYMBOL_EXISTS(EVP_PKEY_CTX_set_hkdf_md "string.h;stdarg.h;openssl/kdf.h"
diff --git a/cmake/systemd.cmake b/cmake/systemd.cmake
index 6788cf0d295be..a825cd0cb6809 100644
--- a/cmake/systemd.cmake
+++ b/cmake/systemd.cmake
@@ -50,8 +50,7 @@ MACRO(CHECK_SYSTEMD)
SET(SYSTEMD_SCRIPTS ${SYSTEMD_SCRIPTS} galera_recovery)
ENDIF()
IF(DEB)
- SET(SYSTEMD_EXECSTARTPRE "ExecStartPre=+/usr/bin/install -m 755 -o mysql -g root -d /var/run/mysqld")
- SET(SYSTEMD_EXECSTARTPOST "ExecStartPost=+/etc/mysql/debian-start")
+ SET(SYSTEMD_EXECSTARTPOST "ExecStartPost=!/etc/mysql/debian-start")
ENDIF()
IF(URING_FOUND)
SET(SYSTEMD_LIMIT "# For liburing and io_uring_setup()
diff --git a/cmake/zlib.cmake b/cmake/zlib.cmake
index a933194cd33e6..2a7043b325428 100644
--- a/cmake/zlib.cmake
+++ b/cmake/zlib.cmake
@@ -21,6 +21,11 @@ MACRO (MYSQL_USE_BUNDLED_ZLIB)
SET(ZLIB_LIBRARY ${ZLIB_LIBRARIES})
SET(ZLIB_INCLUDE_DIR ${ZLIB_INCLUDE_DIRS})
SET(ZLIB_FOUND TRUE)
+ IF(VCPKG_INSTALLED_DIR)
+ # Avoid errors in vcpkg's FIND_PACKAGE
+ # for packages dependend on zlib
+ SET(CMAKE_DISABLE_FIND_PACKAGE_ZLIB 1)
+ ENDIF()
SET(WITH_ZLIB "bundled" CACHE STRING "Use bundled zlib")
ADD_SUBDIRECTORY(zlib)
ENDMACRO()
diff --git a/config.h.cmake b/config.h.cmake
index cf3c1afe4eddd..903d2d837b755 100644
--- a/config.h.cmake
+++ b/config.h.cmake
@@ -493,7 +493,6 @@ this is the case with Microsoft Windows VirtualFree(MEM_DECOMMIT) */
#cmakedefine HAVE_COMPRESS 1
#cmakedefine HAVE_EncryptAes128Ctr 1
#cmakedefine HAVE_EncryptAes128Gcm 1
-#cmakedefine HAVE_des 1
#cmakedefine HAVE_hkdf 1
/*
diff --git a/debian/additions/mariadb.conf.d/50-server.cnf b/debian/additions/mariadb.conf.d/50-server.cnf
index 32d65931f6186..6f3abfc668469 100644
--- a/debian/additions/mariadb.conf.d/50-server.cnf
+++ b/debian/additions/mariadb.conf.d/50-server.cnf
@@ -110,7 +110,7 @@ expire_logs_days = 10
# you can put MariaDB-only options here
[mariadbd]
-# This group is only read by MariaDB-12.0 servers.
+# This group is only read by MariaDB servers of the specific version.
# If you use the same .cnf file for MariaDB of different versions,
# use this group for options that older servers don't understand
-[mariadb-12.0]
+[mariadb-13.0]
diff --git a/debian/autobake-deb.sh b/debian/autobake-deb.sh
index 55bffa79f9613..0d7505041c616 100755
--- a/debian/autobake-deb.sh
+++ b/debian/autobake-deb.sh
@@ -109,7 +109,7 @@ in
remove_uring
fi
;&
- "trixie"|"forky"|"sid")
+ "trixie"|"forky"|"duke"|"sid")
# The default packaging should always target Debian Sid, so in this case
# there is intentionally no customizations whatsoever.
;;
@@ -128,7 +128,7 @@ in
replace_uring_with_aio
fi
;&
- "noble"|"oracular"|"plucky"|"questing")
+ "noble"|"oracular"|"plucky"|"questing"|"resolute")
# mariadb-plugin-rocksdb s390x not supported by us (yet)
# ubuntu doesn't support mips64el yet, so keep this just
# in case something changes.
diff --git a/debian/changelog b/debian/changelog
index 45c6112e36a2a..83d25e5a15bd6 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,5 +1,5 @@
-mariadb (1:12.0.0) unstable; urgency=medium
+mariadb (1:13.0.0) unstable; urgency=medium
* Initial Release
- -- Sergei Golubchik Tue Aug 20 08:40:21 CEST 2024
+ -- Sergei Golubchik Wed Feb 11 11:24:57 CET 2026
diff --git a/debian/control b/debian/control
index 7300d3296e9d2..eb73631d68cc5 100644
--- a/debian/control
+++ b/debian/control
@@ -2,54 +2,55 @@ Source: mariadb
Section: database
Priority: optional
Maintainer: MariaDB Developers
-Build-Depends: bison,
- cmake,
- cracklib-runtime ,
- debhelper (>= 11),
- default-jdk,
- dh-exec,
- dh-package-notes,
- flex [amd64 arm64],
- gdb ,
- libaio-dev [linux-any],
- libboost-atomic-dev [amd64 arm64],
- libboost-chrono-dev [amd64 arm64],
- libboost-date-time-dev [amd64 arm64],
- libboost-dev,
- libboost-filesystem-dev [amd64 arm64],
- libboost-regex-dev [amd64 arm64],
- libboost-system-dev [amd64 arm64],
- libboost-thread-dev [amd64 arm64],
- libbz2-dev,
- libcrack2-dev (>= 2.9.0),
- libcurl4-openssl-dev | libcurl4-dev,
- libedit-dev,
- libedit-dev:native,
- libfmt-dev (>= 7.0.0),
- libjemalloc-dev [linux-any],
- libjudy-dev,
- libkrb5-dev,
- liblz4-dev,
- liblzma-dev,
- liblzo2-dev,
- libncurses-dev,
- libnuma-dev [linux-any],
- libpam0g-dev,
- libpcre2-dev,
- libsnappy-dev,
- libssl-dev,
- libssl-dev:native,
- libsystemd-dev [linux-any],
- liburing-dev [linux-any],
- libxml2-dev,
- libzstd-dev (>= 1.1.3),
- lsb-release,
- perl:any,
- po-debconf,
- psmisc,
- unixodbc-dev,
- uuid-dev,
- zlib1g-dev (>= 1:1.1.3-5~)
+Build-Depends:
+ debhelper (>= 11),
+ dh-exec,
+ dh-package-notes,
+ bison,
+ cmake,
+ cracklib-runtime ,
+ default-jdk,
+ flex [amd64 arm64],
+ gdb ,
+ libaio-dev [linux-any],
+ libboost-atomic-dev [amd64 arm64],
+ libboost-chrono-dev [amd64 arm64],
+ libboost-date-time-dev [amd64 arm64],
+ libboost-dev,
+ libboost-filesystem-dev [amd64 arm64],
+ libboost-regex-dev [amd64 arm64],
+ libboost-system-dev [amd64 arm64],
+ libboost-thread-dev [amd64 arm64],
+ libbz2-dev,
+ libcrack2-dev (>= 2.9.0),
+ libcurl4-openssl-dev | libcurl4-dev,
+ libedit-dev,
+ libedit-dev:native,
+ libfmt-dev (>= 7.0.0),
+ libjemalloc-dev [linux-any],
+ libjudy-dev,
+ libkrb5-dev,
+ liblz4-dev,
+ liblzma-dev,
+ liblzo2-dev,
+ libncurses-dev,
+ libnuma-dev [linux-any],
+ libpam0g-dev,
+ libpcre2-dev,
+ libsnappy-dev,
+ libssl-dev,
+ libssl-dev:native,
+ libsystemd-dev [linux-any],
+ liburing-dev [linux-any],
+ libxml2-dev,
+ libzstd-dev (>= 1.1.3),
+ lsb-release,
+ perl:any,
+ po-debconf,
+ psmisc,
+ unixodbc-dev,
+ uuid-dev,
+ zlib1g-dev (>= 1:1.1.3-5~),
Rules-Requires-Root: no
Standards-Version: 4.5.0
Homepage: https://mariadb.org/
@@ -59,23 +60,28 @@ Vcs-Git: https://github.com/MariaDB/server.git
Package: libmariadb-dev
Architecture: any
Section: libdevel
-Depends: libmariadb3 (= ${binary:Version}),
- libssl-dev,
- zlib1g-dev,
- ${misc:Depends},
- ${shlibs:Depends}
-Conflicts: libmariadb-dev-compat (<< 3.0.0),
- libmariadbclient-dev,
- libmariadbclient16-dev
-Provides: libmariadbclient-dev
-Breaks: libmariadb-client-lgpl-dev,
- libmysqlclient-dev (<< ${source:Version}),
- libmysqld-dev (<< ${source:Version})
-Replaces: libmariadb-client-lgpl-dev,
- libmariadb-dev-compat (<< 3.0.0),
- libmariadbclient-dev,
- libmysqlclient-dev (<< ${source:Version}),
- libmysqld-dev (<< ${source:Version})
+Depends:
+ libmariadb3 (= ${binary:Version}),
+ libssl-dev,
+ zlib1g-dev,
+ ${misc:Depends},
+ ${shlibs:Depends},
+Conflicts:
+ libmariadb-dev-compat (<< 3.0.0),
+ libmariadbclient-dev,
+ libmariadbclient16-dev,
+Provides:
+ libmariadbclient-dev,
+Breaks:
+ libmariadb-client-lgpl-dev,
+ libmysqlclient-dev (<< ${source:Version}),
+ libmysqld-dev (<< ${source:Version}),
+Replaces:
+ libmariadb-client-lgpl-dev,
+ libmariadb-dev-compat (<< 3.0.0),
+ libmariadbclient-dev,
+ libmysqlclient-dev (<< ${source:Version}),
+ libmysqld-dev (<< ${source:Version}),
Description: MariaDB database development files
MariaDB is a fast, stable and true multi-user, multi-threaded SQL database
server. SQL (Structured Query Language) is the most popular database query
@@ -89,28 +95,33 @@ Description: MariaDB database development files
Package: libmariadb-dev-compat
Architecture: any
Section: libdevel
-Depends: libmariadb-dev (= ${binary:Version}),
- ${misc:Depends}
-Conflicts: libmariadb-client-lgpl-dev,
- libmariadb-client-lgpl-dev-compat,
- libmariadbclient-dev (<< ${source:Version}),
- libmariadbclient-dev-compat,
- libmysqlclient-dev,
- libmysqlclient10-dev,
- libmysqlclient12-dev,
- libmysqlclient14-dev,
- libmysqlclient15-dev,
- libmysqlclient16-dev
-Provides: libmariadb-client-lgpl-dev-compat,
- libmariadbclient-dev-compat,
- libmysqlclient-dev
-Breaks: libmariadb-dev (<< ${source:Version})
-Replaces: libmariadb-client-lgpl-dev,
- libmariadb-client-lgpl-dev-compat,
- libmariadb-dev (<< ${source:Version}),
- libmariadbclient-dev (<< ${source:Version}),
- libmariadbclient-dev-compat,
- libmysqlclient-dev
+Depends:
+ libmariadb-dev (= ${binary:Version}),
+ ${misc:Depends},
+Conflicts:
+ libmariadb-client-lgpl-dev,
+ libmariadb-client-lgpl-dev-compat,
+ libmariadbclient-dev (<< ${source:Version}),
+ libmariadbclient-dev-compat,
+ libmysqlclient-dev,
+ libmysqlclient10-dev,
+ libmysqlclient12-dev,
+ libmysqlclient14-dev,
+ libmysqlclient15-dev,
+ libmysqlclient16-dev,
+Provides:
+ libmariadb-client-lgpl-dev-compat,
+ libmariadbclient-dev-compat,
+ libmysqlclient-dev,
+Breaks:
+ libmariadb-dev (<< ${source:Version}),
+Replaces:
+ libmariadb-client-lgpl-dev,
+ libmariadb-client-lgpl-dev-compat,
+ libmariadb-dev (<< ${source:Version}),
+ libmariadbclient-dev (<< ${source:Version}),
+ libmariadbclient-dev-compat,
+ libmysqlclient-dev,
Description: MariaDB Connector/C, compatibility symlinks
MariaDB is a fast, stable and true multi-user, multi-threaded SQL database
server. SQL (Structured Query Language) is the most popular database query
@@ -124,19 +135,23 @@ Package: libmariadb3
Architecture: any
Multi-Arch: same
Section: libs
-Depends: mariadb-common,
- ${misc:Depends},
- ${shlibs:Depends}
-Conflicts: libmariadbclient18 (<< 10.2.0),
- mariadb-galera-server-10.0,
- mariadb-galera-server-5.5,
- mariadb-server-10.0,
- mariadb-server-5.1,
- mariadb-server-5.2,
- mariadb-server-5.3,
- mariadb-server-5.5
-Breaks: libmariadbclient18 (<< ${source:Version})
-Replaces: libmariadbclient18 (<< ${source:Version})
+Depends:
+ mariadb-common,
+ ${misc:Depends},
+ ${shlibs:Depends},
+Conflicts:
+ libmariadbclient18 (<< 10.2.0),
+ mariadb-galera-server-10.0,
+ mariadb-galera-server-5.5,
+ mariadb-server-10.0,
+ mariadb-server-5.1,
+ mariadb-server-5.2,
+ mariadb-server-5.3,
+ mariadb-server-5.5,
+Breaks:
+ libmariadbclient18 (<< ${source:Version}),
+Replaces:
+ libmariadbclient18 (<< ${source:Version}),
Description: MariaDB database client library
MariaDB is a fast, stable and true multi-user, multi-threaded SQL database
server. SQL (Structured Query Language) is the most popular database query
@@ -148,18 +163,22 @@ Description: MariaDB database client library
Package: libmariadb3-compat
Architecture: any
Section: libs
-Depends: libmariadb3,
- mariadb-common,
- ${misc:Depends}
-Breaks: libmysqlclient19,
- libmysqlclient20,
- libmysqlclient21
-Replaces: libmysqlclient19,
- libmysqlclient20,
- libmysqlclient21
-Provides: libmysqlclient19,
- libmysqlclient20,
- libmysqlclient21
+Depends:
+ libmariadb3,
+ mariadb-common,
+ ${misc:Depends},
+Breaks:
+ libmysqlclient19,
+ libmysqlclient20,
+ libmysqlclient21,
+Replaces:
+ libmysqlclient19,
+ libmysqlclient20,
+ libmysqlclient21,
+Provides:
+ libmysqlclient19,
+ libmysqlclient20,
+ libmysqlclient21,
Description: MariaDB database client library MySQL compat package
MariaDB is a fast, stable and true multi-user, multi-threaded SQL database
server. SQL (Structured Query Language) is the most popular database query
@@ -172,10 +191,13 @@ Description: MariaDB database client library MySQL compat package
Package: libmariadbclient18
Section: libs
Architecture: any
-Depends: libmariadb3 (= ${binary:Version}),
- ${misc:Depends}
-Replaces: libmariadbclient18
-Provides: libmariadbclient18
+Depends:
+ libmariadb3 (= ${binary:Version}),
+ ${misc:Depends},
+Replaces:
+ libmariadbclient18,
+Provides:
+ libmariadbclient18,
Description: Virtual package to satisfy external libmariadbclient18 depends
MariaDB is a fast, stable and true multi-user, multi-threaded SQL database
server. SQL (Structured Query Language) is the most popular database query
@@ -188,10 +210,13 @@ Description: Virtual package to satisfy external libmariadbclient18 depends
Package: libmysqlclient18
Section: libs
Architecture: any
-Depends: libmariadb3 (= ${binary:Version}),
- ${misc:Depends}
-Replaces: libmysqlclient18
-Provides: libmysqlclient18
+Depends:
+ libmariadb3 (= ${binary:Version}),
+ ${misc:Depends},
+Replaces:
+ libmysqlclient18,
+Provides:
+ libmysqlclient18,
Description: Virtual package to satisfy external libmysqlclient18 depends
MariaDB is a fast, stable and true multi-user, multi-threaded SQL database
server. SQL (Structured Query Language) is the most popular database query
@@ -204,11 +229,15 @@ Description: Virtual package to satisfy external libmysqlclient18 depends
Package: libmariadbd19
Architecture: any
Section: libs
-Depends: ${misc:Depends},
- ${shlibs:Depends}
-Breaks: libmariadbd-dev (<< ${source:Version})
-Conflicts: libmariadbd19t64
-Replaces: libmariadbd-dev (<< ${source:Version})
+Depends:
+ ${misc:Depends},
+ ${shlibs:Depends},
+Breaks:
+ libmariadbd-dev (<< ${source:Version}),
+Conflicts:
+ libmariadbd19t64,
+Replaces:
+ libmariadbd-dev (<< ${source:Version}),
Multi-Arch: same
Description: MariaDB embedded database, shared library
MariaDB is a fast, stable and true multi-user, multi-threaded SQL database
@@ -221,17 +250,22 @@ Description: MariaDB embedded database, shared library
Package: libmariadbd-dev
Architecture: any
Section: libdevel
-Provides: libmysqld-dev
-Pre-Depends: ${misc:Pre-Depends}
-Depends: libmariadb-dev (= ${binary:Version}),
- libmariadbd19 (= ${binary:Version}),
- ${misc:Depends}
-Breaks: libmariadb-dev (<< ${source:Version}),
- libmariadbclient-dev (<< ${source:Version}),
- libmysqld-dev
-Replaces: libmariadb-dev (<< ${source:Version}),
- libmariadbclient-dev (<< ${source:Version}),
- libmysqld-dev
+Provides:
+ libmysqld-dev,
+Pre-Depends:
+ ${misc:Pre-Depends},
+Depends:
+ libmariadb-dev (= ${binary:Version}),
+ libmariadbd19 (= ${binary:Version}),
+ ${misc:Depends},
+Breaks:
+ libmariadb-dev (<< ${source:Version}),
+ libmariadbclient-dev (<< ${source:Version}),
+ libmysqld-dev,
+Replaces:
+ libmariadb-dev (<< ${source:Version}),
+ libmariadbclient-dev (<< ${source:Version}),
+ libmysqld-dev,
Description: MariaDB embedded database, development files package
MariaDB is a fast, stable and true multi-user, multi-threaded SQL database
server. SQL (Structured Query Language) is the most popular database query
@@ -243,7 +277,8 @@ Description: MariaDB embedded database, development files package
Package: mysql-common
Architecture: all
-Depends: ${misc:Depends}
+Depends:
+ ${misc:Depends},
Description: MariaDB client common configuration files package (e.g. /etc/mysql/my.cnf)
MariaDB is a fast, stable and true multi-user, multi-threaded SQL database
server. SQL (Structured Query Language) is the most popular database query
@@ -255,8 +290,9 @@ Description: MariaDB client common configuration files package (e.g. /etc/mysql/
Package: mariadb-common
Architecture: all
-Depends: mysql-common (>= 5.6.25),
- ${misc:Depends}
+Depends:
+ mysql-common (>= 5.6.25),
+ ${misc:Depends},
Multi-Arch: foreign
Description: MariaDB database common files (e.g. /etc/mysql/mariadb.conf.d/)
MariaDB is a fast, stable and true multi-user, multi-threaded SQL database
@@ -268,132 +304,137 @@ Description: MariaDB database common files (e.g. /etc/mysql/mariadb.conf.d/)
Package: mariadb-client-core
Architecture: any
-Depends: libmariadb3 (>= 10.5.4),
- mariadb-common (>= ${source:Version}),
- ${misc:Depends},
- ${shlibs:Depends}
-Conflicts: mariadb-client-10.0,
- mariadb-client-10.1,
- mariadb-client-10.2,
- mariadb-client-10.3,
- mariadb-client-10.4,
- mariadb-client-10.5,
- mariadb-client-10.6,
- mariadb-client-10.7,
- mariadb-client-10.8,
- mariadb-client-5.1,
- mariadb-client-5.2,
- mariadb-client-5.3,
- mariadb-client-5.5,
- mariadb-client-core-10.0,
- mariadb-client-core-10.1,
- mariadb-client-core-10.2,
- mariadb-client-core-10.3,
- mariadb-client-core-10.4,
- mariadb-client-core-10.5,
- mariadb-client-core-10.6,
- mariadb-client-core-10.7,
- mariadb-client-core-10.8,
- mariadb-client-core-5.1,
- mariadb-client-core-5.2,
- mariadb-client-core-5.3,
- mariadb-client-core-5.5,
- mysql-client (<< 5.0.51),
- mysql-client-5.0,
- mysql-client-5.1,
- mysql-client-5.5,
- mysql-client-core-5.1,
- mysql-client-core-5.5,
- mysql-client-core-5.6,
- mysql-client-core-5.7,
- mysql-client-core-8.0,
- virtual-mysql-client-core
-Breaks: mariadb-client (<< ${source:Version}),
- mariadb-server-10.0,
- mariadb-server-10.1,
- mariadb-server-core (<< ${source:Version}),
- mariadb-server-core-10.0,
- mariadb-server-core-10.1,
- mariadb-server-core-10.2,
- mariadb-server-core-10.3,
- mariadb-server-core-10.4,
- mariadb-server-core-10.5,
- mariadb-server-core-10.6,
- mariadb-server-core-10.7,
- mariadb-server-core-10.8,
- mysql-cluster-community-client-plugins,
- mysql-server-core-5.5,
- mysql-server-core-5.6,
- mysql-server-core-5.7,
- mysql-server-core-8.0,
- percona-server-server-5.6,
- percona-server-server-5.7,
- percona-server-server-8.0,
- percona-xtradb-cluster-server-5.6,
- percona-xtradb-cluster-server-5.7,
- percona-xtradb-cluster-server-8.0
-Replaces: mariadb-client (<< ${source:Version}),
- mariadb-client-10.0,
- mariadb-client-10.1,
- mariadb-client-10.2,
- mariadb-client-10.3,
- mariadb-client-10.4,
- mariadb-client-10.5,
- mariadb-client-10.6,
- mariadb-client-10.7,
- mariadb-client-10.8,
- mariadb-client-5.1,
- mariadb-client-5.2,
- mariadb-client-5.3,
- mariadb-client-5.5,
- mariadb-client-core-10.0,
- mariadb-client-core-10.1,
- mariadb-client-core-10.2,
- mariadb-client-core-10.3,
- mariadb-client-core-10.4,
- mariadb-client-core-10.5,
- mariadb-client-core-10.6,
- mariadb-client-core-10.7,
- mariadb-client-core-10.8,
- mariadb-client-core-5.1,
- mariadb-client-core-5.2,
- mariadb-client-core-5.3,
- mariadb-client-core-5.5,
- mariadb-server-10.0,
- mariadb-server-10.1,
- mariadb-server-core (<< ${source:Version}),
- mariadb-server-core-10.0,
- mariadb-server-core-10.1,
- mariadb-server-core-10.2,
- mariadb-server-core-10.3,
- mariadb-server-core-10.4,
- mariadb-server-core-10.5,
- mariadb-server-core-10.6,
- mariadb-server-core-10.7,
- mariadb-server-core-10.8,
- mysql-client (<< 5.0.51),
- mysql-client-5.0,
- mysql-client-5.1,
- mysql-client-5.5,
- mysql-client-core-5.1,
- mysql-client-core-5.5,
- mysql-client-core-5.6,
- mysql-client-core-5.7,
- mysql-client-core-8.0,
- mysql-cluster-community-client-plugins,
- mysql-server-core-5.5,
- mysql-server-core-5.6,
- mysql-server-core-5.7,
- mysql-server-core-8.0,
- percona-server-server-5.6,
- percona-server-server-5.7,
- percona-server-server-8.0,
- percona-xtradb-cluster-server-5.6,
- percona-xtradb-cluster-server-5.7,
- percona-xtradb-cluster-server-8.0,
- virtual-mysql-client-core
-Provides: default-mysql-client-core,
- virtual-mysql-client-core
+Depends:
+ libmariadb3 (>= 10.5.4),
+ mariadb-common (>= ${source:Version}),
+ ${misc:Depends},
+ ${shlibs:Depends},
+Conflicts:
+ mariadb-client-10.0,
+ mariadb-client-10.1,
+ mariadb-client-10.2,
+ mariadb-client-10.3,
+ mariadb-client-10.4,
+ mariadb-client-10.5,
+ mariadb-client-10.6,
+ mariadb-client-10.7,
+ mariadb-client-10.8,
+ mariadb-client-5.1,
+ mariadb-client-5.2,
+ mariadb-client-5.3,
+ mariadb-client-5.5,
+ mariadb-client-core-10.0,
+ mariadb-client-core-10.1,
+ mariadb-client-core-10.2,
+ mariadb-client-core-10.3,
+ mariadb-client-core-10.4,
+ mariadb-client-core-10.5,
+ mariadb-client-core-10.6,
+ mariadb-client-core-10.7,
+ mariadb-client-core-10.8,
+ mariadb-client-core-5.1,
+ mariadb-client-core-5.2,
+ mariadb-client-core-5.3,
+ mariadb-client-core-5.5,
+ mysql-client (<< 5.0.51),
+ mysql-client-5.0,
+ mysql-client-5.1,
+ mysql-client-5.5,
+ mysql-client-core-5.1,
+ mysql-client-core-5.5,
+ mysql-client-core-5.6,
+ mysql-client-core-5.7,
+ mysql-client-core-8.0,
+ virtual-mysql-client-core,
+Breaks:
+ mariadb-client (<< ${source:Version}),
+ mariadb-server-10.0,
+ mariadb-server-10.1,
+ mariadb-server-core (<< ${source:Version}),
+ mariadb-server-core-10.0,
+ mariadb-server-core-10.1,
+ mariadb-server-core-10.2,
+ mariadb-server-core-10.3,
+ mariadb-server-core-10.4,
+ mariadb-server-core-10.5,
+ mariadb-server-core-10.6,
+ mariadb-server-core-10.7,
+ mariadb-server-core-10.8,
+ mysql-cluster-community-client-plugins,
+ mysql-server-core-5.5,
+ mysql-server-core-5.6,
+ mysql-server-core-5.7,
+ mysql-server-core-8.0,
+ percona-server-server-5.6,
+ percona-server-server-5.7,
+ percona-server-server-8.0,
+ percona-xtradb-cluster-server-5.6,
+ percona-xtradb-cluster-server-5.7,
+ percona-xtradb-cluster-server-8.0,
+Replaces:
+ mariadb-client (<< ${source:Version}),
+ mariadb-client-10.0,
+ mariadb-client-10.1,
+ mariadb-client-10.2,
+ mariadb-client-10.3,
+ mariadb-client-10.4,
+ mariadb-client-10.5,
+ mariadb-client-10.6,
+ mariadb-client-10.7,
+ mariadb-client-10.8,
+ mariadb-client-5.1,
+ mariadb-client-5.2,
+ mariadb-client-5.3,
+ mariadb-client-5.5,
+ mariadb-client-core-10.0,
+ mariadb-client-core-10.1,
+ mariadb-client-core-10.2,
+ mariadb-client-core-10.3,
+ mariadb-client-core-10.4,
+ mariadb-client-core-10.5,
+ mariadb-client-core-10.6,
+ mariadb-client-core-10.7,
+ mariadb-client-core-10.8,
+ mariadb-client-core-5.1,
+ mariadb-client-core-5.2,
+ mariadb-client-core-5.3,
+ mariadb-client-core-5.5,
+ mariadb-server-10.0,
+ mariadb-server-10.1,
+ mariadb-server-core (<< ${source:Version}),
+ mariadb-server-core-10.0,
+ mariadb-server-core-10.1,
+ mariadb-server-core-10.2,
+ mariadb-server-core-10.3,
+ mariadb-server-core-10.4,
+ mariadb-server-core-10.5,
+ mariadb-server-core-10.6,
+ mariadb-server-core-10.7,
+ mariadb-server-core-10.8,
+ mysql-client (<< 5.0.51),
+ mysql-client-5.0,
+ mysql-client-5.1,
+ mysql-client-5.5,
+ mysql-client-core-5.1,
+ mysql-client-core-5.5,
+ mysql-client-core-5.6,
+ mysql-client-core-5.7,
+ mysql-client-core-8.0,
+ mysql-cluster-community-client-plugins,
+ mysql-server-core-5.5,
+ mysql-server-core-5.6,
+ mysql-server-core-5.7,
+ mysql-server-core-8.0,
+ percona-server-server-5.6,
+ percona-server-server-5.7,
+ percona-server-server-8.0,
+ percona-xtradb-cluster-server-5.6,
+ percona-xtradb-cluster-server-5.7,
+ percona-xtradb-cluster-server-8.0,
+ virtual-mysql-client-core,
+Provides:
+ default-mysql-client-core,
+ virtual-mysql-client-core,
Description: MariaDB database core client binaries
MariaDB is a fast, stable and true multi-user, multi-threaded SQL database
server. SQL (Structured Query Language) is the most popular database query
@@ -404,157 +445,163 @@ Description: MariaDB database core client binaries
Package: mariadb-client
Architecture: any
-Depends: debianutils (>=1.6),
- libconfig-inifiles-perl,
- mariadb-client-core (>= ${source:Version}),
- mariadb-common,
- ${misc:Depends},
- ${perl:Depends},
- ${shlibs:Depends}
-Conflicts: mariadb-client-10.0,
- mariadb-client-10.1,
- mariadb-client-10.2,
- mariadb-client-10.3,
- mariadb-client-10.4,
- mariadb-client-10.5,
- mariadb-client-10.6,
- mariadb-client-10.7,
- mariadb-client-10.8,
- mariadb-client-5.1,
- mariadb-client-5.2,
- mariadb-client-5.3,
- mariadb-client-5.5,
- mysql-client (<< 5.0.51),
- mysql-client-5.0,
- mysql-client-5.1,
- mysql-client-5.5,
- mysql-client-5.6,
- mysql-client-5.7,
- mysql-client-8.0,
- mysql-client-core-5.0,
- mysql-client-core-5.1,
- mysql-client-core-5.5,
- mysql-client-core-5.6,
- mysql-client-core-5.7,
- mysql-client-core-8.0,
- mytop,
- virtual-mysql-client
-Breaks: mariadb-client-core (<< ${source:Version}),
- mariadb-client-core-10.0,
- mariadb-client-core-10.1,
- mariadb-client-core-10.2,
- mariadb-client-core-10.3,
- mariadb-client-core-10.4,
- mariadb-client-core-10.5,
- mariadb-client-core-10.6,
- mariadb-client-core-10.7,
- mariadb-client-core-10.8,
- mariadb-server (<< ${source:Version}),
- mariadb-server-10.0,
- mariadb-server-10.1,
- mariadb-server-10.2,
- mariadb-server-10.3,
- mariadb-server-10.4,
- mariadb-server-10.5,
- mariadb-server-10.6,
- mariadb-server-10.7,
- mariadb-server-10.8,
- mariadb-server-core (<< ${source:Version}),
- mariadb-server-core-10.0,
- mariadb-server-core-10.1,
- mariadb-server-core-10.2,
- mariadb-server-core-10.3,
- mariadb-server-core-10.4,
- mariadb-server-core-10.5,
- mariadb-server-core-10.6,
- mariadb-server-core-10.7,
- mariadb-server-core-10.8,
- mysql-server-5.5,
- mysql-server-5.6,
- mysql-server-5.7,
- mysql-server-8.0,
- mysql-server-core-5.5,
- mysql-server-core-5.6,
- mysql-server-core-5.7,
- mysql-server-core-8.0,
- percona-server-server-5.6,
- percona-xtradb-cluster-server-5.6,
- percona-xtradb-cluster-server-5.7
-Replaces: mariadb-client-10.0,
- mariadb-client-10.1,
- mariadb-client-10.2,
- mariadb-client-10.3,
- mariadb-client-10.4,
- mariadb-client-10.5,
- mariadb-client-10.6,
- mariadb-client-10.7,
- mariadb-client-10.8,
- mariadb-client-5.1,
- mariadb-client-5.2,
- mariadb-client-5.3,
- mariadb-client-5.5,
- mariadb-client-core (<< ${source:Version}),
- mariadb-client-core-10.0,
- mariadb-client-core-10.1,
- mariadb-client-core-10.2,
- mariadb-client-core-10.3,
- mariadb-client-core-10.4,
- mariadb-client-core-10.5,
- mariadb-client-core-10.6,
- mariadb-client-core-10.7,
- mariadb-client-core-10.8,
- mariadb-server (<< ${source:Version}),
- mariadb-server-10.0,
- mariadb-server-10.1,
- mariadb-server-10.2,
- mariadb-server-10.3,
- mariadb-server-10.4,
- mariadb-server-10.5,
- mariadb-server-10.6,
- mariadb-server-10.7,
- mariadb-server-10.8,
- mariadb-server-core (<< ${source:Version}),
- mariadb-server-core-10.0,
- mariadb-server-core-10.1,
- mariadb-server-core-10.2,
- mariadb-server-core-10.3,
- mariadb-server-core-10.4,
- mariadb-server-core-10.5,
- mariadb-server-core-10.6,
- mariadb-server-core-10.7,
- mariadb-server-core-10.8,
- mysql-client (<< 5.0.51),
- mysql-client-5.0,
- mysql-client-5.1,
- mysql-client-5.5,
- mysql-client-5.6,
- mysql-client-5.7,
- mysql-client-8.0,
- mysql-client-core-5.0,
- mysql-client-core-5.1,
- mysql-client-core-5.5,
- mysql-client-core-5.6,
- mysql-client-core-5.7,
- mysql-client-core-8.0,
- mysql-server-5.5,
- mysql-server-5.6,
- mysql-server-5.7,
- mysql-server-8.0,
- mysql-server-core-5.5,
- mysql-server-core-5.6,
- mysql-server-core-5.7,
- mysql-server-core-8.0,
- mytop,
- percona-server-server-5.6,
- percona-xtradb-cluster-server-5.6,
- percona-xtradb-cluster-server-5.7,
- virtual-mysql-client
-Provides: default-mysql-client,
- virtual-mysql-client
-Recommends: libdbd-mariadb-perl | libdbd-mysql-perl,
- libdbi-perl,
- libterm-readkey-perl,
- mariadb-client-compat
+Depends:
+ debianutils (>=1.6),
+ libconfig-inifiles-perl,
+ mariadb-client-core (>= ${source:Version}),
+ mariadb-common,
+ ${misc:Depends},
+ ${perl:Depends},
+ ${shlibs:Depends},
+Conflicts:
+ mariadb-client-10.0,
+ mariadb-client-10.1,
+ mariadb-client-10.2,
+ mariadb-client-10.3,
+ mariadb-client-10.4,
+ mariadb-client-10.5,
+ mariadb-client-10.6,
+ mariadb-client-10.7,
+ mariadb-client-10.8,
+ mariadb-client-5.1,
+ mariadb-client-5.2,
+ mariadb-client-5.3,
+ mariadb-client-5.5,
+ mysql-client (<< 5.0.51),
+ mysql-client-5.0,
+ mysql-client-5.1,
+ mysql-client-5.5,
+ mysql-client-5.6,
+ mysql-client-5.7,
+ mysql-client-8.0,
+ mysql-client-core-5.0,
+ mysql-client-core-5.1,
+ mysql-client-core-5.5,
+ mysql-client-core-5.6,
+ mysql-client-core-5.7,
+ mysql-client-core-8.0,
+ mytop,
+ virtual-mysql-client,
+Breaks:
+ mariadb-client-core (<< ${source:Version}),
+ mariadb-client-core-10.0,
+ mariadb-client-core-10.1,
+ mariadb-client-core-10.2,
+ mariadb-client-core-10.3,
+ mariadb-client-core-10.4,
+ mariadb-client-core-10.5,
+ mariadb-client-core-10.6,
+ mariadb-client-core-10.7,
+ mariadb-client-core-10.8,
+ mariadb-server (<< ${source:Version}),
+ mariadb-server-10.0,
+ mariadb-server-10.1,
+ mariadb-server-10.2,
+ mariadb-server-10.3,
+ mariadb-server-10.4,
+ mariadb-server-10.5,
+ mariadb-server-10.6,
+ mariadb-server-10.7,
+ mariadb-server-10.8,
+ mariadb-server-core (<< ${source:Version}),
+ mariadb-server-core-10.0,
+ mariadb-server-core-10.1,
+ mariadb-server-core-10.2,
+ mariadb-server-core-10.3,
+ mariadb-server-core-10.4,
+ mariadb-server-core-10.5,
+ mariadb-server-core-10.6,
+ mariadb-server-core-10.7,
+ mariadb-server-core-10.8,
+ mysql-server-5.5,
+ mysql-server-5.6,
+ mysql-server-5.7,
+ mysql-server-8.0,
+ mysql-server-core-5.5,
+ mysql-server-core-5.6,
+ mysql-server-core-5.7,
+ mysql-server-core-8.0,
+ percona-server-server-5.6,
+ percona-xtradb-cluster-server-5.6,
+ percona-xtradb-cluster-server-5.7,
+Replaces:
+ mariadb-client-10.0,
+ mariadb-client-10.1,
+ mariadb-client-10.2,
+ mariadb-client-10.3,
+ mariadb-client-10.4,
+ mariadb-client-10.5,
+ mariadb-client-10.6,
+ mariadb-client-10.7,
+ mariadb-client-10.8,
+ mariadb-client-5.1,
+ mariadb-client-5.2,
+ mariadb-client-5.3,
+ mariadb-client-5.5,
+ mariadb-client-core (<< ${source:Version}),
+ mariadb-client-core-10.0,
+ mariadb-client-core-10.1,
+ mariadb-client-core-10.2,
+ mariadb-client-core-10.3,
+ mariadb-client-core-10.4,
+ mariadb-client-core-10.5,
+ mariadb-client-core-10.6,
+ mariadb-client-core-10.7,
+ mariadb-client-core-10.8,
+ mariadb-server (<< ${source:Version}),
+ mariadb-server-10.0,
+ mariadb-server-10.1,
+ mariadb-server-10.2,
+ mariadb-server-10.3,
+ mariadb-server-10.4,
+ mariadb-server-10.5,
+ mariadb-server-10.6,
+ mariadb-server-10.7,
+ mariadb-server-10.8,
+ mariadb-server-core (<< ${source:Version}),
+ mariadb-server-core-10.0,
+ mariadb-server-core-10.1,
+ mariadb-server-core-10.2,
+ mariadb-server-core-10.3,
+ mariadb-server-core-10.4,
+ mariadb-server-core-10.5,
+ mariadb-server-core-10.6,
+ mariadb-server-core-10.7,
+ mariadb-server-core-10.8,
+ mysql-client (<< 5.0.51),
+ mysql-client-5.0,
+ mysql-client-5.1,
+ mysql-client-5.5,
+ mysql-client-5.6,
+ mysql-client-5.7,
+ mysql-client-8.0,
+ mysql-client-core-5.0,
+ mysql-client-core-5.1,
+ mysql-client-core-5.5,
+ mysql-client-core-5.6,
+ mysql-client-core-5.7,
+ mysql-client-core-8.0,
+ mysql-server-5.5,
+ mysql-server-5.6,
+ mysql-server-5.7,
+ mysql-server-8.0,
+ mysql-server-core-5.5,
+ mysql-server-core-5.6,
+ mysql-server-core-5.7,
+ mysql-server-core-8.0,
+ mytop,
+ percona-server-server-5.6,
+ percona-xtradb-cluster-server-5.6,
+ percona-xtradb-cluster-server-5.7,
+ virtual-mysql-client,
+Provides:
+ default-mysql-client,
+ virtual-mysql-client,
+Recommends:
+ libdbd-mariadb-perl | libdbd-mysql-perl,
+ libdbi-perl,
+ libterm-readkey-perl,
+ mariadb-client-compat,
Description: MariaDB database client binaries
MariaDB is a fast, stable and true multi-user, multi-threaded SQL database
server. SQL (Structured Query Language) is the most popular database query
@@ -566,75 +613,77 @@ Description: MariaDB database client binaries
Package: mariadb-client-compat
Architecture: all
-Depends: mariadb-client (>= ${source:Version})
-Conflicts: mariadb-client (<< 11.0.0),
- mariadb-client-10.0,
- mariadb-client-10.1,
- mariadb-client-10.2,
- mariadb-client-10.3,
- mariadb-client-10.4,
- mariadb-client-10.5,
- mariadb-client-10.6,
- mariadb-client-10.7,
- mariadb-client-10.8,
- mariadb-client-5.1,
- mariadb-client-5.2,
- mariadb-client-5.3,
- mariadb-client-5.5,
- mariadb-client-core (<< 11.0.0),
- mariadb-client-core-10.0,
- mariadb-client-core-10.1,
- mariadb-client-core-10.2,
- mariadb-client-core-10.3,
- mariadb-client-core-10.4,
- mariadb-client-core-10.5,
- mariadb-client-core-10.6,
- mariadb-client-core-10.7,
- mariadb-client-core-10.8,
- mariadb-client-core-5.1,
- mariadb-client-core-5.2,
- mariadb-client-core-5.3,
- mariadb-client-core-5.5,
- mariadb-server (<< 11.0.0),
- mariadb-server-10.0,
- mariadb-server-10.1,
- mariadb-server-10.2,
- mariadb-server-10.3,
- mariadb-server-10.4,
- mariadb-server-10.5,
- mariadb-server-10.6,
- mariadb-server-10.7,
- mariadb-server-10.8,
- mariadb-server-core (<< 11.0.0),
- mariadb-server-core-10.0,
- mariadb-server-core-10.1,
- mariadb-server-core-10.2,
- mariadb-server-core-10.3,
- mariadb-server-core-10.4,
- mariadb-server-core-10.5,
- mariadb-server-core-10.6,
- mariadb-server-core-10.7,
- mariadb-server-core-10.8,
- mysql-client (<< 5.0.51),
- mysql-client-5.0,
- mysql-client-5.1,
- mysql-client-5.5,
- mysql-client-5.6,
- mysql-client-5.7,
- mysql-client-8.0,
- mysql-client-core-5.0,
- mysql-client-core-5.1,
- mysql-client-core-5.5,
- mysql-client-core-5.6,
- mysql-client-core-5.7,
- mysql-client-core-8.0,
- mysql-server-5.7,
- mysql-server-core-8.0,
- percona-server-server,
- percona-server-server-5.6,
- percona-xtradb-cluster-server,
- percona-xtradb-cluster-server-5.6,
- percona-xtradb-cluster-server-5.7
+Depends:
+ mariadb-client (>= ${source:Version}),
+Conflicts:
+ mariadb-client (<< 11.0.0),
+ mariadb-client-10.0,
+ mariadb-client-10.1,
+ mariadb-client-10.2,
+ mariadb-client-10.3,
+ mariadb-client-10.4,
+ mariadb-client-10.5,
+ mariadb-client-10.6,
+ mariadb-client-10.7,
+ mariadb-client-10.8,
+ mariadb-client-5.1,
+ mariadb-client-5.2,
+ mariadb-client-5.3,
+ mariadb-client-5.5,
+ mariadb-client-core (<< 11.0.0),
+ mariadb-client-core-10.0,
+ mariadb-client-core-10.1,
+ mariadb-client-core-10.2,
+ mariadb-client-core-10.3,
+ mariadb-client-core-10.4,
+ mariadb-client-core-10.5,
+ mariadb-client-core-10.6,
+ mariadb-client-core-10.7,
+ mariadb-client-core-10.8,
+ mariadb-client-core-5.1,
+ mariadb-client-core-5.2,
+ mariadb-client-core-5.3,
+ mariadb-client-core-5.5,
+ mariadb-server (<< 11.0.0),
+ mariadb-server-10.0,
+ mariadb-server-10.1,
+ mariadb-server-10.2,
+ mariadb-server-10.3,
+ mariadb-server-10.4,
+ mariadb-server-10.5,
+ mariadb-server-10.6,
+ mariadb-server-10.7,
+ mariadb-server-10.8,
+ mariadb-server-core (<< 11.0.0),
+ mariadb-server-core-10.0,
+ mariadb-server-core-10.1,
+ mariadb-server-core-10.2,
+ mariadb-server-core-10.3,
+ mariadb-server-core-10.4,
+ mariadb-server-core-10.5,
+ mariadb-server-core-10.6,
+ mariadb-server-core-10.7,
+ mariadb-server-core-10.8,
+ mysql-client (<< 5.0.51),
+ mysql-client-5.0,
+ mysql-client-5.1,
+ mysql-client-5.5,
+ mysql-client-5.6,
+ mysql-client-5.7,
+ mysql-client-8.0,
+ mysql-client-core-5.0,
+ mysql-client-core-5.1,
+ mysql-client-core-5.5,
+ mysql-client-core-5.6,
+ mysql-client-core-5.7,
+ mysql-client-core-8.0,
+ mysql-server-5.7,
+ mysql-server-core-8.0,
+ percona-server-server,
+ percona-server-server-5.6,
+ percona-xtradb-cluster-server,
+ percona-xtradb-cluster-server-5.6,
+ percona-xtradb-cluster-server-5.7,
Multi-Arch: foreign
Description: MySQL compatibility links to mariadb-client binaries/scripts.
The package contains links and binaries that are needed by MySQL centric
@@ -645,106 +694,111 @@ Description: MySQL compatibility links to mariadb-client binaries/scripts.
Package: mariadb-server-core
Architecture: any
-Depends: mariadb-common (>= ${source:Version}),
- ${misc:Depends},
- ${shlibs:Depends}
-Conflicts: mariadb-server-core-10.0,
- mariadb-server-core-10.1,
- mariadb-server-core-10.2,
- mariadb-server-core-10.3,
- mariadb-server-core-10.4,
- mariadb-server-core-10.5,
- mariadb-server-core-10.6,
- mariadb-server-core-10.7,
- mariadb-server-core-10.8,
- mariadb-server-core-5.1,
- mariadb-server-core-5.2,
- mariadb-server-core-5.3,
- mariadb-server-core-5.5,
- mysql-server-5.0,
- mysql-server-core-5.0,
- mysql-server-core-5.1,
- mysql-server-core-5.5,
- mysql-server-core-5.6,
- mysql-server-core-5.7,
- mysql-server-core-8.0,
- virtual-mysql-server-core
-Breaks: mariadb-client (<< ${source:Version}),
- mariadb-client-10.0,
- mariadb-client-10.1,
- mariadb-client-10.2,
- mariadb-client-10.3,
- mariadb-client-10.4,
- mariadb-client-10.5,
- mariadb-client-10.6,
- mariadb-client-10.7,
- mariadb-client-10.8,
- mariadb-server (<< ${source:Version}),
- mariadb-server-10.0,
- mariadb-server-10.1,
- mariadb-server-10.2,
- mariadb-server-10.3,
- mariadb-server-10.4,
- mariadb-server-10.5,
- mariadb-server-10.6,
- mariadb-server-10.7,
- mariadb-server-10.8,
- mysql-client-5.5,
- mysql-server-5.5,
- mysql-server-5.6,
- mysql-server-5.7,
- mysql-server-8.0,
- percona-server-server-5.6,
- percona-xtradb-cluster-server-5.6,
- percona-xtradb-cluster-server-5.7
-Replaces: mariadb-client (<< ${source:Version}),
- mariadb-client-10.0,
- mariadb-client-10.1,
- mariadb-client-10.2,
- mariadb-client-10.3,
- mariadb-client-10.4,
- mariadb-client-10.5,
- mariadb-client-10.6,
- mariadb-client-10.7,
- mariadb-client-10.8,
- mariadb-server (<< ${source:Version}),
- mariadb-server-10.0,
- mariadb-server-10.1,
- mariadb-server-10.2,
- mariadb-server-10.3,
- mariadb-server-10.4,
- mariadb-server-10.5,
- mariadb-server-10.6,
- mariadb-server-10.7,
- mariadb-server-10.8,
- mariadb-server-core-10.0,
- mariadb-server-core-10.1,
- mariadb-server-core-10.2,
- mariadb-server-core-10.3,
- mariadb-server-core-10.4,
- mariadb-server-core-10.5,
- mariadb-server-core-5.1,
- mariadb-server-core-5.2,
- mariadb-server-core-5.3,
- mariadb-server-core-5.5,
- mysql-client-5.5,
- mysql-server-5.0,
- mysql-server-5.5,
- mysql-server-5.6,
- mysql-server-5.7,
- mysql-server-8.0,
- mysql-server-core-5.0,
- mysql-server-core-5.1,
- mysql-server-core-5.5,
- mysql-server-core-5.6,
- mysql-server-core-5.7,
- mysql-server-core-8.0,
- percona-server-server-5.6,
- percona-xtradb-cluster-server-5.6,
- percona-xtradb-cluster-server-5.7,
- virtual-mysql-server-core
-Provides: default-mysql-server-core,
- virtual-mysql-server-core
+Depends:
+ mariadb-common (>= ${source:Version}),
+ ${misc:Depends},
+ ${shlibs:Depends},
+Conflicts:
+ mariadb-server-core-10.0,
+ mariadb-server-core-10.1,
+ mariadb-server-core-10.2,
+ mariadb-server-core-10.3,
+ mariadb-server-core-10.4,
+ mariadb-server-core-10.5,
+ mariadb-server-core-10.6,
+ mariadb-server-core-10.7,
+ mariadb-server-core-10.8,
+ mariadb-server-core-5.1,
+ mariadb-server-core-5.2,
+ mariadb-server-core-5.3,
+ mariadb-server-core-5.5,
+ mysql-server-5.0,
+ mysql-server-core-5.0,
+ mysql-server-core-5.1,
+ mysql-server-core-5.5,
+ mysql-server-core-5.6,
+ mysql-server-core-5.7,
+ mysql-server-core-8.0,
+ virtual-mysql-server-core,
+Breaks:
+ mariadb-client (<< ${source:Version}),
+ mariadb-client-10.0,
+ mariadb-client-10.1,
+ mariadb-client-10.2,
+ mariadb-client-10.3,
+ mariadb-client-10.4,
+ mariadb-client-10.5,
+ mariadb-client-10.6,
+ mariadb-client-10.7,
+ mariadb-client-10.8,
+ mariadb-server (<< ${source:Version}),
+ mariadb-server-10.0,
+ mariadb-server-10.1,
+ mariadb-server-10.2,
+ mariadb-server-10.3,
+ mariadb-server-10.4,
+ mariadb-server-10.5,
+ mariadb-server-10.6,
+ mariadb-server-10.7,
+ mariadb-server-10.8,
+ mysql-client-5.5,
+ mysql-server-5.5,
+ mysql-server-5.6,
+ mysql-server-5.7,
+ mysql-server-8.0,
+ percona-server-server-5.6,
+ percona-xtradb-cluster-server-5.6,
+ percona-xtradb-cluster-server-5.7,
+Replaces:
+ mariadb-client (<< ${source:Version}),
+ mariadb-client-10.0,
+ mariadb-client-10.1,
+ mariadb-client-10.2,
+ mariadb-client-10.3,
+ mariadb-client-10.4,
+ mariadb-client-10.5,
+ mariadb-client-10.6,
+ mariadb-client-10.7,
+ mariadb-client-10.8,
+ mariadb-server (<< ${source:Version}),
+ mariadb-server-10.0,
+ mariadb-server-10.1,
+ mariadb-server-10.2,
+ mariadb-server-10.3,
+ mariadb-server-10.4,
+ mariadb-server-10.5,
+ mariadb-server-10.6,
+ mariadb-server-10.7,
+ mariadb-server-10.8,
+ mariadb-server-core-10.0,
+ mariadb-server-core-10.1,
+ mariadb-server-core-10.2,
+ mariadb-server-core-10.3,
+ mariadb-server-core-10.4,
+ mariadb-server-core-10.5,
+ mariadb-server-core-5.1,
+ mariadb-server-core-5.2,
+ mariadb-server-core-5.3,
+ mariadb-server-core-5.5,
+ mysql-client-5.5,
+ mysql-server-5.0,
+ mysql-server-5.5,
+ mysql-server-5.6,
+ mysql-server-5.7,
+ mysql-server-8.0,
+ mysql-server-core-5.0,
+ mysql-server-core-5.1,
+ mysql-server-core-5.5,
+ mysql-server-core-5.6,
+ mysql-server-core-5.7,
+ mysql-server-core-8.0,
+ percona-server-server-5.6,
+ percona-xtradb-cluster-server-5.6,
+ percona-xtradb-cluster-server-5.7,
+ virtual-mysql-server-core,
+Provides:
+ default-mysql-server-core,
+ virtual-mysql-server-core,
Description: MariaDB database core server files
MariaDB is a fast, stable and true multi-user, multi-threaded SQL database
server. SQL (Structured Query Language) is the most popular database query
@@ -755,106 +809,107 @@ Description: MariaDB database core server files
Package: mariadb-server
Architecture: any
-Suggests: mailx,
- mariadb-test,
- netcat-openbsd
-Recommends: libhtml-template-perl,
- mariadb-server-compat,
- pv
-Pre-Depends: adduser (>= 3.40),
- debconf,
- mariadb-common (>= ${source:Version})
-Depends: galera-4 (>= 26.4),
- gawk,
- iproute2 [linux-any],
- libdbi-perl,
- lsof [linux-any],
- mariadb-client (>= ${source:Version}),
- mariadb-server-core (>= ${source:Version}),
- passwd,
- perl (>= 5.6),
- procps,
- psmisc,
- rsync,
- socat,
- ${misc:Depends},
- ${perl:Depends},
- ${shlibs:Depends}
-Conflicts: mariadb-server-10.0,
- mariadb-server-10.1,
- mariadb-server-10.2,
- mariadb-server-10.3,
- mariadb-server-10.4,
- mariadb-server-10.5,
- mariadb-server-10.6,
- mariadb-server-10.7,
- mariadb-server-10.8,
- mariadb-server-5.1,
- mariadb-server-5.2,
- mariadb-server-5.3,
- mariadb-server-5.5,
- mysql-client-5.5,
- mysql-client-5.6,
- mysql-client-5.7,
- mysql-client-8.0,
- mysql-client-core-8.0,
- mysql-server,
- mysql-server-4.1,
- mysql-server-5.0,
- mysql-server-5.1,
- mysql-server-5.5,
- mysql-server-5.6,
- mysql-server-5.7,
- mysql-server-8.0,
- mysql-server-core-5.5,
- mysql-server-core-5.6,
- mysql-server-core-5.7,
- mysql-server-core-8.0,
- virtual-mysql-server
-Breaks: handlersocket-mysql-5.5,
- percona-server-server-5.6,
- percona-xtradb-cluster-server-5.6,
- percona-xtradb-cluster-server-5.7
-Replaces: handlersocket-mysql-5.5,
- libmariadbclient-dev (<< 5.5.0),
- libmariadbclient16,
- mariadb-client (<< ${source:Version}),
- mariadb-client-10.5,
- mariadb-client-10.6,
- mariadb-client-10.7,
- mariadb-client-10.8,
- mariadb-server-10.0,
- mariadb-server-10.1,
- mariadb-server-10.2,
- mariadb-server-10.3,
- mariadb-server-10.4,
- mariadb-server-10.5,
- mariadb-server-10.6,
- mariadb-server-10.7,
- mariadb-server-10.8,
- mariadb-server-5.1,
- mariadb-server-5.2,
- mariadb-server-5.3,
- mariadb-server-5.5,
- mysql-client-5.5,
- mysql-client-5.6,
- mysql-client-5.7,
- mysql-client-8.0,
- mysql-client-core-8.0,
- mysql-server,
- mysql-server-4.1,
- mysql-server-5.0,
- mysql-server-5.1,
- mysql-server-5.5,
- mysql-server-5.6,
- mysql-server-5.7,
- mysql-server-8.0,
- percona-server-server-5.6,
- percona-xtradb-cluster-server-5.6,
- percona-xtradb-cluster-server-5.7,
- virtual-mysql-server
-Provides: default-mysql-server,
- virtual-mysql-server
+Suggests:
+ mailx,
+ mariadb-test,
+ netcat-openbsd,
+Recommends:
+ libhtml-template-perl,
+ mariadb-server-compat,
+Pre-Depends:
+ adduser (>= 3.40),
+ debconf,
+ mariadb-common (>= ${source:Version}),
+Depends:
+ libdbi-perl,
+ mariadb-client (>= ${source:Version}),
+ mariadb-server-core (>= ${source:Version}),
+ passwd,
+ perl (>= 5.6),
+ procps,
+ psmisc,
+ ${misc:Depends},
+ ${perl:Depends},
+ ${shlibs:Depends},
+Conflicts:
+ mariadb-server-10.0,
+ mariadb-server-10.1,
+ mariadb-server-10.2,
+ mariadb-server-10.3,
+ mariadb-server-10.4,
+ mariadb-server-10.5,
+ mariadb-server-10.6,
+ mariadb-server-10.7,
+ mariadb-server-10.8,
+ mariadb-server-5.1,
+ mariadb-server-5.2,
+ mariadb-server-5.3,
+ mariadb-server-5.5,
+ mysql-client-5.5,
+ mysql-client-5.6,
+ mysql-client-5.7,
+ mysql-client-8.0,
+ mysql-client-core-8.0,
+ mysql-server,
+ mysql-server-4.1,
+ mysql-server-5.0,
+ mysql-server-5.1,
+ mysql-server-5.5,
+ mysql-server-5.6,
+ mysql-server-5.7,
+ mysql-server-8.0,
+ mysql-server-core-5.5,
+ mysql-server-core-5.6,
+ mysql-server-core-5.7,
+ mysql-server-core-8.0,
+ virtual-mysql-server,
+Breaks:
+ handlersocket-mysql-5.5,
+ percona-server-server-5.6,
+ percona-xtradb-cluster-server-5.6,
+ percona-xtradb-cluster-server-5.7,
+Replaces:
+ handlersocket-mysql-5.5,
+ libmariadbclient-dev (<< 5.5.0),
+ libmariadbclient16,
+ mariadb-client (<< ${source:Version}),
+ mariadb-client-10.5,
+ mariadb-client-10.6,
+ mariadb-client-10.7,
+ mariadb-client-10.8,
+ mariadb-server-10.0,
+ mariadb-server-10.1,
+ mariadb-server-10.2,
+ mariadb-server-10.3,
+ mariadb-server-10.4,
+ mariadb-server-10.5,
+ mariadb-server-10.6,
+ mariadb-server-10.7,
+ mariadb-server-10.8,
+ mariadb-server-5.1,
+ mariadb-server-5.2,
+ mariadb-server-5.3,
+ mariadb-server-5.5,
+ mysql-client-5.5,
+ mysql-client-5.6,
+ mysql-client-5.7,
+ mysql-client-8.0,
+ mysql-client-core-8.0,
+ mysql-server,
+ mysql-server-4.1,
+ mysql-server-5.0,
+ mysql-server-5.1,
+ mysql-server-5.5,
+ mysql-server-5.6,
+ mysql-server-5.7,
+ mysql-server-8.0,
+ percona-server-server-5.6,
+ percona-xtradb-cluster-server-5.6,
+ percona-xtradb-cluster-server-5.7,
+ virtual-mysql-server,
+Provides:
+ default-mysql-server,
+ virtual-mysql-server,
Description: MariaDB database server binaries
MariaDB is a fast, stable and true multi-user, multi-threaded SQL database
server. SQL (Structured Query Language) is the most popular database query
@@ -865,48 +920,50 @@ Description: MariaDB database server binaries
Package: mariadb-server-compat
Architecture: all
-Depends: mariadb-server (>= ${source:Version})
-Conflicts: mariadb-server (<< 11.0.0),
- mariadb-server-10.0,
- mariadb-server-10.1,
- mariadb-server-10.2,
- mariadb-server-10.3,
- mariadb-server-10.4,
- mariadb-server-10.5,
- mariadb-server-10.6,
- mariadb-server-10.7,
- mariadb-server-10.8,
- mariadb-server-5.1,
- mariadb-server-5.2,
- mariadb-server-5.3,
- mariadb-server-5.5,
- mariadb-server-core (<< 11.0.0),
- mariadb-server-core-10.0,
- mariadb-server-core-10.1,
- mariadb-server-core-10.2,
- mariadb-server-core-10.3,
- mariadb-server-core-10.4,
- mariadb-server-core-10.5,
- mariadb-server-core-10.6,
- mariadb-server-core-10.7,
- mariadb-server-core-10.8,
- mariadb-server-core-5.1,
- mariadb-server-core-5.2,
- mariadb-server-core-5.3,
- mariadb-server-core-5.5,
- mysql-server-5.0,
- mysql-server-core-5.0,
- mysql-server-core-5.1,
- mysql-server-core-5.5,
- mysql-server-core-5.6,
- mysql-server-core-5.7,
- mysql-server-core-8.0,
- percona-server-server,
- percona-server-server-5.6,
- percona-server-server-5.7,
- percona-xtradb-cluster-server,
- percona-xtradb-cluster-server-5.6,
- percona-xtradb-cluster-server-5.7
+Depends:
+ mariadb-server (>= ${source:Version}),
+Conflicts:
+ mariadb-server (<< 11.0.0),
+ mariadb-server-10.0,
+ mariadb-server-10.1,
+ mariadb-server-10.2,
+ mariadb-server-10.3,
+ mariadb-server-10.4,
+ mariadb-server-10.5,
+ mariadb-server-10.6,
+ mariadb-server-10.7,
+ mariadb-server-10.8,
+ mariadb-server-5.1,
+ mariadb-server-5.2,
+ mariadb-server-5.3,
+ mariadb-server-5.5,
+ mariadb-server-core (<< 11.0.0),
+ mariadb-server-core-10.0,
+ mariadb-server-core-10.1,
+ mariadb-server-core-10.2,
+ mariadb-server-core-10.3,
+ mariadb-server-core-10.4,
+ mariadb-server-core-10.5,
+ mariadb-server-core-10.6,
+ mariadb-server-core-10.7,
+ mariadb-server-core-10.8,
+ mariadb-server-core-5.1,
+ mariadb-server-core-5.2,
+ mariadb-server-core-5.3,
+ mariadb-server-core-5.5,
+ mysql-server-5.0,
+ mysql-server-core-5.0,
+ mysql-server-core-5.1,
+ mysql-server-core-5.5,
+ mysql-server-core-5.6,
+ mysql-server-core-5.7,
+ mysql-server-core-8.0,
+ percona-server-server,
+ percona-server-server-5.6,
+ percona-server-server-5.7,
+ percona-xtradb-cluster-server,
+ percona-xtradb-cluster-server-5.6,
+ percona-xtradb-cluster-server-5.7,
Multi-Arch: foreign
Description: MySQL compatibility links to mariadb-server binaries/scripts.
The package contains links and binaries that are needed by MySQL centric
@@ -917,17 +974,20 @@ Description: MySQL compatibility links to mariadb-server binaries/scripts.
Package: mariadb-backup
Architecture: any
-Breaks: mariadb-backup-10.1,
- mariadb-backup-10.2,
- mariadb-backup-10.3,
- mariadb-client-10.1
-Replaces: mariadb-backup-10.1,
- mariadb-backup-10.2,
- mariadb-backup-10.3,
- mariadb-client-10.1
-Depends: mariadb-client-core (= ${binary:Version}),
- ${misc:Depends},
- ${shlibs:Depends}
+Breaks:
+ mariadb-backup-10.1,
+ mariadb-backup-10.2,
+ mariadb-backup-10.3,
+ mariadb-client-10.1,
+Replaces:
+ mariadb-backup-10.1,
+ mariadb-backup-10.2,
+ mariadb-backup-10.3,
+ mariadb-client-10.1,
+Depends:
+ mariadb-client-core (= ${binary:Version}),
+ ${misc:Depends},
+ ${shlibs:Depends},
Description: Backup tool for MariaDB server
Based on Xtrabackup, but improved to work with MariaDB server.
This backup tool is guaranteed to be compatible with MariaDB server.
@@ -937,27 +997,31 @@ Description: Backup tool for MariaDB server
Package: mariadb-plugin-connect
Architecture: any
-Depends: libxml2,
- mariadb-server (= ${server:Version}),
- unixodbc,
- ${misc:Depends},
- ${shlibs:Depends}
-Recommends: curl
-Breaks: mariadb-connect-engine-10.0,
- mariadb-connect-engine-10.1,
- mariadb-connect-engine-10.2,
- mariadb-connect-engine-10.3,
- mariadb-connect-engine-10.4,
- mariadb-server-10.0,
- mariadb-server-10.1
-Replaces: mariadb-connect-engine-10.0,
- mariadb-connect-engine-10.1,
- mariadb-connect-engine-10.2,
- mariadb-connect-engine-10.3,
- mariadb-connect-engine-10.4,
- mariadb-server-10.0,
- mariadb-server-10.1
-Suggests: mariadb-plugin-connect-jdbc
+Depends:
+ mariadb-server (= ${server:Version}),
+ unixodbc,
+ ${misc:Depends},
+ ${shlibs:Depends},
+Recommends:
+ curl,
+Breaks:
+ mariadb-connect-engine-10.0,
+ mariadb-connect-engine-10.1,
+ mariadb-connect-engine-10.2,
+ mariadb-connect-engine-10.3,
+ mariadb-connect-engine-10.4,
+ mariadb-server-10.0,
+ mariadb-server-10.1,
+Replaces:
+ mariadb-connect-engine-10.0,
+ mariadb-connect-engine-10.1,
+ mariadb-connect-engine-10.2,
+ mariadb-connect-engine-10.3,
+ mariadb-connect-engine-10.4,
+ mariadb-server-10.0,
+ mariadb-server-10.1,
+Suggests:
+ mariadb-plugin-connect-jdbc,
Description: Connect storage engine for MariaDB server
Connect engine supports a number of file formats (dbf, xml, txt, bin, etc),
connections to ODBC tables and remote MySQL tables, as well as a number of
@@ -966,13 +1030,16 @@ Description: Connect storage engine for MariaDB server
Package: mariadb-plugin-connect-jdbc
Architecture: any
-Depends: default-jre-headless
-Suggests: libcsvjdbc-java,
- libmariadb-java,
- libpostgis-java,
- libpostgresql-jdbc-java,
- libxerial-sqlite-jdbc-java
-Enhances: mariadb-plugin-connect
+Depends:
+ default-jre-headless,
+Suggests:
+ libcsvjdbc-java,
+ libmariadb-java,
+ libpostgis-java,
+ libpostgresql-jdbc-java,
+ libxerial-sqlite-jdbc-java,
+Enhances:
+ mariadb-plugin-connect,
Description: Connect storage engine JDBC interface for MariaDB server.
To connect to remote DBMS using Connect Storage Engine (SE) and JDBC driver,
there is need for JDBC interface byte code.
@@ -981,10 +1048,10 @@ Description: Connect storage engine JDBC interface for MariaDB server.
Package: mariadb-plugin-s3
Architecture: any
-Depends: libcurl4,
- mariadb-server (= ${server:Version}),
- ${misc:Depends},
- ${shlibs:Depends}
+Depends:
+ mariadb-server (= ${server:Version}),
+ ${misc:Depends},
+ ${shlibs:Depends},
Description: Amazon S3 archival storage engine for MariaDB
The S3 storage engine allows one to archive MariaDB tables in Amazon S3 (or any
third-party public or private cloud that implements S3 API), but still have
@@ -992,18 +1059,22 @@ Description: Amazon S3 archival storage engine for MariaDB
Package: mariadb-plugin-rocksdb
Architecture: amd64 arm64 mips64el ppc64el riscv64
-Depends: mariadb-server (= ${server:Version}),
- python3:any,
- rocksdb-tools,
- ${misc:Depends},
- ${shlibs:Depends}
-Breaks: mariadb-rocksdb-engine-10.2,
- mariadb-rocksdb-engine-10.3,
- mariadb-rocksdb-engine-10.4
-Replaces: mariadb-rocksdb-engine-10.2,
- mariadb-rocksdb-engine-10.3,
- mariadb-rocksdb-engine-10.4
-Recommends: python3-mysqldb
+Depends:
+ mariadb-server (= ${server:Version}),
+ python3:any,
+ rocksdb-tools,
+ ${misc:Depends},
+ ${shlibs:Depends},
+Breaks:
+ mariadb-rocksdb-engine-10.2,
+ mariadb-rocksdb-engine-10.3,
+ mariadb-rocksdb-engine-10.4,
+Replaces:
+ mariadb-rocksdb-engine-10.2,
+ mariadb-rocksdb-engine-10.3,
+ mariadb-rocksdb-engine-10.4,
+Recommends:
+ python3-mysqldb,
Description: RocksDB storage engine for MariaDB server
The RocksDB storage engine is a high performance storage engine, aimed
at maximising storage efficiency while maintaining InnoDB-like performance.
@@ -1011,24 +1082,26 @@ Description: RocksDB storage engine for MariaDB server
Package: mariadb-plugin-oqgraph
Architecture: any
-Depends: libjudydebian1,
- mariadb-server (= ${server:Version}),
- ${misc:Depends},
- ${shlibs:Depends}
-Breaks: mariadb-oqgraph-engine-10.0,
- mariadb-oqgraph-engine-10.1,
- mariadb-oqgraph-engine-10.2,
- mariadb-oqgraph-engine-10.3,
- mariadb-oqgraph-engine-10.4,
- mariadb-server-10.0,
- mariadb-server-10.1
-Replaces: mariadb-oqgraph-engine-10.0,
- mariadb-oqgraph-engine-10.1,
- mariadb-oqgraph-engine-10.2,
- mariadb-oqgraph-engine-10.3,
- mariadb-oqgraph-engine-10.4,
- mariadb-server-10.0,
- mariadb-server-10.1
+Depends:
+ mariadb-server (= ${server:Version}),
+ ${misc:Depends},
+ ${shlibs:Depends},
+Breaks:
+ mariadb-oqgraph-engine-10.0,
+ mariadb-oqgraph-engine-10.1,
+ mariadb-oqgraph-engine-10.2,
+ mariadb-oqgraph-engine-10.3,
+ mariadb-oqgraph-engine-10.4,
+ mariadb-server-10.0,
+ mariadb-server-10.1,
+Replaces:
+ mariadb-oqgraph-engine-10.0,
+ mariadb-oqgraph-engine-10.1,
+ mariadb-oqgraph-engine-10.2,
+ mariadb-oqgraph-engine-10.3,
+ mariadb-oqgraph-engine-10.4,
+ mariadb-server-10.0,
+ mariadb-server-10.1,
Description: OQGraph storage engine for MariaDB server
The OQGraph engine is a computation engine plugin for handling hierarchies
(trees) and graphs (friend-of-a-friend, etc) cleanly through standard SQL.
@@ -1036,19 +1109,22 @@ Description: OQGraph storage engine for MariaDB server
Package: mariadb-plugin-mroonga
Architecture: any-alpha any-amd64 any-arm any-arm64 any-i386 any-ia64 any-mips64el any-mips64r6el any-mipsel any-mipsr6el any-nios2 any-powerpcel any-ppc64el any-sh3 any-sh4 any-tilegx
-Depends: mariadb-server (= ${server:Version}),
- ${misc:Depends},
- ${shlibs:Depends}
-Breaks: mariadb-server-10.0,
- mariadb-server-10.1,
- mariadb-server-10.2,
- mariadb-server-10.3,
- mariadb-server-10.4
-Replaces: mariadb-server-10.0,
- mariadb-server-10.1,
- mariadb-server-10.2,
- mariadb-server-10.3,
- mariadb-server-10.4
+Depends:
+ mariadb-server (= ${server:Version}),
+ ${misc:Depends},
+ ${shlibs:Depends},
+Breaks:
+ mariadb-server-10.0,
+ mariadb-server-10.1,
+ mariadb-server-10.2,
+ mariadb-server-10.3,
+ mariadb-server-10.4,
+Replaces:
+ mariadb-server-10.0,
+ mariadb-server-10.1,
+ mariadb-server-10.2,
+ mariadb-server-10.3,
+ mariadb-server-10.4,
Description: Mroonga storage engine for MariaDB server
Mroonga (formerly named Groonga Storage Engine) is a storage engine that
provides fast CJK-ready full text searching using column store.
@@ -1056,19 +1132,22 @@ Description: Mroonga storage engine for MariaDB server
Package: mariadb-plugin-spider
Architecture: any
-Depends: mariadb-server (= ${server:Version}),
- ${misc:Depends},
- ${shlibs:Depends}
-Breaks: mariadb-server-10.0,
- mariadb-server-10.1,
- mariadb-server-10.2,
- mariadb-server-10.3,
- mariadb-server-10.4
-Replaces: mariadb-server-10.0,
- mariadb-server-10.1,
- mariadb-server-10.2,
- mariadb-server-10.3,
- mariadb-server-10.4
+Depends:
+ mariadb-server (= ${server:Version}),
+ ${misc:Depends},
+ ${shlibs:Depends},
+Breaks:
+ mariadb-server-10.0,
+ mariadb-server-10.1,
+ mariadb-server-10.2,
+ mariadb-server-10.3,
+ mariadb-server-10.4,
+Replaces:
+ mariadb-server-10.0,
+ mariadb-server-10.1,
+ mariadb-server-10.2,
+ mariadb-server-10.3,
+ mariadb-server-10.4,
Description: Spider storage engine for MariaDB server
The Spider storage engine with built-in sharding features. It supports
partitioning and xa transactions, and allows tables of different MariaDB server
@@ -1077,22 +1156,24 @@ Description: Spider storage engine for MariaDB server
Package: mariadb-plugin-gssapi-server
Architecture: any
-Depends: libgssapi-krb5-2,
- mariadb-server,
- ${misc:Depends},
- ${shlibs:Depends}
-Breaks: mariadb-gssapi-server-10.1,
- mariadb-gssapi-server-10.2,
- mariadb-gssapi-server-10.3,
- mariadb-gssapi-server-10.4,
- mariadb-server-10.0,
- mariadb-server-10.1
-Replaces: mariadb-gssapi-server-10.1,
- mariadb-gssapi-server-10.2,
- mariadb-gssapi-server-10.3,
- mariadb-gssapi-server-10.4,
- mariadb-server-10.0,
- mariadb-server-10.1
+Depends:
+ mariadb-server (= ${server:Version}),
+ ${misc:Depends},
+ ${shlibs:Depends},
+Breaks:
+ mariadb-gssapi-server-10.1,
+ mariadb-gssapi-server-10.2,
+ mariadb-gssapi-server-10.3,
+ mariadb-gssapi-server-10.4,
+ mariadb-server-10.0,
+ mariadb-server-10.1,
+Replaces:
+ mariadb-gssapi-server-10.1,
+ mariadb-gssapi-server-10.2,
+ mariadb-gssapi-server-10.3,
+ mariadb-gssapi-server-10.4,
+ mariadb-server-10.0,
+ mariadb-server-10.1,
Description: GSSAPI authentication plugin for MariaDB server
This plugin includes support for Kerberos on Unix, but can also be used for
Windows authentication with or without domain environment.
@@ -1101,18 +1182,20 @@ Description: GSSAPI authentication plugin for MariaDB server
Package: mariadb-plugin-gssapi-client
Architecture: any
-Depends: libgssapi-krb5-2,
- mariadb-client (= ${binary:Version}),
- ${misc:Depends},
- ${shlibs:Depends}
-Breaks: mariadb-gssapi-client-10.1,
- mariadb-gssapi-client-10.2,
- mariadb-gssapi-client-10.3,
- mariadb-gssapi-client-10.4
-Replaces: mariadb-gssapi-client-10.1,
- mariadb-gssapi-client-10.2,
- mariadb-gssapi-client-10.3,
- mariadb-gssapi-client-10.4
+Depends:
+ mariadb-client (= ${binary:Version}),
+ ${misc:Depends},
+ ${shlibs:Depends},
+Breaks:
+ mariadb-gssapi-client-10.1,
+ mariadb-gssapi-client-10.2,
+ mariadb-gssapi-client-10.3,
+ mariadb-gssapi-client-10.4,
+Replaces:
+ mariadb-gssapi-client-10.1,
+ mariadb-gssapi-client-10.2,
+ mariadb-gssapi-client-10.3,
+ mariadb-gssapi-client-10.4,
Description: GSSAPI authentication plugin for MariaDB client
This plugin includes support for Kerberos on Unix, but can also be used for
Windows authentication with or without domain environment.
@@ -1121,10 +1204,10 @@ Description: GSSAPI authentication plugin for MariaDB client
Package: mariadb-plugin-cracklib-password-check
Architecture: any
-Depends: libcrack2 (>= 2.9.0),
- mariadb-server,
- ${misc:Depends},
- ${shlibs:Depends}
+Depends:
+ mariadb-server,
+ ${misc:Depends},
+ ${shlibs:Depends},
Description: CrackLib Password Validation Plugin for MariaDB server
This password validation plugin uses cracklib to allow only
sufficiently secure (as defined by cracklib) user passwords in
@@ -1135,19 +1218,20 @@ Description: CrackLib Password Validation Plugin for MariaDB server
Package: mariadb-plugin-hashicorp-key-management
Architecture: any
-Depends: libcurl4,
- mariadb-server,
- ${misc:Depends},
- ${shlibs:Depends}
+Depends:
+ mariadb-server,
+ ${misc:Depends},
+ ${shlibs:Depends},
Description: Hashicorp Key Management plugin for MariaDB
This encryption plugin uses Hashicorp Vault for storing encryption
keys for MariaDB Data-at-Rest encryption.
Package: mariadb-plugin-provider-bzip2
Architecture: any
-Depends: mariadb-server,
- ${misc:Depends},
- ${shlibs:Depends}
+Depends:
+ mariadb-server,
+ ${misc:Depends},
+ ${shlibs:Depends},
Description: BZip2 compression support in the server and storage engines
The various MariaDB storage engines, such as InnoDB, RocksDB, Mroonga,
can use different compression libraries.
@@ -1159,9 +1243,10 @@ Description: BZip2 compression support in the server and storage engines
Package: mariadb-plugin-provider-lz4
Architecture: any
-Depends: mariadb-server,
- ${misc:Depends},
- ${shlibs:Depends}
+Depends:
+ mariadb-server,
+ ${misc:Depends},
+ ${shlibs:Depends},
Description: LZ4 compression support in the server and storage engines
The various MariaDB storage engines, such as InnoDB, RocksDB, Mroonga,
can use different compression libraries.
@@ -1173,9 +1258,10 @@ Description: LZ4 compression support in the server and storage engines
Package: mariadb-plugin-provider-lzma
Architecture: any
-Depends: mariadb-server,
- ${misc:Depends},
- ${shlibs:Depends}
+Depends:
+ mariadb-server,
+ ${misc:Depends},
+ ${shlibs:Depends},
Description: LZMA compression support in the server and storage engines
The various MariaDB storage engines, such as InnoDB, RocksDB, Mroonga,
can use different compression libraries.
@@ -1187,9 +1273,10 @@ Description: LZMA compression support in the server and storage engines
Package: mariadb-plugin-provider-lzo
Architecture: any
-Depends: mariadb-server,
- ${misc:Depends},
- ${shlibs:Depends}
+Depends:
+ mariadb-server,
+ ${misc:Depends},
+ ${shlibs:Depends},
Description: LZO compression support in the server and storage engines
The various MariaDB storage engines, such as InnoDB, RocksDB, Mroonga,
can use different compression libraries.
@@ -1201,9 +1288,10 @@ Description: LZO compression support in the server and storage engines
Package: mariadb-plugin-provider-snappy
Architecture: any
-Depends: mariadb-server,
- ${misc:Depends},
- ${shlibs:Depends}
+Depends:
+ mariadb-server,
+ ${misc:Depends},
+ ${shlibs:Depends},
Description: Snappy compression support in the server and storage engines
The various MariaDB storage engines, such as InnoDB, RocksDB, Mroonga,
can use different compression libraries.
@@ -1213,58 +1301,75 @@ Description: Snappy compression support in the server and storage engines
Note that these affect InnoDB and Mroonga only;
RocksDB still uses the compression algorithms from its own library
-Package: mariadb-test
+Package: mariadb-plugin-videx
Architecture: any
-Depends: libnet-ssleay-perl,
- mariadb-client (= ${binary:Version}),
- mariadb-server (= ${server:Version}),
- mariadb-test-data (= ${source:Version}),
- virtual-mysql-testsuite,
+Depends: mariadb-server (= ${server:Version}),
${misc:Depends},
- ${perl:Depends},
${shlibs:Depends}
-Conflicts: mariadb-server-5.5,
- mysql-server-5.7,
- mysql-server-core-8.0
-Breaks: mariadb-test-10.0,
- mariadb-test-10.1,
- mariadb-test-10.2,
- mariadb-test-10.3,
- mariadb-test-10.4,
- mariadb-test-5.5,
- mysql-client-5.5,
- mysql-server-5.5,
- mysql-server-5.7,
- mysql-server-core-8.0,
- mysql-testsuite,
- mysql-testsuite-5.5,
- mysql-testsuite-5.6,
- mysql-testsuite-5.7,
- mysql-testsuite-8.0,
- percona-server-server-5.6,
- percona-xtradb-cluster-server-5.6,
- percona-xtradb-cluster-server-5.7
-Replaces: mariadb-test-10.0,
- mariadb-test-10.1,
- mariadb-test-10.2,
- mariadb-test-10.3,
- mariadb-test-10.4,
- mariadb-test-5.5,
- mysql-client-5.5,
- mysql-server-5.5,
- mysql-server-5.7,
- mysql-server-core-8.0,
- mysql-testsuite,
- mysql-testsuite-5.5,
- mysql-testsuite-5.6,
- mysql-testsuite-5.7,
- mysql-testsuite-8.0,
- percona-server-server-5.6,
- percona-xtradb-cluster-server-5.6,
- percona-xtradb-cluster-server-5.7,
- virtual-mysql-testsuite
-Provides: virtual-mysql-testsuite
-Suggests: patch
+Description: Virtual index engine for what-if analysis in MariaDB
+ The VIDEX storage engine allows developers and DBAs to perform what-if
+ analysis by evaluating the impact of potential indexes on query plans.
+ It simulates the cost and behavior of engines like InnoDB without requiring
+ the indexes to be physically built, saving significant time and resources.
+
+Package: mariadb-test
+Architecture: any
+Depends:
+ libnet-ssleay-perl,
+ mariadb-client (= ${binary:Version}),
+ mariadb-server (= ${server:Version}),
+ mariadb-test-data (= ${source:Version}),
+ virtual-mysql-testsuite,
+ ${misc:Depends},
+ ${perl:Depends},
+ ${shlibs:Depends},
+Conflicts:
+ mariadb-server-5.5,
+ mysql-server-5.7,
+ mysql-server-core-8.0,
+Breaks:
+ mariadb-test-10.0,
+ mariadb-test-10.1,
+ mariadb-test-10.2,
+ mariadb-test-10.3,
+ mariadb-test-10.4,
+ mariadb-test-5.5,
+ mysql-client-5.5,
+ mysql-server-5.5,
+ mysql-server-5.7,
+ mysql-server-core-8.0,
+ mysql-testsuite,
+ mysql-testsuite-5.5,
+ mysql-testsuite-5.6,
+ mysql-testsuite-5.7,
+ mysql-testsuite-8.0,
+ percona-server-server-5.6,
+ percona-xtradb-cluster-server-5.6,
+ percona-xtradb-cluster-server-5.7,
+Replaces:
+ mariadb-test-10.0,
+ mariadb-test-10.1,
+ mariadb-test-10.2,
+ mariadb-test-10.3,
+ mariadb-test-10.4,
+ mariadb-test-5.5,
+ mysql-client-5.5,
+ mysql-server-5.5,
+ mysql-server-5.7,
+ mysql-server-core-8.0,
+ mysql-testsuite,
+ mysql-testsuite-5.5,
+ mysql-testsuite-5.6,
+ mysql-testsuite-5.7,
+ mysql-testsuite-8.0,
+ percona-server-server-5.6,
+ percona-xtradb-cluster-server-5.6,
+ percona-xtradb-cluster-server-5.7,
+ virtual-mysql-testsuite,
+Provides:
+ virtual-mysql-testsuite,
+Suggests:
+ patch,
Description: MariaDB database regression test suite
MariaDB is a fast, stable and true multi-user, multi-threaded SQL database
server. SQL (Structured Query Language) is the most popular database query
@@ -1276,29 +1381,32 @@ Description: MariaDB database regression test suite
Package: mariadb-test-data
Architecture: all
Multi-Arch: foreign
-Depends: ${misc:Depends},
- ${perl:Depends},
- ${shlibs:Depends}
-Breaks: mariadb-test-10.0,
- mariadb-test-10.1,
- mariadb-test-10.2,
- mariadb-test-5.5,
- mariadb-test-data-10.0,
- mysql-testsuite,
- mysql-testsuite-5.5,
- mysql-testsuite-5.6,
- mysql-testsuite-5.7,
- mysql-testsuite-8.0
-Replaces: mariadb-test-10.0,
- mariadb-test-10.1,
- mariadb-test-10.2,
- mariadb-test-5.5,
- mariadb-test-data-10.0,
- mysql-testsuite,
- mysql-testsuite-5.5,
- mysql-testsuite-5.6,
- mysql-testsuite-5.7,
- mysql-testsuite-8.0
+Depends:
+ ${misc:Depends},
+ ${perl:Depends},
+ ${shlibs:Depends},
+Breaks:
+ mariadb-test-10.0,
+ mariadb-test-10.1,
+ mariadb-test-10.2,
+ mariadb-test-5.5,
+ mariadb-test-data-10.0,
+ mysql-testsuite,
+ mysql-testsuite-5.5,
+ mysql-testsuite-5.6,
+ mysql-testsuite-5.7,
+ mysql-testsuite-8.0,
+Replaces:
+ mariadb-test-10.0,
+ mariadb-test-10.1,
+ mariadb-test-10.2,
+ mariadb-test-5.5,
+ mariadb-test-data-10.0,
+ mysql-testsuite,
+ mysql-testsuite-5.5,
+ mysql-testsuite-5.6,
+ mysql-testsuite-5.7,
+ mysql-testsuite-8.0,
Description: MariaDB database regression test suite - data files
MariaDB is a fast, stable and true multi-user, multi-threaded SQL database
server. SQL (Structured Query Language) is the most popular database query
diff --git a/debian/libmariadb3.install b/debian/libmariadb3.install
index be143ad5f13ee..1910b8fcd10b8 100644
--- a/debian/libmariadb3.install
+++ b/debian/libmariadb3.install
@@ -3,5 +3,5 @@ usr/lib/*/libmariadb3/plugin/caching_sha2_password.so
usr/lib/*/libmariadb3/plugin/client_ed25519.so
usr/lib/*/libmariadb3/plugin/dialog.so
usr/lib/*/libmariadb3/plugin/mysql_clear_password.so
-usr/lib/*/libmariadb3/plugin/sha256_password.so
usr/lib/*/libmariadb3/plugin/parsec.so
+usr/lib/*/libmariadb3/plugin/sha256_password.so
diff --git a/debian/mariadb-plugin-videx.install b/debian/mariadb-plugin-videx.install
new file mode 100644
index 0000000000000..8c8a327fe7afc
--- /dev/null
+++ b/debian/mariadb-plugin-videx.install
@@ -0,0 +1,2 @@
+etc/mysql/mariadb.conf.d/videx.cnf
+usr/lib/mysql/plugin/ha_videx.so
\ No newline at end of file
diff --git a/debian/mariadb-server.install b/debian/mariadb-server.install
index 5889bd827ae1d..e2563ca5b4519 100644
--- a/debian/mariadb-server.install
+++ b/debian/mariadb-server.install
@@ -7,11 +7,11 @@ etc/apparmor.d/usr.sbin.mariadbd
etc/logrotate.d/mariadb
etc/security/user_map.conf
lib/*/security/pam_user_map.so
-lib/systemd/system/mariadb@bootstrap.service.d/use_galera_new_cluster.conf
lib/systemd/system/mariadb-extra@.socket
lib/systemd/system/mariadb.service
lib/systemd/system/mariadb@.service
lib/systemd/system/mariadb@.socket
+lib/systemd/system/mariadb@bootstrap.service.d/use_galera_new_cluster.conf
lib/systemd/system/mysql.service
lib/systemd/system/mysqld.service
support-files/rpm/enable_encryption.preset etc/mysql/mariadb.conf.d/99-enable-encryption.cnf.preset
@@ -36,6 +36,7 @@ usr/bin/wsrep_sst_mysqldump
usr/bin/wsrep_sst_rsync
usr/bin/wsrep_sst_rsync_wan
usr/lib/mysql/plugin/auth_ed25519.so
+usr/lib/mysql/plugin/auth_mysql_sha2.so
usr/lib/mysql/plugin/auth_pam.so
usr/lib/mysql/plugin/auth_pam_tool_dir/auth_pam_tool
usr/lib/mysql/plugin/auth_pam_v1.so
@@ -58,6 +59,7 @@ usr/lib/mysql/plugin/simple_password_check.so
usr/lib/mysql/plugin/sql_errlog.so
usr/lib/mysql/plugin/type_mysql_json.so
usr/lib/mysql/plugin/wsrep_info.so
+usr/lib/tmpfiles.d/mariadb.conf
usr/share/doc/mariadb-server/mariadbd.sym.gz
usr/share/man/man1/aria_chk.1
usr/share/man/man1/aria_dump_log.1
diff --git a/debian/mariadb-server.links b/debian/mariadb-server.links
new file mode 100644
index 0000000000000..40b0b80a143dd
--- /dev/null
+++ b/debian/mariadb-server.links
@@ -0,0 +1,6 @@
+#!/usr/bin/dh-exec
+usr/lib/${DEB_HOST_MULTIARCH}/libmariadb3/plugin/caching_sha2_password.so usr/lib/mysql/plugin/caching_sha2_password.so
+usr/lib/${DEB_HOST_MULTIARCH}/libmariadb3/plugin/client_ed25519.so usr/lib/mysql/plugin/client_ed25519.so
+usr/lib/${DEB_HOST_MULTIARCH}/libmariadb3/plugin/dialog.so usr/lib/mysql/plugin/dialog.so
+usr/lib/${DEB_HOST_MULTIARCH}/libmariadb3/plugin/mysql_clear_password.so usr/lib/mysql/plugin/mysql_clear_password.so
+usr/lib/${DEB_HOST_MULTIARCH}/libmariadb3/plugin/sha256_password.so usr/lib/mysql/plugin/sha256_password.so
diff --git a/debian/not-installed b/debian/not-installed
index 16cd355f55973..8936d8e7d76c4 100644
--- a/debian/not-installed
+++ b/debian/not-installed
@@ -22,7 +22,6 @@ usr/lib/*/pkgconfig/mariadb.pc
usr/bin/uca-dump
usr/bin/wsrep_sst_backup
usr/lib/sysusers.d/mariadb.conf # Not used (yet) in Debian systemd
-usr/lib/tmpfiles.d/mariadb.conf # Not used (yet) in Debian systemd
usr/sbin/rcmysql
usr/share/doc/mariadb-server/COPYING (related file: "debian/tmp/usr/share/mariadb/mroonga/COPYING")
usr/share/doc/mariadb-server/CREDITS
diff --git a/debian/rules b/debian/rules
index cdbbd0e818b72..bc0ea43a5a6e2 100644
--- a/debian/rules
+++ b/debian/rules
@@ -146,9 +146,6 @@ override_dh_auto_install:
# If mariadb-test package is removed, also remove most of it's files
grep --quiet "Package: mariadb-test" debian/control || rm -rf $(TMP)/usr/share/mariadb/mariadb-test
- # Delete private files from libraries so they don't get shipped in the -dev packages
- rm -r $(TMP)/usr/include/mariadb/server/private
-
# Don't ship sql-bench at all, just delete it completely even though it builds
rm -r $(TMP)/usr/sql-bench
diff --git a/debian/tests/control b/debian/tests/control
index 01bb919578a35..f11e41aecb64b 100644
--- a/debian/tests/control
+++ b/debian/tests/control
@@ -1,17 +1,26 @@
-Tests: smoke
+Tests:
+ smoke,
# RocksDB is not built for all archs. Rather than duplicating the condition
# for its existence (see the list in debian/control), install it if available
# and check in the test if it's functional when it should be.
# The plugin package also already depends on the other one.
-Depends: mariadb-plugin-provider-bzip2,
- mariadb-plugin-provider-lz4,
- mariadb-plugin-provider-lzma,
- mariadb-plugin-provider-lzo,
- mariadb-plugin-provider-snappy,
- mariadb-plugin-rocksdb | mariadb-server
-Restrictions: allow-stderr needs-root isolation-container
+Depends:
+ mariadb-plugin-provider-bzip2,
+ mariadb-plugin-provider-lz4,
+ mariadb-plugin-provider-lzma,
+ mariadb-plugin-provider-lzo,
+ mariadb-plugin-provider-snappy,
+ mariadb-plugin-rocksdb | mariadb-server,
+Restrictions:
+ allow-stderr,
+ isolation-container,
+ needs-root,
-Tests: upstream
-Depends: eatmydata,
- mariadb-test
-Restrictions: allow-stderr breaks-testbed
+Tests:
+ upstream,
+Depends:
+ eatmydata,
+ mariadb-test,
+Restrictions:
+ allow-stderr,
+ breaks-testbed,
diff --git a/extra/innochecksum.cc b/extra/innochecksum.cc
index 864a576bd09a6..ee8d4c4ef91af 100644
--- a/extra/innochecksum.cc
+++ b/extra/innochecksum.cc
@@ -51,7 +51,6 @@ The parts not included are excluded by #ifndef UNIV_INNOCHECKSUM. */
#include "page0zip.h" /* page_zip_*() */
#include "trx0undo.h" /* TRX_* */
#include "fil0crypt.h" /* fil_space_verify_crypt_checksum */
-
#include
#ifndef PRIuMAX
@@ -74,6 +73,8 @@ static ulint extent_size;
static ulint xdes_size;
ulong srv_page_size;
uint32_t srv_page_size_shift;
+static uint32_t dblwr_1;
+static uint32_t dblwr_2;
/* Current page number (0 based). */
uint32_t cur_page_num;
/* Current space. */
@@ -97,8 +98,10 @@ FILE* log_file = NULL;
/* Enabled for log write option. */
static bool is_log_enabled = false;
static bool skip_freed_pages;
+static uint32_t tablespace_flags= 0;
static byte field_ref_zero_buf[UNIV_PAGE_SIZE_MAX];
const byte *field_ref_zero = field_ref_zero_buf;
+constexpr uint32_t USE_FSP_FLAGS{UINT32_MAX};
#ifndef _WIN32
/* advisory lock for non-window system. */
@@ -253,12 +256,9 @@ void print_leaf_stats(
}
/** Init the page size for the tablespace.
-@param[in] buf buffer used to read the page */
-static void init_page_size(const byte* buf)
+@param[in] flags InnoDB tablespace flags */
+static void init_page_size_from_flags(const uint32_t flags)
{
- const unsigned flags = mach_read_from_4(buf + FIL_PAGE_DATA
- + FSP_SPACE_FLAGS);
-
if (fil_space_t::full_crc32(flags)) {
const uint32_t ssize = FSP_FLAGS_FCRC32_GET_PAGE_SSIZE(flags);
srv_page_size_shift = UNIV_ZIP_SIZE_SHIFT_MIN - 1 + ssize;
@@ -540,24 +540,15 @@ static bool is_page_corrupted(byte *buf, bool is_encrypted, uint32_t flags)
return(is_corrupted);
}
-/********************************************//*
- Check if page is doublewrite buffer or not.
- @param [in] page buffer page
-
- @retval true if page is doublewrite buffer otherwise false.
-*/
-static
-bool
-is_page_doublewritebuffer(
- const byte* page)
+/** Check if page is doublewrite buffer or not.
+@retval true if page is doublewrite buffer otherwise false. */
+static bool is_page_doublewritebuffer()
{
- if ((cur_page_num >= extent_size)
- && (cur_page_num < extent_size * 3)) {
- /* page is doublewrite buffer. */
- return (true);
- }
-
- return (false);
+ if (cur_space != 0) return false;
+ const uint32_t extent{static_cast(
+ cur_page_num & ~(extent_size - 1))};
+ return cur_page_num > FSP_DICT_HDR_PAGE_NO &&
+ extent && (extent == dblwr_1 || extent == dblwr_2);
}
/*******************************************************//*
@@ -764,7 +755,7 @@ Parse the page and collect/dump the information about page type
@param [in] file file for diagnosis.
@param [in] is_encrypted tablespace is encrypted
*/
-void
+static void
parse_page(
const byte* page,
byte* xdes,
@@ -784,6 +775,12 @@ parse_page(
str = skip_page ? "Double_write_buffer" : "-";
page_no = mach_read_from_4(page + FIL_PAGE_OFFSET);
if (skip_freed_pages) {
+
+ /** Skip doublewrite pages when -r is enabled */
+ if (is_page_doublewritebuffer()) {
+ return;
+ }
+
const byte *des= xdes + XDES_ARR_OFFSET +
xdes_size * ((page_no & (physical_page_size - 1))
/ extent_size);
@@ -978,6 +975,18 @@ parse_page(
fprintf(file, "#::" UINT32PF "\t\t|\t\tTransaction system "
"page\t\t|\t%s\n", cur_page_num, str);
}
+
+ if (cur_space == 0 &&
+ (mach_read_from_4(page + TRX_SYS_DOUBLEWRITE +
+ TRX_SYS_DOUBLEWRITE_MAGIC) ==
+ TRX_SYS_DOUBLEWRITE_MAGIC_N)) {
+ dblwr_1 = mach_read_from_4(
+ page + TRX_SYS_DOUBLEWRITE +
+ TRX_SYS_DOUBLEWRITE_BLOCK1);
+ dblwr_2 = mach_read_from_4(
+ page + TRX_SYS_DOUBLEWRITE +
+ TRX_SYS_DOUBLEWRITE_BLOCK2);
+ }
break;
case FIL_PAGE_TYPE_FSP_HDR:
@@ -1220,6 +1229,9 @@ static struct my_option innochecksum_options[] = {
{"skip-freed-pages", 'r', "skip freed pages for the tablespace",
&skip_freed_pages, &skip_freed_pages, 0, GET_BOOL, NO_ARG,
0, 0, 0, 0, 0, 0},
+ {"tablespace-flags", 0, "InnoDB tablespace flags (default: 4294967295 "
+ "= read from page 0)", &tablespace_flags, &tablespace_flags, 0,
+ GET_UINT, REQUIRED_ARG, USE_FSP_FLAGS, 0, USE_FSP_FLAGS, 0, 0, 0},
{0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
};
@@ -1280,6 +1292,14 @@ innochecksum_get_one_option(
my_end(0);
exit(EXIT_SUCCESS);
break;
+ default:
+ if (tablespace_flags != USE_FSP_FLAGS &&
+ !fil_space_t::is_valid_flags(tablespace_flags, false) &&
+ !fil_space_t::is_valid_flags(tablespace_flags, true)) {
+ fprintf(stderr, "Error: Provided --tablespace-flags "
+ "is not valid.");
+ return true;
+ }
}
return(false);
@@ -1410,6 +1430,87 @@ rewrite_checksum(
&& !write_file(filename, fil_in, buf, flags, pos);
}
+/** Read and validate page 0, then initialize tablespace flags
+and page size.
+@param fil_in File pointer
+@param buf Buffer to read page into
+@return whether the page was read successfully */
+static bool read_and_validate_page0(FILE *fil_in, byte *buf)
+{
+ /* Read the minimum page size first */
+ size_t initial_page_size= UNIV_ZIP_SIZE_MIN;
+ if (tablespace_flags != USE_FSP_FLAGS)
+ {
+ init_page_size_from_flags(tablespace_flags);
+ initial_page_size= physical_page_size;
+ }
+
+ /* Read just enough to get the tablespace flags */
+ size_t bytes= fread(buf, 1, initial_page_size, fil_in);
+
+ if (bytes != initial_page_size)
+ {
+ fprintf(stderr, "Error: Was not able to read the "
+ "minimum page size of %zu bytes. Bytes read "
+ "was %zu\n", initial_page_size, bytes);
+ return false;
+ }
+
+ /* Read space_id and page offset */
+ cur_space= mach_read_from_4(buf + FIL_PAGE_SPACE_ID);
+ cur_page_num= mach_read_from_4(buf + FIL_PAGE_OFFSET);
+
+ /* Get tablespace flags from the FSP header */
+ uint32_t flags= mach_read_from_4(buf + FSP_HEADER_OFFSET +
+ FSP_SPACE_FLAGS);
+
+ if (tablespace_flags != USE_FSP_FLAGS)
+ {
+ if (cur_page_num == 0 && flags != tablespace_flags)
+ fprintf(stderr, "Error: Mismatch between provided tablespace "
+ "flags (0x%x) and file flags (0x%x)\n",
+ tablespace_flags, flags);
+ }
+ else
+ {
+ if (cur_page_num)
+ {
+ fprintf(stderr, "Error: First page of the tablespace file "
+ "should be 0, but encountered page number %" PRIu32 ". "
+ "If you are checking multi file system "
+ "tablespace files, please specify the correct "
+ "tablespace flags using --tablespace-flags option.\n",
+ cur_page_num);
+ return false;
+ }
+ /* Initialize page size parameters based on flags */
+ init_page_size_from_flags(flags);
+ /* Read the rest of the page if it's larger than the minimum size */
+ if (physical_page_size > UNIV_ZIP_SIZE_MIN)
+ {
+ /* Read rest of the page 0 to determine crypt_data */
+ ulint bytes= read_file(buf, true, physical_page_size, fil_in);
+ if (bytes != physical_page_size)
+ {
+ fprintf(stderr, "Error: Was not able to read the rest of the "
+ "page of " ULINTPF " bytes. Bytes read was " ULINTPF "\n",
+ physical_page_size - UNIV_ZIP_SIZE_MIN, bytes);
+ return false;
+ }
+ }
+ tablespace_flags= flags;
+ }
+
+ if (physical_page_size < UNIV_ZIP_SIZE_MIN ||
+ physical_page_size > UNIV_PAGE_SIZE_MAX)
+ {
+ fprintf(stderr, "Error: Invalid page size " ULINTPF
+ " encountered\n", physical_page_size);
+ return false;
+ }
+ return true;
+}
+
int main(
int argc,
char **argv)
@@ -1545,51 +1646,13 @@ int main(
}
}
- /* Read the minimum page size. */
- bytes = fread(buf, 1, UNIV_ZIP_SIZE_MIN, fil_in);
- partial_page_read = true;
-
- if (bytes != UNIV_ZIP_SIZE_MIN) {
- fprintf(stderr, "Error: Was not able to read the "
- "minimum page size ");
- fprintf(stderr, "of %d bytes. Bytes read was " ULINTPF "\n",
- UNIV_ZIP_SIZE_MIN, bytes);
-
+ /* Read and validate page 0 */
+ if (!read_and_validate_page0(fil_in, buf)) {
exit_status = 1;
goto my_exit;
}
- /* enable variable is_system_tablespace when space_id of given
- file is zero. Use to skip the checksum verification and rewrite
- for doublewrite pages. */
- cur_space = mach_read_from_4(buf + FIL_PAGE_SPACE_ID);
- cur_page_num = mach_read_from_4(buf + FIL_PAGE_OFFSET);
-
- /* Determine page size, zip_size and page compression
- from fsp_flags and encryption metadata from page 0 */
- init_page_size(buf);
-
- uint32_t flags = mach_read_from_4(FSP_HEADER_OFFSET + FSP_SPACE_FLAGS + buf);
-
- if (physical_page_size == UNIV_ZIP_SIZE_MIN) {
- partial_page_read = false;
- } else {
- /* Read rest of the page 0 to determine crypt_data */
- bytes = read_file(buf, partial_page_read, physical_page_size, fil_in);
- if (bytes != physical_page_size) {
- fprintf(stderr, "Error: Was not able to read the "
- "rest of the page ");
- fprintf(stderr, "of " ULINTPF " bytes. Bytes read was " ULINTPF "\n",
- physical_page_size - UNIV_ZIP_SIZE_MIN, bytes);
-
- exit_status = 1;
- goto my_exit;
- }
- partial_page_read = false;
- }
-
-
- /* Now that we have full page 0 in buffer, check encryption */
+ /* Check if tablespace is encrypted */
bool is_encrypted = check_encryption(filename, buf);
/* Verify page 0 contents. Note that we can't allow
@@ -1600,7 +1663,8 @@ int main(
allow_mismatches = 0;
exit_status = verify_checksum(buf, is_encrypted,
- &mismatch_count, flags);
+ &mismatch_count,
+ tablespace_flags);
if (exit_status) {
fprintf(stderr, "Error: Page 0 checksum mismatch, can't continue. \n");
@@ -1611,7 +1675,8 @@ int main(
if ((exit_status = rewrite_checksum(
filename, fil_in, buf,
- &pos, is_encrypted, flags))) {
+ &pos, is_encrypted,
+ tablespace_flags))) {
goto my_exit;
}
@@ -1807,7 +1872,7 @@ int main(
first_non_zero:
if (is_system_tablespace) {
/* enable when page is double write buffer.*/
- skip_page = is_page_doublewritebuffer(buf);
+ skip_page = is_page_doublewritebuffer();
} else {
skip_page = false;
}
@@ -1828,13 +1893,16 @@ int main(
&& !is_page_free(xdes, physical_page_size, cur_page_num)
&& (exit_status = verify_checksum(
buf, is_encrypted,
- &mismatch_count, flags))) {
+ &mismatch_count,
+ tablespace_flags))) {
goto my_exit;
}
- if ((exit_status = rewrite_checksum(
- filename, fil_in, buf,
- &pos, is_encrypted, flags))) {
+ if (!is_page_doublewritebuffer() &&
+ (exit_status = rewrite_checksum(
+ filename, fil_in, buf,
+ &pos, is_encrypted,
+ tablespace_flags))) {
goto my_exit;
}
diff --git a/extra/mariabackup/aria_backup_client.cc b/extra/mariabackup/aria_backup_client.cc
index ab293c07989b1..eefeb78c6a8dd 100644
--- a/extra/mariabackup/aria_backup_client.cc
+++ b/extra/mariabackup/aria_backup_client.cc
@@ -161,7 +161,10 @@ class Table {
File m_data_file = -1;
MY_STAT m_data_file_stat;
};
- Table() = default;
+ Table()
+ {
+ bzero(&m_cap, sizeof(m_cap));
+ }
Table (Table &&other) = delete;
Table & operator= (Table &&other) = delete;
Table(const Table &) = delete;
@@ -222,6 +225,7 @@ class Table {
};
Table::~Table() {
+ aria_free_capabilities(&m_cap);
(void)close();
}
@@ -298,7 +302,8 @@ bool Table::open(MYSQL *con, bool opt_no_lock, unsigned thread_num) {
goto exit;
}
if (!have_capabilities) {
- if ((error= aria_get_capabilities(partition.m_index_file, &m_cap))) {
+ if ((error= aria_get_capabilities(partition.m_index_file,
+ m_full_name.c_str(), &m_cap))) {
msg(thread_num, "aria_get_capabilities failed: %d", error);
goto exit;
}
@@ -343,6 +348,7 @@ bool Table::open(MYSQL *con, bool opt_no_lock, unsigned thread_num) {
}
bool Table::close() {
+ aria_free_capabilities(&m_cap);
for (Partition &partition : m_partitions) {
if (partition.m_index_file >= 0) {
my_close(partition.m_index_file, MYF(MY_WME));
@@ -399,26 +405,27 @@ bool Table::copy(ds_ctxt_t *ds, bool is_index, unsigned thread_num) {
for (ulonglong block= 0 ; ; block++) {
size_t length = m_cap.block_size;
- if (is_index) {
- if ((error= aria_read_index(
- partition.m_index_file, &m_cap, block, copy_buffer) ==
- HA_ERR_END_OF_FILE))
- break;
- } else {
- if ((error= aria_read_data(
- partition.m_data_file, &m_cap, block, copy_buffer, &length) ==
- HA_ERR_END_OF_FILE))
- break;
- }
- if (error) {
- msg(thread_num, "error: aria_read %s failed: %d",
- is_index ? "index" : "data", error);
- goto err;
+ if (is_index)
+ error= aria_read_index(partition.m_index_file, &m_cap,
+ block, copy_buffer);
+ else
+ error= aria_read_data(partition.m_data_file, &m_cap,
+ block, copy_buffer, &length);
+ if (error)
+ {
+ if (error == HA_ERR_END_OF_FILE)
+ break;
+ msg(thread_num, "error: aria_read %s from %s failed "
+ "with error %d",
+ is_index ? "index" : "data", full_name.c_str(),
+ error);
+ goto err;
}
xtrabackup_io_throttling();
if ((error = ds_write(dst_file, copy_buffer, length))) {
- msg(thread_num, "error: aria_write failed: %d", error);
- goto err;
+ msg(thread_num, "error: aria_write to %s failed "
+ "with error: %d", dst_path, error);
+ goto err;
}
}
@@ -990,8 +997,8 @@ bool prepare(const char *target_dir) {
logs.find_logs_after_last(target_dir);
last_logno= logs.last(); // Update last_logno if extra logs were found
- if (init_pagecache(maria_pagecache, 1024L*1024L, 0, 0,
- static_cast(maria_block_size), 0, MY_WME) == 0)
+ if (multi_init_pagecache(&maria_pagecaches, 1, 1024L*1024L, 0, 0,
+ static_cast(maria_block_size), 0, MY_WME))
die("Got error in Aria init_pagecache() (errno: %d)", errno);
if (init_pagecache(maria_log_pagecache, 1024L*1024L,
diff --git a/extra/mariabackup/backup_copy.cc b/extra/mariabackup/backup_copy.cc
index ed308c75c9e10..36e4210b7f498 100644
--- a/extra/mariabackup/backup_copy.cc
+++ b/extra/mariabackup/backup_copy.cc
@@ -61,6 +61,7 @@ Street, Fifth Floor, Boston, MA 02110-1335 USA
#include "backup_debug.h"
#include "backup_mysql.h"
#include
+#include
#ifdef _WIN32
#include /* rmdir */
#endif
@@ -1630,7 +1631,10 @@ class Copy_back_dst_dir
return mysql_data_home;
if (is_absolute_path(path))
return path;
- return buf.assign(mysql_data_home).append(path).c_str();
+ buf.assign(mysql_data_home);
+ if (!buf.empty() && buf.back() != '/' IF_WIN(&& buf.back() != '\\', ))
+ buf.append("/");
+ return buf.append(path).c_str();
}
};
@@ -1674,6 +1678,7 @@ copy_back()
datadir_iter_t *it = NULL;
datadir_node_t node;
const char *dst_dir;
+ ds_ctxt *ds_binlogs = NULL;
memset(&node, 0, sizeof(node));
@@ -1753,7 +1758,7 @@ copy_back()
for (uint i = 1; i <= TRX_SYS_MAX_UNDO_SPACES; i++) {
char filename[20];
- sprintf(filename, "undo%03u", i);
+ snprintf(filename, sizeof(filename), "undo%03u", i);
if (!file_exists(filename)) {
break;
}
@@ -1799,6 +1804,10 @@ copy_back()
ds_destroy(ds_tmp);
+ /* Prepare destination directory for any InnoDB binlog files. */
+ dst_dir = dst_dir_buf.make(opt_binlog_directory);
+ ds_binlogs = ds_create(dst_dir, DS_TYPE_LOCAL);
+
/* copy the rest of tablespaces */
ds_tmp = ds_create(mysql_data_home, DS_TYPE_LOCAL);
@@ -1860,6 +1869,16 @@ copy_back()
filename = base_name(node.filepath);
+ /* Copy InnoDB binlog files into --binlog-directory. */
+ uint64_t file_no;
+ if (is_binlog_name(filename, &file_no)) {
+ if (!(ret = copy_or_move_file(ds_binlogs, filename, filename,
+ dst_dir, 1))) {
+ goto cleanup;
+ }
+ continue;
+ }
+
/* skip .qp files */
if (filename_matches(filename, ext_list)) {
continue;
@@ -1920,6 +1939,11 @@ copy_back()
ds_tmp = NULL;
+ if (ds_binlogs != NULL) {
+ ds_destroy(ds_binlogs);
+ ds_binlogs = NULL;
+ }
+
return(ret);
}
diff --git a/extra/mariabackup/backup_mysql.cc b/extra/mariabackup/backup_mysql.cc
index 4492827eb9715..713c2cb44fb04 100644
--- a/extra/mariabackup/backup_mysql.cc
+++ b/extra/mariabackup/backup_mysql.cc
@@ -77,6 +77,7 @@ bool have_lock_wait_timeout = false;
bool have_galera_enabled = false;
bool have_multi_threaded_slave = false;
bool have_gtid_slave = false;
+bool innobase_data_file_path_allocated= false;
/* Kill long selects */
static mysql_mutex_t kill_query_thread_mutex;
@@ -147,7 +148,7 @@ xb_mysql_connect()
char mysql_port_str[std::numeric_limits::digits10 + 3];
const char *user= opt_user ? opt_user : get_os_user();
- sprintf(mysql_port_str, "%d", opt_port);
+ snprintf(mysql_port_str, sizeof(mysql_port_str), "%d", opt_port);
if (connection == NULL) {
msg("Failed to init MariaDB struct: %s.",
@@ -162,11 +163,6 @@ xb_mysql_connect()
}
#endif
- if (!opt_secure_auth) {
- mysql_options(connection, MYSQL_SECURE_AUTH,
- (char *) &opt_secure_auth);
- }
-
if (xb_plugin_dir && *xb_plugin_dir){
mysql_options(connection, MYSQL_PLUGIN_DIR, xb_plugin_dir);
}
@@ -384,6 +380,7 @@ bool get_mysql_vars(MYSQL *connection)
char *aria_log_dir_path_var= NULL;
char *page_zip_level_var= NULL;
char *ignore_db_dirs= NULL;
+ char *binlog_directory_var= NULL;
char *endptr;
ulong server_version= mysql_get_server_version(connection);
@@ -410,6 +407,7 @@ bool get_mysql_vars(MYSQL *connection)
{"innodb_compression_level", &page_zip_level_var},
{"ignore_db_dirs", &ignore_db_dirs},
{"aria_log_dir_path", &aria_log_dir_path_var},
+ {"binlog_directory", &binlog_directory_var},
{NULL, NULL}};
read_mysql_variables(connection, "SHOW VARIABLES", mysql_vars, true);
@@ -500,21 +498,19 @@ bool get_mysql_vars(MYSQL *connection)
}
if (innodb_data_file_path_var && *innodb_data_file_path_var)
- innobase_data_file_path= my_strdup(PSI_NOT_INSTRUMENTED,
- innodb_data_file_path_var, MYF(MY_FAE));
+ innobase_data_file_path= my_once_strdup(innodb_data_file_path_var,
+ MYF(MY_FAE));
if (innodb_data_home_dir_var)
- innobase_data_home_dir= my_strdup(PSI_NOT_INSTRUMENTED,
- innodb_data_home_dir_var, MYF(MY_FAE));
+ innobase_data_home_dir= my_once_strdup(innodb_data_home_dir_var,
+ MYF(MY_FAE));
if (innodb_log_group_home_dir_var && *innodb_log_group_home_dir_var)
- srv_log_group_home_dir= my_strdup(PSI_NOT_INSTRUMENTED,
- innodb_log_group_home_dir_var,
- MYF(MY_FAE));
+ srv_log_group_home_dir= my_once_strdup(innodb_log_group_home_dir_var,
+ MYF(MY_FAE));
if (innodb_undo_directory_var && *innodb_undo_directory_var)
- srv_undo_dir= my_strdup(PSI_NOT_INSTRUMENTED, innodb_undo_directory_var,
- MYF(MY_FAE));
+ srv_undo_dir= my_once_strdup(innodb_undo_directory_var, MYF(MY_FAE));
if (innodb_log_file_size_var)
{
@@ -536,10 +532,7 @@ bool get_mysql_vars(MYSQL *connection)
}
if (aria_log_dir_path_var)
- {
- aria_log_dir_path= my_strdup(PSI_NOT_INSTRUMENTED,
- aria_log_dir_path_var, MYF(MY_FAE));
- }
+ aria_log_dir_path= my_once_strdup(aria_log_dir_path_var, MYF(MY_FAE));
if (page_zip_level_var != NULL)
{
@@ -551,12 +544,20 @@ bool get_mysql_vars(MYSQL *connection)
if (ignore_db_dirs)
xb_load_list_string(ignore_db_dirs, ",", register_ignore_db_dirs_filter);
+ if (free_opt_binlog_directory)
+ my_free(const_cast(opt_binlog_directory));
+ opt_binlog_directory= my_strdup(PSI_NOT_INSTRUMENTED,
+ (binlog_directory_var ? binlog_directory_var : ""),
+ MYF(MY_FAE));
+ free_opt_binlog_directory= true;
+
out:
free_mysql_variables(mysql_vars);
return (ret);
}
+
static
bool
select_incremental_lsn_from_history(lsn_t *incremental_lsn)
@@ -932,7 +933,7 @@ lock_for_backup_stage_flush(MYSQL *connection) {
if (opt_kill_long_queries_timeout) {
start_query_killer();
}
- xb_mysql_query(connection, "BACKUP STAGE FLUSH", true);
+ xb_mysql_query(connection, "BACKUP STAGE FLUSH", false);
if (opt_kill_long_queries_timeout) {
stop_query_killer();
}
@@ -944,7 +945,7 @@ lock_for_backup_stage_block_ddl(MYSQL *connection) {
if (opt_kill_long_queries_timeout) {
start_query_killer();
}
- xb_mysql_query(connection, "BACKUP STAGE BLOCK_DDL", true);
+ xb_mysql_query(connection, "BACKUP STAGE BLOCK_DDL", false);
DBUG_MARIABACKUP_EVENT("after_backup_stage_block_ddl", {});
if (opt_kill_long_queries_timeout) {
stop_query_killer();
@@ -957,7 +958,7 @@ lock_for_backup_stage_commit(MYSQL *connection) {
if (opt_kill_long_queries_timeout) {
start_query_killer();
}
- xb_mysql_query(connection, "BACKUP STAGE BLOCK_COMMIT", true);
+ xb_mysql_query(connection, "BACKUP STAGE BLOCK_COMMIT", false);
DBUG_MARIABACKUP_EVENT("after_backup_stage_block_commit", {});
if (opt_kill_long_queries_timeout) {
stop_query_killer();
@@ -968,12 +969,12 @@ lock_for_backup_stage_commit(MYSQL *connection) {
bool backup_lock(MYSQL *con, const char *table_name) {
static const std::string backup_lock_prefix("BACKUP LOCK ");
std::string backup_lock_query = backup_lock_prefix + table_name;
- xb_mysql_query(con, backup_lock_query.c_str(), true);
+ xb_mysql_query(con, backup_lock_query.c_str(), false);
return true;
}
bool backup_unlock(MYSQL *con) {
- xb_mysql_query(con, "BACKUP UNLOCK", true);
+ xb_mysql_query(con, "BACKUP UNLOCK", false);
return true;
}
@@ -987,6 +988,8 @@ get_tables_in_use(MYSQL *con) {
msg("Table %s is in use", tk.c_str());
result.insert(std::move(tk));
}
+ if (q_res)
+ mysql_free_result(q_res);
return result;
}
@@ -1517,7 +1520,9 @@ write_galera_info(ds_ctxt *datasink, MYSQL *connection)
domain_id ? domain_id : domain_id55);
cleanup:
+ free_mysql_variables(vars);
free_mysql_variables(status);
+ free_mysql_variables(value);
return(result);
}
@@ -2070,6 +2075,7 @@ ulonglong get_current_lsn(MYSQL *connection)
{
static const char lsn_prefix[] = "\nLog sequence number ";
ulonglong lsn = 0;
+ msg("Getting InnoDB LSN");
if (MYSQL_RES *res = xb_mysql_query(connection,
"SHOW ENGINE INNODB STATUS",
true, false)) {
@@ -2083,5 +2089,10 @@ ulonglong get_current_lsn(MYSQL *connection)
}
mysql_free_result(res);
}
+ msg("InnoDB LSN: %llu, Flushing Logs", lsn);
+ /* Make sure that current LSN is written and flushed to disk. */
+ xb_mysql_query(connection, "FLUSH NO_WRITE_TO_BINLOG ENGINE LOGS",
+ false, false);
+ msg("Flushed Logs");
return lsn;
}
diff --git a/extra/mariabackup/backup_mysql.h b/extra/mariabackup/backup_mysql.h
index ce7755d17afea..55700dddf6d67 100644
--- a/extra/mariabackup/backup_mysql.h
+++ b/extra/mariabackup/backup_mysql.h
@@ -97,5 +97,4 @@ bool
write_slave_info(ds_ctxt *datasink, MYSQL *connection);
ulonglong get_current_lsn(MYSQL *connection);
-
#endif
diff --git a/extra/mariabackup/common_engine.cc b/extra/mariabackup/common_engine.cc
index a360f63d84f9f..366e2da38ca6a 100644
--- a/extra/mariabackup/common_engine.cc
+++ b/extra/mariabackup/common_engine.cc
@@ -9,6 +9,9 @@
#include
#include
+#include "innodb_binlog.h"
+
+
namespace common_engine {
class Table {
@@ -298,17 +301,21 @@ class BackupImpl {
}
bool copy_log_tables(bool finalize);
bool copy_stats_tables();
+ bool copy_engine_binlogs(const char *binlog_dir, lsn_t backup_lsn);
bool wait_for_finish();
bool close_log_tables();
private:
void process_table_job(Table *table, bool no_lock, bool delete_table,
bool finalize, unsigned thread_num);
+ void process_binlog_job(std::string src, std::string dst,
+ lsn_t backup_lsn, unsigned thread_num);
const char *m_datadir_path;
ds_ctxt_t *m_ds;
std::vector &m_con_pool;
TasksGroup m_process_table_jobs;
+ std::unique_ptr m_page_buf;
post_copy_table_hook_t m_table_post_copy_hook;
std::unordered_map> m_log_tables;
@@ -337,6 +344,35 @@ void BackupImpl::process_table_job(Table *table, bool no_lock,
m_process_table_jobs.finish_task(result);
}
+void BackupImpl::process_binlog_job(std::string src, std::string dst,
+ lsn_t backup_lsn, unsigned thread_num) {
+ int result = 0;
+ const char *c_src= src.c_str();
+ bool is_empty= true;
+ lsn_t start_lsn;
+ int binlog_found;
+
+ if (!m_process_table_jobs.get_result())
+ goto exit;
+
+ binlog_found= get_binlog_header(c_src, m_page_buf.get(), start_lsn, is_empty);
+ if (binlog_found > 0 && !is_empty && start_lsn <= backup_lsn) {
+ // Test binlog_in_engine.mariabackup_binlogs will try to inject
+ // RESET MASTER and PURGE BINARY LOGS here.
+ DBUG_EXECUTE_IF("binlog_copy_sleep_2",
+ if (src.find("binlog-000002.ibb") !=
+ std::string::npos)
+ my_sleep(2000000););
+ if (!m_ds->copy_file(c_src, dst.c_str(), thread_num))
+ goto exit;
+ }
+
+ result = 1;
+
+exit:
+ m_process_table_jobs.finish_task(result);
+}
+
bool BackupImpl::scan(const std::unordered_set &exclude_tables,
std::unordered_set *out_processed_tables, bool no_lock,
bool collect_log_and_stats) {
@@ -461,6 +497,26 @@ bool BackupImpl::copy_stats_tables() {
return true;
}
+bool BackupImpl::copy_engine_binlogs(const char *binlog_dir, lsn_t backup_lsn) {
+ std::vectorfiles;
+ std::string dir(binlog_dir && binlog_dir[0] ? binlog_dir : m_datadir_path);
+ foreach_file_in_datadir(dir.c_str(),
+ [&](const char *name)->bool {
+ uint64_t file_no;
+ if (is_binlog_name(name, &file_no))
+ files.emplace_back(name);
+ return true;
+ });
+ m_page_buf.reset(new byte [ibb_page_size]);
+ for (auto &file : files) {
+ std::string path(dir + "/" + file);
+ m_process_table_jobs.push_task(
+ std::bind(&BackupImpl::process_binlog_job, this, path,
+ file, backup_lsn, std::placeholders::_1));
+ }
+ return true;
+}
+
bool BackupImpl::wait_for_finish() {
/* Wait for threads to exit */
return m_process_table_jobs.wait_for_finish();
@@ -499,6 +555,10 @@ bool Backup::copy_stats_tables() {
return m_backup_impl->copy_stats_tables();
}
+bool Backup::copy_engine_binlogs(const char *binlog_dir, lsn_t backup_lsn) {
+ return m_backup_impl->copy_engine_binlogs(binlog_dir, backup_lsn);
+}
+
bool Backup::wait_for_finish() {
return m_backup_impl->wait_for_finish();
}
diff --git a/extra/mariabackup/common_engine.h b/extra/mariabackup/common_engine.h
index 6f5d8062e5040..3e6035f47f368 100644
--- a/extra/mariabackup/common_engine.h
+++ b/extra/mariabackup/common_engine.h
@@ -28,6 +28,7 @@ class Backup {
bool no_lock, bool collect_log_and_stats);
bool copy_log_tables(bool finalize);
bool copy_stats_tables();
+ bool copy_engine_binlogs(const char *binlog_dir, lsn_t backup_lsn);
bool wait_for_finish();
bool close_log_tables();
void set_post_copy_table_hook(const post_copy_table_hook_t &hook);
diff --git a/extra/mariabackup/ds_local.cc b/extra/mariabackup/ds_local.cc
index ff2021fc03522..bd2b6d02ecd02 100644
--- a/extra/mariabackup/ds_local.cc
+++ b/extra/mariabackup/ds_local.cc
@@ -211,7 +211,7 @@ static void init_ibd_data(ds_local_file_t *local_file, const uchar *buf, size_t
? fil_space_t::is_compressed(flags)
: bool(FSP_FLAGS_HAS_PAGE_COMPRESSION(flags));
-#if defined(_WIN32) && (MYSQL_VERSION_ID > 100200)
+#if defined(_WIN32)
/* Make compressed file sparse, on Windows.
In 10.1, we do not use sparse files. */
if (local_file->compressed) {
diff --git a/extra/mariabackup/encryption_plugin.cc b/extra/mariabackup/encryption_plugin.cc
index e7e8d95823cb1..9d98a4a631f40 100644
--- a/extra/mariabackup/encryption_plugin.cc
+++ b/extra/mariabackup/encryption_plugin.cc
@@ -29,6 +29,7 @@
extern struct st_maria_plugin *mysql_optional_plugins[];
extern struct st_maria_plugin *mysql_mandatory_plugins[];
static void encryption_plugin_init(int argc, char **argv);
+void initialize_default_encryption();
extern char *xb_plugin_load;
extern char *xb_plugin_dir;
@@ -140,7 +141,10 @@ void encryption_plugin_backup_init(MYSQL *mysql)
}
mysql_free_result(result);
if (!plugin_load.length())
+ {
+ initialize_default_encryption();
return;
+ }
oss << "plugin_load=" << plugin_load.c_str() + 1 << std::endl;
@@ -248,3 +252,45 @@ static void encryption_plugin_init(int argc, char **argv)
plugin_init(&argc, argv, PLUGIN_INIT_SKIP_PLUGIN_TABLE);
}
+
+/*
+ Setup encryption_handler with default encryption to avoid crashes when
+ calling encryption_get_key
+*/
+uint no_get_key(uint, uint, uchar*, uint*)
+{
+ return ENCRYPTION_KEY_VERSION_INVALID;
+}
+uint no_key(uint)
+{
+ return ENCRYPTION_KEY_VERSION_INVALID;
+}
+
+static int ctx_init(void *ctx, const unsigned char* key, unsigned int klen,
+ const unsigned char* iv, unsigned int ivlen, int flags,
+ unsigned int key_id, unsigned int key_version)
+{
+ return my_aes_crypt_init(ctx, MY_AES_CBC, flags, key, klen, iv, ivlen);
+}
+
+static unsigned int get_length(unsigned int slen, unsigned int key_id,
+ unsigned int key_version)
+{
+ return my_aes_get_size(MY_AES_CBC, slen);
+}
+
+uint ctx_size(unsigned int, unsigned int)
+{
+ return MY_AES_CTX_SIZE;
+}
+
+void initialize_default_encryption()
+{
+ encryption_handler.encryption_ctx_size_func= ctx_size;
+ encryption_handler.encryption_ctx_init_func= ctx_init;
+ encryption_handler.encryption_ctx_update_func= my_aes_crypt_update;
+ encryption_handler.encryption_ctx_finish_func= my_aes_crypt_finish;
+ encryption_handler.encryption_encrypted_length_func= get_length;
+ encryption_handler.encryption_key_get_func= no_get_key;
+ encryption_handler.encryption_key_get_latest_version_func= no_key;
+}
diff --git a/extra/mariabackup/innobackupex.cc b/extra/mariabackup/innobackupex.cc
index 867afa1a6f47a..1c0bc11b45f21 100644
--- a/extra/mariabackup/innobackupex.cc
+++ b/extra/mariabackup/innobackupex.cc
@@ -447,7 +447,7 @@ static struct my_option ibx_long_options[] =
{"startup-wait-timeout", OPT_LOCK_WAIT_TIMEOUT,
"This option specifies time in seconds that mariadb-backup should wait for "
"BACKUP STAGE START to complete. BACKUP STAGE START has to wait until all "
- "currently running queries using explicite LOCK TABLES has ended. "
+ "currently running queries using explicit LOCK TABLES has ended. "
"If there are still such queries when the timeout expires, mariadb-backup "
"terminates with an error. Default is 0, in which case mariadb-backup waits "
"indefinitely for BACKUP STAGE START to finish",
diff --git a/extra/mariabackup/xtrabackup.cc b/extra/mariabackup/xtrabackup.cc
index d36011b5bf548..445e336734d5a 100644
--- a/extra/mariabackup/xtrabackup.cc
+++ b/extra/mariabackup/xtrabackup.cc
@@ -129,6 +129,7 @@ int sd_notifyf() { return 0; }
}
int sys_var_init();
+void sys_var_end();
extern const char* fts_common_tables[];
extern const fts_index_selector_t fts_index_selector[];
@@ -203,6 +204,8 @@ struct xb_filter_entry_t{
/** whether log_copying_thread() is active; protected by recv_sys.mutex */
static bool log_copying_running;
+/** the log parsing function for --backup */
+static recv_sys_t::parser backup_log_parse;
/** for --backup, target LSN to copy the log to; protected by recv_sys.mutex */
lsn_t metadata_to_lsn;
@@ -373,6 +376,7 @@ my_bool tty_password= FALSE;
my_bool opt_lock_ddl_per_table = FALSE;
static my_bool opt_check_privileges;
+my_bool opt_backup_binlog= TRUE;
extern const char *innodb_checksum_algorithm_names[];
extern TYPELIB innodb_checksum_algorithm_typelib;
@@ -395,6 +399,8 @@ char *opt_incremental_history_uuid;
char *opt_user;
const char *opt_password;
+bool free_opt_password;
+bool free_opt_binlog_directory= false;
char *opt_host;
char *opt_defaults_group;
char *opt_socket;
@@ -660,11 +666,12 @@ void CorruptedPages::zero_out_free_pages()
if (!space)
die("Can't find space object for space name %s to check corrupted page",
space_name.c_str());
+ mtr_t mtr{nullptr};
for (std::set::const_iterator page_it=
space_it->second.pages.begin();
page_it != space_it->second.pages.end(); ++page_it)
{
- if (fseg_page_is_allocated(space, *page_it))
+ if (fseg_page_is_allocated(&mtr, space, *page_it))
{
space_info_t &space_info = non_free_pages[space_id];
space_info.pages.insert(*page_it);
@@ -1232,7 +1239,7 @@ static void backup_file_op_fail(uint32_t space_id, int type,
msg("DDL tracking : create %" PRIu32 " \"%.*s\"",
space_id, int(len), name);
fail = !check_if_skip_table(spacename.c_str());
- if (!opt_no_lock && fail &&
+ if (fail && !opt_no_lock &&
check_if_fts_table(spacename.c_str())) {
/* Ignore the FTS internal table because InnoDB does
create intermediate table and their associative FTS
@@ -1259,6 +1266,11 @@ static void backup_file_op_fail(uint32_t space_id, int type,
break;
case FILE_DELETE:
fail = !check_if_skip_table(spacename.c_str())
+ /* Ignore the FTS internal table because InnoDB may
+ drop intermediate table and their associative FTS
+ internal table as a part of inplace rollback operation.
+ backup_set_alter_copy_lock() downgrades the
+ MDL_BACKUP_DDL before inplace phase of alter */
&& !check_if_fts_table(spacename.c_str());
msg("DDL tracking : delete %" PRIu32 " \"%.*s\"",
space_id, int(len), name);
@@ -1448,7 +1460,9 @@ enum options_xtrabackup
OPT_XB_IGNORE_INNODB_PAGE_CORRUPTION,
OPT_INNODB_FORCE_RECOVERY,
OPT_INNODB_CHECKPOINT,
- OPT_ARIA_LOG_DIR_PATH
+ OPT_ARIA_LOG_DIR_PATH,
+ OPT_BINLOG,
+ OPT_BINLOG_DIRECTORY
};
struct my_option xb_client_options[]= {
@@ -1798,7 +1812,7 @@ struct my_option xb_client_options[]= {
{"startup-wait-timeout", OPT_LOCK_WAIT_TIMEOUT,
"This option specifies time in seconds that mariadb-backup should wait for "
"BACKUP STAGE START to complete. BACKUP STAGE START has to wait until all "
- "currently running queries using explicite LOCK TABLES has ended. "
+ "currently running queries using explicit LOCK TABLES has ended. "
"If there are still such queries when the timeout expires, mariadb-backup "
"terminates with an error. Default is 0, in which case mariadb-backup waits "
"indefinitely for BACKUP STAGE START to finish",
@@ -1825,11 +1839,8 @@ struct my_option xb_client_options[]= {
&opt_binlog_info, &opt_binlog_info, &binlog_info_typelib, GET_ENUM,
OPT_ARG, BINLOG_INFO_AUTO, 0, 0, 0, 0, 0},
- {"secure-auth", OPT_XB_SECURE_AUTH,
- "Refuse client connecting to server if it"
- " uses old (pre-4.1.1) protocol.",
- &opt_secure_auth, &opt_secure_auth, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0,
- 0},
+ {"secure-auth", OPT_XB_SECURE_AUTH, "Unused",
+ 0, 0, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
{"log-innodb-page-corruption", OPT_XB_IGNORE_INNODB_PAGE_CORRUPTION,
"Continue backup if innodb corrupted pages are found. The pages are "
@@ -1960,7 +1971,7 @@ struct my_option xb_server_options[] =
"Whether ib_logfile0 should be memory-mapped",
(G_PTR*) &log_sys.log_mmap,
(G_PTR*) &log_sys.log_mmap, 0, GET_BOOL, NO_ARG,
- log_sys.log_mmap_default, 0, 0, 0, 0, 0},
+ FALSE, 0, 0, 0, 0, 0},
#if defined __linux__ || defined _WIN32
{"innodb_log_file_buffering", OPT_INNODB_LOG_FILE_BUFFERING,
"Whether the file system cache for ib_logfile0 is enabled during --backup",
@@ -2099,7 +2110,7 @@ struct my_option xb_server_options[] =
"(for --backup): Force an InnoDB checkpoint",
(G_PTR*)&innodb_log_checkpoint_now,
(G_PTR*)&innodb_log_checkpoint_now,
- 0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0},
+ 0, GET_BOOL, OPT_ARG, 0, 0, 0, 0, 0, 0},
{"mysqld-args", OPT_XTRA_MYSQLD_ARGS,
"All arguments that follow this argument are considered as server "
@@ -2113,6 +2124,24 @@ struct my_option xb_server_options[] =
(G_PTR *) &xtrabackup_help, (G_PTR *) &xtrabackup_help, 0,
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"binlog", OPT_BINLOG,
+ "Backup the server binary logs. Only applies to server configured with "
+ "--binlog-storage-engine, old-style binlog is not backed up. Enabled by "
+ "default, specify --skip-binlog to not backup the binlog files. The "
+ "--skip-binlog option, if used, must be specified with both --backup and "
+ "--prepare",
+ (G_PTR*)&opt_backup_binlog,
+ (G_PTR*)&opt_backup_binlog,
+ 0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0},
+
+ {"binlog-directory", OPT_BINLOG_DIRECTORY,
+ "The directory into which to copy any binlog files in the backup. This can "
+ "be used to put binlog files in the correct location if the restored "
+ "server is to be configured with a non-default --binlog-directory. Only "
+ "used with --copy-back",
+ &opt_binlog_directory, &opt_binlog_directory,
+ 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
+
{ 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
};
@@ -2428,6 +2457,10 @@ xb_get_one_option(const struct my_option *opt,
if (my_handle_options_init_variables)
fprintf(stderr, "Obsolete option: %s. Ignored\n", opt->name);
break;
+ case OPT_BINLOG_DIRECTORY:
+
+ ADD_PRINT_PARAM_OPT(opt_binlog_directory);
+ break;
#define MYSQL_CLIENT
#include "sslopt-case.h"
#undef MYSQL_CLIENT
@@ -2448,6 +2481,7 @@ xb_get_one_option(const struct my_option *opt,
static bool innodb_init_param()
{
+ static bool mysql_tmpdir_list_set= 0;
if (!ut_is_2pow(log_sys.write_size)) {
msg("InnoDB: innodb_log_write_ahead_size=%u"
" is not a power of two", log_sys.write_size);
@@ -2455,12 +2489,15 @@ static bool innodb_init_param()
}
srv_is_being_started = TRUE;
/* === some variables from mysqld === */
- memset((G_PTR) &mysql_tmpdir_list, 0, sizeof(mysql_tmpdir_list));
-
- if (init_tmpdir(&mysql_tmpdir_list, opt_mysql_tmpdir)) {
- msg("init_tmpdir() failed");
- return true;
- }
+ if (!mysql_tmpdir_list_set)
+ {
+ mysql_tmpdir_list_set= 1;
+ memset((G_PTR) &mysql_tmpdir_list, 0, sizeof(mysql_tmpdir_list));
+ if (init_tmpdir(&mysql_tmpdir_list, opt_mysql_tmpdir)) {
+ msg("init_tmpdir() failed");
+ return true;
+ }
+ }
xtrabackup_tmpdir = my_tmpdir(&mysql_tmpdir_list);
/* dummy for initialize all_charsets[] */
get_charset_name(0);
@@ -2591,6 +2628,13 @@ static bool innodb_init_param()
srv_undo_dir = (char*) ".";
}
+ if (!opt_binlog_directory || !xtrabackup_backup) {
+ if (free_opt_binlog_directory)
+ my_free(const_cast(opt_binlog_directory));
+ opt_binlog_directory = ".";
+ free_opt_binlog_directory= false;
+ }
+
compile_time_assert(SRV_FORCE_IGNORE_CORRUPT == 1);
/*
@@ -2628,7 +2672,10 @@ static byte log_hdr_buf[log_t::START_OFFSET + SIZE_OF_FILE_CHECKPOINT];
static void log_hdr_init()
{
memset(log_hdr_buf, 0, sizeof log_hdr_buf);
- mach_write_to_4(LOG_HEADER_FORMAT + log_hdr_buf, log_t::FORMAT_10_8);
+ /* log_t::FORMAT_ENC_10_8 is written to the file as FORMAT_10_8 */
+ mach_write_to_4(LOG_HEADER_FORMAT + log_hdr_buf,
+ log_sys.format == log_t::FORMAT_ENC_11
+ ? log_t::FORMAT_ENC_11 : log_t::FORMAT_10_8);
mach_write_to_8(LOG_HEADER_START_LSN + log_hdr_buf,
log_sys.next_checkpoint_lsn);
snprintf(reinterpret_cast(LOG_HEADER_CREATOR + log_hdr_buf),
@@ -3460,87 +3507,51 @@ static bool xtrabackup_copy_mmap_logfile()
recv_sys.len= size_t(log_sys.file_size);
const size_t seq_offset{log_sys.is_encrypted() ? 8U + 5U : 5U};
const char one{'\1'};
+ const byte *start= &log_sys.buf[recv_sys.offset];
+ ut_d(recv_sys_t::parse_mtr_result r);
- for (unsigned retry_count{0};;)
+ if ((ut_d(r=) backup_log_parse(false)) == recv_sys_t::OK)
{
- recv_sys_t::parse_mtr_result r;
- const byte *start= &log_sys.buf[recv_sys.offset];
-
- if (recv_sys.parse_mmap(false) ==
- recv_sys_t::OK)
+ do
{
- const byte *end;
-
- do
+ /* Set the sequence bit (the backed-up log will not wrap around) */
+ size_t seqo= recv_sys.offset - seq_offset;
+ if (seqo < log_sys.START_OFFSET)
+ seqo+= static_cast(log_sys.file_size - log_sys.START_OFFSET);
+ const byte *seq= &log_sys.buf[seqo];
+ ut_ad(*seq == log_sys.get_sequence_bit(recv_sys.lsn - seq_offset));
+ if (!*seq)
{
- /* Set the sequence bit (the backed-up log will not wrap around) */
- size_t seqo= recv_sys.offset - seq_offset;
- if (seqo < log_sys.START_OFFSET)
- seqo+= static_cast(log_sys.file_size - log_sys.START_OFFSET);
- const byte *seq= &log_sys.buf[seqo];
- ut_ad(*seq == log_sys.get_sequence_bit(recv_sys.lsn - seq_offset));
- if (!*seq)
- {
- if (xtrabackup_copy_mmap_snippet(dst_log_file, start, seq) ||
- ds_write(dst_log_file, &one, 1))
- goto write_error;
- start = seq + 1;
- }
+ if (xtrabackup_copy_mmap_snippet(dst_log_file, start, seq) ||
+ ds_write(dst_log_file, &one, 1))
+ goto write_error;
+ start = seq + 1;
}
- while ((r= recv_sys.parse_mmap(false)) ==
- recv_sys_t::OK);
-
- end= &log_sys.buf[recv_sys.offset];
-
- if (xtrabackup_copy_mmap_snippet(dst_log_file, start, end))
- {
- write_error:
- msg("Error: write to ib_logfile0 failed");
- return true;
- }
-
- start= end;
-
- pthread_cond_broadcast(&scanned_lsn_cond);
-
- if (r == recv_sys_t::GOT_EOF)
- break;
-
- retry_count= 0;
}
- else
- {
- if (metadata_to_lsn)
- {
- if (metadata_to_lsn <= recv_sys.lsn)
- return false;
- }
- else if (xtrabackup_throttle && io_ticket-- < 0)
- mysql_cond_wait(&wait_throttle, &recv_sys.mutex);
+ while ((ut_d(r=) backup_log_parse(false)) == recv_sys_t::OK);
- if (!retry_count++)
- msg("Retrying read of log at LSN=" LSN_PF, recv_sys.lsn);
- else if (retry_count == 100)
- break;
- else
- {
- timespec abstime;
- set_timespec_nsec(abstime, 1000000ULL /* 1 ms */);
- if (!mysql_cond_timedwait(&log_copying_stop, &recv_sys.mutex,
- &abstime))
- return true;
- }
+ if (xtrabackup_copy_mmap_snippet(dst_log_file, start,
+ &log_sys.buf[recv_sys.offset]))
+ {
+ write_error:
+ msg("Error: write to ib_logfile0 failed");
+ return true;
}
+
+ pthread_cond_broadcast(&scanned_lsn_cond);
}
+ ut_ad(r == recv_sys_t::GOT_EOF);
+
if (verbose)
msg(">> log scanned up to (" LSN_PF ")", recv_sys.lsn);
return false;
}
/** Copy redo log until the current end of the log is reached
+@param early_exit parse and copy only logs from first read and return
@return whether the operation failed */
-static bool xtrabackup_copy_logfile()
+static bool xtrabackup_copy_logfile(bool early_exit)
{
mysql_mutex_assert_owner(&recv_sys.mutex);
DBUG_EXECUTE_IF("log_checksum_mismatch", return false;);
@@ -3556,7 +3567,6 @@ static bool xtrabackup_copy_logfile()
recv_sys.offset= size_t(recv_sys.lsn - log_sys.get_first_lsn()) &
block_size_1;
- recv_sys.len= 0;
for (unsigned retry_count{0};;)
{
@@ -3564,12 +3574,12 @@ static bool xtrabackup_copy_logfile()
size_t start_offset{recv_sys.offset};
{
+ recv_sys.len= 0;
{
auto source_offset=
- log_sys.calc_lsn_offset(recv_sys.lsn + recv_sys.len -
- recv_sys.offset);
+ log_sys.calc_lsn_offset(recv_sys.lsn - recv_sys.offset);
source_offset&= ~block_size_1;
- size_t size{log_sys.buf_size - recv_sys.len};
+ size_t size{log_sys.buf_size};
if (UNIV_UNLIKELY(source_offset + size > log_sys.file_size))
{
const size_t first{size_t(log_sys.file_size - source_offset)};
@@ -3591,8 +3601,7 @@ static bool xtrabackup_copy_logfile()
if (log_sys.buf[recv_sys.offset] <= 1)
break;
- if (recv_sys.parse_mtr(false) ==
- recv_sys_t::OK)
+ if (backup_log_parse(false) == recv_sys_t::OK)
{
do
{
@@ -3602,8 +3611,7 @@ static bool xtrabackup_copy_logfile()
sequence_offset));
*seq= 1;
}
- while ((r= recv_sys.parse_mtr(false)) ==
- recv_sys_t::OK);
+ while ((r= backup_log_parse(false)) == recv_sys_t::OK);
if (ds_write(dst_log_file, log_sys.buf + start_offset,
recv_sys.offset - start_offset))
@@ -3611,32 +3619,25 @@ static bool xtrabackup_copy_logfile()
msg("Error: write to ib_logfile0 failed");
return true;
}
- else
- {
- const auto ofs= recv_sys.offset & ~block_size_1;
- memmove_aligned<64>(log_sys.buf, log_sys.buf + ofs,
- recv_sys.len - ofs);
- recv_sys.len-= ofs;
- recv_sys.offset&= block_size_1;
- }
-
pthread_cond_broadcast(&scanned_lsn_cond);
- if (r == recv_sys_t::GOT_EOF)
+ if (r == recv_sys_t::GOT_EOF || early_exit)
break;
+ ut_ad(r == recv_sys_t::PREMATURE_EOF);
+
if (recv_sys.offset < log_sys.write_size)
break;
if (xtrabackup_throttle && io_ticket-- < 0)
mysql_cond_wait(&wait_throttle, &recv_sys.mutex);
+ recv_sys.offset&= block_size_1;
retry_count= 0;
continue;
}
else
{
- recv_sys.len= recv_sys.offset & ~block_size_1;
if (retry_count == 100)
break;
@@ -3716,7 +3717,7 @@ static void log_copying_thread()
{
my_thread_init();
mysql_mutex_lock(&recv_sys.mutex);
- while (!xtrabackup_copy_logfile() &&
+ while (!xtrabackup_copy_logfile(false) &&
(!metadata_last_lsn || metadata_last_lsn > recv_sys.lsn))
{
timespec abstime;
@@ -4934,7 +4935,7 @@ static bool backup_wait_for_commit_lsn()
ut_ad(metadata_to_lsn);
metadata_last_lsn= lsn;
- last_lsn= backup_wait_for_lsn_low(LSN_MAX);
+ last_lsn= backup_wait_for_lsn_low(lsn);
metadata_last_lsn= last_lsn;
stop_backup_threads();
@@ -5425,6 +5426,29 @@ class BackupStages {
return res;
}
+ bool do_backup_binlogs() {
+ // Copy InnoDB binlog files.
+ // Going to BACKUP STAGE START protects against RESET
+ // MASTER deleting files during the copy, or FLUSH
+ // BINARY LOGS truncating them.
+ if (!opt_no_lock)
+ xb_mysql_query(mysql_connection, "BACKUP STAGE START",
+ false, false);
+ if (!m_common_backup.copy_engine_binlogs(opt_binlog_directory,
+ recv_sys.lsn)) {
+ msg("Error on copy InnoDB binlog files");
+ return false;
+ }
+ if (!m_common_backup.wait_for_finish()) {
+ msg("InnoDB binlog file backup process is finished with error");
+ return false;
+ }
+ if (!opt_no_lock)
+ xb_mysql_query(mysql_connection, "BACKUP STAGE END",
+ false, false);
+ return true;
+ }
+
bool stage_end(Backup_datasinks &backup_datasinks) {
msg("Starting BACKUP STAGE END");
/* release all locks */
@@ -5445,6 +5469,11 @@ class BackupStages {
nullptr);
);
+ if (opt_backup_binlog) {
+ if (!do_backup_binlogs())
+ return false;
+ }
+
backup_finish(backup_datasinks.m_data);
return true;
}
@@ -5490,12 +5519,14 @@ static bool xtrabackup_backup_func()
}
msg("cd to %s", mysql_real_data_home);
encryption_plugin_backup_init(mysql_connection);
- if (innodb_log_checkpoint_now != false && mysql_send_query(
- mysql_connection,
+ if (innodb_log_checkpoint_now) {
+ msg("Initiating checkpoint");
+ if (mysql_send_query(mysql_connection,
C_STRING_WITH_LEN("SET GLOBAL "
"innodb_log_checkpoint_now=ON;"))) {
- msg("initiating checkpoint failed");
- return(false);
+ msg("initiating checkpoint failed");
+ return(false);
+ }
}
msg("open files limit requested %lu, set to %lu",
@@ -5536,12 +5567,14 @@ static bool xtrabackup_backup_func()
if (fil_system.is_initialised()) {
innodb_shutdown();
}
+ backup_datasinks.destroy();
return(false);
}
srv_thread_pool_init();
/* Reset the system variables in the recovery module. */
trx_pool_init();
+ btr_search_sys_create();
recv_sys.create();
xb_filters_init();
@@ -5609,6 +5642,7 @@ static bool xtrabackup_backup_func()
server does not support this */
if (innodb_log_checkpoint_now != false) {
mysql_read_query_result(mysql_connection);
+ msg("Finished waiting for checkpoint");
}
if (!select_history()) {
@@ -5646,9 +5680,10 @@ static bool xtrabackup_backup_func()
/* copy log file by current position */
mysql_mutex_lock(&recv_sys.mutex);
+ backup_log_parse = recv_sys.get_backup_parser();
recv_sys.lsn = log_sys.next_checkpoint_lsn;
- const bool log_copy_failed = xtrabackup_copy_logfile();
+ const bool log_copy_failed = xtrabackup_copy_logfile(true);
mysql_mutex_unlock(&recv_sys.mutex);
@@ -5875,7 +5910,7 @@ void CorruptedPages::backup_fix_ddl(ds_ctxt *ds_data, ds_ctxt *ds_meta)
}
/* Mariabackup doesn't detect any FILE_OP for the deferred
- tablespace. There is a possiblity that page0 could've
+ tablespace. There is a possibility that page0 could've
been corrupted persistently in the disk */
for (auto space_name: defer_space_names) {
if (!check_if_skip_table(space_name.c_str())) {
@@ -5906,6 +5941,8 @@ void CorruptedPages::backup_fix_ddl(ds_ctxt *ds_data, ds_ctxt *ds_meta)
node, 0, dest_name.c_str(),
wf_write_through, *this);
}
+
+ DBUG_MARIABACKUP_EVENT("after_backup_fix_ddl", {});
}
@@ -6149,16 +6186,12 @@ xb_delta_open_matching_space(
ut_ad(fil_space_t::physical_size(flags) == info.page_size);
mysql_mutex_lock(&fil_system.mutex);
- fil_space_t* space = fil_space_t::create(uint32_t(info.space_id),
- flags, false, 0,
- FIL_ENCRYPTION_DEFAULT, true);
+ std::ignore = fil_space_t::create(uint32_t(info.space_id),
+ flags, false, 0,
+ FIL_ENCRYPTION_DEFAULT, true);
mysql_mutex_unlock(&fil_system.mutex);
- if (space) {
- *success = xb_space_create_file(real_name, info.space_id,
- flags, &file);
- } else {
- msg("Can't create tablespace %s\n", dest_space_name);
- }
+ *success = xb_space_create_file(real_name, info.space_id,
+ flags, &file);
goto exit;
}
@@ -6687,7 +6720,6 @@ void
innodb_free_param()
{
srv_sys_space.shutdown();
- free_tmpdir(&mysql_tmpdir_list);
}
@@ -7336,6 +7368,8 @@ void setup_error_messages()
void handle_options(int argc, char **argv, char ***argv_server,
char ***argv_client, char ***argv_backup)
{
+ char **save_argv_server, **save_argv_client, **save_argv_backup;
+
/* Setup some variables for Innodb.*/
srv_operation = SRV_OPERATION_RESTORE;
@@ -7453,6 +7487,7 @@ void handle_options(int argc, char **argv, char ***argv_server,
load_defaults_or_exit(conf_file, &server_default_groups[0],
&argc_server, argv_server);
+ save_argv_server= *argv_server;
int n;
for (n = 0; (*argv_server)[n]; n++) {};
@@ -7498,6 +7533,7 @@ void handle_options(int argc, char **argv, char ***argv_server,
load_defaults_or_exit(conf_file, xb_client_default_groups,
&argc_client, argv_client);
+ save_argv_client= *argv_client;
for (n = 0; (*argv_client)[n]; n++) {};
argc_client = n;
@@ -7518,6 +7554,8 @@ void handle_options(int argc, char **argv, char ***argv_server,
load_defaults_or_exit(conf_file, backup_default_groups, &argc_backup,
argv_backup);
+ save_argv_backup= *argv_backup;
+
for (n= 0; (*argv_backup)[n]; n++)
{
};
@@ -7545,12 +7583,13 @@ void handle_options(int argc, char **argv, char ***argv_server,
xb_client_options, xb_get_one_option)))
exit(ho_error);
- if (opt_password)
+ if (opt_password && strlen(opt_password))
{
char *argument= (char*) opt_password;
char *start= (char*) opt_password;
opt_password= my_strdup(PSI_NOT_INSTRUMENTED, opt_password,
MYF(MY_FAE));
+ free_opt_password= 1;
while (*argument)
*argument++= 'x'; // Destroy argument
if (*start)
@@ -7598,6 +7637,14 @@ void handle_options(int argc, char **argv, char ***argv_server,
}
}
}
+ /*
+ Restore load defaults argument to the value after
+ load_defaults_or_exit(). This is needed for caller
+ when calling free_defaults()
+ */
+ *argv_server= save_argv_server;
+ *argv_client= save_argv_client;
+ *argv_backup= save_argv_backup;
}
static int main_low(char** argv);
@@ -7702,10 +7749,23 @@ int main(int argc, char **argv)
cleanup_errmsgs();
free_error_messages();
mysql_mutex_destroy(&LOCK_error_log);
+ free_tmpdir(&mysql_tmpdir_list);
+ if (free_opt_password)
+ my_free((char*) opt_password);
+ plugin_shutdown();
+ free_list(opt_plugin_load_list_ptr);
+ if (free_opt_binlog_directory)
+ my_free(const_cast(opt_binlog_directory));
+ mysql_server_end();
+ sys_var_end();
if (status == EXIT_SUCCESS) {
- msg("completed OK!");
+ msg("completed OK!");
}
+ my_end(MY_CHECK_ERROR);
+ sf_leaking_memory= 0;
+ if (SAFEMALLOC_HAVE_MEMORY_LEAK)
+ status= EXIT_FAILURE;
return status;
}
diff --git a/extra/mariabackup/xtrabackup.h b/extra/mariabackup/xtrabackup.h
index 38d7e5fdd03d1..d7f3435871f4c 100644
--- a/extra/mariabackup/xtrabackup.h
+++ b/extra/mariabackup/xtrabackup.h
@@ -151,6 +151,7 @@ extern char *opt_incremental_history_uuid;
extern char *opt_user;
extern const char *opt_password;
+extern bool free_opt_binlog_directory;
extern char *opt_host;
extern char *opt_defaults_group;
extern char *opt_socket;
@@ -178,6 +179,7 @@ extern const char *opt_history;
enum binlog_info_enum { BINLOG_INFO_OFF, BINLOG_INFO_LOCKLESS, BINLOG_INFO_ON,
BINLOG_INFO_AUTO};
+extern bool backup_binlog;
extern ulong opt_binlog_info;
extern ulong xtrabackup_innodb_force_recovery;
diff --git a/extra/perror.c b/extra/perror.c
index 83b8d6eb8cd94..3b7e9663f2d70 100644
--- a/extra/perror.c
+++ b/extra/perror.c
@@ -354,7 +354,8 @@ int main(int argc,char *argv[])
found= 1;
if (verbose)
printf("MariaDB error code %3d (%s): %s\n"
- "Learn more: https://mariadb.com/kb/en/e%3d/\n", code, name, msg, code);
+ "Learn more: https://err.mariadb.com/%3d\n",
+ code, name, msg, code);
else
puts(msg);
}
diff --git a/extra/wolfssl/wolfssl b/extra/wolfssl/wolfssl
index b077c81eb6353..59f4fa5686153 160000
--- a/extra/wolfssl/wolfssl
+++ b/extra/wolfssl/wolfssl
@@ -1 +1 @@
-Subproject commit b077c81eb635392e694ccedbab8b644297ec0285
+Subproject commit 59f4fa568615396fbf381b073b220d1e8d61e4c2
diff --git a/include/aria_backup.h b/include/aria_backup.h
index f399f6a6f40d9..dc931dbd33c48 100644
--- a/include/aria_backup.h
+++ b/include/aria_backup.h
@@ -15,11 +15,15 @@
/* Interfaces for doing backups of Aria tables */
+#ifndef ARIA_BACKUP_INCLUDED
+
C_MODE_START
typedef struct st_aria_table_capabilities
{
my_off_t header_size;
+ MARIA_CRYPT_DATA *crypt_data;
+ uint crypt_page_header_space;
ulong bitmap_pages_covered;
uint block_size;
uint keypage_header;
@@ -32,11 +36,15 @@ typedef struct st_aria_table_capabilities
/* s3 capabilities */
ulong s3_block_size;
uint8 compression;
+ char filename[FN_REFLEN];
} ARIA_TABLE_CAPABILITIES;
-int aria_get_capabilities(File kfile, ARIA_TABLE_CAPABILITIES *cap);
+int aria_get_capabilities(File kfile, const char *table_name, ARIA_TABLE_CAPABILITIES *cap);
+void aria_free_capabilities(ARIA_TABLE_CAPABILITIES *cap);
int aria_read_index(File kfile, ARIA_TABLE_CAPABILITIES *cap, ulonglong block,
uchar *buffer);
int aria_read_data(File dfile, ARIA_TABLE_CAPABILITIES *cap, ulonglong block,
uchar *buffer, size_t *bytes_read);
C_MODE_END
+
+#endif /* ARIA_BACKUP_INCLUDED */
diff --git a/include/handler_binlog_reader.h b/include/handler_binlog_reader.h
new file mode 100644
index 0000000000000..be97c14111fa4
--- /dev/null
+++ b/include/handler_binlog_reader.h
@@ -0,0 +1,97 @@
+#ifndef HANDLER_BINLOG_READER_INCLUDED
+#define HANDLER_BINLOG_READER_INCLUDED
+
+/* Copyright (c) 2025, Kristian Nielsen.
+
+ 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 */
+
+
+class String;
+class THD;
+struct slave_connection_state;
+struct rpl_binlog_state_base;
+
+
+/*
+ Class for reading a binlog implemented in an engine.
+*/
+class handler_binlog_reader {
+public:
+ /*
+ Approximate current position (from which next call to read_binlog_data()
+ will need to read). Updated by the engine. Used to know which binlog files
+ the active dump threads are currently reading from, to avoid purging
+ actively used binlogs.
+ */
+ uint64_t cur_file_no;
+ uint64_t cur_file_pos;
+
+private:
+ /* Position and length of any remaining data in buf[]. */
+ uint32_t buf_data_pos;
+ uint32_t buf_data_remain;
+ /* Buffer used when reading data out via read_binlog_data(). */
+ static constexpr size_t BUF_SIZE= 32768;
+ uchar *buf;
+
+public:
+ handler_binlog_reader()
+ : cur_file_no(~(uint64_t)0), cur_file_pos(~(uint64_t)0),
+ buf_data_pos(0), buf_data_remain(0)
+ {
+ buf= (uchar *)my_malloc(PSI_INSTRUMENT_ME, BUF_SIZE, MYF(0));
+ }
+ virtual ~handler_binlog_reader() {
+ my_free(buf);
+ };
+ virtual int read_binlog_data(uchar *buf, uint32_t len) = 0;
+ virtual bool data_available()= 0;
+ /*
+ Wait for data to be available to read, for kill, or for timeout.
+ Returns true in case of timeout reached, false otherwise.
+ Caller should check for kill before calling again (to avoid busy-loop).
+ */
+ virtual bool wait_available(THD *thd, const struct timespec *abstime) = 0;
+ /*
+ This initializes the current read position to the point of the slave GTID
+ position passed in as POS. It is permissible to start at a position a bit
+ earlier in the binlog, only cost is the extra read cost of reading not
+ needed event data.
+
+ If position is found, must return the corresponding binlog state in the
+ STATE output parameter and initialize cur_file_no and cur_file_pos members.
+
+ Returns:
+ -1 Error
+ 0 The requested GTID position not found, needed binlogs have been purged
+ 1 Ok, position found and returned.
+ */
+ virtual int init_gtid_pos(THD *thd, slave_connection_state *pos,
+ rpl_binlog_state_base *state) = 0;
+ /*
+ Initialize to a legacy-type position (filename, offset). This mostly to
+ support legacy SHOW BINLOG EVENTS.
+ */
+ virtual int init_legacy_pos(THD *thd, const char *filename,
+ ulonglong offset) = 0;
+ /*
+ Can be called after init_gtid_pos() or init_legacy_pos() to make the reader
+ stop (return EOF) at the end of the binlog file. Used for SHOW BINLOG
+ EVENTS, which has a file-based interface based on legacy file name.
+ */
+ virtual void enable_single_file() = 0;
+ int read_log_event(String *packet, uint32_t ev_offset, size_t max_allowed);
+};
+
+#endif /* HANDLER_BINLOG_READER_INCLUDED */
diff --git a/include/ilist.h b/include/ilist.h
index 3349959e17e0e..46f706eaef9f3 100644
--- a/include/ilist.h
+++ b/include/ilist.h
@@ -189,6 +189,9 @@ template class ilist
ListNode *prev= pos.node_->prev;
ListNode *next= pos.node_->next;
+ DBUG_ASSERT(prev->next == pos.node_);
+ DBUG_ASSERT(next->prev == pos.node_);
+
prev->next= next;
next->prev= prev;
@@ -202,7 +205,7 @@ template class ilist
}
void push_back(reference value) noexcept { insert(end(), value); }
- void pop_back() noexcept { erase(end()); }
+ void pop_back() noexcept { erase(--end()); }
void push_front(reference value) noexcept { insert(begin(), value); }
void pop_front() noexcept { erase(begin()); }
diff --git a/include/json_lib.h b/include/json_lib.h
index c619ad9d91574..13fbfed0186f6 100644
--- a/include/json_lib.h
+++ b/include/json_lib.h
@@ -7,8 +7,27 @@
extern "C" {
#endif
-#define JSON_DEPTH_LIMIT 32
+#define JSON_DEPTH_DEFAULT 32
+#define JSON_DEPTH_LIMIT 32 /* Still used in columnstore. */
+#define JSON_DEPTH_INC JSON_DEPTH_DEFAULT*100
+/*
+ Because this array will store approximate two arrays of
+ type json_path_step_t and one or two integer arrays,
+ each of average 70 elements. So this size should suffice.
+*/
+#define BLOCK_SIZE_JSON_DYN_ARRAY 4096
+
+#define get_json_step(p,s) if (p->last_step_idx < (int)(p->steps.max_element)) \
+ s= ((json_path_step_t*)(p->steps.buffer))+p->last_step_idx; \
+ else \
+ s= (json_path_step_t*) mem_root_dynamic_array_resize_and_get_val(&p->steps, p->last_step_idx);
+
+#define set_json_array_value_ptr(idx, max_element, dyn_arr_ptr, val) \
+ if ((size_t)(idx) < (max_element)) \
+ memcpy((dyn_arr_ptr)->buffer + (dyn_arr_ptr)->size_of_element * (idx), &(val), sizeof(val)); \
+ else \
+ mem_root_dynamic_array_resize_and_set_val((dyn_arr_ptr), &(val), (idx));
/*
When error happens, the c_next of the JSON engine contains the
character that caused the error, and the c_str is the position
@@ -28,7 +47,7 @@ enum json_errors {
JE_ESCAPING= -6, /* Error in the escaping. */
- JE_DEPTH= -7, /* The limit on the JSON depth was overrun. */
+ JE_DEPTH= -7, /* The limit on the JSON depth was overrun. Still used in columnstore*/
};
@@ -104,8 +123,8 @@ typedef struct st_json_path_step_t
typedef struct st_json_path_t
{
json_string_t s; /* The string to be parsed. */
- json_path_step_t steps[JSON_DEPTH_LIMIT]; /* Steps of the path. */
- json_path_step_t *last_step; /* Points to the last step. */
+ MEM_ROOT_DYNAMIC_ARRAY steps; /* Steps of the path. */
+ int last_step_idx;
int mode_strict; /* TRUE if the path specified as 'strict' */
enum json_path_step_types types_used; /* The '|' of all step's 'type'-s */
@@ -225,8 +244,8 @@ typedef struct st_json_engine_t
const uchar *value_end; /* Points to the next character after the value. */
int value_len; /* The length of the value. Does not count quotations for */
/* string constants. */
-
- int stack[JSON_DEPTH_LIMIT]; /* Keeps the stack of nested JSON structures. */
+ /* Keeps the stack of nested JSON structures. */
+ MEM_ROOT_DYNAMIC_ARRAY stack;
int stack_p; /* The 'stack' pointer. */
volatile uchar *killed_ptr;
} json_engine_t;
@@ -341,6 +360,13 @@ int json_skip_level_and_count(json_engine_t *j, int *n_items_skipped);
*/
#define json_value_scalar(je) ((je)->value_type > JSON_VALUE_ARRAY)
+#define report_json_error(js, je, n_param) \
+ report_json_error_ex(js->ptr(), je, func_name(), n_param, \
+ Sql_condition::WARN_LEVEL_WARN)
+
+#define report_path_error(js, je, n_param) \
+ report_path_error_ex(js->ptr(), je, func_name(), n_param,\
+ Sql_condition::WARN_LEVEL_WARN)
/*
Look for the JSON PATH in the json string.
@@ -350,7 +376,7 @@ int json_skip_level_and_count(json_engine_t *j, int *n_items_skipped);
initialized with the JSON string, and the json_path_t with the JSON path
appropriately. The 'p_cur_step' should point at the first
step of the path.
- The 'array_counters' is the array of JSON_DEPTH_LIMIT size.
+ The 'array_counters' is the array of 'curr_json_depth_limit' size.
It stores the array counters of the parsed JSON.
If function returns 0, it means it found the match. The position of
the match is je->s.c_str. Then we can call the json_find_path()
@@ -360,7 +386,7 @@ int json_skip_level_and_count(json_engine_t *j, int *n_items_skipped);
*/
int json_find_path(json_engine_t *je,
json_path_t *p, json_path_step_t **p_cur_step,
- int *array_counters);
+ MEM_ROOT_DYNAMIC_ARRAY *array_counters);
typedef struct st_json_find_paths_t
@@ -369,7 +395,7 @@ typedef struct st_json_find_paths_t
json_path_t *paths;
uint cur_depth;
uint *path_depths;
- int array_counters[JSON_DEPTH_LIMIT];
+ MEM_ROOT_DYNAMIC_ARRAY array_counters;
} json_find_paths_t;
@@ -431,17 +457,22 @@ int json_get_path_start(json_engine_t *je, CHARSET_INFO *i_cs,
int json_get_path_next(json_engine_t *je, json_path_t *p);
int json_path_compare(const json_path_t *a, const json_path_t *b,
- enum json_value_types vt, const int* array_size_counter);
+ enum json_value_types vt,
+ MEM_ROOT_DYNAMIC_ARRAY* array_size_counter);
-int json_valid(const char *js, size_t js_len, CHARSET_INFO *cs);
+int json_valid(const char *js, size_t js_len,
+ CHARSET_INFO *cs, json_engine_t *je);
-int json_locate_key(const char *js, const char *js_end,
+int json_locate_key(json_engine_t *je, const char *js, const char *js_end,
const char *kname,
const char **key_start, const char **key_end,
int *comma_pos);
int json_normalize(DYNAMIC_STRING *result,
- const char *s, size_t size, CHARSET_INFO *cs);
+ const char *s, size_t size, CHARSET_INFO *cs,
+ MEM_ROOT *current_mem_root,
+ json_engine_t *temp_je,
+ MEM_ROOT_DYNAMIC_ARRAY *stack);
int json_skip_array_and_count(json_engine_t *j, int* n_item);
@@ -450,6 +481,8 @@ inline static int json_scan_ended(json_engine_t *j)
return (j->state == JST_ARRAY_END && j->stack_p == 0);
}
+void initJsonArray(MEM_ROOT *mem_root, MEM_ROOT_DYNAMIC_ARRAY *mem_root_array, size_t size, void *buffer, myf myflag);
+
#ifdef __cplusplus
}
#endif
diff --git a/include/m_ctype.h b/include/m_ctype.h
index c029f36c5bf32..d8e11012d5e3e 100644
--- a/include/m_ctype.h
+++ b/include/m_ctype.h
@@ -23,6 +23,8 @@
#include
#include
+/* Provides portable uint64 type uint64_t */
+#include
enum loglevel {
ERROR_LEVEL= 0,
@@ -186,6 +188,15 @@ typedef struct my_uca_level_booster_t
This array is used for prefix optimization.
*/
MY_UCA_WEIGHT2 weight_strings_2bytes_to_1_or_2_weights[0x10000];
+
+ /*
+ A helper array to process one-character ASCII strings.
+ Suitable only for stand-alone characters,
+ which are known not to be contraction parts,
+ e.g. the very last character of a string.
+ */
+ uint16 weight_1byte_to_1weight_standalone[0x100];
+
} MY_UCA_LEVEL_BOOSTER;
@@ -495,13 +506,58 @@ typedef struct my_charset_loader_st
extern int (*my_string_stack_guard)(int);
+typedef struct my_hasher_st
+{
+ union {
+ struct {
+ ulong m_nr1; /* mysql5x hash value */
+ ulong m_nr2; /* mysql5x aux value */
+ };
+ uint64_t m_nr; /* The hash value */
+ };
+ /* Whether a streaming algorithm has been in use */
+ my_bool m_streaming;
+ /* One-shot string hash function */
+ void (*m_hash_str)(struct my_hasher_st *hasher, const uchar* str,
+ size_t len);
+ /*
+ Byte-streaming hash function, fallback to m_hash_str on one byte
+ if NULL
+ */
+ void (*m_hash_byte)(struct my_hasher_st *hasher, uchar value);
+ /*
+ One-shot number hash function. This is for backward compatibility:
+ mysql5x algorithms hashes numerical fields as if they are strings
+ (by using my_charset_latin1's hash_sort function), but new
+ algorithms should use the default my_hasher_hash_num which uses
+ my_charset_bin's hash_sort function
+ */
+ void (*m_hash_num)(struct my_hasher_st *hasher, const uchar* num,
+ size_t binary_size);
+ /* Function to clean up and return the hash value */
+ uint64_t (*m_finalize)(struct my_hasher_st *hasher);
+ /* Custom pointer e.g. to a state */
+ void *m_specific;
+} my_hasher_st;
+
+/* Defined in hasher-xxx.c files */
+extern my_hasher_st my_hasher_mysql5x(void);
+extern my_hasher_st my_hasher_mysql5x_for_unique(void);
+extern my_hasher_st my_hasher_base31(void);
+extern my_hasher_st my_hasher_crc32c(void);
+extern my_hasher_st my_hasher_xxh32(void);
+extern my_hasher_st my_hasher_xxh3(void);
+
+#define MY_HASH_ADD_MARIADB(A, B, value) \
+ do { A^= (((A & 63)+B)*((value)))+ (A << 8); B+=3; } while(0)
+
/* See strings/CHARSET_INFO.txt for information about this structure */
struct my_collation_handler_st
{
my_bool (*init)(struct charset_info_st *, MY_CHARSET_LOADER *);
/* Collation routines */
int (*strnncoll)(CHARSET_INFO *,
- const uchar *, size_t, const uchar *, size_t, my_bool);
+ const uchar *, size_t, const uchar *, size_t, my_bool*);
int (*strnncollsp)(CHARSET_INFO *,
const uchar *, size_t, const uchar *, size_t);
/*
@@ -580,8 +636,8 @@ struct my_collation_handler_st
my_match_t *match, uint nmatch);
/* Hash calculation */
- void (*hash_sort)(CHARSET_INFO *cs, const uchar *key, size_t len,
- ulong *nr1, ulong *nr2);
+ void (*hash_sort)(my_hasher_st *hasher, CHARSET_INFO *cs, const uchar *key,
+ size_t len);
my_bool (*propagate)(CHARSET_INFO *cs, const uchar *str, size_t len);
/*
Make minimum and maximum strings for the collation.
@@ -660,6 +716,7 @@ struct my_charset_handler_st
size_t (*numchars)(CHARSET_INFO *, const char *b, const char *e);
size_t (*charpos)(CHARSET_INFO *, const char *b, const char *e,
size_t pos);
+ /* Length without trailing space */
size_t (*lengthsp)(CHARSET_INFO *, const char *ptr, size_t length);
size_t (*numcells)(CHARSET_INFO *, const char *b, const char *e);
@@ -1090,22 +1147,23 @@ struct charset_info_st
}
int strnncoll(const LEX_CSTRING a, const LEX_CSTRING b,
- my_bool b_is_prefix= FALSE) const
+ my_bool *b_is_prefix= 0) const
{
DBUG_ASSERT(is_valid_string(a));
DBUG_ASSERT(is_valid_string(b));
return (coll->strnncoll)(this,
(const uchar *) a.str, a.length,
- (const uchar *) b.str, b.length, b_is_prefix);
+ (const uchar *) b.str, b.length,
+ b_is_prefix);
}
int strnncoll(const uchar *a, size_t alen,
- const uchar *b, size_t blen, my_bool b_is_prefix= FALSE) const
+ const uchar *b, size_t blen, my_bool *b_is_prefix= 0) const
{
return (coll->strnncoll)(this, a, alen, b, blen, b_is_prefix);
}
int strnncoll(const char *a, size_t alen,
- const char *b, size_t blen, my_bool b_is_prefix= FALSE) const
+ const char *b, size_t blen, my_bool *b_is_prefix= 0) const
{
return (coll->strnncoll)(this,
(const uchar *) a, alen,
@@ -1182,9 +1240,9 @@ struct charset_info_st
return (coll->instr)(this, b, b_length, s, s_length, match, nmatch);
}
- void hash_sort(const uchar *key, size_t len, ulong *nr1, ulong *nr2) const
+ void hash_sort(my_hasher_st *hasher, const uchar *key, size_t len) const
{
- (coll->hash_sort)(this, key, len, nr1, nr2);
+ (coll->hash_sort)(hasher, this, key, len);
}
my_bool propagate(const uchar *str, size_t len) const
@@ -1422,7 +1480,7 @@ static inline int
my_ci_strnncoll(CHARSET_INFO *ci,
const uchar *a, size_t alen,
const uchar *b, size_t blen,
- my_bool b_is_prefix)
+ my_bool *b_is_prefix)
{
return (ci->coll->strnncoll)(ci, a, alen, b, blen, b_is_prefix);
}
@@ -1435,6 +1493,16 @@ my_ci_strnncollsp(CHARSET_INFO *ci,
return (ci->coll->strnncollsp)(ci, a, alen, b, blen);
}
+static inline int
+my_ci_strnncollsp_nchars(CHARSET_INFO *ci,
+ const uchar *a, size_t alen,
+ const uchar *b, size_t blen,
+ size_t nchars,
+ uint flags)
+{
+ return (ci->coll->strnncollsp_nchars)(ci, a, alen, b, blen, nchars, flags);
+}
+
static inline my_bool
my_ci_like_range(CHARSET_INFO *ci,
@@ -1462,11 +1530,10 @@ my_ci_instr(CHARSET_INFO *ci,
static inline void
-my_ci_hash_sort(CHARSET_INFO *ci,
- const uchar *key, size_t len,
- ulong *nr1, ulong *nr2)
+my_ci_hash_sort(my_hasher_st *hasher, CHARSET_INFO *ci,
+ const uchar *key, size_t len)
{
- (ci->coll->hash_sort)(ci, key, len, nr1, nr2);
+ (ci->coll->hash_sort)(hasher, ci, key, len);
}
@@ -1580,22 +1647,24 @@ const uint16 *my_cs_contraction2_weight(CHARSET_INFO *cs, my_wc_t wc1,
/* declarations for simple charsets */
extern int my_strnncoll_simple(CHARSET_INFO *, const uchar *, size_t,
- const uchar *, size_t, my_bool);
+ const uchar *, size_t, my_bool*);
extern int my_strnncollsp_simple(CHARSET_INFO *, const uchar *, size_t,
const uchar *, size_t);
-extern void my_hash_sort_simple(CHARSET_INFO *cs,
- const uchar *key, size_t len,
- ulong *nr1, ulong *nr2);
+extern void my_hash_sort_simple(my_hasher_st *hasher,
+ CHARSET_INFO *cs,
+ const uchar *key, size_t len);
+
+extern void my_hash_sort_simple_nopad(my_hasher_st *hasher,
+ CHARSET_INFO *cs,
+ const uchar *key, size_t len);
-extern void my_hash_sort_simple_nopad(CHARSET_INFO *cs,
- const uchar *key, size_t len,
- ulong *nr1, ulong *nr2);
+extern void my_hash_sort_bin(my_hasher_st *hasher, CHARSET_INFO *cs,
+ const uchar *key, size_t len);
-extern void my_hash_sort_bin(CHARSET_INFO *cs,
- const uchar *key, size_t len, ulong *nr1,
- ulong *nr2);
+extern void my_hasher_hash_num(struct my_hasher_st *hasher,
+ const uchar* num, size_t binary_size);
/**
Compare a string to an array of spaces, for PAD SPACE comparison.
@@ -1761,12 +1830,13 @@ int my_wildcmp_mb_bin(CHARSET_INFO *cs,
const char *wildstr,const char *wildend,
int escape, int w_one, int w_many);
-void my_hash_sort_mb_bin(CHARSET_INFO *cs __attribute__((unused)),
- const uchar *key, size_t len,ulong *nr1, ulong *nr2);
+void my_hash_sort_mb_bin(my_hasher_st *hasher,
+ CHARSET_INFO *cs __attribute__((unused)),
+ const uchar *key, size_t len);
-void my_hash_sort_mb_nopad_bin(CHARSET_INFO *cs __attribute__((unused)),
- const uchar *key, size_t len,
- ulong *nr1, ulong *nr2);
+void my_hash_sort_mb_nopad_bin(my_hasher_st *hasher,
+ CHARSET_INFO *cs __attribute__((unused)),
+ const uchar *key, size_t len);
extern my_bool my_parse_charset_xml(MY_CHARSET_LOADER *loader,
@@ -1997,6 +2067,10 @@ class Well_formed_prefix: public Well_formed_prefix_status
:Well_formed_prefix_status(cs, str.str, str.str + str.length, nchars),
m_str(str.str)
{ }
+ Well_formed_prefix(CHARSET_INFO *cs, LEX_CSTRING str)
+ :Well_formed_prefix_status(cs, str.str, str.str + str.length, str.length),
+ m_str(str.str)
+ { }
size_t length() const { return m_source_end_pos - m_str; }
};
diff --git a/include/m_string.h b/include/m_string.h
index 060ab2c21d1f8..04b1a70ad40eb 100644
--- a/include/m_string.h
+++ b/include/m_string.h
@@ -80,12 +80,6 @@ extern const char _dig_vec_lower[];
extern char *strmov_overlapp(char *dest, const char *src);
-#if defined(_lint) || defined(FORCE_INIT_OF_VARS)
-#define LINT_INIT_STRUCT(var) bzero(&var, sizeof(var)) /* No uninitialize-warning */
-#else
-#define LINT_INIT_STRUCT(var)
-#endif
-
/* Prototypes for string functions */
extern void bmove_upp(uchar *dst,const uchar *src,size_t len);
@@ -325,6 +319,9 @@ static inline int safe_strcat(char *dst, size_t dst_size, const char *src)
#ifdef __cplusplus
static inline char *safe_str(char *str)
{ return str ? str : const_cast(""); }
+
+static inline const char *safe_str(const LEX_CSTRING *lcs)
+{ return lcs && lcs->str ? lcs->str : ""; }
#endif
static inline const char *safe_str(const char *str)
diff --git a/include/maria.h b/include/maria.h
index 0fe5d76598f78..68e278f98453b 100644
--- a/include/maria.h
+++ b/include/maria.h
@@ -147,6 +147,8 @@ extern int maria_create(const char *name, enum data_file_type record_type,
uint uniques, MARIA_UNIQUEDEF *uniquedef,
MARIA_CREATE_INFO *create_info, uint flags);
+extern void aria_reset_pagecache_counters();
+
#ifdef __cplusplus
}
#endif
diff --git a/include/my_base.h b/include/my_base.h
index 21f6e1dfcb5e1..8fdd1397ff09d 100644
--- a/include/my_base.h
+++ b/include/my_base.h
@@ -51,6 +51,13 @@
#define HA_OPEN_FOR_DROP (1U << 13) /* Open part of drop */
#define HA_OPEN_GLOBAL_TMP_TABLE (1U << 14) /* TMP table used by repliction */
#define HA_OPEN_SIZE_TRACKING (1U << 15)
+/*
+ This is to signal that the table will not be cached by the caller
+ and the table should be open in read-only mode if the tool requests
+ that
+*/
+#define HA_OPEN_FORCE_MODE (1U << 16) /* Force open mode */
+#define HA_OPEN_DATA_READONLY (1U << 17) /* Use readonly for data */
/*
Allow opening even if table is incompatible as this is for ALTER TABLE which
diff --git a/include/my_bit.h b/include/my_bit.h
index 9179e0a85efdd..64097a750ac24 100644
--- a/include/my_bit.h
+++ b/include/my_bit.h
@@ -221,4 +221,72 @@ static inline uint my_find_first_bit(ulonglong n)
}
C_MODE_END
+/*
+The helper function my_nlz(x) calculates the number of leading zeros
+in the binary representation of the number "x", either using a
+built-in compiler function or a substitute trick based on the use
+of the multiplication operation and a table indexed by the prefix
+of the multiplication result:
+
+Moved to mysys from ha_innodb.cc to be able to use in non-InnoDB code.
+*/
+#ifdef __GNUC__
+#define my_nlz(x) __builtin_clzll(x)
+#elif defined(_MSC_VER) && !defined(_M_CEE_PURE) && \
+ (defined(_M_IX86) || defined(_M_X64) || defined(_M_ARM64))
+#ifndef __INTRIN_H_
+#pragma warning(push, 4)
+#pragma warning(disable: 4255 4668)
+#include
+#pragma warning(pop)
+#endif
+__forceinline unsigned int my_nlz (unsigned long long x)
+{
+#if defined(_M_IX86) || defined(_M_X64)
+ unsigned long n;
+#ifdef _M_X64
+ _BitScanReverse64(&n, x);
+ return (unsigned int) n ^ 63;
+#else
+ unsigned long y = (unsigned long) (x >> 32);
+ unsigned int m = 31;
+ if (y == 0)
+ {
+ y = (unsigned long) x;
+ m = 63;
+ }
+ _BitScanReverse(&n, y);
+ return (unsigned int) n ^ m;
+#endif
+#elif defined(_M_ARM64)
+ return _CountLeadingZeros64(x);
+#endif
+}
+#else
+inline unsigned int my_nlz (unsigned long long x)
+{
+ static unsigned char table [48] = {
+ 32, 6, 5, 0, 4, 12, 0, 20,
+ 15, 3, 11, 0, 0, 18, 25, 31,
+ 8, 14, 2, 0, 10, 0, 0, 0,
+ 0, 0, 0, 21, 0, 0, 19, 26,
+ 7, 0, 13, 0, 16, 1, 22, 27,
+ 9, 0, 17, 23, 28, 24, 29, 30
+ };
+ unsigned int y= (unsigned int) (x >> 32);
+ unsigned int n= 0;
+ if (y == 0) {
+ y= (unsigned int) x;
+ n= 32;
+ }
+ y = y | (y >> 1); // Propagate leftmost 1-bit to the right.
+ y = y | (y >> 2);
+ y = y | (y >> 4);
+ y = y | (y >> 8);
+ y = y & ~(y >> 16);
+ y = y * 0x3EF5D037;
+ return n + table[y >> 26];
+}
+#endif
+
#endif /* MY_BIT_INCLUDED */
diff --git a/include/my_bitmap.h b/include/my_bitmap.h
index d54670653f3ec..0b519e0531174 100644
--- a/include/my_bitmap.h
+++ b/include/my_bitmap.h
@@ -61,8 +61,10 @@ extern my_bool bitmap_exists_intersection(MY_BITMAP **bitmap_array,
extern uint bitmap_set_next(MY_BITMAP *map);
extern uint bitmap_get_first_clear(const MY_BITMAP *map);
extern uint bitmap_get_first_set(const MY_BITMAP *map);
+extern uint bitmap_get_last_set(const MY_BITMAP *map);
extern uint bitmap_bits_set(const MY_BITMAP *map);
extern uint bitmap_get_next_set(const MY_BITMAP *map, uint bitmap_bit);
+extern uint bitmap_get_prev_set(const MY_BITMAP *map, uint bitmap_bit);
extern void my_bitmap_free(MY_BITMAP *map);
extern void bitmap_set_above(MY_BITMAP *map, uint from_byte, uint use_bit);
extern void bitmap_set_prefix(MY_BITMAP *map, uint prefix_size);
diff --git a/include/my_compare.h b/include/my_compare.h
index 44ae7022a2c65..8155d9dfc587c 100644
--- a/include/my_compare.h
+++ b/include/my_compare.h
@@ -140,7 +140,7 @@ static inline int ha_compare_char_varying(CHARSET_INFO *charset_info,
b, b_length);
return charset_info->coll->strnncoll(charset_info,
a, a_length,
- b, b_length, TRUE/*prefix*/);
+ b, b_length, &b_is_prefix);
}
@@ -190,7 +190,7 @@ static inline int ha_compare_char_fixed(CHARSET_INFO *charset_info,
MY_STRNNCOLLSP_NCHARS_EMULATE_TRIMMED_TRAILING_SPACES);
return charset_info->coll->strnncoll(charset_info,
a, a_length,
- b, b_length, TRUE/*prefix*/);
+ b, b_length, &b_is_prefix);
}
@@ -218,10 +218,11 @@ static inline int ha_compare_word_prefix(CHARSET_INFO *charset_info,
const uchar *a, size_t a_length,
const uchar *b, size_t b_length)
{
+ my_bool b_is_prefix;
return charset_info->coll->strnncoll(charset_info,
a, a_length,
b, b_length,
- TRUE/*b_is_prefix*/);
+ &b_is_prefix);
}
diff --git a/include/my_compr_int.h b/include/my_compr_int.h
new file mode 100644
index 0000000000000..5e58ba5366369
--- /dev/null
+++ b/include/my_compr_int.h
@@ -0,0 +1,72 @@
+/*****************************************************************************
+
+Copyright (c) 2024 Kristian Nielsen.
+
+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
+
+*****************************************************************************/
+
+/*
+ Reading and writing of compressed integers.
+
+ Created 2024-10-01 Kristian Nielsen
+*/
+
+#ifndef MY_COMPR_INT_H
+#define MY_COMPR_INT_H
+
+#include "my_bit.h"
+#include
+#include
+
+
+/*
+ Read and write compressed (up to) 64-bit integers.
+
+ A 64-bit number is encoded with 1-9 bytes. The 3 first bits stores a tag
+ that determines the number of bytes used, and the encoding is written in
+ little-endian format as (TAG | (NUMBER << 3)). The tag is the number of
+ bytes used minus 1, except that 7 denotes 9 bytes used (numbers are never
+ encoded with 8 bytes). For example:
+
+ Number Encoding
+ 0 0x00
+ 0x1f 0xf8 (0 | (0x1f << 3))
+ 0x20 0x01 0x01
+ 0xf6 0xb1 0x07
+ 0xd34a 0x52 0x9a 0x06
+ 0x1fffffffffffff 0xfe 0xff 0xff 0xff 0xff 0xff 0xff
+ 0x20000000000000 0x07 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x00
+ 0xffffffffffffffff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0x07
+
+ The main advantage over something like base-128 compression (also called
+ varint) is that the encoding and decoding can happen with just a single
+ conditional jump to determine if one or two 64-bit words are involved (or
+ even no or only well-predicted conditional jump if unaligned reads/writes
+ and buffer padding can be assumed).
+*/
+
+#define COMPR_INT_MAX32 5
+#define COMPR_INT_MAX64 9
+#define COMPR_INT_MAX COMPR_INT_MAX64
+
+/* Write compressed unsigned integer */
+extern unsigned char *compr_int_write(unsigned char *p, uint64_t v);
+/*
+ Read compressed integer.
+ Returns a pair of the value read and the incremented pointer.
+*/
+extern std::pair
+ compr_int_read(const unsigned char *p);
+
+#endif /* MY_COMPR_INT_H */
diff --git a/include/my_dbug.h b/include/my_dbug.h
index 0c0dabef64e18..e1b3d20478987 100644
--- a/include/my_dbug.h
+++ b/include/my_dbug.h
@@ -24,7 +24,7 @@
#ifdef __cplusplus
extern "C" {
#endif
-#if !defined(DBUG_OFF) && !defined(_lint)
+#if !defined(DBUG_OFF)
struct _db_stack_frame_ {
const char *func; /* function name of the previous stack frame */
@@ -75,6 +75,7 @@ extern int (*dbug_sanity)(void);
#define DBUG_PRINT(keyword,arglist) \
do if (_db_pargs_(__LINE__,keyword)) _db_doprnt_ arglist; while(0)
+#define DBUG_DUMP(keyword,a1,a2) _db_dump_(__LINE__,keyword,a1,a2)
#ifdef HAVE_ATTRIBUTE_CLEANUP
#define DBUG_ENTER(a) struct _db_stack_frame_ _db_stack_frame_ __attribute__((cleanup(_db_return_))); \
@@ -94,6 +95,7 @@ extern int (*dbug_sanity)(void);
#define DBUG_RETURN(a1) return(a1)
#define DBUG_VOID_RETURN return
#define DBUG_PRINT(keyword,arglist) do{} while(0)
+#define DBUG_DUMP(keyword,a1,a2) do{} while(0)
#endif
#define DBUG_EXECUTE(keyword,a1) \
@@ -111,7 +113,6 @@ extern int (*dbug_sanity)(void);
#define DBUG_SET_INITIAL(a1) _db_set_init_ (a1)
#define DBUG_PROCESS(a1) _db_process_(a1)
#define DBUG_FILE _db_fp_()
-#define DBUG_DUMP(keyword,a1,a2) _db_dump_(__LINE__,keyword,a1,a2)
#define DBUG_END() _db_end_ ()
#define DBUG_LOCK_FILE _db_lock_file_()
#define DBUG_UNLOCK_FILE _db_unlock_file_()
@@ -206,7 +207,7 @@ extern void (*my_dbug_assert_failed)(const char *assert_expr, const char* file,
#define DBUG_ASSERT(A) do { } while(0)
#define IF_DBUG_ASSERT(A,B) B
#endif /* DBUG_ASSERT_AS_PRINTF */
-#endif /* !defined(DBUG_OFF) && !defined(_lint) */
+#endif /* !defined(DBUG_OFF) */
#ifdef EXTRA_DEBUG
/**
@@ -230,7 +231,7 @@ void debug_sync_point(const char* lock_name, uint lock_timeout);
one should #include . We intentionally avoid including it here to save
compilation time.
*/
-# ifdef DBUG_OFF
+# if defined DBUG_OFF || !defined DBUG_TRACE
# define DBUG_LOG(keyword, v) do {} while (0)
# else
# define DBUG_LOG(keyword, v) do { \
diff --git a/include/my_global.h b/include/my_global.h
index e9b68bd21d0cc..9a6117ad973a4 100644
--- a/include/my_global.h
+++ b/include/my_global.h
@@ -281,10 +281,6 @@ C_MODE_END
#error "Please add -fno-exceptions to CXXFLAGS and reconfigure/recompile"
#endif
-#if defined(_lint) && !defined(lint)
-#define lint
-#endif
-
#ifndef stdin
#include
#endif
@@ -448,22 +444,18 @@ extern "C" int madvise(void *addr, size_t len, int behav);
/*
Suppress uninitialized variable warning without generating code.
*/
-#if defined(__GNUC__)
-/* GCC specific self-initialization which inhibits the warning. */
+#if defined(__GNUC__) && !defined(__clang__)
+/*
+ GCC specific self-initialization which inhibits the warning.
+ clang and static analysis will complain loudly about this.
+*/
#define UNINIT_VAR(x) x= x
-#elif defined(_lint) || defined(FORCE_INIT_OF_VARS)
+#elif defined(FORCE_INIT_OF_VARS)
#define UNINIT_VAR(x) x= 0
#else
#define UNINIT_VAR(x) x
#endif
-/* This is only to be used when resetting variables in a class constructor */
-#if defined(_lint) || defined(FORCE_INIT_OF_VARS)
-#define LINT_INIT(x) x= 0
-#else
-#define LINT_INIT(x)
-#endif
-
#if !defined(HAVE_UINT)
#undef HAVE_UINT
#define HAVE_UINT
@@ -505,7 +497,7 @@ C_MODE_END
#endif
/* We might be forced to turn debug off, if not turned off already */
-#if (defined(FORCE_DBUG_OFF) || defined(_lint)) && !defined(DBUG_OFF)
+#if defined(FORCE_DBUG_OFF) && !defined(DBUG_OFF)
# define DBUG_OFF
# ifdef DBUG_ON
# undef DBUG_ON
@@ -527,7 +519,7 @@ typedef int my_socket; /* File descriptor for sockets */
#endif
/* Type for functions that handles signals */
#define sig_handler RETSIGTYPE
-#if defined(__GNUC__) && !defined(_lint)
+#if defined(__GNUC__)
typedef char pchar; /* Mixed prototypes can take char */
typedef char puchar; /* Mixed prototypes can take char */
typedef char pbool; /* Mixed prototypes can take char */
@@ -689,9 +681,11 @@ typedef SOCKET_SIZE_TYPE size_socket;
/* Typical record cache */
#define RECORD_CACHE_SIZE (uint) (128*1024)
/* Typical key cache */
-#define KEY_CACHE_SIZE (uint) (128L*1024L*1024L)
+#define KEY_CACHE_SIZE (ulong) (128L*1024L*1024L)
/* Default size of a key cache block */
#define KEY_CACHE_BLOCK_SIZE (uint) 1024
+ /* Min resonable key cache size, only for testing */
+#define MIN_KEY_CACHE_SIZE 8192*16L
/* Some things that this system doesn't have */
@@ -1035,7 +1029,7 @@ typedef ulong myf; /* Type of MyFlags in my_funcs */
#define YESNO(X) ((X) ? "yes" : "no")
#define MY_HOW_OFTEN_TO_ALARM 2 /* How often we want info on screen */
-#define MY_HOW_OFTEN_TO_WRITE 10000 /* How often we want info on screen */
+#define MY_HOW_OFTEN_TO_WRITE 100000 /* How often we want info on screen */
#include
diff --git a/include/my_sys.h b/include/my_sys.h
index faf2e7ec5c8ed..3fd85988a7619 100644
--- a/include/my_sys.h
+++ b/include/my_sys.h
@@ -89,6 +89,7 @@ C_MODE_START
#define MY_FREE_ON_ERROR 128U /* my_realloc() ; Free old ptr on error */
#define MY_DONT_OVERWRITE_FILE 2048U /* my_copy: Don't overwrite file */
#define MY_THREADSAFE 2048U /* my_seek(): lock fd mutex */
+#define MY_BUFFER_NO_RESIZE 512U
#define MY_SYNC 4096U /* my_copy(): sync dst file */
#define MY_SYNC_DIR 32768U /* my_create/delete/rename: sync directory */
#define MY_THREAD_SPECIFIC 0x10000U /* my_malloc(): thread specific */
@@ -154,12 +155,15 @@ char *guess_malloc_library();
/* If we have our own safemalloc (for debugging) */
#if defined(SAFEMALLOC)
-void sf_report_leaked_memory(my_thread_id id);
+my_bool sf_report_leaked_memory(my_thread_id id);
int sf_sanity();
+my_bool sf_have_memory_leak();
extern my_thread_id (*sf_malloc_dbug_id)(void);
#define SAFEMALLOC_REPORT_MEMORY(X) if (!sf_leaking_memory) sf_report_leaked_memory(X)
+#define SAFEMALLOC_HAVE_MEMORY_LEAK sf_have_memory_leak()
#else
#define SAFEMALLOC_REPORT_MEMORY(X) do {} while(0)
+#define SAFEMALLOC_HAVE_MEMORY_LEAK 0
#endif
typedef void (*MALLOC_SIZE_CB) (long long size, my_bool is_thread_specific);
@@ -362,6 +366,17 @@ typedef struct st_dynamic_array
myf malloc_flags;
} DYNAMIC_ARRAY;
+typedef struct st_mem_root_dynamic_array
+{
+ MEM_ROOT *mem_root;
+ uchar *buffer;
+ size_t elements, max_element;
+ size_t alloc_increment;
+ size_t size_of_element;
+ PSI_memory_key m_psi_key;
+ myf malloc_flags;
+} MEM_ROOT_DYNAMIC_ARRAY;
+
typedef struct st_dynamic_array_append
{
@@ -1176,6 +1191,74 @@ extern void thd_increment_bytes_sent(void *thd, size_t length);
extern void thd_increment_bytes_received(void *thd, size_t length);
extern void thd_increment_net_big_packet_count(void *thd, size_t length);
+extern int mem_root_dynamic_array_init(MEM_ROOT *mem_root,
+ PSI_memory_key psi_key,
+ MEM_ROOT_DYNAMIC_ARRAY *array,
+ size_t element_size, void *init_buffer,
+ size_t init_alloc,
+ size_t alloc_increment,
+ myf my_flags);
+int mem_root_allocate_dynamic(MEM_ROOT *mem_root,
+ MEM_ROOT_DYNAMIC_ARRAY *array,
+ size_t idx);
+extern void* mem_root_dynamic_array_get_val(MEM_ROOT_DYNAMIC_ARRAY *array, size_t idx);
+extern void mem_root_dynamic_array_reset(MEM_ROOT_DYNAMIC_ARRAY *array);
+extern int mem_root_dynamic_array_resize_not_allowed(MEM_ROOT_DYNAMIC_ARRAY *array);
+extern void mem_root_dynamic_array_copy_values(MEM_ROOT_DYNAMIC_ARRAY *dest, MEM_ROOT_DYNAMIC_ARRAY *src);
+static inline int mem_root_dynamic_array_set_val(MEM_ROOT_DYNAMIC_ARRAY *array,
+ const void *element, size_t idx)
+{
+ DBUG_ASSERT(idx < array->max_element);
+
+ memcpy(array->buffer+(idx * array->size_of_element), element,
+ array->size_of_element);
+ return TRUE;
+}
+static inline int mem_root_dynamic_array_resize_and_set_val(MEM_ROOT_DYNAMIC_ARRAY *array,
+ const void *element, size_t idx)
+{
+ if (array->malloc_flags & MY_BUFFER_NO_RESIZE)
+ return TRUE;
+
+ if (idx >= array->max_element)
+ {
+ if (mem_root_allocate_dynamic(array->mem_root, array, idx))
+ return 1;
+ array->elements++;
+ }
+
+ /*
+ Ensure the array size has increased and the index is
+ now well within the array bounds.
+ */
+ DBUG_ASSERT(idx < array->max_element);
+
+ memcpy(array->buffer+(idx * array->size_of_element), element,
+ array->size_of_element);
+
+ return FALSE;
+}
+
+static inline void* mem_root_dynamic_array_resize_and_get_val(MEM_ROOT_DYNAMIC_ARRAY *array, size_t idx)
+{
+ if (array->malloc_flags & MY_BUFFER_NO_RESIZE)
+ return NULL;
+
+ if (idx >= array->max_element)
+ {
+ if (mem_root_allocate_dynamic(array->mem_root, array, idx))
+ return NULL;
+ }
+
+ /*
+ Ensure the array size has increased and the index is
+ now well within the array bounds.
+ */
+ DBUG_ASSERT(idx < array->max_element);
+
+ return mem_root_dynamic_array_get_val(array, idx);
+}
+
#include
#ifdef HAVE_PSI_INTERFACE
diff --git a/include/my_time.h b/include/my_time.h
index 97fd81e4acc78..08fef1b5c6d9a 100644
--- a/include/my_time.h
+++ b/include/my_time.h
@@ -176,9 +176,18 @@ double TIME_to_double(const MYSQL_TIME *my_time);
int check_time_range(struct st_mysql_time *my_time, uint dec, int *warning);
my_bool check_datetime_range(const MYSQL_TIME *ltime);
+/*
+ Accurate only for the past couple of centuries.
+ Also works with 2 digit year 01-99 (1971-2069)
+ Year 0 is ignored as MariaDB uses year 0 as 'not specifed'. This
+ matches how things how leap year was calculated in calc_days_in_year().
+*/
+
+#define isleap(y) (((y) & 3) == 0 && (((y) % 100) != 0 || (((y) % 400) == 0 && y != 0)))
long calc_daynr(uint year,uint month,uint day);
uint calc_days_in_year(uint year);
+uint calc_days_in_month(uint year, uint month);
uint year_2000_handling(uint year);
void my_init_time(void);
diff --git a/include/myisamchk.h b/include/myisamchk.h
index d1702357250f7..af23a4de7f65b 100644
--- a/include/myisamchk.h
+++ b/include/myisamchk.h
@@ -117,7 +117,7 @@ typedef struct st_handler_check_param
void (*init_repair_thread)(void *);
void *init_repair_thread_arg;
mysql_mutex_t print_msg_mutex;
- my_bool need_print_msg_lock;
+ my_bool need_print_msg_lock, status_reporting;
myf malloc_flags;
} HA_CHECK;
diff --git a/include/mysql.h b/include/mysql.h
index da9371afeca21..b9735a15d8f1b 100644
--- a/include/mysql.h
+++ b/include/mysql.h
@@ -146,6 +146,7 @@ typedef unsigned long long my_ulonglong;
#define ER_SPATIAL_CANT_HAVE_NULL ER_INDEX_CANNOT_HAVE_NULL
#define ER_INNODB_NO_FT_TEMP_TABLE ER_NO_INDEX_ON_TEMPORARY
#define ER_CANT_CHANGE_TX_CHARACTERISTICS ER_CANT_SET_IN_TRANSACTION
+#define ER_VARIABLE_NOT_SETTABLE_IN_SF_OR_TRIGGER ER_VARIABLE_NOT_SETTABLE_IN_SF_OR_TRG
typedef struct st_mysql_rows {
struct st_mysql_rows *next; /* list of rows */
diff --git a/include/mysql/client_plugin.h.pp b/include/mysql/client_plugin.h.pp
index ff35364bd44f3..37a7c5391d58e 100644
--- a/include/mysql/client_plugin.h.pp
+++ b/include/mysql/client_plugin.h.pp
@@ -8,6 +8,7 @@
enum { MYSQL_VIO_INVALID, MYSQL_VIO_TCP, MYSQL_VIO_SOCKET,
MYSQL_VIO_PIPE, MYSQL_VIO_MEMORY } protocol;
int socket;
+ int tls;
} MYSQL_PLUGIN_VIO_INFO;
typedef struct st_plugin_vio
{
diff --git a/include/mysql/plugin.h b/include/mysql/plugin.h
index 2bf5455cdeabc..ef70b36f497fd 100644
--- a/include/mysql/plugin.h
+++ b/include/mysql/plugin.h
@@ -81,7 +81,7 @@ typedef struct st_mysql_xid MYSQL_XID;
*/
/** MySQL plugin interface version */
-#define MYSQL_PLUGIN_INTERFACE_VERSION 0x0104
+#define MYSQL_PLUGIN_INTERFACE_VERSION 0x0105
/** MariaDB plugin interface version */
#define MARIA_PLUGIN_INTERFACE_VERSION 0x010f
diff --git a/include/mysql/plugin_audit.h.pp b/include/mysql/plugin_audit.h.pp
index 93efe24f4a163..2aeb19207de54 100644
--- a/include/mysql/plugin_audit.h.pp
+++ b/include/mysql/plugin_audit.h.pp
@@ -128,26 +128,36 @@
void (*logger_init_mutexes)();
LOGGER_HANDLE* (*open)(const char *path,
unsigned long long size_limit,
- unsigned int rotations);
+ unsigned int rotations, size_t buffer_size);
int (*close)(LOGGER_HANDLE *log);
int (*vprintf)(LOGGER_HANDLE *log, const char *fmt, va_list argptr)
__attribute__((format(printf, 2, 0)));
int (*printf)(LOGGER_HANDLE *log, const char *fmt, ...)
__attribute__((format(printf, 2, 3)));
- int (*write)(LOGGER_HANDLE *log, const char *buffer, size_t size);
+ int (*write)(LOGGER_HANDLE *log, const void *data, size_t size);
int (*rotate)(LOGGER_HANDLE *log);
+ int (*sync)(LOGGER_HANDLE *log);
+ int (*resize_buffer)(LOGGER_HANDLE *log, size_t new_buffer_size);
+ int (*set_filesize_limit)(LOGGER_HANDLE *log,
+ unsigned long long new_file_limit);
+ int (*set_rotations)(LOGGER_HANDLE *log, unsigned int new_rotations);
} *logger_service;
void logger_init_mutexes();
LOGGER_HANDLE *logger_open(const char *path,
unsigned long long size_limit,
- unsigned int rotations);
+ unsigned int rotations, size_t buffer_size);
int logger_close(LOGGER_HANDLE *log);
int logger_vprintf(LOGGER_HANDLE *log, const char *fmt, va_list argptr)
__attribute__((format(printf, 2, 0)));
int logger_printf(LOGGER_HANDLE *log, const char *fmt, ...)
__attribute__((format(printf, 2, 3)));
- int logger_write(LOGGER_HANDLE *log, const char *buffer, size_t size);
+ int logger_write(LOGGER_HANDLE *log, const void *data, size_t size);
int logger_rotate(LOGGER_HANDLE *log);
+ int logger_sync(LOGGER_HANDLE *log);
+ int logger_resize_buffer(LOGGER_HANDLE *log, size_t new_buffer_size);
+ int logger_set_filesize_limit(LOGGER_HANDLE *log,
+ unsigned long long new_file_limit);
+ int logger_set_rotations(LOGGER_HANDLE *log, unsigned int new_rotations);
}
extern "C" {
extern struct my_md5_service_st {
diff --git a/include/mysql/plugin_auth.h b/include/mysql/plugin_auth.h
index 3827db3343106..84dc83b1ad337 100644
--- a/include/mysql/plugin_auth.h
+++ b/include/mysql/plugin_auth.h
@@ -27,7 +27,7 @@
#include
-#define MYSQL_AUTHENTICATION_INTERFACE_VERSION 0x0202
+#define MYSQL_AUTHENTICATION_INTERFACE_VERSION 0x0203
#include
diff --git a/include/mysql/plugin_auth.h.pp b/include/mysql/plugin_auth.h.pp
index 4e9bfcfd10348..08e6b91ed9044 100644
--- a/include/mysql/plugin_auth.h.pp
+++ b/include/mysql/plugin_auth.h.pp
@@ -128,26 +128,36 @@
void (*logger_init_mutexes)();
LOGGER_HANDLE* (*open)(const char *path,
unsigned long long size_limit,
- unsigned int rotations);
+ unsigned int rotations, size_t buffer_size);
int (*close)(LOGGER_HANDLE *log);
int (*vprintf)(LOGGER_HANDLE *log, const char *fmt, va_list argptr)
__attribute__((format(printf, 2, 0)));
int (*printf)(LOGGER_HANDLE *log, const char *fmt, ...)
__attribute__((format(printf, 2, 3)));
- int (*write)(LOGGER_HANDLE *log, const char *buffer, size_t size);
+ int (*write)(LOGGER_HANDLE *log, const void *data, size_t size);
int (*rotate)(LOGGER_HANDLE *log);
+ int (*sync)(LOGGER_HANDLE *log);
+ int (*resize_buffer)(LOGGER_HANDLE *log, size_t new_buffer_size);
+ int (*set_filesize_limit)(LOGGER_HANDLE *log,
+ unsigned long long new_file_limit);
+ int (*set_rotations)(LOGGER_HANDLE *log, unsigned int new_rotations);
} *logger_service;
void logger_init_mutexes();
LOGGER_HANDLE *logger_open(const char *path,
unsigned long long size_limit,
- unsigned int rotations);
+ unsigned int rotations, size_t buffer_size);
int logger_close(LOGGER_HANDLE *log);
int logger_vprintf(LOGGER_HANDLE *log, const char *fmt, va_list argptr)
__attribute__((format(printf, 2, 0)));
int logger_printf(LOGGER_HANDLE *log, const char *fmt, ...)
__attribute__((format(printf, 2, 3)));
- int logger_write(LOGGER_HANDLE *log, const char *buffer, size_t size);
+ int logger_write(LOGGER_HANDLE *log, const void *data, size_t size);
int logger_rotate(LOGGER_HANDLE *log);
+ int logger_sync(LOGGER_HANDLE *log);
+ int logger_resize_buffer(LOGGER_HANDLE *log, size_t new_buffer_size);
+ int logger_set_filesize_limit(LOGGER_HANDLE *log,
+ unsigned long long new_file_limit);
+ int logger_set_rotations(LOGGER_HANDLE *log, unsigned int new_rotations);
}
extern "C" {
extern struct my_md5_service_st {
@@ -707,6 +717,7 @@
enum { MYSQL_VIO_INVALID, MYSQL_VIO_TCP, MYSQL_VIO_SOCKET,
MYSQL_VIO_PIPE, MYSQL_VIO_MEMORY } protocol;
int socket;
+ int tls;
} MYSQL_PLUGIN_VIO_INFO;
typedef struct st_plugin_vio
{
diff --git a/include/mysql/plugin_auth_common.h b/include/mysql/plugin_auth_common.h
index cba0257fa27bb..c57850bb7d31f 100644
--- a/include/mysql/plugin_auth_common.h
+++ b/include/mysql/plugin_auth_common.h
@@ -98,6 +98,7 @@ typedef struct st_plugin_vio_info
#ifdef _WIN32
HANDLE handle; /**< it's set, if the protocol is PIPE or MEMORY */
#endif
+ int tls;
} MYSQL_PLUGIN_VIO_INFO;
/**
diff --git a/include/mysql/plugin_data_type.h.pp b/include/mysql/plugin_data_type.h.pp
index 35641802e0371..41b68c66fab42 100644
--- a/include/mysql/plugin_data_type.h.pp
+++ b/include/mysql/plugin_data_type.h.pp
@@ -128,26 +128,36 @@
void (*logger_init_mutexes)();
LOGGER_HANDLE* (*open)(const char *path,
unsigned long long size_limit,
- unsigned int rotations);
+ unsigned int rotations, size_t buffer_size);
int (*close)(LOGGER_HANDLE *log);
int (*vprintf)(LOGGER_HANDLE *log, const char *fmt, va_list argptr)
__attribute__((format(printf, 2, 0)));
int (*printf)(LOGGER_HANDLE *log, const char *fmt, ...)
__attribute__((format(printf, 2, 3)));
- int (*write)(LOGGER_HANDLE *log, const char *buffer, size_t size);
+ int (*write)(LOGGER_HANDLE *log, const void *data, size_t size);
int (*rotate)(LOGGER_HANDLE *log);
+ int (*sync)(LOGGER_HANDLE *log);
+ int (*resize_buffer)(LOGGER_HANDLE *log, size_t new_buffer_size);
+ int (*set_filesize_limit)(LOGGER_HANDLE *log,
+ unsigned long long new_file_limit);
+ int (*set_rotations)(LOGGER_HANDLE *log, unsigned int new_rotations);
} *logger_service;
void logger_init_mutexes();
LOGGER_HANDLE *logger_open(const char *path,
unsigned long long size_limit,
- unsigned int rotations);
+ unsigned int rotations, size_t buffer_size);
int logger_close(LOGGER_HANDLE *log);
int logger_vprintf(LOGGER_HANDLE *log, const char *fmt, va_list argptr)
__attribute__((format(printf, 2, 0)));
int logger_printf(LOGGER_HANDLE *log, const char *fmt, ...)
__attribute__((format(printf, 2, 3)));
- int logger_write(LOGGER_HANDLE *log, const char *buffer, size_t size);
+ int logger_write(LOGGER_HANDLE *log, const void *data, size_t size);
int logger_rotate(LOGGER_HANDLE *log);
+ int logger_sync(LOGGER_HANDLE *log);
+ int logger_resize_buffer(LOGGER_HANDLE *log, size_t new_buffer_size);
+ int logger_set_filesize_limit(LOGGER_HANDLE *log,
+ unsigned long long new_file_limit);
+ int logger_set_rotations(LOGGER_HANDLE *log, unsigned int new_rotations);
}
extern "C" {
extern struct my_md5_service_st {
diff --git a/include/mysql/plugin_encryption.h.pp b/include/mysql/plugin_encryption.h.pp
index e8b7f7b3e6026..bbe46404fa15d 100644
--- a/include/mysql/plugin_encryption.h.pp
+++ b/include/mysql/plugin_encryption.h.pp
@@ -128,26 +128,36 @@
void (*logger_init_mutexes)();
LOGGER_HANDLE* (*open)(const char *path,
unsigned long long size_limit,
- unsigned int rotations);
+ unsigned int rotations, size_t buffer_size);
int (*close)(LOGGER_HANDLE *log);
int (*vprintf)(LOGGER_HANDLE *log, const char *fmt, va_list argptr)
__attribute__((format(printf, 2, 0)));
int (*printf)(LOGGER_HANDLE *log, const char *fmt, ...)
__attribute__((format(printf, 2, 3)));
- int (*write)(LOGGER_HANDLE *log, const char *buffer, size_t size);
+ int (*write)(LOGGER_HANDLE *log, const void *data, size_t size);
int (*rotate)(LOGGER_HANDLE *log);
+ int (*sync)(LOGGER_HANDLE *log);
+ int (*resize_buffer)(LOGGER_HANDLE *log, size_t new_buffer_size);
+ int (*set_filesize_limit)(LOGGER_HANDLE *log,
+ unsigned long long new_file_limit);
+ int (*set_rotations)(LOGGER_HANDLE *log, unsigned int new_rotations);
} *logger_service;
void logger_init_mutexes();
LOGGER_HANDLE *logger_open(const char *path,
unsigned long long size_limit,
- unsigned int rotations);
+ unsigned int rotations, size_t buffer_size);
int logger_close(LOGGER_HANDLE *log);
int logger_vprintf(LOGGER_HANDLE *log, const char *fmt, va_list argptr)
__attribute__((format(printf, 2, 0)));
int logger_printf(LOGGER_HANDLE *log, const char *fmt, ...)
__attribute__((format(printf, 2, 3)));
- int logger_write(LOGGER_HANDLE *log, const char *buffer, size_t size);
+ int logger_write(LOGGER_HANDLE *log, const void *data, size_t size);
int logger_rotate(LOGGER_HANDLE *log);
+ int logger_sync(LOGGER_HANDLE *log);
+ int logger_resize_buffer(LOGGER_HANDLE *log, size_t new_buffer_size);
+ int logger_set_filesize_limit(LOGGER_HANDLE *log,
+ unsigned long long new_file_limit);
+ int logger_set_rotations(LOGGER_HANDLE *log, unsigned int new_rotations);
}
extern "C" {
extern struct my_md5_service_st {
diff --git a/include/mysql/plugin_ftparser.h.pp b/include/mysql/plugin_ftparser.h.pp
index 4de3fc3a9e624..06de1668e7658 100644
--- a/include/mysql/plugin_ftparser.h.pp
+++ b/include/mysql/plugin_ftparser.h.pp
@@ -128,26 +128,36 @@
void (*logger_init_mutexes)();
LOGGER_HANDLE* (*open)(const char *path,
unsigned long long size_limit,
- unsigned int rotations);
+ unsigned int rotations, size_t buffer_size);
int (*close)(LOGGER_HANDLE *log);
int (*vprintf)(LOGGER_HANDLE *log, const char *fmt, va_list argptr)
__attribute__((format(printf, 2, 0)));
int (*printf)(LOGGER_HANDLE *log, const char *fmt, ...)
__attribute__((format(printf, 2, 3)));
- int (*write)(LOGGER_HANDLE *log, const char *buffer, size_t size);
+ int (*write)(LOGGER_HANDLE *log, const void *data, size_t size);
int (*rotate)(LOGGER_HANDLE *log);
+ int (*sync)(LOGGER_HANDLE *log);
+ int (*resize_buffer)(LOGGER_HANDLE *log, size_t new_buffer_size);
+ int (*set_filesize_limit)(LOGGER_HANDLE *log,
+ unsigned long long new_file_limit);
+ int (*set_rotations)(LOGGER_HANDLE *log, unsigned int new_rotations);
} *logger_service;
void logger_init_mutexes();
LOGGER_HANDLE *logger_open(const char *path,
unsigned long long size_limit,
- unsigned int rotations);
+ unsigned int rotations, size_t buffer_size);
int logger_close(LOGGER_HANDLE *log);
int logger_vprintf(LOGGER_HANDLE *log, const char *fmt, va_list argptr)
__attribute__((format(printf, 2, 0)));
int logger_printf(LOGGER_HANDLE *log, const char *fmt, ...)
__attribute__((format(printf, 2, 3)));
- int logger_write(LOGGER_HANDLE *log, const char *buffer, size_t size);
+ int logger_write(LOGGER_HANDLE *log, const void *data, size_t size);
int logger_rotate(LOGGER_HANDLE *log);
+ int logger_sync(LOGGER_HANDLE *log);
+ int logger_resize_buffer(LOGGER_HANDLE *log, size_t new_buffer_size);
+ int logger_set_filesize_limit(LOGGER_HANDLE *log,
+ unsigned long long new_file_limit);
+ int logger_set_rotations(LOGGER_HANDLE *log, unsigned int new_rotations);
}
extern "C" {
extern struct my_md5_service_st {
diff --git a/include/mysql/plugin_function.h.pp b/include/mysql/plugin_function.h.pp
index 63c63cefa10c7..d56255818bfd2 100644
--- a/include/mysql/plugin_function.h.pp
+++ b/include/mysql/plugin_function.h.pp
@@ -128,26 +128,36 @@
void (*logger_init_mutexes)();
LOGGER_HANDLE* (*open)(const char *path,
unsigned long long size_limit,
- unsigned int rotations);
+ unsigned int rotations, size_t buffer_size);
int (*close)(LOGGER_HANDLE *log);
int (*vprintf)(LOGGER_HANDLE *log, const char *fmt, va_list argptr)
__attribute__((format(printf, 2, 0)));
int (*printf)(LOGGER_HANDLE *log, const char *fmt, ...)
__attribute__((format(printf, 2, 3)));
- int (*write)(LOGGER_HANDLE *log, const char *buffer, size_t size);
+ int (*write)(LOGGER_HANDLE *log, const void *data, size_t size);
int (*rotate)(LOGGER_HANDLE *log);
+ int (*sync)(LOGGER_HANDLE *log);
+ int (*resize_buffer)(LOGGER_HANDLE *log, size_t new_buffer_size);
+ int (*set_filesize_limit)(LOGGER_HANDLE *log,
+ unsigned long long new_file_limit);
+ int (*set_rotations)(LOGGER_HANDLE *log, unsigned int new_rotations);
} *logger_service;
void logger_init_mutexes();
LOGGER_HANDLE *logger_open(const char *path,
unsigned long long size_limit,
- unsigned int rotations);
+ unsigned int rotations, size_t buffer_size);
int logger_close(LOGGER_HANDLE *log);
int logger_vprintf(LOGGER_HANDLE *log, const char *fmt, va_list argptr)
__attribute__((format(printf, 2, 0)));
int logger_printf(LOGGER_HANDLE *log, const char *fmt, ...)
__attribute__((format(printf, 2, 3)));
- int logger_write(LOGGER_HANDLE *log, const char *buffer, size_t size);
+ int logger_write(LOGGER_HANDLE *log, const void *data, size_t size);
int logger_rotate(LOGGER_HANDLE *log);
+ int logger_sync(LOGGER_HANDLE *log);
+ int logger_resize_buffer(LOGGER_HANDLE *log, size_t new_buffer_size);
+ int logger_set_filesize_limit(LOGGER_HANDLE *log,
+ unsigned long long new_file_limit);
+ int logger_set_rotations(LOGGER_HANDLE *log, unsigned int new_rotations);
}
extern "C" {
extern struct my_md5_service_st {
diff --git a/include/mysql/plugin_password_validation.h.pp b/include/mysql/plugin_password_validation.h.pp
index 6cc728a852957..529f50e26894c 100644
--- a/include/mysql/plugin_password_validation.h.pp
+++ b/include/mysql/plugin_password_validation.h.pp
@@ -128,26 +128,36 @@
void (*logger_init_mutexes)();
LOGGER_HANDLE* (*open)(const char *path,
unsigned long long size_limit,
- unsigned int rotations);
+ unsigned int rotations, size_t buffer_size);
int (*close)(LOGGER_HANDLE *log);
int (*vprintf)(LOGGER_HANDLE *log, const char *fmt, va_list argptr)
__attribute__((format(printf, 2, 0)));
int (*printf)(LOGGER_HANDLE *log, const char *fmt, ...)
__attribute__((format(printf, 2, 3)));
- int (*write)(LOGGER_HANDLE *log, const char *buffer, size_t size);
+ int (*write)(LOGGER_HANDLE *log, const void *data, size_t size);
int (*rotate)(LOGGER_HANDLE *log);
+ int (*sync)(LOGGER_HANDLE *log);
+ int (*resize_buffer)(LOGGER_HANDLE *log, size_t new_buffer_size);
+ int (*set_filesize_limit)(LOGGER_HANDLE *log,
+ unsigned long long new_file_limit);
+ int (*set_rotations)(LOGGER_HANDLE *log, unsigned int new_rotations);
} *logger_service;
void logger_init_mutexes();
LOGGER_HANDLE *logger_open(const char *path,
unsigned long long size_limit,
- unsigned int rotations);
+ unsigned int rotations, size_t buffer_size);
int logger_close(LOGGER_HANDLE *log);
int logger_vprintf(LOGGER_HANDLE *log, const char *fmt, va_list argptr)
__attribute__((format(printf, 2, 0)));
int logger_printf(LOGGER_HANDLE *log, const char *fmt, ...)
__attribute__((format(printf, 2, 3)));
- int logger_write(LOGGER_HANDLE *log, const char *buffer, size_t size);
+ int logger_write(LOGGER_HANDLE *log, const void *data, size_t size);
int logger_rotate(LOGGER_HANDLE *log);
+ int logger_sync(LOGGER_HANDLE *log);
+ int logger_resize_buffer(LOGGER_HANDLE *log, size_t new_buffer_size);
+ int logger_set_filesize_limit(LOGGER_HANDLE *log,
+ unsigned long long new_file_limit);
+ int logger_set_rotations(LOGGER_HANDLE *log, unsigned int new_rotations);
}
extern "C" {
extern struct my_md5_service_st {
diff --git a/include/mysql/psi/mysql_file.h b/include/mysql/psi/mysql_file.h
index 096815ed02da1..36d073c32e233 100644
--- a/include/mysql/psi/mysql_file.h
+++ b/include/mysql/psi/mysql_file.h
@@ -775,7 +775,7 @@ inline_mysql_file_stat(
#ifdef HAVE_PSI_FILE_INTERFACE
struct PSI_file_locker *locker;
PSI_file_locker_state state;
- locker= PSI_FILE_CALL(get_thread_file_name_locker)(&state, key, PSI_FILE_STAT, path, &locker);
+ locker= PSI_FILE_CALL(get_thread_file_name_locker)(&state, key, PSI_FILE_STAT, path, NULL);
if (psi_likely(locker != NULL))
{
PSI_FILE_CALL(start_file_open_wait)(locker, src_file, src_line);
@@ -1025,7 +1025,7 @@ inline_mysql_file_create(
struct PSI_file_locker *locker;
PSI_file_locker_state state;
locker= PSI_FILE_CALL(get_thread_file_name_locker)(&state, key, PSI_FILE_CREATE, filename,
- &locker);
+ NULL);
if (psi_likely(locker != NULL))
{
PSI_FILE_CALL(start_file_open_wait)(locker, src_file, src_line);
@@ -1051,7 +1051,7 @@ inline_mysql_file_create_temp(
struct PSI_file_locker *locker;
PSI_file_locker_state state;
locker= PSI_FILE_CALL(get_thread_file_name_locker)
- (&state, key, PSI_FILE_CREATE, NULL, &locker);
+ (&state, key, PSI_FILE_CREATE, NULL, NULL);
if (psi_likely(locker != NULL))
{
PSI_FILE_CALL(start_file_open_wait)(locker, src_file, src_line);
@@ -1078,7 +1078,7 @@ inline_mysql_file_open(
struct PSI_file_locker *locker;
PSI_file_locker_state state;
locker= PSI_FILE_CALL(get_thread_file_name_locker)(&state, key, PSI_FILE_OPEN, filename,
- &locker);
+ NULL);
if (psi_likely(locker != NULL))
{
PSI_FILE_CALL(start_file_open_wait)(locker, src_file, src_line);
@@ -1298,7 +1298,7 @@ inline_mysql_file_delete(
#ifdef HAVE_PSI_FILE_INTERFACE
struct PSI_file_locker *locker;
PSI_file_locker_state state;
- locker= PSI_FILE_CALL(get_thread_file_name_locker)(&state, key, PSI_FILE_DELETE, name, &locker);
+ locker= PSI_FILE_CALL(get_thread_file_name_locker)(&state, key, PSI_FILE_DELETE, name, NULL);
if (psi_likely(locker != NULL))
{
PSI_FILE_CALL(start_file_close_wait)(locker, src_file, src_line);
@@ -1324,7 +1324,7 @@ inline_mysql_file_rename(
struct PSI_file_locker *locker;
PSI_file_locker_state state;
locker= PSI_FILE_CALL(get_thread_file_name_locker)
- (&state, key, PSI_FILE_RENAME, from, &locker);
+ (&state, key, PSI_FILE_RENAME, from, NULL);
if (psi_likely(locker != NULL))
{
PSI_FILE_CALL(start_file_wait)(locker, (size_t) 0, src_file, src_line);
@@ -1352,7 +1352,7 @@ inline_mysql_file_create_with_symlink(
struct PSI_file_locker *locker;
PSI_file_locker_state state;
locker= PSI_FILE_CALL(get_thread_file_name_locker)(&state, key, PSI_FILE_CREATE, filename,
- &locker);
+ NULL);
if (psi_likely(locker != NULL))
{
PSI_FILE_CALL(start_file_open_wait)(locker, src_file, src_line);
@@ -1383,7 +1383,7 @@ inline_mysql_file_delete_with_symlink(
struct PSI_file_locker *locker;
PSI_file_locker_state state;
locker= PSI_FILE_CALL(get_thread_file_name_locker)(&state, key, PSI_FILE_DELETE, fullname,
- &locker);
+ NULL);
if (psi_likely(locker != NULL))
{
PSI_FILE_CALL(start_file_close_wait)(locker, src_file, src_line);
@@ -1410,7 +1410,7 @@ inline_mysql_file_rename_with_symlink(
struct PSI_file_locker *locker;
PSI_file_locker_state state;
locker= PSI_FILE_CALL(get_thread_file_name_locker)
- (&state, key, PSI_FILE_RENAME, from, &locker);
+ (&state, key, PSI_FILE_RENAME, from, NULL);
if (psi_likely(locker != NULL))
{
PSI_FILE_CALL(start_file_wait)(locker, (size_t) 0, src_file, src_line);
diff --git a/include/mysql/service_logger.h b/include/mysql/service_logger.h
index 35c2eb1e3a959..d11dd4291ae32 100644
--- a/include/mysql/service_logger.h
+++ b/include/mysql/service_logger.h
@@ -64,41 +64,58 @@ extern struct logger_service_st {
void (*logger_init_mutexes)();
LOGGER_HANDLE* (*open)(const char *path,
unsigned long long size_limit,
- unsigned int rotations);
+ unsigned int rotations, size_t buffer_size);
int (*close)(LOGGER_HANDLE *log);
int (*vprintf)(LOGGER_HANDLE *log, const char *fmt, va_list argptr)
ATTRIBUTE_FORMAT_FPTR(printf, 2, 0);
int (*printf)(LOGGER_HANDLE *log, const char *fmt, ...)
ATTRIBUTE_FORMAT_FPTR(printf, 2, 3);
- int (*write)(LOGGER_HANDLE *log, const char *buffer, size_t size);
+ int (*write)(LOGGER_HANDLE *log, const void *data, size_t size);
int (*rotate)(LOGGER_HANDLE *log);
+ int (*sync)(LOGGER_HANDLE *log);
+ int (*resize_buffer)(LOGGER_HANDLE *log, size_t new_buffer_size);
+ int (*set_filesize_limit)(LOGGER_HANDLE *log,
+ unsigned long long new_file_limit);
+ int (*set_rotations)(LOGGER_HANDLE *log, unsigned int new_rotations);
} *logger_service;
#ifdef MYSQL_DYNAMIC_PLUGIN
#define logger_init_mutexes logger_service->logger_init_mutexes
-#define logger_open(path, size_limit, rotations) \
- (logger_service->open(path, size_limit, rotations))
+#define logger_open(path, size_limit, rotations, buffer_size) \
+ (logger_service->open(path, size_limit, rotations, buffer_size))
#define logger_close(log) (logger_service->close(log))
#define logger_rotate(log) (logger_service->rotate(log))
#define logger_vprintf(log, fmt, argptr) (logger_service->\
vprintf(log, fmt, argptr))
#define logger_printf (*logger_service->printf)
-#define logger_write(log, buffer, size) \
- (logger_service->write(log, buffer, size))
+#define logger_write(log, data, size) \
+ (logger_service->write(log, data, size))
+#define logger_sync(log) (logger_service->sync(log))
+#define logger_resize_buffer(log, new_buffer_size) \
+ (logger_service->resize_buffer(log, new_buffer_size))
+#define logger_set_filesize_limit(log, new_file_limit) \
+ (logger_service->set_filesize_limit(log, new_file_limit))
+#define logger_set_rotations(log, new_rotations) \
+ (logger_service->set_rotations(log, new_rotations))
#else
void logger_init_mutexes();
LOGGER_HANDLE *logger_open(const char *path,
unsigned long long size_limit,
- unsigned int rotations);
+ unsigned int rotations, size_t buffer_size);
int logger_close(LOGGER_HANDLE *log);
int logger_vprintf(LOGGER_HANDLE *log, const char *fmt, va_list argptr)
ATTRIBUTE_FORMAT(printf, 2, 0);
int logger_printf(LOGGER_HANDLE *log, const char *fmt, ...)
ATTRIBUTE_FORMAT(printf, 2, 3);
- int logger_write(LOGGER_HANDLE *log, const char *buffer, size_t size);
+ int logger_write(LOGGER_HANDLE *log, const void *data, size_t size);
int logger_rotate(LOGGER_HANDLE *log);
+ int logger_sync(LOGGER_HANDLE *log);
+ int logger_resize_buffer(LOGGER_HANDLE *log, size_t new_buffer_size);
+ int logger_set_filesize_limit(LOGGER_HANDLE *log,
+ unsigned long long new_file_limit);
+ int logger_set_rotations(LOGGER_HANDLE *log, unsigned int new_rotations);
#endif
diff --git a/include/mysql/service_wsrep.h b/include/mysql/service_wsrep.h
index cf94364c1cf82..8c001ca147063 100644
--- a/include/mysql/service_wsrep.h
+++ b/include/mysql/service_wsrep.h
@@ -9,6 +9,11 @@ enum Wsrep_service_key_type
WSREP_SERVICE_KEY_EXCLUSIVE
};
+
+/* the bits in the bitmask for disabling temporarily some asserts */
+#define WSREP_ASSERT_INNODB_TRX 1
+
+
#if (defined (MYSQL_DYNAMIC_PLUGIN) && defined(MYSQL_SERVICE_WSREP_DYNAMIC_INCLUDED)) || (!defined(MYSQL_DYNAMIC_PLUGIN) && defined(MYSQL_SERVICE_WSREP_STATIC_INCLUDED))
#else
@@ -64,6 +69,7 @@ extern struct wsrep_service_st {
bool (*wsrep_thd_ignore_table_func)(MYSQL_THD thd);
long long (*wsrep_thd_trx_seqno_func)(const MYSQL_THD thd);
my_bool (*wsrep_thd_is_aborting_func)(const MYSQL_THD thd);
+ my_bool (*wsrep_thd_in_rollback_func)(const THD *thd);
void (*wsrep_set_data_home_dir_func)(const char *data_dir);
my_bool (*wsrep_thd_is_BF_func)(const MYSQL_THD thd, my_bool sync);
my_bool (*wsrep_thd_is_local_func)(const MYSQL_THD thd);
@@ -123,6 +129,7 @@ extern struct wsrep_service_st {
#define wsrep_set_data_home_dir(A) wsrep_service->wsrep_set_data_home_dir_func(A)
#define wsrep_thd_is_BF(T,S) wsrep_service->wsrep_thd_is_BF_func(T,S)
#define wsrep_thd_is_aborting(T) wsrep_service->wsrep_thd_is_aborting_func(T)
+#define wsrep_thd_in_rollback_func(T) wsrep_service->wsrep_thd_in_rollback_func(T)
#define wsrep_thd_is_local(T) wsrep_service->wsrep_thd_is_local_func(T)
#define wsrep_thd_self_abort(T) wsrep_service->wsrep_thd_self_abort_func(T)
#define wsrep_thd_append_key(T,W,N,K) wsrep_service->wsrep_thd_append_key_func(T,W,N,K)
@@ -225,6 +232,8 @@ extern "C" my_bool wsrep_thd_order_before(const MYSQL_THD left, const MYSQL_THD
extern "C" my_bool wsrep_thd_skip_locking(const MYSQL_THD thd);
/* Return true if thd is aborting */
extern "C" my_bool wsrep_thd_is_aborting(const MYSQL_THD thd);
+/* Return true if thd is a WSREP applier rolling back a transaction locally */
+extern "C" my_bool wsrep_thd_in_rollback(const MYSQL_THD thd);
struct wsrep_key;
struct wsrep_key_array;
diff --git a/include/mysql_com.h b/include/mysql_com.h
index b9fae54e7f476..9ef905ab39140 100644
--- a/include/mysql_com.h
+++ b/include/mysql_com.h
@@ -214,7 +214,7 @@ enum enum_indicator_type
#define REFRESH_QUERY_CACHE (1ULL << 16) /* clear the query cache */
#define REFRESH_QUERY_CACHE_FREE (1ULL << 17) /* pack query cache */
-#define REFRESH_DES_KEY_FILE (1ULL << 18)
+/* unused (1ULL << 18) */
#define REFRESH_USER_RESOURCES (1ULL << 19)
#define REFRESH_FOR_EXPORT (1ULL << 20) /* FLUSH TABLES ... FOR EXPORT */
#define REFRESH_SSL (1ULL << 21)
@@ -406,6 +406,13 @@ enum mariadb_field_attr_t
#define SERVER_STATUS_ANSI_QUOTES 32768U
+/*
+ Set for stored procedures if the select query returned a row
+ To check for an empty query, one must also check thd::get_sent_row_count()
+*/
+
+#define SERVER_STATUS_RETURNED_ROW (1U << 16)
+
/**
Server status flags that must be cleared when starting
execution of a new SQL statement.
@@ -422,7 +429,8 @@ enum mariadb_field_attr_t
SERVER_STATUS_DB_DROPPED |\
SERVER_STATUS_CURSOR_EXISTS|\
SERVER_STATUS_LAST_ROW_SENT|\
- SERVER_SESSION_STATE_CHANGED)
+ SERVER_SESSION_STATE_CHANGED|\
+ SERVER_STATUS_RETURNED_ROW)
#define MYSQL_ERRMSG_SIZE 512
#define NET_READ_TIMEOUT 30 /* Timeout on read */
diff --git a/include/rpl_gtid_base.h b/include/rpl_gtid_base.h
new file mode 100644
index 0000000000000..e197c71a4f6ab
--- /dev/null
+++ b/include/rpl_gtid_base.h
@@ -0,0 +1,130 @@
+/* Copyright (c) 2013,2024, Kristian Nielsen and MariaDB Services Ab.
+
+ 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 */
+
+#ifndef RPL_GTID_BASE_H
+#define RPL_GTID_BASE_H
+
+#include "hash.h"
+
+
+/* Definitions for MariaDB global transaction ID (GTID). */
+
+struct slave_connection_state;
+
+struct rpl_gtid
+{
+ uint32 domain_id;
+ uint32 server_id;
+ uint64 seq_no;
+};
+
+/*
+ Binlog state.
+
+ A binlog state records the last GTID written to the binlog for every
+ distinct (domain_id, server_id) pair. Thus, each point in the binlog
+ corresponds to a specific binlog state.
+
+ When starting replication from a specific GTID position, the starting point
+ is identified as the most recent one where the binlog state has no higher
+ seq_no than the GTID position for any (domain_id, server_id) combination.
+
+ We also remember the most recent logged GTID for every domain_id. This is
+ used to know where to start when a master is changed to a slave. As a side
+ effect, it also allows to skip a hash lookup in the very common case of
+ logging a new GTID with same server id as last GTID.
+
+ This base class rpl_binlog_state_base contains just be basic data operations
+ to insert/update GTIDs, and is used eg. from Gtid_index_*.
+*/
+struct rpl_binlog_state_base
+{
+ struct element {
+ uint32 domain_id;
+ HASH hash; /* Containing all server_id for one domain_id */
+ /* The most recent entry in the hash. */
+ rpl_gtid *last_gtid;
+ /* Counter to allocate next seq_no for this domain. */
+ uint64 seq_no_counter;
+
+ int update_element(const rpl_gtid *gtid);
+ };
+
+ /* Mapping from domain_id to collection of elements. */
+ HASH hash;
+ my_bool initialized;
+
+ rpl_binlog_state_base() : initialized(0) {}
+ ~rpl_binlog_state_base();
+ void init();
+ void reset_nolock();
+ void free();
+ bool load_nolock(struct rpl_gtid *list, uint32 count);
+ bool load_nolock(rpl_binlog_state_base *orig_state);
+ int update_nolock(const struct rpl_gtid *gtid);
+ int alloc_element_nolock(const rpl_gtid *gtid);
+ uint32 count_nolock();
+ int get_gtid_list_nolock(rpl_gtid *gtid_list, uint32 list_size);
+ rpl_gtid *find_nolock(uint32 domain_id, uint32 server_id);
+ bool is_before_pos(slave_connection_state *pos);
+
+ /*
+ Inline iterator over a binlog state, most recent GTID comes last for each
+ domain just like get_gtid_list_nolock().
+
+ The ITERATOR_FUNC should have signature bool f(const rpl_gtid *), and
+ return true in case of error (in which case iterate() aborts and also
+ returns true).
+
+ Intended to do custom GTID state processing without requiring the overhead
+ of an intermediate list, and where the extra code generation is justified.
+ */
+ template bool iterate(F iterator_func)
+ {
+ uint32 i, j;
+ ulong outer_records= hash.records;
+
+ for (i= 0; i < outer_records; ++i)
+ {
+ element *e= (element *)my_hash_element(&hash, i);
+ ulong inner_records= e->hash.records;
+ const rpl_gtid *last_gtid= e->last_gtid;
+ if (unlikely(!last_gtid))
+ {
+ DBUG_ASSERT(inner_records==0);
+ continue;
+ }
+ for (j= 0; j <= inner_records; ++j)
+ {
+ const rpl_gtid *gtid;
+ if (j < inner_records)
+ {
+ gtid= (rpl_gtid *)my_hash_element(&e->hash, j);
+ if (gtid == last_gtid)
+ continue;
+ }
+ else
+ gtid= e->last_gtid;
+ if (iterator_func(gtid))
+ return true;
+ }
+ }
+
+ return false; // No error
+ }
+};
+
+
+#endif /* RPL_GTID_BASE_H */
diff --git a/include/service_versions.h b/include/service_versions.h
index 40e668ea84366..45cad4d86ae06 100644
--- a/include/service_versions.h
+++ b/include/service_versions.h
@@ -26,7 +26,7 @@
#define VERSION_base64 0x0100
#define VERSION_encryption 0x0300
#define VERSION_encryption_scheme 0x0100
-#define VERSION_logger 0x0200
+#define VERSION_logger 0x0300
#define VERSION_my_crypt 0x0101
#define VERSION_my_md5 0x0100
#define VERSION_my_print_error 0x0200
diff --git a/include/thr_timer.h b/include/thr_timer.h
index 6bca815480b4a..233a66bc6fa87 100644
--- a/include/thr_timer.h
+++ b/include/thr_timer.h
@@ -24,6 +24,7 @@ extern "C" {
typedef struct st_timer {
struct timespec expire_time;
ulonglong period;
+ ulonglong timeout; /* Timeout value in microseconds */
my_bool expired;
uint index_in_queue;
void (*func)(void*);
diff --git a/include/typelib.h b/include/typelib.h
index 9a8ee802cae59..091e58d04c886 100644
--- a/include/typelib.h
+++ b/include/typelib.h
@@ -25,9 +25,16 @@ typedef struct st_typelib { /* Different types saved here */
const char *name; /* Name of typelib */
const char **type_names;
unsigned int *type_lengths;
+ /*
+ An array of indexes of enum values that are no longer supported and so are
+ hidden. One cannot specify hidden values, an attempt to do so will produce
+ a warning (while an attempt to use a name that was never part of this set
+ will produce an error).
+ */
+ const int *hidden_values;
} TYPELIB;
-#define CREATE_TYPELIB_FOR(X) { (unsigned int)(sizeof(X)/sizeof(X[0])) - 1, "", X, NULL }
+#define CREATE_TYPELIB_FOR(X) { (unsigned int)(sizeof(X)/sizeof(X[0])) - 1, "", X, NULL, NULL }
extern my_ulonglong find_typeset(const char *x, TYPELIB *typelib,
int *error_position);
diff --git a/libmariadb b/libmariadb
index b790c6c149c91..7bb4e6cdf787b 160000
--- a/libmariadb
+++ b/libmariadb
@@ -1 +1 @@
-Subproject commit b790c6c149c9119fb73c416e993af1c7ef256b34
+Subproject commit 7bb4e6cdf787b32907429287a636857e3b31e6a1
diff --git a/libmysqld/CMakeLists.txt b/libmysqld/CMakeLists.txt
index e6f4462ad089a..f59354625b345 100644
--- a/libmysqld/CMakeLists.txt
+++ b/libmysqld/CMakeLists.txt
@@ -57,13 +57,14 @@ SET(SQL_EMBEDDED_SOURCES emb_qcache.cc libmysqld.c lib_sql.cc
../sql/field.cc ../sql/field_conv.cc ../sql/field_comp.cc
../sql/filesort_utils.cc ../sql/sql_digest.cc
../sql/filesort.cc ../sql/grant.cc
- ../sql/gstream.cc ../sql/slave.cc
+ ../sql/gstream.cc
../sql/signal_handler.cc
../sql/handler.cc ../sql/hash_filo.cc ../sql/hostname.cc
../sql/init.cc ../sql/item_buff.cc ../sql/item_cmpfunc.cc
../sql/item.cc ../sql/item_create.cc ../sql/item_func.cc
../sql/item_geofunc.cc ../sql/item_row.cc ../sql/item_strfunc.cc
../sql/item_subselect.cc ../sql/item_sum.cc ../sql/item_timefunc.cc
+ ../sql/item_numconvfunc.cc
../sql/item_xmlfunc.cc ../sql/item_jsonfunc.cc
../sql/json_schema.cc ../sql/json_schema_helper.cc
../sql/key.cc ../sql/lock.cc ../sql/log.cc ../sql/log_cache.cc
@@ -78,7 +79,7 @@ SET(SQL_EMBEDDED_SOURCES emb_qcache.cc libmysqld.c lib_sql.cc
../sql/opt_vcol_substitution.cc
../sql/parse_file.cc ../sql/procedure.cc ../sql/protocol.cc
../sql/records.cc ../sql/repl_failsafe.cc ../sql/rpl_filter.cc
- ../sql/rpl_record.cc ../sql/des_key_file.cc
+ ../sql/rpl_record.cc
../sql/rpl_injector.cc ../sql/set_var.cc ../sql/spatial.cc
../sql/sp_cache.cc ../sql/sp.cc ../sql/sp_head.cc
../sql/sp_pcontext.cc ../sql/sp_rcontext.cc ../sql/sql_acl.cc
@@ -92,6 +93,7 @@ SET(SQL_EMBEDDED_SOURCES emb_qcache.cc libmysqld.c lib_sql.cc
../sql/sql_lex.cc ../sql/keycaches.cc
../sql/sql_list.cc ../sql/sql_load.cc ../sql/sql_locale.cc
../sql/sql_binlog.cc ../sql/sql_manager.cc
+ ../sql/sql_oracle_outer_join.cc
../sql/sql_parse.cc ../sql/sql_bootstrap.cc
../sql/sql_partition.cc ../sql/sql_plugin.cc
../sql/debug_sync.cc ../sql/debug.cc
@@ -135,6 +137,8 @@ SET(SQL_EMBEDDED_SOURCES emb_qcache.cc libmysqld.c lib_sql.cc
../sql/sql_schema.cc
../sql/lex_charset.cc ../sql/charset_collations.cc
../sql/sql_type.cc ../sql/sql_type.h
+ ../sql/sql_type_composite.cc ../sql/item_composite.cc
+ ../sql/sql_type_row.cc
../sql/sql_mode.cc
../sql/sql_type_string.cc
../sql/sql_type_json.cc
@@ -160,6 +164,8 @@ SET(SQL_EMBEDDED_SOURCES emb_qcache.cc libmysqld.c lib_sql.cc
../sql/opt_hints_parser.cc ../sql/opt_hints_parser.h
../sql/scan_char.h
../sql/opt_hints.cc ../sql/opt_hints.h
+ ../sql/opt_trace_ddl_info.cc ../sql/opt_trace_ddl_info.h
+ ../sql/sql_path.cc
${GEN_SOURCES}
${MYSYS_LIBWRAP_SOURCE}
)
diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc
index cf958c4e9a0be..4f1d98293aaa1 100644
--- a/libmysqld/lib_sql.cc
+++ b/libmysqld/lib_sql.cc
@@ -789,9 +789,21 @@ int check_embedded_connection(MYSQL *mysql, const char *db)
sctx->proxy_user[0]= 0;
sctx->master_access= GLOBAL_ACLS; // Full rights
emb_transfer_connect_attrs(mysql);
+
/* Change database if necessary */
- if (!(result= (db && db[0] && mysql_change_db(thd, &db_str, FALSE))))
+ result = 0;
+ if (db && db[0])
+ {
+ result = mysql_change_db(thd, db_str, FALSE);
+ if (!result)
+ {
+ my_free(mysql->db);
+ mysql->db = my_strdup(PSI_NOT_INSTRUMENTED, db, MYF(0));
+ }
+ }
+ if (!result)
my_ok(thd);
+
thd->protocol->end_statement();
emb_read_query_result(mysql);
return result;
diff --git a/man/aria_chk.1 b/man/aria_chk.1
index 435dac75d702a..e9e09fd15b345 100644
--- a/man/aria_chk.1
+++ b/man/aria_chk.1
@@ -241,4 +241,4 @@ Read this file after the global files are read.
.SH "SEE ALSO"
\fBmyisamchk(1)\fR
.PP
-For more information, please refer to the MariaDB Knowledge Base, available online at https://mariadb.com/kb/
+For more information, please refer to the MariaDB Documentation, available online at https://mariadb.com/docs/
diff --git a/man/aria_dump_log.1 b/man/aria_dump_log.1
index 16463fc222da2..86cec5a33b956 100644
--- a/man/aria_dump_log.1
+++ b/man/aria_dump_log.1
@@ -50,6 +50,6 @@ Only read default options from the given file #.
Read this file after the global files are read.
.PP
.SH "SEE ALSO"
-For more information, please refer to the MariaDB Knowledge Base, available online at https://mariadb.com/kb/
+For more information, please refer to the MariaDB Documentation, available online at https://mariadb.com/docs/
.SH AUTHOR
MariaDB Foundation (http://www.mariadb.org/).
diff --git a/man/aria_ftdump.1 b/man/aria_ftdump.1
index 7b5ba5f5211a6..ddbc572167fe8 100644
--- a/man/aria_ftdump.1
+++ b/man/aria_ftdump.1
@@ -25,4 +25,4 @@ Be verbose.
.SH "SEE ALSO"
\fBmyisam_ftdump(1)\fR
.PP
-For more information, please refer to the MariaDB Knowledge Base, available online at https://mariadb.com/kb/
+For more information, please refer to the MariaDB Documentation, available online at https://mariadb.com/docs/
diff --git a/man/aria_pack.1 b/man/aria_pack.1
index 2557507b999a5..0cd34e6756ffc 100644
--- a/man/aria_pack.1
+++ b/man/aria_pack.1
@@ -72,4 +72,4 @@ Read this file after the global files are read.
.SH "SEE ALSO"
\fBmyisampack(1)\fR
.PP
-For more information, please refer to the MariaDB Knowledge Base, available online at https://mariadb.com/kb/
+For more information, please refer to the MariaDB Documentation, available online at https://mariadb.com/docs/
diff --git a/man/aria_read_log.1 b/man/aria_read_log.1
index db42162c48fb1..355573927a826 100644
--- a/man/aria_read_log.1
+++ b/man/aria_read_log.1
@@ -104,4 +104,4 @@ Read this file after the global files are read.
.SH "SEE ALSO"
\fBmyisamlog(1)\fR
.PP
-For more information, please refer to the MariaDB Knowledge Base, available online at https://mariadb.com/kb/
+For more information, please refer to the MariaDB Documentation, available online at https://mariadb.com/docs/
diff --git a/man/comp_err.1 b/man/comp_err.1
index ba8b2635bb44a..2fcf3d505a622 100644
--- a/man/comp_err.1
+++ b/man/comp_err.1
@@ -256,6 +256,6 @@ This documentation is distributed in the hope that it will be useful, but WITHOU
You should have received a copy of the GNU General Public License along with the program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA or see http://www.gnu.org/licenses/.
.sp
.SH "SEE ALSO"
-For more information, please refer to the MariaDB Knowledge Base, available online at https://mariadb.com/kb/
+For more information, please refer to the MariaDB Documentation, available online at https://mariadb.com/docs/
.SH AUTHOR
MariaDB Foundation (http://www.mariadb.org/).
diff --git a/man/galera_recovery.1 b/man/galera_recovery.1
index 7464ff79ccce6..b0199530b15e9 100644
--- a/man/galera_recovery.1
+++ b/man/galera_recovery.1
@@ -13,4 +13,4 @@ galera_recovery \- recover from non\-graceful shutdown
.SH DESCRIPTION
Use: Recover from non\-graceful shutdown\.
.PP
-For more information, please refer to the MariaDB Knowledge Base, available online at https://mariadb.com/kb/
+For more information, please refer to the MariaDB Documentation, available online at https://mariadb.com/docs/
diff --git a/man/innochecksum.1 b/man/innochecksum.1
index 940e059a29dac..c47702a41d953 100644
--- a/man/innochecksum.1
+++ b/man/innochecksum.1
@@ -312,6 +312,6 @@ This documentation is distributed in the hope that it will be useful, but WITHOU
You should have received a copy of the GNU General Public License along with the program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA or see http://www.gnu.org/licenses/.
.sp
.SH "SEE ALSO"
-For more information, please refer to the MariaDB Knowledge Base, available online at https://mariadb.com/kb/
+For more information, please refer to the MariaDB Documentation, available online at https://mariadb.com/docs/
.SH AUTHOR
MariaDB Foundation (http://www.mariadb.org/).
diff --git a/man/mariadb-access.1 b/man/mariadb-access.1
index d0aa39aae1096..f23680c9af40e 100644
--- a/man/mariadb-access.1
+++ b/man/mariadb-access.1
@@ -424,6 +424,6 @@ This documentation is distributed in the hope that it will be useful, but WITHOU
You should have received a copy of the GNU General Public License along with the program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA or see http://www.gnu.org/licenses/.
.sp
.SH "SEE ALSO"
-For more information, please refer to the MariaDB Knowledge Base, available online at https://mariadb.com/kb/
+For more information, please refer to the MariaDB Documentation, available online at https://mariadb.com/docs/
.SH AUTHOR
MariaDB Foundation (http://www.mariadb.org/).
diff --git a/man/mariadb-admin.1 b/man/mariadb-admin.1
index 2f2993aaf9357..b0cbf59a3d52f 100644
--- a/man/mariadb-admin.1
+++ b/man/mariadb-admin.1
@@ -1531,6 +1531,6 @@ This documentation is distributed in the hope that it will be useful, but WITHOU
You should have received a copy of the GNU General Public License along with the program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA or see http://www.gnu.org/licenses/.
.sp
.SH "SEE ALSO"
-For more information, please refer to the MariaDB Knowledge Base, available online at https://mariadb.com/kb/
+For more information, please refer to the MariaDB Documentation, available online at https://mariadb.com/docs/
.SH AUTHOR
MariaDB Foundation (http://www.mariadb.org/).
diff --git a/man/mariadb-backup.1 b/man/mariadb-backup.1
index 531dc24b020b6..3973032929518 100644
--- a/man/mariadb-backup.1
+++ b/man/mariadb-backup.1
@@ -13,4 +13,4 @@ mariabackup \- Backup tool
.SH DESCRIPTION
Use \fBmariabackup \-\-help\fR for details on usage\.
.PP
-For more information, please refer to the MariaDB Knowledge Base, available online at https://mariadb.com/kb/
+For more information, please refer to the MariaDB Documentation, available online at https://mariadb.com/docs/
diff --git a/man/mariadb-binlog.1 b/man/mariadb-binlog.1
index 4a2aaa08f9e57..dcf98a93ae57c 100644
--- a/man/mariadb-binlog.1
+++ b/man/mariadb-binlog.1
@@ -2143,6 +2143,6 @@ Bug#42941
\%http://bugs.mysql.com/bug.php?id=42941
.RE
.SH "SEE ALSO"
-For more information, please refer to the MariaDB Knowledge Base, available online at https://mariadb.com/kb/
+For more information, please refer to the MariaDB Documentation, available online at https://mariadb.com/docs/
.SH AUTHOR
MariaDB Foundation (http://www.mariadb.org/).
diff --git a/man/mariadb-check.1 b/man/mariadb-check.1
index 64902abb1d8cc..2bf4b3053f9e1 100644
--- a/man/mariadb-check.1
+++ b/man/mariadb-check.1
@@ -87,7 +87,7 @@ note : The storage engine for the table doesn't support check
.PP
If
\fBmariadb-check\fR
-is unable to repair a table, see the MariaDB Knowledge Base
+is unable to repair a table, see the MariaDB Documentation
for manual table repair strategies\&. This will be the case, for example, for
InnoDB
tables, which can be checked with
@@ -1152,6 +1152,6 @@ This documentation is distributed in the hope that it will be useful, but WITHOU
You should have received a copy of the GNU General Public License along with the program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA or see http://www.gnu.org/licenses/.
.sp
.SH "SEE ALSO"
-For more information, please refer to the MariaDB Knowledge Base, available online at https://mariadb.com/kb/
+For more information, please refer to the MariaDB Documentation, available online at https://mariadb.com/docs/
.SH AUTHOR
MariaDB Foundation (http://www.mariadb.org/).
diff --git a/man/mariadb-client-test.1 b/man/mariadb-client-test.1
index 0c82aac4902fd..1993c8eeab943 100644
--- a/man/mariadb-client-test.1
+++ b/man/mariadb-client-test.1
@@ -327,6 +327,6 @@ This documentation is distributed in the hope that it will be useful, but WITHOU
You should have received a copy of the GNU General Public License along with the program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA or see http://www.gnu.org/licenses/.
.sp
.SH "SEE ALSO"
-For more information, please refer to the MariaDB Knowledge Base, available online at https://mariadb.com/kb/
+For more information, please refer to the MariaDB Documentation, available online at https://mariadb.com/docs/
.SH AUTHOR
MariaDB Foundation (http://www.mariadb.org/).
diff --git a/man/mariadb-conv.1 b/man/mariadb-conv.1
index a9fa6177207e1..9c75bdab8c233 100644
--- a/man/mariadb-conv.1
+++ b/man/mariadb-conv.1
@@ -99,6 +99,6 @@ This documentation is distributed in the hope that it will be useful, but WITHOU
You should have received a copy of the GNU General Public License along with the program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA or see http://www.gnu.org/licenses/.
.sp
.SH "SEE ALSO"
-For more information, please refer to the MariaDB Knowledge Base, available online at https://mariadb.com/kb/en/mariadb-conv/
+For more information, please refer to the MariaDB Documentation, available online at https://mariadb.com/docs/server/clients-and-utilities/administrative-tools/mariadb-conv
.SH AUTHOR
MariaDB Foundation (http://www.mariadb.org/).
diff --git a/man/mariadb-convert-table-format.1 b/man/mariadb-convert-table-format.1
index 63951400ea7e8..eb1183c97e63d 100644
--- a/man/mariadb-convert-table-format.1
+++ b/man/mariadb-convert-table-format.1
@@ -217,6 +217,6 @@ This documentation is distributed in the hope that it will be useful, but WITHOU
You should have received a copy of the GNU General Public License along with the program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA or see http://www.gnu.org/licenses/.
.sp
.SH "SEE ALSO"
-For more information, please refer to the MariaDB Knowledge Base, available online at https://mariadb.com/kb/
+For more information, please refer to the MariaDB Documentation, available online at https://mariadb.com/docs/
.SH AUTHOR
MariaDB Foundation (http://www.mariadb.org/).
diff --git a/man/mariadb-dump.1 b/man/mariadb-dump.1
index 0c8868a9e13a4..4296e91b79155 100644
--- a/man/mariadb-dump.1
+++ b/man/mariadb-dump.1
@@ -2915,6 +2915,6 @@ This documentation is distributed in the hope that it will be useful, but WITHOU
You should have received a copy of the GNU General Public License along with the program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA or see http://www.gnu.org/licenses/.
.sp
.SH "SEE ALSO"
-For more information, please refer to the MariaDB Knowledge Base, available online at https://mariadb.com/kb/
+For more information, please refer to the MariaDB Documentation, available online at https://mariadb.com/docs/
.SH AUTHOR
MariaDB Foundation (http://www.mariadb.org/).
diff --git a/man/mariadb-dumpslow.1 b/man/mariadb-dumpslow.1
index c1b180c025c84..ce7308d316e17 100644
--- a/man/mariadb-dumpslow.1
+++ b/man/mariadb-dumpslow.1
@@ -327,6 +327,6 @@ This documentation is distributed in the hope that it will be useful, but WITHOU
You should have received a copy of the GNU General Public License along with the program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA or see http://www.gnu.org/licenses/.
.sp
.SH "SEE ALSO"
-For more information, please refer to the MariaDB Knowledge Base, available online at https://mariadb.com/kb/
+For more information, please refer to the MariaDB Documentation, available online at https://mariadb.com/docs/
.SH AUTHOR
MariaDB Foundation (http://www.mariadb.org/).
diff --git a/man/mariadb-find-rows.1 b/man/mariadb-find-rows.1
index 0b07401a84aa4..def7d0baae6ab 100644
--- a/man/mariadb-find-rows.1
+++ b/man/mariadb-find-rows.1
@@ -153,6 +153,6 @@ This documentation is distributed in the hope that it will be useful, but WITHOU
You should have received a copy of the GNU General Public License along with the program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA or see http://www.gnu.org/licenses/.
.sp
.SH "SEE ALSO"
-For more information, please refer to the MariaDB Knowledge Base, available online at https://mariadb.com/kb/
+For more information, please refer to the MariaDB Documentation, available online at https://mariadb.com/docs/
.SH AUTHOR
MariaDB Foundation (http://www.mariadb.org/).
diff --git a/man/mariadb-fix-extensions.1 b/man/mariadb-fix-extensions.1
index 4eaee13777bf0..604686aae8358 100644
--- a/man/mariadb-fix-extensions.1
+++ b/man/mariadb-fix-extensions.1
@@ -65,6 +65,6 @@ This documentation is distributed in the hope that it will be useful, but WITHOU
You should have received a copy of the GNU General Public License along with the program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA or see http://www.gnu.org/licenses/.
.sp
.SH "SEE ALSO"
-For more information, please refer to the MariaDB Knowledge Base, available online at https://mariadb.com/kb/
+For more information, please refer to the MariaDB Documentation, available online at https://mariadb.com/docs/
.SH AUTHOR
MariaDB Foundation (http://www.mariadb.org/).
diff --git a/man/mariadb-hotcopy.1 b/man/mariadb-hotcopy.1
index 24ebb54334468..916fab25b8096 100644
--- a/man/mariadb-hotcopy.1
+++ b/man/mariadb-hotcopy.1
@@ -529,6 +529,6 @@ This documentation is distributed in the hope that it will be useful, but WITHOU
You should have received a copy of the GNU General Public License along with the program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA or see http://www.gnu.org/licenses/.
.sp
.SH "SEE ALSO"
-For more information, please refer to the MariaDB Knowledge Base, available online at https://mariadb.com/kb/
+For more information, please refer to the MariaDB Documentation, available online at https://mariadb.com/docs/
.SH AUTHOR
MariaDB Foundation (http://www.mariadb.org/).
diff --git a/man/mariadb-import.1 b/man/mariadb-import.1
index 2a5e6a784367d..ea997d39aa110 100644
--- a/man/mariadb-import.1
+++ b/man/mariadb-import.1
@@ -903,6 +903,6 @@ This documentation is distributed in the hope that it will be useful, but WITHOU
You should have received a copy of the GNU General Public License along with the program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA or see http://www.gnu.org/licenses/.
.sp
.SH "SEE ALSO"
-For more information, please refer to the MariaDB Knowledge Base, available online at https://mariadb.com/kb/
+For more information, please refer to the MariaDB Documentation, available online at https://mariadb.com/docs/
.SH AUTHOR
MariaDB Foundation (http://www.mariadb.org/).
diff --git a/man/mariadb-install-db.1 b/man/mariadb-install-db.1
index 8f93d080a9c5d..705cd910a6536 100644
--- a/man/mariadb-install-db.1
+++ b/man/mariadb-install-db.1
@@ -393,6 +393,6 @@ This documentation is distributed in the hope that it will be useful, but WITHOU
You should have received a copy of the GNU General Public License along with the program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA or see http://www.gnu.org/licenses/.
.sp
.SH "SEE ALSO"
-For more information, please refer to the MariaDB Knowledge Base, available online at https://mariadb.com/kb/
+For more information, please refer to the MariaDB Documentation, available online at https://mariadb.com/docs/
.SH AUTHOR
MariaDB Foundation (http://www.mariadb.org/).
diff --git a/man/mariadb-plugin.1 b/man/mariadb-plugin.1
index d34bb17c86cd0..6bbbe2fee4778 100644
--- a/man/mariadb-plugin.1
+++ b/man/mariadb-plugin.1
@@ -370,6 +370,6 @@ This documentation is distributed in the hope that it will be useful, but WITHOU
You should have received a copy of the GNU General Public License along with the program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA or see http://www.gnu.org/licenses/.
.sp
.SH "SEE ALSO"
-For more information, please refer to the MariaDB Knowledge Base, available online at https://mariadb.com/kb/
+For more information, please refer to the MariaDB Documentation, available online at https://mariadb.com/docs/
.SH AUTHOR
MariaDB Foundation (http://www.mariadb.org/).
diff --git a/man/mariadb-secure-installation.1 b/man/mariadb-secure-installation.1
index 6248838aedbc2..ab0da2b49096f 100644
--- a/man/mariadb-secure-installation.1
+++ b/man/mariadb-secure-installation.1
@@ -162,6 +162,6 @@ This documentation is distributed in the hope that it will be useful, but WITHOU
You should have received a copy of the GNU General Public License along with the program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA or see http://www.gnu.org/licenses/.
.sp
.SH "SEE ALSO"
-For more information, please refer to the MariaDB Knowledge Base, available online at https://mariadb.com/kb/
+For more information, please refer to the MariaDB Documentation, available online at https://mariadb.com/docs/
.SH AUTHOR
MariaDB Foundation (http://www.mariadb.org/).
diff --git a/man/mariadb-service-convert.1 b/man/mariadb-service-convert.1
index 11597340a81c9..451ddb32e5771 100644
--- a/man/mariadb-service-convert.1
+++ b/man/mariadb-service-convert.1
@@ -17,4 +17,4 @@ a user mariadbd-safe settings in the my.cnf files\.
.PP
Redirect output to user directory like /etc/systemd/system/mariadb.service.d/migrated-from-my.cnf-settings.conf
.PP
-For more information, please refer to the MariaDB Knowledge Base, available online at https://mariadb.com/kb/
+For more information, please refer to the MariaDB Documentation, available online at https://mariadb.com/docs/
diff --git a/man/mariadb-setpermission.1 b/man/mariadb-setpermission.1
index 1cfae88408f19..ec45cf9e66290 100644
--- a/man/mariadb-setpermission.1
+++ b/man/mariadb-setpermission.1
@@ -163,6 +163,6 @@ This documentation is distributed in the hope that it will be useful, but WITHOU
You should have received a copy of the GNU General Public License along with the program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA or see http://www.gnu.org/licenses/.
.sp
.SH "SEE ALSO"
-For more information, please refer to the MariaDB Knowledge Base, available online at https://mariadb.com/kb/
+For more information, please refer to the MariaDB Documentation, available online at https://mariadb.com/docs/
.SH AUTHOR
MariaDB Foundation (http://www.mariadb.org/).
diff --git a/man/mariadb-show.1 b/man/mariadb-show.1
index ce0b6939a605b..ada2fe1082269 100644
--- a/man/mariadb-show.1
+++ b/man/mariadb-show.1
@@ -714,6 +714,6 @@ This documentation is distributed in the hope that it will be useful, but WITHOU
You should have received a copy of the GNU General Public License along with the program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA or see http://www.gnu.org/licenses/.
.sp
.SH "SEE ALSO"
-For more information, please refer to the MariaDB Knowledge Base, available online at https://mariadb.com/kb/
+For more information, please refer to the MariaDB Documentation, available online at https://mariadb.com/docs/
.SH AUTHOR
MariaDB Foundation (http://www.mariadb.org/).
diff --git a/man/mariadb-slap.1 b/man/mariadb-slap.1
index a9ff7e89812f7..85aff76eaf721 100644
--- a/man/mariadb-slap.1
+++ b/man/mariadb-slap.1
@@ -1160,6 +1160,6 @@ This documentation is distributed in the hope that it will be useful, but WITHOU
You should have received a copy of the GNU General Public License along with the program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA or see http://www.gnu.org/licenses/.
.sp
.SH "SEE ALSO"
-For more information, please refer to the MariaDB Knowledge Base, available online at https://mariadb.com/kb/
+For more information, please refer to the MariaDB Documentation, available online at https://mariadb.com/docs/
.SH AUTHOR
MariaDB Foundation (http://www.mariadb.org/).
diff --git a/man/mariadb-test.1 b/man/mariadb-test.1
index a94c9c013b26d..8837f4e5b135f 100644
--- a/man/mariadb-test.1
+++ b/man/mariadb-test.1
@@ -1078,6 +1078,6 @@ This documentation is distributed in the hope that it will be useful, but WITHOU
You should have received a copy of the GNU General Public License along with the program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA or see http://www.gnu.org/licenses/.
.sp
.SH "SEE ALSO"
-For more information, please refer to the MariaDB Knowledge Base, available online at https://mariadb.com/kb/
+For more information, please refer to the MariaDB Documentation, available online at https://mariadb.com/docs/
.SH AUTHOR
MariaDB Foundation (http://www.mariadb.org/).
diff --git a/man/mariadb-tzinfo-to-sql.1 b/man/mariadb-tzinfo-to-sql.1
index 8037b16d8e016..742badf4de291 100644
--- a/man/mariadb-tzinfo-to-sql.1
+++ b/man/mariadb-tzinfo-to-sql.1
@@ -118,6 +118,6 @@ This documentation is distributed in the hope that it will be useful, but WITHOU
You should have received a copy of the GNU General Public License along with the program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA or see http://www.gnu.org/licenses/.
.sp
.SH "SEE ALSO"
-For more information, please refer to the MariaDB Knowledge Base, available online at https://mariadb.com/kb/
+For more information, please refer to the MariaDB Documentation, available online at https://mariadb.com/docs/
.SH AUTHOR
MariaDB Foundation (http://www.mariadb.org/).
diff --git a/man/mariadb-upgrade.1 b/man/mariadb-upgrade.1
index 3c1c0d4ab50fc..d294cadbe8f26 100644
--- a/man/mariadb-upgrade.1
+++ b/man/mariadb-upgrade.1
@@ -723,6 +723,6 @@ This documentation is distributed in the hope that it will be useful, but WITHOU
You should have received a copy of the GNU General Public License along with the program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA or see http://www.gnu.org/licenses/.
.sp
.SH "SEE ALSO"
-For more information, please refer to the MariaDB Knowledge Base, available online at https://mariadb.com/kb/
+For more information, please refer to the MariaDB Documentation, available online at https://mariadb.com/docs/
.SH AUTHOR
MariaDB Foundation (http://www.mariadb.org/).
diff --git a/man/mariadb-waitpid.1 b/man/mariadb-waitpid.1
index f1f70893280b3..70b100111cece 100644
--- a/man/mariadb-waitpid.1
+++ b/man/mariadb-waitpid.1
@@ -122,6 +122,6 @@ This documentation is distributed in the hope that it will be useful, but WITHOU
You should have received a copy of the GNU General Public License along with the program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA or see http://www.gnu.org/licenses/.
.sp
.SH "SEE ALSO"
-For more information, please refer to the MariaDB Knowledge Base, available online at https://mariadb.com/kb/
+For more information, please refer to the MariaDB Documentation, available online at https://mariadb.com/docs/
.SH AUTHOR
MariaDB Foundation (http://www.mariadb.org/).
diff --git a/man/mariadb.1 b/man/mariadb.1
index ea5fd56e9fa91..73307bd4341df 100644
--- a/man/mariadb.1
+++ b/man/mariadb.1
@@ -3130,6 +3130,6 @@ Bug#25946
\%http://bugs.mysql.com/bug.php?id=25946
.RE
.SH "SEE ALSO"
-For more information, please refer to the MariaDB Knowledge Base, available online at https://mariadb.com/kb/
+For more information, please refer to the MariaDB Documentation, available online at https://mariadb.com/docs/
.SH AUTHOR
MariaDB Foundation (http://www.mariadb.org/).
diff --git a/man/mariadb_config.1 b/man/mariadb_config.1
index 6a1c727d6c760..dcb3fb7061365 100644
--- a/man/mariadb_config.1
+++ b/man/mariadb_config.1
@@ -242,6 +242,6 @@ This documentation is distributed in the hope that it will be useful, but WITHOU
You should have received a copy of the GNU General Public License along with the program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA or see http://www.gnu.org/licenses/.
.sp
.SH "SEE ALSO"
-For more information, please refer to the MariaDB Knowledge Base, available online at https://mariadb.com/kb/
+For more information, please refer to the MariaDB Documentation, available online at https://mariadb.com/docs/
.SH AUTHOR
MariaDB Foundation (http://www.mariadb.org/).
diff --git a/man/mariadbd-multi.1 b/man/mariadbd-multi.1
index 398045b061ab0..ce1cc67abb9fa 100644
--- a/man/mariadbd-multi.1
+++ b/man/mariadbd-multi.1
@@ -677,6 +677,6 @@ This documentation is distributed in the hope that it will be useful, but WITHOU
You should have received a copy of the GNU General Public License along with the program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA or see http://www.gnu.org/licenses/.
.sp
.SH "SEE ALSO"
-For more information, please refer to the MariaDB Knowledge Base, available online at https://mariadb.com/kb/
+For more information, please refer to the MariaDB Documentation, available online at https://mariadb.com/docs/
.SH AUTHOR
MariaDB Foundation (http://www.mariadb.org/).
diff --git a/man/mariadbd-safe-helper.1 b/man/mariadbd-safe-helper.1
index cca851e3eb094..6f383b651f3e6 100644
--- a/man/mariadbd-safe-helper.1
+++ b/man/mariadbd-safe-helper.1
@@ -13,4 +13,4 @@ mariadbd-safe-helper \- helper script (mysqld_safe_helper is now a symlink to ma
.SH DESCRIPTION
Use: Helper script\.
.PP
-For more information, please refer to the MariaDB Knowledge Base, available online at https://mariadb.com/kb/
+For more information, please refer to the MariaDB Documentation, available online at https://mariadb.com/docs/
diff --git a/man/mariadbd-safe.1 b/man/mariadbd-safe.1
index dea792495d1f4..e579cb20a16c9 100644
--- a/man/mariadbd-safe.1
+++ b/man/mariadbd-safe.1
@@ -866,6 +866,6 @@ This documentation is distributed in the hope that it will be useful, but WITHOU
You should have received a copy of the GNU General Public License along with the program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA or see http://www.gnu.org/licenses/.
.sp
.SH "SEE ALSO"
-For more information, please refer to the MariaDB Knowledge Base, available online at https://mariadb.com/kb/
+For more information, please refer to the MariaDB Documentation, available online at https://mariadb.com/docs/
.SH AUTHOR
MariaDB Foundation (http://www.mariadb.org/).
diff --git a/man/mariadbd.8 b/man/mariadbd.8
index 3dc9627aef1af..1d794b4c421e5 100644
--- a/man/mariadbd.8
+++ b/man/mariadbd.8
@@ -41,7 +41,7 @@ shell> \fBmariadbd \-\-verbose \-\-help\fR
MariaDB Server also has a set of system variables that affect its operation as it runs\&. System variables can be set at server startup, and many of them can be changed at runtime to effect dynamic server reconfiguration\&. MariaDB Server also has a set of status variables that provide information about its operation\&. You can monitor these status variables to access runtime performance characteristics\&.
.PP
For a full description of MariaDB Server command options, system variables, and status variables, see
-the MariaDB Knowledge Base\&.
+the MariaDB Documentation\&.
.SH "COPYRIGHT"
.br
.PP
@@ -54,6 +54,6 @@ This documentation is distributed in the hope that it will be useful, but WITHOU
You should have received a copy of the GNU General Public License along with the program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA or see http://www.gnu.org/licenses/.
.sp
.SH "SEE ALSO"
-For more information, please refer to the MariaDB Knowledge Base, available online at https://mariadb.com/kb/
+For more information, please refer to the MariaDB Documentation, available online at https://mariadb.com/docs/
.SH AUTHOR
MariaDB Foundation (http://www.mariadb.org/).
diff --git a/man/mbstream.1 b/man/mbstream.1
index 4053f0eca7e37..142f7c8d99c4c 100644
--- a/man/mbstream.1
+++ b/man/mbstream.1
@@ -13,4 +13,4 @@ mbstream \- Serialize/deserialize files in the XBSTREAM format
.SH DESCRIPTION
Use \fBmbstream \-\-help\fR for details on usage\.
.PP
-For more information, please refer to the MariaDB Knowledge Base, available online at https://mariadb.com/kb/
+For more information, please refer to the MariaDB Documentation, available online at https://mariadb.com/docs/
diff --git a/man/msql2mysql.1 b/man/msql2mysql.1
index 0a7a0545c70c5..8c1e033910aa3 100644
--- a/man/msql2mysql.1
+++ b/man/msql2mysql.1
@@ -62,6 +62,6 @@ This documentation is distributed in the hope that it will be useful, but WITHOU
You should have received a copy of the GNU General Public License along with the program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA or see http://www.gnu.org/licenses/.
.sp
.SH "SEE ALSO"
-For more information, please refer to the MariaDB Knowledge Base, available online at https://mariadb.com/kb/
+For more information, please refer to the MariaDB Documentation, available online at https://mariadb.com/docs/
.SH AUTHOR
MariaDB Foundation (http://www.mariadb.org/).
diff --git a/man/my_print_defaults.1 b/man/my_print_defaults.1
index 6e4648069206f..004a9ff6b0261 100644
--- a/man/my_print_defaults.1
+++ b/man/my_print_defaults.1
@@ -228,6 +228,6 @@ This documentation is distributed in the hope that it will be useful, but WITHOU
You should have received a copy of the GNU General Public License along with the program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA or see http://www.gnu.org/licenses/.
.sp
.SH "SEE ALSO"
-For more information, please refer to the MariaDB Knowledge Base, available online at https://mariadb.com/kb/
+For more information, please refer to the MariaDB Documentation, available online at https://mariadb.com/docs/
.SH AUTHOR
MariaDB Foundation (http://www.mariadb.org/).
diff --git a/man/my_safe_process.1 b/man/my_safe_process.1
index 7ac2dbc79cfd3..2af4357b40699 100644
--- a/man/my_safe_process.1
+++ b/man/my_safe_process.1
@@ -13,4 +13,4 @@ my_safe_process \- Utility program that encapsulates process creation, monitorin
.SH DESCRIPTION
Use: safe_process [options to safe_process] -- progname arg1 \.\.\. argn\.
.PP
-For more information, please refer to the MariaDB Knowledge Base, available online at https://mariadb.com/kb/
+For more information, please refer to the MariaDB Documentation, available online at https://mariadb.com/docs/
diff --git a/man/myisam_ftdump.1 b/man/myisam_ftdump.1
index fcca2cb06a116..7389fc65d987f 100644
--- a/man/myisam_ftdump.1
+++ b/man/myisam_ftdump.1
@@ -244,6 +244,6 @@ This documentation is distributed in the hope that it will be useful, but WITHOU
You should have received a copy of the GNU General Public License along with the program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA or see http://www.gnu.org/licenses/.
.sp
.SH "SEE ALSO"
-For more information, please refer to the MariaDB Knowledge Base, available online at https://mariadb.com/kb/
+For more information, please refer to the MariaDB Documentation, available online at https://mariadb.com/docs/
.SH AUTHOR
MariaDB Foundation (http://www.mariadb.org/).
diff --git a/man/myisamchk.1 b/man/myisamchk.1
index 0c46fb83cef31..4270cd4b53a94 100644
--- a/man/myisamchk.1
+++ b/man/myisamchk.1
@@ -2514,6 +2514,6 @@ This documentation is distributed in the hope that it will be useful, but WITHOU
You should have received a copy of the GNU General Public License along with the program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA or see http://www.gnu.org/licenses/.
.sp
.SH "SEE ALSO"
-For more information, please refer to the MariaDB Knowledge Base, available online at https://mariadb.com/kb/
+For more information, please refer to the MariaDB Documentation, available online at https://mariadb.com/docs/
.SH AUTHOR
MariaDB Foundation (http://www.mariadb.org/).
diff --git a/man/myisamlog.1 b/man/myisamlog.1
index cd1caf397f995..7726cbae59c43 100644
--- a/man/myisamlog.1
+++ b/man/myisamlog.1
@@ -227,6 +227,6 @@ This documentation is distributed in the hope that it will be useful, but WITHOU
You should have received a copy of the GNU General Public License along with the program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA or see http://www.gnu.org/licenses/.
.sp
.SH "SEE ALSO"
-For more information, please refer to the MariaDB Knowledge Base, available online at https://mariadb.com/kb/
+For more information, please refer to the MariaDB Documentation, available online at https://mariadb.com/docs/
.SH AUTHOR
MariaDB Foundation (http://www.mariadb.org/).
diff --git a/man/myisampack.1 b/man/myisampack.1
index 11040b9b1576f..b46270d5aedda 100644
--- a/man/myisampack.1
+++ b/man/myisampack.1
@@ -832,6 +832,6 @@ This documentation is distributed in the hope that it will be useful, but WITHOU
You should have received a copy of the GNU General Public License along with the program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA or see http://www.gnu.org/licenses/.
.sp
.SH "SEE ALSO"
-For more information, please refer to the MariaDB Knowledge Base, available online at https://mariadb.com/kb/
+For more information, please refer to the MariaDB Documentation, available online at https://mariadb.com/docs/
.SH AUTHOR
MariaDB Foundation (http://www.mariadb.org/).
diff --git a/man/mysql-stress-test.pl.1 b/man/mysql-stress-test.pl.1
index a7b6e08905814..af1f0ac5b1920 100644
--- a/man/mysql-stress-test.pl.1
+++ b/man/mysql-stress-test.pl.1
@@ -491,6 +491,6 @@ This documentation is distributed in the hope that it will be useful, but WITHOU
You should have received a copy of the GNU General Public License along with the program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA or see http://www.gnu.org/licenses/.
.sp
.SH "SEE ALSO"
-For more information, please refer to the MariaDB Knowledge Base, available online at https://mariadb.com/kb/
+For more information, please refer to the MariaDB Documentation, available online at https://mariadb.com/docs/
.SH AUTHOR
MariaDB Foundation (http://www.mariadb.org/).
diff --git a/man/mysql-test-run.pl.1 b/man/mysql-test-run.pl.1
index 0f6e07d42aaee..4a2fa01899a0e 100644
--- a/man/mysql-test-run.pl.1
+++ b/man/mysql-test-run.pl.1
@@ -2313,6 +2313,6 @@ This documentation is distributed in the hope that it will be useful, but WITHOU
You should have received a copy of the GNU General Public License along with the program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA or see http://www.gnu.org/licenses/.
.sp
.SH "SEE ALSO"
-For more information, please refer to the MariaDB Knowledge Base, available online at https://mariadb.com/kb/
+For more information, please refer to the MariaDB Documentation, available online at https://mariadb.com/docs/
.SH AUTHOR
MariaDB Foundation (http://www.mariadb.org/).
diff --git a/man/mysql.server.1 b/man/mysql.server.1
index 6940f2e3aeadb..4538bfbc248e7 100644
--- a/man/mysql.server.1
+++ b/man/mysql.server.1
@@ -175,6 +175,6 @@ This documentation is distributed in the hope that it will be useful, but WITHOU
You should have received a copy of the GNU General Public License along with the program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA or see http://www.gnu.org/licenses/.
.sp
.SH "SEE ALSO"
-For more information, please refer to the MariaDB Knowledge Base, available online at https://mariadb.com/kb/
+For more information, please refer to the MariaDB Documentation, available online at https://mariadb.com/docs/
.SH AUTHOR
MariaDB Foundation (http://www.mariadb.org/).
diff --git a/man/mytop.1 b/man/mytop.1
index d646df1d459e7..2523b65e34ed1 100644
--- a/man/mytop.1
+++ b/man/mytop.1
@@ -2,6 +2,6 @@
.SH NAME
mytop \- display MariaDB server performance info like 'top'
.SH "SEE ALSO"
-For more information, please refer to the MariaDB Knowledge Base, available online at https://mariadb.com/kb/
+For more information, please refer to the MariaDB Documentation, available online at https://mariadb.com/docs/
.SH AUTHOR
MariaDB Foundation (http://www.mariadb.org/).
diff --git a/man/perror.1 b/man/perror.1
index 772d7ef51f0dd..be87611beae5f 100644
--- a/man/perror.1
+++ b/man/perror.1
@@ -152,6 +152,6 @@ This documentation is distributed in the hope that it will be useful, but WITHOU
You should have received a copy of the GNU General Public License along with the program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA or see http://www.gnu.org/licenses/.
.sp
.SH "SEE ALSO"
-For more information, please refer to the MariaDB Knowledge Base, available online at https://mariadb.com/kb/
+For more information, please refer to the MariaDB Documentation, available online at https://mariadb.com/docs/
.SH AUTHOR
MariaDB Foundation (http://www.mariadb.org/).
diff --git a/man/replace.1 b/man/replace.1
index 03568f5e87a73..829674211a895 100644
--- a/man/replace.1
+++ b/man/replace.1
@@ -162,6 +162,6 @@ This documentation is distributed in the hope that it will be useful, but WITHOU
You should have received a copy of the GNU General Public License along with the program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA or see http://www.gnu.org/licenses/.
.sp
.SH "SEE ALSO"
-For more information, please refer to the MariaDB Knowledge Base, available online at https://mariadb.com/kb/
+For more information, please refer to the MariaDB Documentation, available online at https://mariadb.com/docs/
.SH AUTHOR
MariaDB Foundation (http://www.mariadb.org/).
diff --git a/man/resolve_stack_dump.1 b/man/resolve_stack_dump.1
index 2ee42345e1a32..2a1d1c161f6a9 100644
--- a/man/resolve_stack_dump.1
+++ b/man/resolve_stack_dump.1
@@ -119,6 +119,6 @@ This documentation is distributed in the hope that it will be useful, but WITHOU
You should have received a copy of the GNU General Public License along with the program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA or see http://www.gnu.org/licenses/.
.sp
.SH "SEE ALSO"
-For more information, please refer to the MariaDB Knowledge Base, available online at https://mariadb.com/kb/
+For more information, please refer to the MariaDB Documentation, available online at https://mariadb.com/docs/
.SH AUTHOR
MariaDB Foundation (http://www.mariadb.org/).
diff --git a/man/resolveip.1 b/man/resolveip.1
index f4151af50613f..2c4c66c35a2f5 100644
--- a/man/resolveip.1
+++ b/man/resolveip.1
@@ -101,6 +101,6 @@ This documentation is distributed in the hope that it will be useful, but WITHOU
You should have received a copy of the GNU General Public License along with the program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA or see http://www.gnu.org/licenses/.
.sp
.SH "SEE ALSO"
-For more information, please refer to the MariaDB Knowledge Base, available online at https://mariadb.com/kb/
+For more information, please refer to the MariaDB Documentation, available online at https://mariadb.com/docs/
.SH AUTHOR
MariaDB Foundation (http://www.mariadb.org/).
diff --git a/man/wsrep_sst_backup.1 b/man/wsrep_sst_backup.1
index 2d34f8ce61702..196293ee04d2c 100644
--- a/man/wsrep_sst_backup.1
+++ b/man/wsrep_sst_backup.1
@@ -13,4 +13,4 @@ wsrep_sst_backup \- backup helper script for the MariaDB Galera Cluster
.SH DESCRIPTION
Use: See source code of script\.
.PP
-For more information, please refer to the MariaDB Knowledge Base, available online at https://mariadb.com/kb/
+For more information, please refer to the MariaDB Documentation, available online at https://mariadb.com/docs/
diff --git a/man/wsrep_sst_common.1 b/man/wsrep_sst_common.1
index e9d2745599126..a7e159cb91ad4 100644
--- a/man/wsrep_sst_common.1
+++ b/man/wsrep_sst_common.1
@@ -13,4 +13,4 @@ wsrep_sst_common \- common command line parser to be sourced by other SST script
.SH DESCRIPTION
Use: Common command line parser to be sourced by other SST scripts\.
.PP
-For more information, please refer to the MariaDB Knowledge Base, available online at https://mariadb.com/kb/
+For more information, please refer to the MariaDB Documentation, available online at https://mariadb.com/docs/
diff --git a/man/wsrep_sst_mariabackup.1 b/man/wsrep_sst_mariabackup.1
index 6df4342372de7..aa6b8295c85d2 100644
--- a/man/wsrep_sst_mariabackup.1
+++ b/man/wsrep_sst_mariabackup.1
@@ -13,4 +13,4 @@ wsrep_sst_mariabackup \- mariabackup\-based state snapshot transfer
.SH DESCRIPTION
Use: mariabackup-based state snapshot transfer\.
.PP
-For more information, please refer to the MariaDB Knowledge Base, available online at https://mariadb.com/kb/
+For more information, please refer to the MariaDB Documentation, available online at https://mariadb.com/docs/
diff --git a/man/wsrep_sst_mysqldump.1 b/man/wsrep_sst_mysqldump.1
index cab1ae90bc334..a025be61cde2b 100644
--- a/man/wsrep_sst_mysqldump.1
+++ b/man/wsrep_sst_mysqldump.1
@@ -13,4 +13,4 @@ wsrep_sst_mysqldump \- mysqldump\-based state snapshot transfer
.SH DESCRIPTION
Use: mysqldump-based state snapshot transfer\.
.PP
-For more information, please refer to the MariaDB Knowledge Base, available online at https://mariadb.com/kb/
+For more information, please refer to the MariaDB Documentation, available online at https://mariadb.com/docs/
diff --git a/man/wsrep_sst_rsync.1 b/man/wsrep_sst_rsync.1
index 93ae6086a7efd..684d7aa360918 100644
--- a/man/wsrep_sst_rsync.1
+++ b/man/wsrep_sst_rsync.1
@@ -13,4 +13,4 @@ wsrep_sst_rsync \- rsync-based state snapshot transfer
.SH DESCRIPTION
Use: rsync-based state snapshot transfer\.
.PP
-For more information, please refer to the MariaDB Knowledge Base, available online at https://mariadb.com/kb/
+For more information, please refer to the MariaDB Documentation, available online at https://mariadb.com/docs/
diff --git a/man/wsrep_sst_rsync_wan.1 b/man/wsrep_sst_rsync_wan.1
index 9894bda4231ca..bf5b106d6255c 100644
--- a/man/wsrep_sst_rsync_wan.1
+++ b/man/wsrep_sst_rsync_wan.1
@@ -13,4 +13,4 @@ wsrep_sst_rsync_wan \- rsync_wan (rsync with delta transfers)\-based state snaps
.SH DESCRIPTION
Use: rsync_wan\-based state snapshot transfer\.
.PP
-For more information, please refer to the MariaDB Knowledge Base, available online at https://mariadb.com/kb/
+For more information, please refer to the MariaDB Documentation, available online at https://mariadb.com/docs/
diff --git a/mariadb-plugin-columnstore.install.generated b/mariadb-plugin-columnstore.install.generated
new file mode 100644
index 0000000000000..d987525f2a671
--- /dev/null
+++ b/mariadb-plugin-columnstore.install.generated
@@ -0,0 +1 @@
+#File is generated by ColumnstoreLibrary.cmake, do not edit
diff --git a/mysql-test/collections/buildbot_suites.bat b/mysql-test/collections/buildbot_suites.bat
index b1a4a6f0561fd..053057872bf40 100644
--- a/mysql-test/collections/buildbot_suites.bat
+++ b/mysql-test/collections/buildbot_suites.bat
@@ -8,6 +8,8 @@ plugins,^
mariabackup,^
roles,^
auth_gssapi,^
+mysql_sha2,^
query_response_time,^
+mysql_sha2,^
rocksdb,^
sysschema
diff --git a/mysql-test/include/assert_grep.inc b/mysql-test/include/assert_grep.inc
index c4f184405a297..a6abc35c1953f 100644
--- a/mysql-test/include/assert_grep.inc
+++ b/mysql-test/include/assert_grep.inc
@@ -58,7 +58,7 @@ if ($assert_match == '')
{
if ($assert_count == '')
{
- --die !!!ERROR IN TEST: you must set either $assert_match or $assert_count
+ --die !!!ERROR IN TEST: you must set either \$assert_match or \$assert_count
}
}
if ($assert_match != '')
@@ -66,7 +66,7 @@ if ($assert_match != '')
if ($assert_count != '')
{
--echo assert_text='$assert_text' assert_count='$assert_count'
- --die !!!ERROR IN TEST: you must set only one of $assert_match or $assert_count
+ --die !!!ERROR IN TEST: you must set only one of \$assert_match or \$assert_count
}
}
diff --git a/mysql-test/include/binlog_start_pos.inc b/mysql-test/include/binlog_start_pos.inc
index 5412a7ea75f54..023678f66ff20 100644
--- a/mysql-test/include/binlog_start_pos.inc
+++ b/mysql-test/include/binlog_start_pos.inc
@@ -22,7 +22,7 @@
##############################################################################
--disable_query_log
-set @binlog_start_pos=256 + @@encrypt_binlog * (36 + (@@binlog_checksum != 'NONE') * 4);
+set @binlog_start_pos=257 + @@encrypt_binlog * (36 + (@@binlog_checksum != 'NONE') * 4);
--enable_query_log
let $binlog_start_pos=`select @binlog_start_pos`;
diff --git a/mysql-test/include/check_connect.inc b/mysql-test/include/check_connect.inc
new file mode 100644
index 0000000000000..e34d3a4a0d12c
--- /dev/null
+++ b/mysql-test/include/check_connect.inc
@@ -0,0 +1,6 @@
+# Check if connect engine is loaded and enabled
+
+if (`SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.ENGINES WHERE engine = 'CONNECT' AND support IN ('YES', 'DEFAULT', 'ENABLED')`)
+{
+ --skip Test requires connect engine
+}
diff --git a/mysql-test/include/common-tests.inc b/mysql-test/include/common-tests.inc
index 890309be5e00a..1cc4ae23446eb 100644
--- a/mysql-test/include/common-tests.inc
+++ b/mysql-test/include/common-tests.inc
@@ -1737,17 +1737,21 @@ select t2.companynr,companyname,count(*) from t2,t4 where t2.companynr=t4.compan
select count(*) from t2;
select count(*) from t2 where fld1 < 098024;
# PS does correct pre-zero here. MySQL can't do it as it returns a number.
+--disable_view_protocol
--disable_ps_protocol
select min(fld1) from t2 where fld1>= 098024;
--enable_ps_protocol
+--enable_view_protocol
select max(fld1) from t2 where fld1>= 098024;
select count(*) from t3 where price2=76234234;
select count(*) from t3 where companynr=512 and price2=76234234;
explain select min(fld1),max(fld1),count(*) from t2;
# PS does correct pre-zero here. MySQL can't do it as it returns a number.
+--disable_view_protocol
--disable_ps_protocol
select min(fld1),max(fld1),count(*) from t2;
--enable_ps_protocol
+--enable_view_protocol
select min(t2nr),max(t2nr) from t3 where t2nr=2115 and price2=823742;
select count(*),min(t2nr),max(t2nr) from t3 where name='spates' and companynr=78;
select t2nr,count(*) from t3 where name='gems' group by t2nr limit 20;
diff --git a/mysql-test/include/crash_mysqld.inc b/mysql-test/include/crash_mysqld.inc
index 89bc8ced4161f..6d2e1c522ceee 100644
--- a/mysql-test/include/crash_mysqld.inc
+++ b/mysql-test/include/crash_mysqld.inc
@@ -1,6 +1,6 @@
# Crash mysqld hard and wait until it's restarted
---source include/have_debug_sync.inc
+--source include/have_debug.inc
--source include/not_embedded.inc
# Write file to make mysql-test-run.pl expect crash and restart
diff --git a/mysql-test/include/ctype_numconv.inc b/mysql-test/include/ctype_numconv.inc
index 2546980ddc31d..a7e31d1f56b31 100644
--- a/mysql-test/include/ctype_numconv.inc
+++ b/mysql-test/include/ctype_numconv.inc
@@ -1149,13 +1149,6 @@ insert into t1 values (1.1), (10.1), (100.1), (1000.1), (10000.1);
select hex(concat(a)), a from t1;
drop table t1;
-create table t1 (a year(2));
-insert into t1 values (1);
-select hex(concat(a)) from t1;
-create table t2 as select concat(a) from t1;
-show create table t2;
-drop table t1, t2;
-
create table t1 (a year);
insert into t1 values (1);
select hex(concat(a)) from t1;
@@ -1457,14 +1450,6 @@ select hex(a) from v1;
drop table t1;
drop view v1;
-create table t1 (a year(2));
-insert into t1 values (1);
-create view v1(a) as select concat(a) from t1;
-show columns from v1;
-select hex(a) from v1;
-drop table t1;
-drop view v1;
-
create table t1 (a year);
insert into t1 values (1);
create view v1(a) as select concat(a) from t1;
diff --git a/mysql-test/include/deselect_db.inc b/mysql-test/include/deselect_db.inc
new file mode 100644
index 0000000000000..eda2875245dcc
--- /dev/null
+++ b/mysql-test/include/deselect_db.inc
@@ -0,0 +1,4 @@
+# Drop the current db. This de-selects any db.
+CREATE DATABASE deselect_db;
+USE deselect_db;
+DROP DATABASE deselect_db;
diff --git a/mysql-test/include/galera_variables_ok.inc b/mysql-test/include/galera_variables_ok.inc
index 9bd31bb32b2c9..d10bf1fd36e2f 100644
--- a/mysql-test/include/galera_variables_ok.inc
+++ b/mysql-test/include/galera_variables_ok.inc
@@ -5,7 +5,7 @@ if (!$_galera_variables_delta) {
--let $galera_variables_delta=0
}
---let $galera_variables_expected=`SELECT 51 + $galera_variables_delta`
+--let $galera_variables_expected=`SELECT 50 + $galera_variables_delta`
--let $galera_variables_count=`SELECT COUNT(*) FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME LIKE 'wsrep%'`
diff --git a/mysql-test/include/grant_cache.inc b/mysql-test/include/grant_cache.inc
index 0fccee64372fe..cf85da89826c1 100644
--- a/mysql-test/include/grant_cache.inc
+++ b/mysql-test/include/grant_cache.inc
@@ -181,27 +181,13 @@ show status like "Qcache_not_cached";
# Cleanup
-connection root;
disconnect root;
---source include/wait_until_disconnected.inc
-connection root2;
disconnect root2;
---source include/wait_until_disconnected.inc
-connection user1;
disconnect user1;
---source include/wait_until_disconnected.inc
-connection user2;
disconnect user2;
---source include/wait_until_disconnected.inc
-connection user3;
disconnect user3;
---source include/wait_until_disconnected.inc
-connection user4;
disconnect user4;
---source include/wait_until_disconnected.inc
-connection unkuser;
disconnect unkuser;
---source include/wait_until_disconnected.inc
connection default;
#
diff --git a/mysql-test/include/have_des.inc b/mysql-test/include/have_des.inc
deleted file mode 100644
index 5abdaf6e2aafe..0000000000000
--- a/mysql-test/include/have_des.inc
+++ /dev/null
@@ -1,6 +0,0 @@
-# in the FIPS mode, OpenSSL disables DES and other weak algorithms
-source include/have_ssl_crypto_functs.inc;
-
-if (`select des_encrypt("a", "b") IS NULL`) {
- skip DES is disabled (fips mode?);
-}
diff --git a/mysql-test/include/have_innodb_binlog.inc b/mysql-test/include/have_innodb_binlog.inc
new file mode 100644
index 0000000000000..c841fece70297
--- /dev/null
+++ b/mysql-test/include/have_innodb_binlog.inc
@@ -0,0 +1 @@
+--source include/have_innodb.inc
diff --git a/mysql-test/include/have_innodb_binlog.opt b/mysql-test/include/have_innodb_binlog.opt
new file mode 100644
index 0000000000000..67fff2dd613e7
--- /dev/null
+++ b/mysql-test/include/have_innodb_binlog.opt
@@ -0,0 +1 @@
+--log-bin --binlog-storage-engine=innodb --max-binlog-size=256K
diff --git a/mysql-test/include/icp_debug_kill.inc b/mysql-test/include/icp_debug_kill.inc
index d0ecc8428694c..41c9bf6b4bdd3 100644
--- a/mysql-test/include/icp_debug_kill.inc
+++ b/mysql-test/include/icp_debug_kill.inc
@@ -1,10 +1,5 @@
--source include/have_debug.inc
--source include/have_debug_sync.inc
---source include/count_sessions.inc
-
---disable_warnings
-drop table if exists t0,t1,t2;
---enable_warnings
create table t0(a int primary key);
insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
@@ -46,5 +41,3 @@ set debug_sync='RESET';
disconnect con1;
drop table t0,t1,t2;
---source include/wait_until_count_sessions.inc
-
diff --git a/mysql-test/include/invalidate_sp_cache.inc b/mysql-test/include/invalidate_sp_cache.inc
new file mode 100644
index 0000000000000..d4503a0f28ec1
--- /dev/null
+++ b/mysql-test/include/invalidate_sp_cache.inc
@@ -0,0 +1,11 @@
+--echo # source invalidate_sp_cache.inc
+--disable_query_log
+DELIMITER $$;
+CREATE FUNCTION dummy() RETURNS TEXT
+BEGIN
+ RETURN 'dummy';
+END;
+$$
+DELIMITER ;$$
+DROP FUNCTION dummy;
+--enable_query_log
diff --git a/mysql-test/include/kill_binlog_dump_threads.inc b/mysql-test/include/kill_binlog_dump_threads.inc
index 38e3e2a7c989c..7c8e63fd52912 100644
--- a/mysql-test/include/kill_binlog_dump_threads.inc
+++ b/mysql-test/include/kill_binlog_dump_threads.inc
@@ -35,10 +35,17 @@ let $success= 0;
while ($wait_counter)
{
dec $wait_counter;
- let $_tid= `SELECT id FROM information_schema.processlist WHERE command = 'Binlog Dump' LIMIT 1`;
+ # Tricky here. The binlog dump thread will normally be identified by the
+ # command name "Binlog Dump". But if it was killed, but didn't have time
+ # to react on the killed yet, it will be 'Killed'. It can also be 'Busy'
+ # if the code fails to obtain the LOCK_thd_data mutex.
+ let $_tid= `SELECT IF(command='Binlog Dump', id, -1) FROM information_schema.processlist WHERE command IN ('Binlog Dump', 'Killed', 'Busy') LIMIT 1`;
if ($_tid)
{
- eval KILL QUERY $_tid;
+ if ($_tid > 0) {
+ --error 0,ER_NO_SUCH_THREAD
+ eval KILL CONNECTION $_tid;
+ }
}
if (!$_tid)
{
@@ -55,6 +62,14 @@ if (!$success)
SHOW FULL PROCESSLIST;
--die Timeout while waiting for binlog dump threads to disappear.
}
+# This an attempt to get more info about a rare sporadic test failure where
+# RESET MASTER still fails with ER_BINLOG_IN_USE after this has run.
+--let $sanity_check= `SELECT COUNT(*) FROM information_schema.processlist WHERE command = 'Binlog Dump'`
+if ($sanity_check > 0) {
+ SHOW FULL PROCESSLIST;
+ --echo ERROR: still $sanity_check dump thread(s) found!
+ --die ERROR: still $sanity_check dump thread(s) found
+}
--enable_query_log
diff --git a/mysql-test/include/percona_nonflushing_analyze_debug.inc b/mysql-test/include/percona_nonflushing_analyze_debug.inc
index 8cdf6218609fa..8ecb9e45a2ed4 100644
--- a/mysql-test/include/percona_nonflushing_analyze_debug.inc
+++ b/mysql-test/include/percona_nonflushing_analyze_debug.inc
@@ -4,8 +4,6 @@
# $percona_nonflushing_analyze_table - table to test
#
---source include/count_sessions.inc
-
--connect con1,localhost,root
SET DEBUG_SYNC="handler_rnd_next_end SIGNAL idx_scan_in_progress WAIT_FOR finish_scan";
@@ -31,5 +29,3 @@ reap;
--disconnect con1
--connection default
SET DEBUG_SYNC='reset';
-
---source include/wait_until_count_sessions.inc
diff --git a/mysql-test/include/query_cache.inc b/mysql-test/include/query_cache.inc
index 840118206f502..f6aae89b81f9a 100644
--- a/mysql-test/include/query_cache.inc
+++ b/mysql-test/include/query_cache.inc
@@ -189,7 +189,6 @@ show status like "Qcache_hits";
# Final cleanup
disconnect connection1;
---source include/wait_until_disconnected.inc
connection default;
set @@global.query_cache_size = @save_query_cache_size;
drop table t2;
diff --git a/mysql-test/include/require_openssl_client.inc b/mysql-test/include/require_openssl_client.inc
index 9b19960041b40..463c44fc8b275 100644
--- a/mysql-test/include/require_openssl_client.inc
+++ b/mysql-test/include/require_openssl_client.inc
@@ -1,5 +1,5 @@
if ($CLIENT_TLS_LIBRARY != "OpenSSL") {
if ($CLIENT_TLS_LIBRARY != "LibreSSL") {
- skip "Test requires Connector/C with OpenSSL library";
+ skip Test requires Connector/C with OpenSSL library;
}
}
diff --git a/mysql-test/include/reset_master.inc b/mysql-test/include/reset_master.inc
new file mode 100644
index 0000000000000..b4036ec31be0f
--- /dev/null
+++ b/mysql-test/include/reset_master.inc
@@ -0,0 +1,58 @@
+# ==== Purpose ====
+#
+# Execute a RESET MASTER on the current connection, first terminating any
+# lingering binlog dump threads that might still be sitting idle and would
+# block the RESTE MASTER.
+#
+# Note that any configured IO threads on other servers must be stopped before
+# calling this, as RESET MASTER cannot be run while there is a slave connected.
+#
+#
+# ==== Usage ====
+#
+# [--let $kill_timeout= NUMBER]
+# [--let $reset_master_retries= NUMBER]
+# --source include/reset_master.inc
+#
+# Parameters:
+# $kill_timeout
+# Maximum number of seconds to wait for dump threads to disappear.
+# $reset_master_retries
+# Maximum number of times RESET MASTER can get ER_BINLOG_IN_USE before
+# giving up.
+
+--let $include_filename= reset_master.inc
+--source include/begin_include_file.inc
+
+--disable_query_log
+
+let $_retries= 10;
+if ($reset_master_retries)
+{
+ let $_retries= $reset_master_retries;
+}
+
+let $_success= 0;
+let $_i= 0;
+while ($_i < $_retries)
+{
+ inc $_i;
+ --source include/kill_binlog_dump_threads.inc
+ --let $errno= 0
+ --error 0,ER_BINLOG_IN_USE
+ RESET MASTER;
+ if (!$errno) {
+ let $_success= 1;
+ let $_i = $_retries;
+ }
+}
+if (!$_success)
+{
+ SHOW FULL PROCESSLIST;
+ --die Timeout while trying to remove dump threads and run RESET MASTER.
+}
+
+--enable_query_log
+
+--let $include_filename= reset_master.inc
+--source include/end_include_file.inc
diff --git a/mysql-test/include/reset_master_slave.inc b/mysql-test/include/reset_master_slave.inc
index af66da2bb8bfb..a468ee873be39 100644
--- a/mysql-test/include/reset_master_slave.inc
+++ b/mysql-test/include/reset_master_slave.inc
@@ -21,6 +21,7 @@ while ($con_name != 'No such row')
--let $con_name = query_get_value(show all slaves status, Connection_name, 1)
}
+--source include/kill_binlog_dump_threads.inc
--error 0,ER_FLUSH_MASTER_BINLOG_CLOSED
reset master;
set global gtid_slave_pos='';
diff --git a/mysql-test/include/rowid_filter_debug_kill.inc b/mysql-test/include/rowid_filter_debug_kill.inc
index 5c3ae214f02c6..8e90e8f728616 100644
--- a/mysql-test/include/rowid_filter_debug_kill.inc
+++ b/mysql-test/include/rowid_filter_debug_kill.inc
@@ -1,7 +1,6 @@
--source include/have_debug.inc
--source include/have_debug_sync.inc
--source include/have_sequence.inc
---source include/count_sessions.inc
--source include/have_sequence.inc
--source include/no_valgrind_without_big.inc
@@ -80,4 +79,3 @@ set debug_sync='RESET';
drop table t2,t3;
---source include/wait_until_count_sessions.inc
diff --git a/mysql-test/include/rpl_clone_slave_using_mariadb-backup.inc b/mysql-test/include/rpl_clone_slave_using_mariadb-backup.inc
index b46da97cafa28..284561d7f564b 100644
--- a/mysql-test/include/rpl_clone_slave_using_mariadb-backup.inc
+++ b/mysql-test/include/rpl_clone_slave_using_mariadb-backup.inc
@@ -293,6 +293,7 @@ if ($cnf == "galera2_to_mariadb")
--connection master
set global wsrep_on=OFF;
+ --source include/kill_binlog_dump_threads.inc
RESET MASTER;
set global wsrep_on=ON;
}
diff --git a/mysql-test/include/rpl_heartbeat.inc b/mysql-test/include/rpl_heartbeat.inc
new file mode 100644
index 0000000000000..248d5652e7874
--- /dev/null
+++ b/mysql-test/include/rpl_heartbeat.inc
@@ -0,0 +1,124 @@
+# Testing master to slave heartbeat protocol
+# Shared between rpl.rpl_heartbeat and binlog_in_engine.rpl_heartbeat.
+#
+# Including:
+# - no rotation of relay log if heartbeat is less that slave_net_timeout
+# - SHOW STATUS like 'Slave_received_heartbeats' action
+# - SHOW STATUS like 'Slave_heartbeat_period' report
+#
+# `rpl.rpl_heartbeat_basic` tests the user interface, grammar, range,
+# and warnings about unreasonable values for the heartbeat period.
+
+connection slave;
+-- source include/stop_slave.inc
+
+connection master;
+--source include/kill_binlog_dump_threads.inc
+reset master;
+
+connection slave;
+set @restore_slave_net_timeout= @@global.slave_net_timeout;
+--disable_warnings
+set @@global.slave_net_timeout= 10;
+--enable_warnings
+
+--enable_prepare_warnings
+#
+# A warning if slave_net_timeout is set to less than the current HB period
+#
+set @@global.slave_net_timeout= 5;
+--replace_result $MASTER_MYPORT MASTER_PORT
+eval change master to master_host='127.0.0.1',master_port=$MASTER_MYPORT, master_user='root', master_heartbeat_period= 4;
+--query_vertical show status like 'Slave_heartbeat_period';
+set @@global.slave_net_timeout= 3 /* must be a warning */;
+
+reset slave;
+
+
+###
+### checking no rotation
+###
+
+connection master;
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+#
+# Even though master_heartbeat_period= 0.5 is 20 times less than
+# @@global.slave_net_timeout= 10 in some circumstances master will
+# not be able to send any heartbeat during the slave's net timeout
+# and slave's relay log will rotate.
+# The probability for such a scenario is pretty small so the following
+# part is almost deterministic.
+#
+
+connection slave;
+set @@global.slave_net_timeout= 10;
+--replace_result $MASTER_MYPORT MASTER_PORT
+# no error this time but rather a warning
+eval change master to master_host='127.0.0.1',master_port=$MASTER_MYPORT, master_user='root', master_ssl_verify_server_cert=0, master_heartbeat_period= 0.5;
+--query_vertical show status like 'Slave_heartbeat_period';
+
+start slave;
+
+connection master;
+create table t1 (f1 int);
+
+connection master;
+--source include/save_master_gtid.inc
+connection slave;
+--source include/sync_with_master_gtid.inc
+let $slave_param= Relay_Log_File;
+let $slave_param_value= query_get_value(SHOW SLAVE STATUS, Relay_Log_File, 1);
+
+# there is an explicit sleep lasting longer than slave_net_timeout
+# to ensure that nothing will come to slave from master for that period.
+# That would cause reconnecting and relaylog rotation w/o the fix i.e
+# without a heartbeat received.
+
+real_sleep 15;
+
+# check (compare with the previous show's results) that no rotation happened
+source include/check_slave_param.inc;
+
+###
+### SHOW STATUS like 'Slave_heartbeat_period' and 'Slave_received_heartbeats'
+###
+
+--query_vertical show status like 'Slave_heartbeat_period';
+
+#
+# proof that there has been received at least one heartbeat;
+# The exact number of received heartbeat is an indeterministic value
+# and therefore it's not recorded into results.
+#
+
+let $slave_wait_param_counter= 300;
+let $slave_value= query_get_value("SHOW STATUS like 'Slave_received_heartbeats'", Value, 1);
+# Checking the fact that at least one heartbeat is received
+while (!$slave_value)
+{
+ dec $slave_wait_param_counter;
+ if (!$slave_wait_param_counter)
+ {
+ --echo ERROR: failed while waiting for slave parameter $slave_param: $slave_param_value
+ query_vertical show slave status;
+ SHOW STATUS like 'Slave_received_heartbeats';
+ exit;
+ }
+ sleep 0.1;
+ let $slave_value= query_get_value("SHOW STATUS like 'Slave_received_heartbeats'", Value, 1);
+}
+--echo A heartbeat has been received by the slave
+# cleanup
+
+connection master;
+drop table t1;
+
+connection master;
+--source include/save_master_gtid.inc
+connection slave;
+--source include/sync_with_master_gtid.inc
+set @@global.slave_net_timeout= @restore_slave_net_timeout;
+
+--disable_prepare_warnings
diff --git a/mysql-test/include/rpl_init.inc b/mysql-test/include/rpl_init.inc
index 26ce4e1b57fd8..671943340b35a 100644
--- a/mysql-test/include/rpl_init.inc
+++ b/mysql-test/include/rpl_init.inc
@@ -162,6 +162,7 @@ while ($_rpl_server)
USE test;
if (!$rpl_skip_reset_master_and_slave)
{
+ --source include/kill_binlog_dump_threads.inc
if (!$rpl_server_skip_log_bin)
{
--error 0
diff --git a/mysql-test/include/rpl_ip_mix.inc b/mysql-test/include/rpl_ip_mix.inc
index d547d77a3ccb1..01db8b4d77d8b 100644
--- a/mysql-test/include/rpl_ip_mix.inc
+++ b/mysql-test/include/rpl_ip_mix.inc
@@ -1,6 +1,7 @@
connect (master,$IPv6,root,,test,$MASTER_MYPORT);
connect (slave,127.0.0.1,root,,test,$SLAVE_MYPORT);
connection master;
+--source include/kill_binlog_dump_threads.inc
reset master;
source include/show_master_status.inc;
save_master_pos;
diff --git a/mysql-test/include/rpl_ipv6.inc b/mysql-test/include/rpl_ipv6.inc
index 69f282e22d98f..762e51a82e987 100644
--- a/mysql-test/include/rpl_ipv6.inc
+++ b/mysql-test/include/rpl_ipv6.inc
@@ -1,5 +1,6 @@
connect (master,$IPv6,root,,test,$MASTER_MYPORT);
connect (slave,$IPv6,root,,test,$SLAVE_MYPORT);
+--source include/kill_binlog_dump_threads.inc
connection master;
reset master;
source include/show_master_status.inc;
diff --git a/mysql-test/include/rpl_multi_engine2.inc b/mysql-test/include/rpl_multi_engine2.inc
index 24154220cb098..e7cd7ef38d318 100644
--- a/mysql-test/include/rpl_multi_engine2.inc
+++ b/mysql-test/include/rpl_multi_engine2.inc
@@ -9,6 +9,7 @@ STOP SLAVE;
RESET SLAVE;
connection master;
+--source include/kill_binlog_dump_threads.inc
RESET MASTER;
connection slave;
diff --git a/mysql-test/include/rpl_parallel_temptable.inc b/mysql-test/include/rpl_parallel_temptable.inc
new file mode 100644
index 0000000000000..28ff0a408eb07
--- /dev/null
+++ b/mysql-test/include/rpl_parallel_temptable.inc
@@ -0,0 +1,302 @@
+--echo *** MDEV-6321: close_temporary_tables() in format description event not serialised correctly ***
+
+--connection server_2
+SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=5;
+--source include/start_slave.inc
+
+--connection server_1
+CREATE TABLE t1 (a INT PRIMARY KEY, b VARCHAR(100) CHARACTER SET utf8);
+--source include/save_master_gtid.inc
+
+--connection server_2
+--source include/sync_with_master_gtid.inc
+--source include/stop_slave.inc
+
+
+--connection server_1
+SET gtid_domain_id= 1;
+INSERT INTO t1 VALUES (1, 0);
+
+CREATE TEMPORARY TABLE t2 (a int);
+
+--connection default
+SET gtid_domain_id= 2;
+CREATE TEMPORARY TABLE t3 (a INT PRIMARY KEY);
+CREATE TEMPORARY TABLE t4 (a int);
+INSERT INTO t3 VALUES (100);
+INSERT INTO t4 SELECT a+1 FROM t3;
+
+--connection server_1
+INSERT INTO t2 VALUES (2), (4), (6), (8), (10), (12), (14), (16), (18), (20);
+INSERT INTO t2 VALUES (3), (6), (9), (12), (15), (18);
+INSERT INTO t2 VALUES (4), (8), (12), (16), (20);
+
+--connection default
+INSERT INTO t3 SELECT a+2 FROM t4;
+INSERT INTO t4 SELECT a+4 FROM t3;
+
+--connection server_1
+INSERT INTO t2 VALUES (5), (10), (15), (20);
+INSERT INTO t2 VALUES (6), (12), (18);
+INSERT INTO t2 VALUES (7), (14);
+INSERT INTO t2 VALUES (8), (16);
+INSERT INTO t2 VALUES (9), (18);
+INSERT INTO t2 VALUES (10), (20);
+
+--connection default
+INSERT INTO t3 SELECT a+8 FROM t4;
+INSERT INTO t4 SELECT a+16 FROM t3;
+
+--connection server_1
+INSERT INTO t2 VALUES (11);
+INSERT INTO t2 VALUES (12);
+INSERT INTO t2 VALUES (13);
+
+--connection default
+INSERT INTO t3 SELECT a+32 FROM t4;
+
+--connection server_1
+INSERT INTO t2 VALUES (14);
+INSERT INTO t2 VALUES (15);
+INSERT INTO t2 VALUES (16);
+
+--connection default
+INSERT INTO t4 SELECT a+64 FROM t3;
+
+--connection server_1
+INSERT INTO t2 VALUES (17);
+INSERT INTO t2 VALUES (18);
+INSERT INTO t2 VALUES (19);
+
+--connection default
+INSERT INTO t3 SELECT a+128 FROM t4;
+
+--connection server_1
+INSERT INTO t2 VALUES (20);
+
+--connection default
+INSERT INTO t1 SELECT a, a MOD 7 FROM t3;
+INSERT INTO t1 SELECT a, a MOD 7 FROM t4;
+
+--connection server_1
+INSERT INTO t1 SELECT a, COUNT(*) FROM t2 GROUP BY a;
+
+# Crash the master server, so that temporary tables are implicitly dropped.
+--write_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+wait
+EOF
+
+FLUSH TABLES;
+SET SESSION debug_dbug="+d,crash_dispatch_command_before";
+--error 2006,2013
+SELECT 1;
+
+--source include/wait_until_disconnected.inc
+--connection default
+--source include/wait_until_disconnected.inc
+
+--append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+restart
+EOF
+
+--connection default
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+
+--connection server_1
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+
+INSERT INTO t1 VALUES (0, 1);
+--source include/save_master_gtid.inc
+
+--connection server_2
+# Start the slave replicating the events.
+# The bug was that the format description event written after the crash could
+# be fetched ahead of the execution of the temporary table events and executed
+# out-of-band. This would cause drop of all temporary tables and thus failure
+# for execution of remaining events.
+
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+
+SELECT * FROM t1 WHERE a <= 20 ORDER BY a;
+SELECT COUNT(*) FROM t1 WHERE a BETWEEN 100+0 AND 100+256;
+SHOW STATUS LIKE 'Slave_open_temp_tables';
+
+
+--echo *** Test that if master logged partial event group before crash, we finish that group correctly before executing format description event ***
+
+--source include/stop_slave.inc
+
+--connection server_1
+CALL mtr.add_suppression("Statement accesses nontransactional table as well as transactional or temporary table, and writes to any of them");
+SET gtid_domain_id= 1;
+DELETE FROM t1;
+ALTER TABLE t1 ENGINE=InnoDB;
+CREATE TEMPORARY TABLE t2 (a INT PRIMARY KEY);
+INSERT INTO t2 VALUES (1);
+INSERT INTO t2 VALUES (2);
+
+--connection default
+SET gtid_domain_id= 2;
+CREATE TEMPORARY TABLE t3 (a INT PRIMARY KEY);
+INSERT INTO t3 VALUES (10);
+INSERT INTO t3 VALUES (20);
+
+--connection server_1
+INSERT INTO t1 SELECT a, 'server_1' FROM t2;
+
+--connection default
+INSERT INTO t1 SELECT a, 'default' FROM t3;
+
+--connection server_1
+INSERT INTO t1 SELECT a+2, '+server_1' FROM t2;
+
+# Crash the master server in the middle of writing an event group.
+--write_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+wait
+EOF
+
+# Don't run this part of the test when testing binlog-in-engine.
+# Because with binlog-in-engine, partial event groups cannot result
+# from server crash, binlog writes are atomic and crash-recovered.
+if (!$binlog_in_engine) {
+ FLUSH TABLES;
+ SET SESSION debug_dbug="+d,crash_before_writing_xid";
+ --error 2006,2013
+ INSERT INTO t1 SELECT a+4, '++server_1' FROM t2;
+
+--source include/wait_until_disconnected.inc
+--connection default
+--source include/wait_until_disconnected.inc
+}
+
+--append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+restart
+EOF
+
+if (!$binlog_in_engine) {
+--connection default
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+
+--connection server_1
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+}
+if ($binlog_in_engine) {
+ # Drop the temporary tables manually, as we did not crash the server.
+ --connection default
+ DROP TEMPORARY TABLE t3;
+ --connection server_1
+ DROP TEMPORARY TABLE t2;
+}
+
+INSERT INTO t1 VALUES (0, 1);
+--source include/save_master_gtid.inc
+
+--connection server_2
+# Start the slave replicating the events.
+# The main thing to test here is that the slave will know that it
+# needs to abort the partially received event group, so that the
+# execution of format_description event will not wait infinitely
+# for a commit of the incomplete group that never happens.
+
+# Apart from the suppression, MDEV-27697 refinement to the original test needs
+# an allowance to one time accept malformed event group.
+set @@sql_log_bin=0;
+call mtr.add_suppression("Unexpected break of being relay-logged GTID 1-1-32 event group by the current GTID event 0-1-4");
+set @@sql_log_bin=1;
+set @@global.debug_dbug="+d,slave_discard_xid_for_gtid_0_x_1000";
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+set @@global.debug_dbug="";
+
+SELECT * FROM t1 ORDER BY a;
+SHOW STATUS LIKE 'Slave_open_temp_tables';
+
+--connection server_1
+# This FLUSH can be removed once MDEV-6608 is fixed.
+FLUSH LOGS;
+
+--echo *** MDEV-7936: Assertion `!table || table->in_use == _current_thd()' failed on parallel replication in optimistic mode ***
+
+--connection server_1
+CREATE TEMPORARY TABLE t4 (a INT PRIMARY KEY) ENGINE=InnoDB;
+SET @old_dbug= @@SESSION.debug_dbug;
+SET SESSION debug_dbug="+d,binlog_force_commit_id";
+SET @commit_id= 10000;
+INSERT INTO t4 VALUES (30);
+INSERT INTO t4 VALUES (31);
+SET SESSION debug_dbug= @old_dbug;
+INSERT INTO t1 SELECT a, "conservative" FROM t4;
+DROP TEMPORARY TABLE t4;
+SELECT * FROM t1 WHERE a >= 30 ORDER BY a;
+--source include/save_master_gtid.inc
+
+--connection server_2
+--source include/sync_with_master_gtid.inc
+
+SELECT * FROM t1 WHERE a >= 30 ORDER BY a;
+
+--source include/stop_slave.inc
+SET @old_mode= @@GLOBAL.slave_parallel_mode;
+SET GLOBAL slave_parallel_mode=optimistic;
+
+--connection server_1
+CREATE TEMPORARY TABLE t4 (a INT PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t4 VALUES (32);
+INSERT INTO t4 VALUES (33);
+INSERT INTO t1 SELECT a, "optimistic" FROM t4;
+DROP TEMPORARY TABLE t4;
+
+SELECT * FROM t1 WHERE a >= 30 ORDER BY a;
+--source include/save_master_gtid.inc
+
+--connection server_2
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+
+SELECT * FROM t1 WHERE a >= 30 ORDER BY a;
+
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_mode=@old_mode;
+--source include/start_slave.inc
+
+
+--echo *** MDEV33426: Memory allocation accounting incorrect for replicated temptable
+--connection server_1
+CREATE TEMPORARY TABLE t5 (a int) ENGINE=Aria;
+CREATE TEMPORARY TABLE t6 (a int) ENGINE=Heap;
+INSERT INTO t5 VALUES (1);
+INSERT INTO t6 VALUES (2);
+--source include/save_master_gtid.inc
+
+--connection server_2
+--source include/sync_with_master_gtid.inc
+--source include/stop_slave.inc
+
+--connection server_1
+INSERT INTO t1 SELECT a+40, 5 FROM t5;
+INSERT INTO t1 SELECT a+40, 6 FROM t6;
+DROP TABLE t5, t6;
+
+--source include/save_master_gtid.inc
+
+--connection server_2
+--source include/start_slave.inc
+--source include/sync_with_master_gtid.inc
+SELECT * FROM t1 WHERE a>=40 ORDER BY a;
+
+# Clean up.
+
+--connection server_2
+--source include/stop_slave.inc
+SET GLOBAL slave_parallel_threads=@old_parallel_threads;
+--source include/start_slave.inc
+
+--connection server_1
+DROP TABLE t1;
diff --git a/mysql-test/include/rpl_reset.inc b/mysql-test/include/rpl_reset.inc
index 53ed1de98749d..82961c2e0e0e9 100644
--- a/mysql-test/include/rpl_reset.inc
+++ b/mysql-test/include/rpl_reset.inc
@@ -31,6 +31,9 @@
# Set the timeout when waiting for slave threads to stop and
# start, respectively. See include/wait_for_slave_param.inc
#
+# $rpl_skip_sync
+# Don't sync the slaves before resetting them.
+#
# Note:
# This script will fail if Last_SQL_Error or Last_IO_Error is
# nonempty. If you expect an error in the SQL thread, you should
@@ -50,7 +53,10 @@ if (!$rpl_debug)
}
---source include/rpl_sync.inc
+if (!$rpl_skip_sync)
+{
+ --source include/rpl_sync.inc
+}
if ($rpl_debug)
@@ -63,11 +69,26 @@ while ($_rpl_server)
--let $rpl_connection_name= server_$_rpl_server
--source include/rpl_connection.inc
- RESET MASTER;
# Check if this server is configured to have a master
if (`SELECT SUBSTRING('$rpl_master_list', 1 + ($_rpl_server - 1) * $rpl_server_count_length, $rpl_server_count_length) != ''`)
{
--source include/stop_slave.inc
+ }
+ --dec $_rpl_server
+}
+
+--let $_rpl_server= $rpl_server_count
+while ($_rpl_server)
+{
+ --let $rpl_connection_name= server_$_rpl_server
+ --source include/rpl_connection.inc
+
+ --source include/kill_binlog_dump_threads.inc
+ RESET MASTER;
+
+ # Check if this server is configured to have a master
+ if (`SELECT SUBSTRING('$rpl_master_list', 1 + ($_rpl_server - 1) * $rpl_server_count_length, $rpl_server_count_length) != ''`)
+ {
--source include/reset_slave.inc
}
--dec $_rpl_server
diff --git a/mysql-test/include/rpl_restart_server.inc b/mysql-test/include/rpl_restart_server.inc
index 5df2c67d3da23..c2b6427390374 100644
--- a/mysql-test/include/rpl_restart_server.inc
+++ b/mysql-test/include/rpl_restart_server.inc
@@ -6,6 +6,7 @@
# ==== Usage ====
#
# --let $rpl_server_number= N
+# [--let $shutdown_timeout= 60]
# [--let $rpl_server_parameters= --flag1 --flag2 ...]
# [--let $rpl_debug= 1]
# --source include/rpl_restart_server.inc
diff --git a/mysql-test/include/rpl_stmt_seq.inc b/mysql-test/include/rpl_stmt_seq.inc
index b23178ee5343a..372473cfb7f52 100644
--- a/mysql-test/include/rpl_stmt_seq.inc
+++ b/mysql-test/include/rpl_stmt_seq.inc
@@ -81,7 +81,10 @@ if ($show_binlog)
--let $binlog_file= master-bin.$_log_num_s
--source include/show_binlog_events.inc
}
-sync_slave_with_master;
+--connection master
+--source include/save_master_gtid.inc
+--connection slave
+--source include/sync_with_master_gtid.inc
connection slave;
# results before DDL(to be tested)
@@ -106,7 +109,10 @@ if ($show_binlog)
--let $binlog_file= master-bin.$_log_num_s
--source include/show_binlog_events.inc
}
-sync_slave_with_master;
+--connection master
+--source include/save_master_gtid.inc
+--connection slave
+--source include/sync_with_master_gtid.inc
connection slave;
# results after DDL(to be tested)
@@ -139,7 +145,10 @@ if ($show_binlog)
--let $binlog_file= master-bin.$_log_num_s
--source include/show_binlog_events.inc
}
-sync_slave_with_master;
+--connection master
+--source include/save_master_gtid.inc
+--connection slave
+--source include/sync_with_master_gtid.inc
connection slave;
# results after final ROLLBACK
@@ -173,7 +182,10 @@ connection master;
flush logs;
# sleep 1;
# eval SHOW BINLOG EVENTS IN 'master-bin.$_log_num_s';
-sync_slave_with_master;
+--connection master
+--source include/save_master_gtid.inc
+--connection slave
+--source include/sync_with_master_gtid.inc
connection slave;
# the final content of the binary log
diff --git a/mysql-test/include/rpl_stop_server.inc b/mysql-test/include/rpl_stop_server.inc
index 1e4a64cca250d..ee331d49cad7a 100644
--- a/mysql-test/include/rpl_stop_server.inc
+++ b/mysql-test/include/rpl_stop_server.inc
@@ -5,6 +5,7 @@
# ==== Usage ====
#
# --let $rpl_server_number= N
+# [--let $shutdown_timeout= 60]
# [--let $rpl_debug= 1]
# --source include/rpl_stop_server.inc
#
@@ -50,6 +51,10 @@ if ($rpl_debug)
# it 60 seconds (of mysqltest's default) to die before zapping it
let $rpl_shutdown_timeout= `select 60*(1+9*count(*)) from information_schema.system_variables where variable_name='have_sanitizer' and global_value like "MSAN%"`;
+if ($shutdown_timeout != '') {
+ --let $rpl_shutdown_timeout= $shutdown_timeout
+}
+
shutdown_server $rpl_shutdown_timeout;
--source include/wait_until_disconnected.inc
diff --git a/mysql-test/include/rpl_sync.inc b/mysql-test/include/rpl_sync.inc
index 83d4a2e4628bc..64275fade63f1 100644
--- a/mysql-test/include/rpl_sync.inc
+++ b/mysql-test/include/rpl_sync.inc
@@ -10,6 +10,7 @@
# [--let $rpl_only_running_threads= 1]
# [--let $rpl_debug= 1]
# [--let $slave_timeout= NUMBER]
+# [--let $disable_gtid= 1]
# --source include/rpl_sync.inc
#
# Parameters:
@@ -23,6 +24,11 @@
# - If only SQL thread is running, sync SQL thread with IO thread.
# - If no thread is running, don't sync.
#
+# $disable_gtid
+# Use old-style file/offset for syncing, even if slave is configured
+# to connect using GTID. (Useful for tests that run without properly
+# configuring domain_id, like rpl.rpl_circular_for_4_hosts).
+#
# $slave_timeout
# Set the timeout when waiting for threads to sync. See
# include/wait_for_slave_param.inc
@@ -75,6 +81,17 @@ while ($_rpl_i) {
if ($_rpl_server)
{
+ disable_query_log;
+ --connection server_$_rpl_server
+ enable_query_log;
+ # By default, sync using GTID (when GTID is enabled), as GTID is now
+ # on by default. But allow to fallback explicitly to old-style file/pos
+ # for tests that need this.
+ --let $_rpl_gtid_mode= query_get_value(SHOW SLAVE STATUS, Using_Gtid, 1)
+ if ($disable_gtid)
+ {
+ --let $_rpl_gtid_mode= No
+ }
if ($rpl_debug)
{
--echo [sync server_$_rpl_prev_server -> server_$_rpl_server]
@@ -99,15 +116,30 @@ while ($_rpl_i) {
enable_query_log;
if ($_rpl_slave_sql_running)
{
- if ($rpl_debug)
+ if ($_rpl_gtid_mode == 'No')
+ {
+ if ($rpl_debug)
+ {
+ --let $_rpl_master_file= query_get_value("SHOW MASTER STATUS", File, 1)
+ --let $_rpl_master_pos= query_get_value("SHOW MASTER STATUS", Position, 1)
+ --echo syncing master_file='$_rpl_master_file' master_pos='$_rpl_master_pos'
+ }
+ disable_connect_log;
+ --sync_slave_with_master server_$_rpl_server
+ enable_connect_log;
+ }
+ if ($_rpl_gtid_mode != 'No')
{
- --let $_rpl_master_file= query_get_value("SHOW MASTER STATUS", File, 1)
- --let $_rpl_master_pos= query_get_value("SHOW MASTER STATUS", Position, 1)
- --echo syncing master_file='$_rpl_master_file' master_pos='$_rpl_master_pos'
+ --source include/save_master_gtid.inc
+ disable_connect_log;
+ --connection server_$_rpl_server
+ if ($rpl_debug)
+ {
+ --echo syncing with GTID position '$master_pos'
+ }
+ --source include/sync_with_master_gtid.inc
+ enable_connect_log;
}
- disable_connect_log;
- --sync_slave_with_master server_$_rpl_server
- enable_connect_log;
}
if (!$_rpl_slave_sql_running)
{
@@ -127,13 +159,25 @@ while ($_rpl_i) {
{
disable_connect_log;
--connection server_$_rpl_prev_server
- if ($rpl_debug)
- {
- --let $_rpl_master_file= query_get_value("SHOW MASTER STATUS", File, 1)
- --let $_rpl_master_pos= query_get_value("SHOW MASTER STATUS", Position, 1)
- --echo syncing master_file='$_rpl_master_file' master_pos='$_rpl_master_pos'
+ if ($_rpl_gtid_mode == 'No') {
+ if ($rpl_debug)
+ {
+ --let $_rpl_master_file= query_get_value("SHOW MASTER STATUS", File, 1)
+ --let $_rpl_master_pos= query_get_value("SHOW MASTER STATUS", Position, 1)
+ --echo syncing master_file='$_rpl_master_file' master_pos='$_rpl_master_pos'
+ }
+ --sync_slave_with_master server_$_rpl_server
+ }
+ if ($_rpl_gtid_mode != 'No') {
+ --source include/save_master_gtid.inc
+ disable_connect_log;
+ --connection server_$_rpl_server
+ if ($rpl_debug)
+ {
+ --echo syncing with GTID position'$master_pos'
+ }
+ --source include/sync_with_master_gtid.inc
}
- --sync_slave_with_master server_$_rpl_server
enable_connect_log;
}
}
diff --git a/mysql-test/include/show_binlog_events2.inc b/mysql-test/include/show_binlog_events2.inc
index 69391ff8fa2f0..ef1c45f700ebf 100644
--- a/mysql-test/include/show_binlog_events2.inc
+++ b/mysql-test/include/show_binlog_events2.inc
@@ -26,7 +26,7 @@ if ($binlog_start)
}
if (!$binlog_start)
{
- --let $_binlog_start=256
+ --let $_binlog_start=257
}
if ($binlog_file)
{
diff --git a/mysql-test/include/show_master_status.inc b/mysql-test/include/show_master_status.inc
index b7b32a65df411..642b06f64d731 100644
--- a/mysql-test/include/show_master_status.inc
+++ b/mysql-test/include/show_master_status.inc
@@ -1,5 +1,5 @@
# show master status
# mask out the binlog position
--- replace_column 2 # 3 4
+--replace_column 2 # 3 4 5
show master status;
diff --git a/mysql-test/include/test_fieldsize.inc b/mysql-test/include/test_fieldsize.inc
index 1ce846eed0b49..cbf69c2df80c4 100644
--- a/mysql-test/include/test_fieldsize.inc
+++ b/mysql-test/include/test_fieldsize.inc
@@ -17,6 +17,7 @@ eval $test_table_slave;
connection master;
eval $test_table_master;
+--source include/kill_binlog_dump_threads.inc
RESET MASTER;
eval $test_insert;
@@ -33,6 +34,7 @@ STOP SLAVE;
--source include/reset_slave.inc
connection master;
+--source include/kill_binlog_dump_threads.inc
RESET MASTER;
connection slave;
diff --git a/mysql-test/include/wait_for_engine_binlog.inc b/mysql-test/include/wait_for_engine_binlog.inc
new file mode 100644
index 0000000000000..040d1de6279ce
--- /dev/null
+++ b/mysql-test/include/wait_for_engine_binlog.inc
@@ -0,0 +1,77 @@
+# include/wait_for_engine_binlog.inc
+#
+# SUMMARY
+#
+# Waits until a specific (engine-implemented) binlog file is seen with
+# the specified size in SHOW BINARY LOGS.
+# Used to avoid sporadic failures due to races with the binlog
+# pre-allocation thread.
+#
+# USAGE
+#
+# --let $binlog_name= binlog-000002.ibb
+# --let $binlog_size= 262144
+# --source include/wait_for_engine_binlog.inc
+#
+# OPTIONALLY:
+#
+# let $wait_timeout= 60; # Override default 30 seconds with 60.
+# let $wait_notfound= 1; # Wait until specified binlog _not_ found.
+#
+# EXAMPLE
+# binlog_in_engine.binlog_flush_purge.test
+#
+
+--disable_query_log
+
+let $_wait_counter= 300;
+if ($wait_timeout)
+{
+ let $_wait_counter= `SELECT $wait_timeout * 10`;
+}
+# Reset $wait_timeout so that its value won't be used on subsequent
+# calls, and default will be used instead.
+let $wait_timeout= 0;
+
+--let $_expect= 1
+--let $_message= exist
+if ($wait_notfound) {
+ --let $_expect= 0
+ --let $_message= no longer exist
+}
+let $wait_notfound= 0;
+
+--let $_done= 0
+--let $_i= 0
+while (!$_done) {
+ --let $_j= 1
+ --let $_end= 0
+ --let $_found= 0
+ while (!$_end) {
+ --let $_x= query_get_value(SHOW BINARY LOGS, Log_name, $_j)
+ if ($_x == No such row) {
+ --let $_end= 1
+ }
+ if ($_x == $binlog_name) {
+ --let $_y= query_get_value(SHOW BINARY LOGS, File_size, $_j)
+ if ($_y == $binlog_size) {
+ --let $_found= 1
+ --let $_end= 1
+ }
+ }
+ inc $_j;
+ }
+ if ($_found == $_expect) {
+ --let $_done= 1
+ }
+ if (!$_done) {
+ sleep 0.1;
+ inc $_i;
+ if ($_i >= $_wait_counter) {
+ SHOW BINARY LOGS;
+ --die Timeout waiting for binlog '$binlog_name' to $_message
+ }
+ }
+}
+
+--enable_query_log
diff --git a/mysql-test/include/wait_for_line_count_in_file.inc b/mysql-test/include/wait_for_line_count_in_file.inc
index 838a3ff342bfa..93531821f1314 100644
--- a/mysql-test/include/wait_for_line_count_in_file.inc
+++ b/mysql-test/include/wait_for_line_count_in_file.inc
@@ -15,4 +15,5 @@ perl;
die "Timeout waiting for $search_count lines in $search_file\n";
sleep(0.1);
}
+ print "Line count in file: $search_count\n";
EOF
diff --git a/mysql-test/lib/My/Debugger.pm b/mysql-test/lib/My/Debugger.pm
index 2ab8a3520c897..a3985e65bab96 100644
--- a/mysql-test/lib/My/Debugger.pm
+++ b/mysql-test/lib/My/Debugger.pm
@@ -81,6 +81,7 @@ my %debuggers = (
options => '_RR_TRACE_DIR={log} rr record {exe} {args}',
run => 'env',
pre => sub {
+ push @::global_suppressions, qr/InnoDB: native AIO failed/;
::mtr_error('rr requires kernel.perf_event_paranoid <= 1')
if ::mtr_grab_file('/proc/sys/kernel/perf_event_paranoid') > 1;
}
diff --git a/mysql-test/lib/My/SafeProcess/safe_process.cc b/mysql-test/lib/My/SafeProcess/safe_process.cc
index dcaea161097db..204351bbc4014 100644
--- a/mysql-test/lib/My/SafeProcess/safe_process.cc
+++ b/mysql-test/lib/My/SafeProcess/safe_process.cc
@@ -237,7 +237,8 @@ int main(int argc, char* const argv[] )
sigaction(SIGCHLD, &sa,NULL);
sigaction(SIGABRT, &sa_abort,NULL);
- sprintf(safe_process_name, "safe_process[%ld]", (long) own_pid);
+ snprintf(safe_process_name, sizeof(safe_process_name),
+ "safe_process[%ld]", (long) own_pid);
message("Started");
diff --git a/mysql-test/lib/generate-ssl-certs.sh b/mysql-test/lib/generate-ssl-certs.sh
index f698464b93294..1c6cda56fe2d0 100755
--- a/mysql-test/lib/generate-ssl-certs.sh
+++ b/mysql-test/lib/generate-ssl-certs.sh
@@ -67,3 +67,156 @@ rm -fv crldir/*
cp -v client-cert.crl crldir/`openssl x509 -in client-cert.pem -noout -issuer_hash`.r0
rm -rf demoCA
+
+# --- Certificate Chain ---
+# These tests are inspired from the following commit from MySQL Server
+# https://github.com/mysql/mysql-server/commit/969afef933f1872c5f38ea93047ef05c4509c335
+#
+# Credits to salman.s.khan@oracle.com
+#
+# -------------------------------------------------------------------------------------
+#
+# STEPS TO GENERATE THE FOLLOWING CHAINED CERTIFICATES WHICH IS USED IN THE TEST CASE :
+#
+# +---------+
+# | Root CA |
+# +---------+
+# |
+# /------------+-----------\
+# | |
+# +------------------+ +------------------+
+# | Intermediate CA1 | | Intermediate CA2 |
+# +------------------+ +------------------+
+# | |
+# +-------------+ +-------------+
+# | Server | | Client |
+# | certificate | | certificate |
+# +-------------+ +-------------+
+
+cd cachain
+
+mkdir ca
+mkdir server
+mkdir clients
+
+mkdir ca/root.certs
+touch ca/root.index.txt
+touch ca/root.index.txt.attr
+echo '01' > ca/root.serial
+
+cat > ca/root.cfg << EOF
+[ ca ]
+default_ca = CA_default
+[ CA_default ]
+dir = $PWD/ca
+certs = \$dir/certs
+database = \$dir/root.index.txt
+serial = \$dir/root.serial
+policy= policy_match
+[ policy_match ]
+organizationName = match
+organizationalUnitName = optional
+commonName = supplied
+emailAddress = optional
+[ v3_ca ]
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid:always,issuer
+basicConstraints = critical,CA:TRUE
+keyUsage = critical,keyCertSign,cRLSign
+[ v3_ca_intermediate ]
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid:always,issuer
+basicConstraints = critical,CA:TRUE,pathlen:0
+keyUsage = critical,keyCertSign,cRLSign
+EOF
+
+# Generate Root CA key and cert
+openssl genrsa -out ca/root.key 4096
+openssl req -new -x509 '-sha256' -key ca/root.key -out ca/root.crt -days 7200 -subj "/O=MariaDB/OU=MariaDB/CN=Root CA" -config ca/root.cfg -extensions v3_ca
+
+# Generate Intermediate CA1 key and cert
+openssl genrsa -out ca/intermediate_ca1.key 4096
+openssl req -new '-sha256' -key ca/intermediate_ca1.key -out ca/intermediate_ca1.csr -subj "/O=MariaDB/OU=MariaDB/CN=Intermediate CA1"
+
+openssl ca -batch -days 7200 -notext -md sha256 -in ca/intermediate_ca1.csr -out ca/intermediate_ca1.crt -keyfile ca/root.key -cert ca/root.crt -outdir ca/root.certs/ -config ca/root.cfg -extensions v3_ca_intermediate
+
+mkdir ca/intermediate_ca1.certs
+touch ca/intermediate_ca1.index.txt
+touch ca/intermediate_ca1.index.txt.attr
+echo '01' > ca/intermediate_ca1.serial
+
+cat > ca/intermediate_ca1.cfg << EOF
+[ ca ]
+default_ca = CA_default
+[ CA_default ]
+dir = $PWD/ca
+certs = \$dir/intermediate_ca1.certs
+database = \$dir/intermediate_ca1.index.txt
+serial = \$dir/intermediate_ca1.serial
+policy= policy_match
+[ policy_match ]
+commonName = supplied
+[ alt_names ]
+DNS.1 = localhost
+IP.1 = 127.0.0.1
+[ server_cert ]
+basicConstraints = CA:FALSE
+keyUsage = critical,digitalSignature,keyEncipherment
+extendedKeyUsage = serverAuth
+subjectAltName = @alt_names
+EOF
+
+# Generate Server key and cert
+openssl genrsa -out server/server.key 4096
+openssl req -new '-sha256' -key server/server.key -out server/server.csr -subj "/CN=localhost"
+
+openssl ca -batch -days 7200 -notext -md sha256 -in server/server.csr -out server/server.crt -keyfile ca/intermediate_ca1.key -cert ca/intermediate_ca1.crt -outdir ca/intermediate_ca1.certs/ -config ca/intermediate_ca1.cfg -extensions server_cert
+
+# Generate Intermediate CA2 key and cert
+openssl genrsa -out ca/intermediate_ca2.key 4096
+
+openssl req -new '-sha256' -key ca/intermediate_ca2.key -out ca/intermediate_ca2.csr -subj "/O=MariaDB/OU=MariaDB/CN=Intermediate CA2"
+openssl ca -batch -days 7200 -notext -md sha256 -in ca/intermediate_ca2.csr -out ca/intermediate_ca2.crt -keyfile ca/root.key -cert ca/root.crt -outdir ca/root.certs/ -config ca/root.cfg -extensions v3_ca_intermediate
+
+mkdir ca/intermediate_ca2.certs
+touch ca/intermediate_ca2.index.txt
+touch ca/intermediate_ca2.index.txt.attr
+echo '01' > ca/intermediate_ca2.serial
+
+cat > ca/intermediate_ca2.cfg << EOF
+[ ca ]
+default_ca = CA_default
+[ CA_default ]
+dir = $PWD/ca
+certs = \$dir/intermediate_ca2.certs
+database = \$dir/intermediate_ca2.index.txt
+serial = \$dir/intermediate_ca2.serial
+policy= policy_match
+[ policy_match ]
+commonName = supplied
+[ client_cert ]
+basicConstraints = CA:FALSE
+keyUsage = critical,digitalSignature,keyEncipherment
+extendedKeyUsage = clientAuth
+EOF
+
+# Generate Client key and cert
+openssl genrsa -out clients/client.key 4096
+openssl req -new '-sha256' -key clients/client.key -out clients/client.csr -subj "/CN=client"
+
+openssl ca -batch -days 7200 -notext -md sha256 -in clients/client.csr -out clients/client.crt -keyfile ca/intermediate_ca2.key -cert ca/intermediate_ca2.crt -outdir ca/intermediate_ca2.certs/ -config ca/intermediate_ca2.cfg -extensions client_cert
+
+cat server/server.crt ca/intermediate_ca1.crt > server/server.cachain
+
+cat clients/client.crt ca/intermediate_ca2.crt > clients/client.cachain
+
+cat ca/root.crt ca/intermediate_ca1.crt > ca/root_intermediate_ca1.crt
+
+# Generate Unrelated Root CA key and cert
+openssl genrsa -out ca/unrelated_root.key 4096
+openssl req -new -x509 '-sha256' -key ca/unrelated_root.key -out ca/unrelated_root.crt -days 7200 -subj "/O=MariaDB/OU=MariaDB/CN=Root CA" -config ca/root.cfg -extensions v3_ca
+
+cp -v ca/root.crt ca/root_intermediate_ca1.crt ca/unrelated_root.crt server/server.key server/server.cachain clients/client.key clients/client.cachain ./
+rm -rf ca server clients
+
+cd ..
diff --git a/mysql-test/lib/v1/mtr_cases.pl b/mysql-test/lib/v1/mtr_cases.pl
index 968f13bcc6102..4cf8c2b48239a 100644
--- a/mysql-test/lib/v1/mtr_cases.pl
+++ b/mysql-test/lib/v1/mtr_cases.pl
@@ -863,6 +863,7 @@ ($$$$$$$$$)
"binlog_formats", ["row", "statement"]],
["include/have_innodb.inc", "innodb_test", 1],
+ ["include/have_innodb_binlog.inc", "innodb_test", 1],
["include/have_log_bin.inc", "need_binlog", 1],
["include/big_test.inc", "big_test", 1],
["include/have_debug.inc", "need_debug", 1],
diff --git a/mysql-test/main/aborted_clients.test b/mysql-test/main/aborted_clients.test
index 200bac031336e..74651dbd7b9d1 100644
--- a/mysql-test/main/aborted_clients.test
+++ b/mysql-test/main/aborted_clients.test
@@ -2,15 +2,13 @@
# Check that ordinary connect/disconnect does not increase aborted_clients
# status variable, but KILL connection does
--- source include/not_embedded.inc
--- source include/count_sessions.inc
+--source include/not_embedded.inc
FLUSH GLOBAL STATUS;
# Connect/Disconnect look that aborted_clients stays 0
connect (con1,localhost,root,,);
disconnect con1;
connection default;
--- source include/wait_until_count_sessions.inc
# Check that there is 0 aborted clients so far
SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME='aborted_clients';
@@ -21,7 +19,6 @@ connect(con2,localhost,root,,);
KILL CONNECTION_ID();
disconnect con2;
connection default;
--- source include/wait_until_count_sessions.inc
# aborted clients must be 1 now
SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME='aborted_clients';
diff --git a/mysql-test/main/alter_table.result b/mysql-test/main/alter_table.result
index 7c97739eeadce..056cee0534b15 100644
--- a/mysql-test/main/alter_table.result
+++ b/mysql-test/main/alter_table.result
@@ -1539,13 +1539,13 @@ t2 CREATE TABLE `t2` (
KEY `fk` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci
ALTER TABLE t2 ADD FOREIGN KEY (id) REFERENCES t1(id);
-ALTER TABLE t2 ADD FOREIGN KEY IF NOT EXISTS t2_ibfk_1(id) REFERENCES t1(id);
+ALTER TABLE t2 ADD FOREIGN KEY IF NOT EXISTS `1`(id) REFERENCES t1(id);
Warnings:
-Note 1061 Duplicate key name 't2_ibfk_1'
-ALTER TABLE t2 DROP FOREIGN KEY IF EXISTS t2_ibfk_1;
-ALTER TABLE t2 DROP FOREIGN KEY IF EXISTS t2_ibfk_1;
+Note 1061 Duplicate key name '1'
+ALTER TABLE t2 DROP FOREIGN KEY IF EXISTS `1`;
+ALTER TABLE t2 DROP FOREIGN KEY IF EXISTS `1`;
Warnings:
-Note 1091 Can't DROP FOREIGN KEY `t2_ibfk_1`; check that it exists
+Note 1091 Can't DROP FOREIGN KEY `1`; check that it exists
SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
@@ -1780,7 +1780,6 @@ DROP TABLE t1;
# --enable_info allows us to see how many rows were updated
# by ALTER TABLE. in-place will show 0 rows, while copy > 0.
#
-DROP TABLE IF EXISTS ti1, ti2, ti3, tm1, tm2, tm3;
# Single operation tests
CREATE TABLE ti1(a INT NOT NULL, b INT, c INT) engine=InnoDB;
CREATE TABLE tm1(a INT NOT NULL, b INT, c INT) engine=MyISAM;
@@ -3153,12 +3152,36 @@ DROP TABLE t;
# End of 10.7 tests
#
#
+# MDEV-37275 Cannot remove default value of NOT NULL column
+#
+create table t1 (d time default '00:00:00');
+alter table t1 alter column d drop default;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `d` time DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci
+create table t2 (d datetime not null default current_timestamp());
+alter table t2 alter column d drop default;
+show create table t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `d` datetime NOT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci
+create table t3 (d datetime not null);
+alter table t3 alter column d set default current_timestamp();
+show create table t3;
+Table Create Table
+t3 CREATE TABLE `t3` (
+ `d` datetime NOT NULL DEFAULT current_timestamp()
+) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci
+drop tables t1, t2, t3;
+# End of 10.11 tests
+#
# MDEV-33655 Remove alter_algorithm
#
CREATE TABLE t1 (a INT) ENGINE=MyISAM;
CREATE TABLE t2 (a INT) ENGINE=MERGE, UNION(t1);
ALTER TABLE t2 COMMENT 'x', LOCK=SHARED;
DROP TABLE t2,t1;
-#
# End of 11.5 tests
-#
diff --git a/mysql-test/main/alter_table.test b/mysql-test/main/alter_table.test
index e9bc5f63cc98f..7b2b2c7f98379 100644
--- a/mysql-test/main/alter_table.test
+++ b/mysql-test/main/alter_table.test
@@ -1318,8 +1318,6 @@ SELECT LENGTH(my_t3_fld1) FROM t3;
# Cleanup
--disconnect con1
---source include/wait_until_disconnected.inc
-
--connection default
DROP TABLE t1, t2, t3;
@@ -1384,9 +1382,9 @@ ALTER TABLE t2 DROP FOREIGN KEY IF EXISTS fk;
ALTER TABLE t2 DROP FOREIGN KEY IF EXISTS fk;
SHOW CREATE TABLE t2;
ALTER TABLE t2 ADD FOREIGN KEY (id) REFERENCES t1(id);
-ALTER TABLE t2 ADD FOREIGN KEY IF NOT EXISTS t2_ibfk_1(id) REFERENCES t1(id);
-ALTER TABLE t2 DROP FOREIGN KEY IF EXISTS t2_ibfk_1;
-ALTER TABLE t2 DROP FOREIGN KEY IF EXISTS t2_ibfk_1;
+ALTER TABLE t2 ADD FOREIGN KEY IF NOT EXISTS `1`(id) REFERENCES t1(id);
+ALTER TABLE t2 DROP FOREIGN KEY IF EXISTS `1`;
+ALTER TABLE t2 DROP FOREIGN KEY IF EXISTS `1`;
SHOW CREATE TABLE t2;
DROP TABLE t2;
@@ -1569,8 +1567,6 @@ connection con1;
--echo # Reaping: ALTER TABLE t1 DISABLE KEYS
--reap
disconnect con1;
---source include/wait_until_disconnected.inc
-
connection default;
DROP TABLE t1;
@@ -1584,10 +1580,6 @@ DROP TABLE t1;
--echo # by ALTER TABLE. in-place will show 0 rows, while copy > 0.
--echo #
---disable_warnings
-DROP TABLE IF EXISTS ti1, ti2, ti3, tm1, tm2, tm3;
---enable_warnings
-
--echo # Single operation tests
CREATE TABLE ti1(a INT NOT NULL, b INT, c INT) engine=InnoDB;
@@ -2449,6 +2441,25 @@ DROP TABLE t;
--echo # End of 10.7 tests
--echo #
+--echo #
+--echo # MDEV-37275 Cannot remove default value of NOT NULL column
+--echo #
+create table t1 (d time default '00:00:00');
+alter table t1 alter column d drop default;
+show create table t1;
+
+create table t2 (d datetime not null default current_timestamp());
+alter table t2 alter column d drop default;
+show create table t2;
+
+create table t3 (d datetime not null);
+alter table t3 alter column d set default current_timestamp();
+show create table t3;
+
+drop tables t1, t2, t3;
+
+--echo # End of 10.11 tests
+
--echo #
--echo # MDEV-33655 Remove alter_algorithm
--echo #
@@ -2458,6 +2469,4 @@ CREATE TABLE t2 (a INT) ENGINE=MERGE, UNION(t1);
ALTER TABLE t2 COMMENT 'x', LOCK=SHARED;
DROP TABLE t2,t1;
---echo #
--echo # End of 11.5 tests
---echo #
diff --git a/mysql-test/main/alter_table_combinations,aria.rdiff b/mysql-test/main/alter_table_combinations,aria.rdiff
index 6564dbb44a629..f5f05cf954332 100644
--- a/mysql-test/main/alter_table_combinations,aria.rdiff
+++ b/mysql-test/main/alter_table_combinations,aria.rdiff
@@ -5,7 +5,7 @@
`a` int(11) DEFAULT NULL,
`b` int(11) DEFAULT NULL,
- KEY `b` (`b`),
-- CONSTRAINT `t3_ibfk_1` FOREIGN KEY (`b`) REFERENCES `t1` (`bb`)
+- CONSTRAINT `1` FOREIGN KEY (`b`) REFERENCES `t1` (`bb`)
+ KEY `b` (`b`)
) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci
ALTER TABLE t1 RENAME COLUMN bb TO b;
@@ -15,7 +15,7 @@
`a` int(11) DEFAULT NULL,
`c` int(11) DEFAULT NULL,
- KEY `b` (`c`),
-- CONSTRAINT `t3_ibfk_1` FOREIGN KEY (`c`) REFERENCES `t1` (`b`)
+- CONSTRAINT `1` FOREIGN KEY (`c`) REFERENCES `t1` (`b`)
+ KEY `b` (`c`)
) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci
CREATE TABLE t4(a int);
diff --git a/mysql-test/main/alter_table_combinations,heap.rdiff b/mysql-test/main/alter_table_combinations,heap.rdiff
index 81633a8255ff6..c9c7907f7d6d7 100644
--- a/mysql-test/main/alter_table_combinations,heap.rdiff
+++ b/mysql-test/main/alter_table_combinations,heap.rdiff
@@ -14,7 +14,7 @@
`a` int(11) DEFAULT NULL,
`b` int(11) DEFAULT NULL,
- KEY `b` (`b`),
-- CONSTRAINT `t3_ibfk_1` FOREIGN KEY (`b`) REFERENCES `t1` (`bb`)
+- CONSTRAINT `1` FOREIGN KEY (`b`) REFERENCES `t1` (`bb`)
+ KEY `b` (`b`)
) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci
ALTER TABLE t1 RENAME COLUMN bb TO b;
@@ -24,7 +24,7 @@
`a` int(11) DEFAULT NULL,
`c` int(11) DEFAULT NULL,
- KEY `b` (`c`),
-- CONSTRAINT `t3_ibfk_1` FOREIGN KEY (`c`) REFERENCES `t1` (`b`)
+- CONSTRAINT `1` FOREIGN KEY (`c`) REFERENCES `t1` (`b`)
+ KEY `b` (`c`)
) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci
CREATE TABLE t4(a int);
diff --git a/mysql-test/main/alter_table_combinations.result b/mysql-test/main/alter_table_combinations.result
index 1e8d1ee599b67..d14aaaac8f73d 100644
--- a/mysql-test/main/alter_table_combinations.result
+++ b/mysql-test/main/alter_table_combinations.result
@@ -174,7 +174,7 @@ t3 CREATE TABLE `t3` (
`a` int(11) DEFAULT NULL,
`b` int(11) DEFAULT NULL,
KEY `b` (`b`),
- CONSTRAINT `t3_ibfk_1` FOREIGN KEY (`b`) REFERENCES `t1` (`bb`)
+ CONSTRAINT `1` FOREIGN KEY (`b`) REFERENCES `t1` (`bb`)
) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci
ALTER TABLE t1 RENAME COLUMN bb TO b;
SHOW CREATE TABLE t1;
@@ -191,7 +191,7 @@ t3 CREATE TABLE `t3` (
`a` int(11) DEFAULT NULL,
`c` int(11) DEFAULT NULL,
KEY `b` (`c`),
- CONSTRAINT `t3_ibfk_1` FOREIGN KEY (`c`) REFERENCES `t1` (`b`)
+ CONSTRAINT `1` FOREIGN KEY (`c`) REFERENCES `t1` (`b`)
) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci
CREATE TABLE t4(a int);
ALTER TABLE t4 RENAME COLUMN a TO aa, ALGORITHM = INPLACE;
diff --git a/mysql-test/main/alter_table_lock.result b/mysql-test/main/alter_table_lock.result
index 170a7c47e6b67..c42a621faf1b0 100644
--- a/mysql-test/main/alter_table_lock.result
+++ b/mysql-test/main/alter_table_lock.result
@@ -1,23 +1,4 @@
#
-# MDEV-23836: Assertion `! is_set() || m_can_overwrite_status' in
-# Diagnostics_area::set_error_status (interrupted ALTER TABLE under LOCK)
-#
-SET @max_session_mem_used_save= @@max_session_mem_used;
-CREATE TABLE t1 (a INT);
-SELECT * FROM t1;
-a
-ALTER TABLE x MODIFY xx INT;
-ERROR 42S02: Table 'test.x' doesn't exist
-SET SESSION max_session_mem_used= 8192;
-LOCK TABLE t1 WRITE;
-ALTER TABLE t1 CHANGE COLUMN IF EXISTS b c INT;
-SET SESSION max_session_mem_used = @max_session_mem_used_save;
-UNLOCK TABLES;
-DROP TABLE t1;
-#
-# End of 10.5 tests
-#
-#
# MDEV-28943 Online alter fails under LOCK TABLE with ER_ALTER_OPERATION_NOT_SUPPORTED_REASON
#
create table t1 (f int) engine=innodb;
@@ -58,9 +39,6 @@ alter online table t1 add column s blob not null, algorithm=inplace;
ERROR 0A000: LOCK=NONE is not supported. Reason: Fulltext index creation requires a lock. Try LOCK=SHARED
drop table t1;
#
-# End of 10.11 tests
-#
-#
# MDEV-35611 Assertion failure in Diagnostics_area::sql_errno upon interrupted ALTER
#
CREATE TABLE t (a INT) ENGINE=MyISAM;
@@ -69,13 +47,11 @@ LOCK TABLE t READ;
connection con1;
SET max_statement_time=0.001;
ALTER TABLE t FORCE;
-ERROR 70100: Query execution was interrupted (max_statement_time exceeded)
+ERROR 70100: Query was interrupted: execution time limit 0.001 sec exceeded
ALTER TABLE IF EXISTS t FORCE;
-ERROR 70100: Query execution was interrupted (max_statement_time exceeded)
+ERROR 70100: Query was interrupted: execution time limit 0.001 sec exceeded
disconnect con1;
connection default;
UNLOCK TABLES;
DROP TABLE t;
-#
# End of 11.4 tests
-#
diff --git a/mysql-test/main/alter_table_lock.test b/mysql-test/main/alter_table_lock.test
index a01bd721e04d3..aaf40243a1bbb 100644
--- a/mysql-test/main/alter_table_lock.test
+++ b/mysql-test/main/alter_table_lock.test
@@ -1,36 +1,6 @@
--source include/not_embedded.inc
--source include/have_innodb.inc
---echo #
---echo # MDEV-23836: Assertion `! is_set() || m_can_overwrite_status' in
---echo # Diagnostics_area::set_error_status (interrupted ALTER TABLE under LOCK)
---echo #
-
-SET @max_session_mem_used_save= @@max_session_mem_used;
-
-CREATE TABLE t1 (a INT);
-SELECT * FROM t1;
-
---error ER_NO_SUCH_TABLE
-ALTER TABLE x MODIFY xx INT;
-
-SET SESSION max_session_mem_used= 8192;
---error 0,ER_OPTION_PREVENTS_STATEMENT
-LOCK TABLE t1 WRITE;
-
---disable_warnings
---error 0,ER_OPTION_PREVENTS_STATEMENT
-ALTER TABLE t1 CHANGE COLUMN IF EXISTS b c INT;
---enable_warnings
-
-SET SESSION max_session_mem_used = @max_session_mem_used_save;
-UNLOCK TABLES;
-DROP TABLE t1;
-
---echo #
---echo # End of 10.5 tests
---echo #
-
--echo #
--echo # MDEV-28943 Online alter fails under LOCK TABLE with ER_ALTER_OPERATION_NOT_SUPPORTED_REASON
--echo #
@@ -75,10 +45,6 @@ lock table t1 write;
alter online table t1 add column s blob not null, algorithm=inplace;
drop table t1;
---echo #
---echo # End of 10.11 tests
---echo #
-
--echo #
--echo # MDEV-35611 Assertion failure in Diagnostics_area::sql_errno upon interrupted ALTER
--echo #
@@ -97,6 +63,4 @@ ALTER TABLE IF EXISTS t FORCE;
UNLOCK TABLES;
DROP TABLE t;
---echo #
--echo # End of 11.4 tests
---echo #
diff --git a/mysql-test/main/alter_table_online_debug.result b/mysql-test/main/alter_table_online_debug.result
index 1148e178428df..537556e2e2db9 100644
--- a/mysql-test/main/alter_table_online_debug.result
+++ b/mysql-test/main/alter_table_online_debug.result
@@ -414,23 +414,23 @@ set debug_sync= 'now SIGNAL start_replication';
set debug_sync= 'now WAIT_FOR applied';
select stage, progress, examined_rows from INFORMATION_SCHEMA.PROCESSLIST where id = @con;
stage progress examined_rows
-3 53.390 0
+3 53.488 0
set debug_sync= 'now SIGNAL proceed WAIT_FOR applied';
select stage, progress, examined_rows from INFORMATION_SCHEMA.PROCESSLIST where id = @con;
stage progress examined_rows
-3 63.559 1
+3 63.636 1
set debug_sync= 'now SIGNAL proceed WAIT_FOR applied';
select stage, progress, examined_rows from INFORMATION_SCHEMA.PROCESSLIST where id = @con;
stage progress examined_rows
-3 71.610 2
+3 71.670 2
set debug_sync= 'now SIGNAL proceed WAIT_FOR applied';
select stage, progress, examined_rows from INFORMATION_SCHEMA.PROCESSLIST where id = @con;
stage progress examined_rows
-3 81.780 3
+3 81.818 3
set debug_sync= 'now SIGNAL proceed WAIT_FOR applied';
select stage, progress, examined_rows from INFORMATION_SCHEMA.PROCESSLIST where id = @con;
stage progress examined_rows
-3 89.831 4
+3 89.852 4
set debug_sync= 'now SIGNAL proceed WAIT_FOR applied';
select stage, progress, examined_rows from INFORMATION_SCHEMA.PROCESSLIST where id = @con;
stage progress examined_rows
diff --git a/mysql-test/main/alter_user.result b/mysql-test/main/alter_user.result
index 19e427e8f10fa..16147a6c7d237 100644
--- a/mysql-test/main/alter_user.result
+++ b/mysql-test/main/alter_user.result
@@ -34,12 +34,14 @@ select @@global.read_only;
ON
alter user foo;
ERROR HY000: The MariaDB server is running with the --read-only=ON option so it cannot execute this statement
+disconnect a;
# Grant READ_ONLY ADMIN privilege to the user.
connection default;
grant READ_ONLY ADMIN on *.* to foo;
# We now have READ_ONLY ADMIN privilege. We should be able to run alter user.
connect b, localhost, foo;
alter user foo;
+disconnect b;
connection default;
SET GLOBAL read_only = @start_read_only;
#
diff --git a/mysql-test/main/alter_user.test b/mysql-test/main/alter_user.test
index 6f4f9fb1e1eff..f00016e98c4c5 100644
--- a/mysql-test/main/alter_user.test
+++ b/mysql-test/main/alter_user.test
@@ -32,6 +32,7 @@ select @@global.read_only;
--error ER_OPTION_PREVENTS_STATEMENT
alter user foo;
+disconnect a;
--echo # Grant READ_ONLY ADMIN privilege to the user.
connection default;
@@ -40,6 +41,7 @@ grant READ_ONLY ADMIN on *.* to foo;
--echo # We now have READ_ONLY ADMIN privilege. We should be able to run alter user.
connect (b, localhost, foo);
alter user foo;
+disconnect b;
connection default;
SET GLOBAL read_only = @start_read_only;
diff --git a/mysql-test/main/analyze.result b/mysql-test/main/analyze.result
index 4af950ddc0048..43da87403a172 100644
--- a/mysql-test/main/analyze.result
+++ b/mysql-test/main/analyze.result
@@ -364,7 +364,7 @@ t1 CREATE TABLE `t1` (
`b` int(11) DEFAULT NULL,
KEY `b` (`b`),
KEY `idx` (`aaaa`),
- CONSTRAINT `t1_ibfk_1` FOREIGN KEY (`aaaa`) REFERENCES `t1` (`b`)
+ CONSTRAINT `1` FOREIGN KEY (`aaaa`) REFERENCES `t1` (`b`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci
SELECT index_name FROM mysql.index_stats WHERE table_name = 't1' order by index_name;
index_name
diff --git a/mysql-test/main/analyze_engine_stats.result b/mysql-test/main/analyze_engine_stats.result
index d68324a4bb527..8c0a0952509e3 100644
--- a/mysql-test/main/analyze_engine_stats.result
+++ b/mysql-test/main/analyze_engine_stats.result
@@ -72,7 +72,8 @@ X
"rows": 10000,
"r_rows": 10000,
"r_total_filtered": 100,
- "r_total_time_ms": "REPLACED",
+ "r_table_time_ms": "REPLACED",
+ "r_other_time_ms": "REPLACED",
"r_engine_stats": {
"pages_accessed": "REPLACED",
"pages_updated": "REPLACED"
@@ -106,7 +107,8 @@ X
"rows": 10000,
"r_rows": 10000,
"r_total_filtered": 50,
- "r_total_time_ms": "REPLACED",
+ "r_table_time_ms": "REPLACED",
+ "r_other_time_ms": "REPLACED",
"r_engine_stats": {
"pages_accessed": "REPLACED",
"pages_updated": "REPLACED"
diff --git a/mysql-test/main/analyze_format_json.result b/mysql-test/main/analyze_format_json.result
index 5797ef435ad30..0889f2ac82903 100644
--- a/mysql-test/main/analyze_format_json.result
+++ b/mysql-test/main/analyze_format_json.result
@@ -431,7 +431,8 @@ ANALYZE
"rows": 1000,
"r_rows": 1000,
"r_total_filtered": 100,
- "r_total_time_ms": "REPLACED",
+ "r_table_time_ms": "REPLACED",
+ "r_other_time_ms": "REPLACED",
"r_engine_stats": REPLACED,
"r_filtered": 100
}
@@ -499,7 +500,8 @@ ANALYZE
"rows": 10,
"r_rows": 10,
"r_total_filtered": 50,
- "r_total_time_ms": "REPLACED",
+ "r_table_time_ms": "REPLACED",
+ "r_other_time_ms": "REPLACED",
"r_engine_stats": REPLACED,
"attached_condition": "t1.pk < 10 and t1.b > 4",
"r_filtered": 50
@@ -1765,3 +1767,125 @@ ANALYZE
}
}
drop table t12,t13;
+#
+# MDEV-33309: ANALYZE FORMAT=JSON: UPDATE|DELETE don't show r_other_time_ms
+#
+create table t1 (pk int primary key, a int);
+insert into t1 select seq, seq from seq_1_to_1000;
+create table t2 like t1;
+insert into t2 select * from t1;
+# Top-level query block must have r_table_time_ms and r_other_time_ms
+analyze format=json
+update t1 set a=a+1
+where t1.pk > (select max(a) from t2 where t2.pk+1 = t1.pk+1 ) - 10;
+ANALYZE
+{
+ "query_optimization": {
+ "r_total_time_ms": "REPLACED"
+ },
+ "query_block": {
+ "select_id": 1,
+ "r_total_time_ms": "REPLACED",
+ "table": {
+ "update": 1,
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 1000,
+ "r_rows": 1000,
+ "r_total_filtered": 100,
+ "r_table_time_ms": "REPLACED",
+ "r_other_time_ms": "REPLACED",
+ "r_engine_stats": REPLACED,
+ "attached_condition": "t1.pk > (subquery#2) - 10",
+ "r_filtered": 100
+ },
+ "subqueries": [
+ {
+ "query_block": {
+ "select_id": 2,
+ "cost": "REPLACED",
+ "r_loops": 1000,
+ "r_total_time_ms": "REPLACED",
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "t2",
+ "access_type": "ALL",
+ "loops": 1,
+ "r_loops": 1000,
+ "rows": 1000,
+ "r_rows": 1000,
+ "cost": "REPLACED",
+ "r_table_time_ms": "REPLACED",
+ "r_other_time_ms": "REPLACED",
+ "r_engine_stats": REPLACED,
+ "filtered": 100,
+ "r_total_filtered": 0.1,
+ "attached_condition": "t2.pk + 1 = t1.pk + 1",
+ "r_filtered": 0.1
+ }
+ }
+ ]
+ }
+ }
+ ]
+ }
+}
+# Top-level query block must have r_table_time_ms and r_other_time_ms
+analyze format=json
+delete from t1
+where t1.pk > (select max(a) from t2 where t2.pk+1 = t1.pk+1 ) - 10;
+ANALYZE
+{
+ "query_optimization": {
+ "r_total_time_ms": "REPLACED"
+ },
+ "query_block": {
+ "select_id": 1,
+ "r_total_time_ms": "REPLACED",
+ "table": {
+ "delete": 1,
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 1000,
+ "r_rows": 1000,
+ "r_total_filtered": 100,
+ "r_table_time_ms": "REPLACED",
+ "r_other_time_ms": "REPLACED",
+ "r_engine_stats": REPLACED,
+ "attached_condition": "t1.pk > (subquery#2) - 10",
+ "r_filtered": 100
+ },
+ "subqueries": [
+ {
+ "query_block": {
+ "select_id": 2,
+ "cost": "REPLACED",
+ "r_loops": 1000,
+ "r_total_time_ms": "REPLACED",
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "t2",
+ "access_type": "ALL",
+ "loops": 1,
+ "r_loops": 1000,
+ "rows": 1000,
+ "r_rows": 1000,
+ "cost": "REPLACED",
+ "r_table_time_ms": "REPLACED",
+ "r_other_time_ms": "REPLACED",
+ "r_engine_stats": REPLACED,
+ "filtered": 100,
+ "r_total_filtered": 0.1,
+ "attached_condition": "t2.pk + 1 = t1.pk + 1",
+ "r_filtered": 0.1
+ }
+ }
+ ]
+ }
+ }
+ ]
+ }
+}
+drop table t1, t2;
diff --git a/mysql-test/main/analyze_format_json.test b/mysql-test/main/analyze_format_json.test
index b4cb24b0335b5..4cc196e84c5a5 100644
--- a/mysql-test/main/analyze_format_json.test
+++ b/mysql-test/main/analyze_format_json.test
@@ -346,3 +346,26 @@ analyze format=json select * from t13,t12 where t13.b between 1 and 2 and t12.a=
between 400 and 450 and t12.b like '%f%';
drop table t12,t13;
+
+--echo #
+--echo # MDEV-33309: ANALYZE FORMAT=JSON: UPDATE|DELETE don't show r_other_time_ms
+--echo #
+--source include/have_sequence.inc
+create table t1 (pk int primary key, a int);
+insert into t1 select seq, seq from seq_1_to_1000;
+create table t2 like t1;
+insert into t2 select * from t1;
+
+--echo # Top-level query block must have r_table_time_ms and r_other_time_ms
+--source include/analyze-format.inc
+analyze format=json
+update t1 set a=a+1
+where t1.pk > (select max(a) from t2 where t2.pk+1 = t1.pk+1 ) - 10;
+
+--echo # Top-level query block must have r_table_time_ms and r_other_time_ms
+--source include/analyze-format.inc
+analyze format=json
+delete from t1
+where t1.pk > (select max(a) from t2 where t2.pk+1 = t1.pk+1 ) - 10;
+
+drop table t1, t2;
diff --git a/mysql-test/main/analyze_stmt_orderby.result b/mysql-test/main/analyze_stmt_orderby.result
index 6db47ec187b17..cf9dc40964845 100644
--- a/mysql-test/main/analyze_stmt_orderby.result
+++ b/mysql-test/main/analyze_stmt_orderby.result
@@ -55,7 +55,8 @@ ANALYZE
"rows": 10000,
"r_rows": 10000,
"r_total_filtered": 100,
- "r_total_time_ms": "REPLACED",
+ "r_table_time_ms": "REPLACED",
+ "r_other_time_ms": "REPLACED",
"r_engine_stats": REPLACED,
"r_filtered": 100
}
@@ -112,7 +113,8 @@ ANALYZE
"rows": 9,
"r_rows": 10,
"r_total_filtered": 100,
- "r_total_time_ms": "REPLACED",
+ "r_table_time_ms": "REPLACED",
+ "r_other_time_ms": "REPLACED",
"r_engine_stats": REPLACED,
"attached_condition": "t2.a < 10",
"r_filtered": 100
@@ -167,7 +169,8 @@ ANALYZE
"rows": 10000,
"r_rows": 10000,
"r_total_filtered": 100,
- "r_total_time_ms": "REPLACED",
+ "r_table_time_ms": "REPLACED",
+ "r_other_time_ms": "REPLACED",
"r_engine_stats": REPLACED,
"r_filtered": 100
}
diff --git a/mysql-test/main/analyze_stmt_prefetch_count.result b/mysql-test/main/analyze_stmt_prefetch_count.result
index f5a5c9bda96d3..d55b416c32a85 100644
--- a/mysql-test/main/analyze_stmt_prefetch_count.result
+++ b/mysql-test/main/analyze_stmt_prefetch_count.result
@@ -33,9 +33,16 @@ select @pages_accessed > 1000 and @pages_accessed < 1500;
@pages_accessed > 1000 and @pages_accessed < 1500
1
set @total_read = (@pages_read_count + @pages_prefetch_read_count);
-select @pages_accessed*0.75 < @total_read, @total_read < @pages_accessed*1.25;
-@pages_accessed*0.75 < @total_read @total_read < @pages_accessed*1.25
+set @low_ok= @pages_accessed*0.75 < @total_read;
+set @high_ok= @total_read < @pages_accessed*1.50;
+select @low_ok, @high_ok;
+@low_ok @high_ok
1 1
+select
+if(@low_ok and @high_ok,0,@pages_accessed) unexpected_accessed,
+if(@low_ok and @high_ok,0,@total_read) unexpected_read;
+unexpected_accessed unexpected_read
+0 0
set @innodb_pages_read1=
(select variable_value
from information_schema.session_status
diff --git a/mysql-test/main/analyze_stmt_prefetch_count.test b/mysql-test/main/analyze_stmt_prefetch_count.test
index b5c6aac67b591..3e52830a0d06f 100644
--- a/mysql-test/main/analyze_stmt_prefetch_count.test
+++ b/mysql-test/main/analyze_stmt_prefetch_count.test
@@ -48,8 +48,13 @@ set @pages_prefetch_read_count= cast(json_value(@js,'$.pages_prefetch_read_count
select @pages_accessed > 1000 and @pages_accessed < 1500;
set @total_read = (@pages_read_count + @pages_prefetch_read_count);
+set @low_ok= @pages_accessed*0.75 < @total_read;
+set @high_ok= @total_read < @pages_accessed*1.50;
-select @pages_accessed*0.75 < @total_read, @total_read < @pages_accessed*1.25;
+select @low_ok, @high_ok;
+select
+if(@low_ok and @high_ok,0,@pages_accessed) unexpected_accessed,
+if(@low_ok and @high_ok,0,@total_read) unexpected_read;
set @innodb_pages_read1=
(select variable_value
diff --git a/mysql-test/main/analyze_stmt_privileges2.test b/mysql-test/main/analyze_stmt_privileges2.test
index 8b011c2b5924a..133572479b236 100644
--- a/mysql-test/main/analyze_stmt_privileges2.test
+++ b/mysql-test/main/analyze_stmt_privileges2.test
@@ -21,9 +21,6 @@
--source include/not_embedded.inc
--source include/default_optimizer_switch.inc
-# Save the initial number of concurrent sessions
---source include/count_sessions.inc
-
set GLOBAL sql_mode="";
set LOCAL sql_mode="";
@@ -5392,8 +5389,4 @@ connection default;
DROP USER 'privtest'@localhost;
USE test;
DROP DATABASE privtest_db;
-
set GLOBAL sql_mode=default;
---source include/wait_until_count_sessions.inc
-
-
diff --git a/mysql-test/main/aria_icp_debug.result b/mysql-test/main/aria_icp_debug.result
index fc01ee4fb3bb9..d9427a93798a2 100644
--- a/mysql-test/main/aria_icp_debug.result
+++ b/mysql-test/main/aria_icp_debug.result
@@ -1,5 +1,4 @@
set default_storage_engine=aria;
-drop table if exists t0,t1,t2;
create table t0(a int primary key);
insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
create table t1(a int primary key);
diff --git a/mysql-test/main/auth_rpl.test b/mysql-test/main/auth_rpl.test
index 9b2c4357cf09f..bfabc83aba56c 100644
--- a/mysql-test/main/auth_rpl.test
+++ b/mysql-test/main/auth_rpl.test
@@ -57,7 +57,9 @@ DROP USER 'plug_user';
--echo # Cleanup (on master).
--connection master
+--disable_warnings
DROP USER 'plug_user';
+--enable_warnings
--let $rpl_only_running_threads= 1
--source include/rpl_end.inc
diff --git a/mysql-test/main/backup_lock.result b/mysql-test/main/backup_lock.result
index 6e2ccad5091ea..0103a0fc92626 100644
--- a/mysql-test/main/backup_lock.result
+++ b/mysql-test/main/backup_lock.result
@@ -55,7 +55,7 @@ MDL_SHARED_WRITE Table metadata lock test t1
MDL_SHARED_UPGRADABLE Table metadata lock test t1
MDL_INTENTION_EXCLUSIVE Schema metadata lock test
SET STATEMENT max_statement_time=1 FOR backup stage block_ddl;
-ERROR 70100: Query execution was interrupted (max_statement_time exceeded)
+ERROR 70100: Query was interrupted: execution time limit 1.0 sec exceeded
backup stage block_ddl;
connection default;
commit;
diff --git a/mysql-test/main/backup_locks.result b/mysql-test/main/backup_locks.result
index 4d5de53c1fbf3..0d4f24cfb611c 100644
--- a/mysql-test/main/backup_locks.result
+++ b/mysql-test/main/backup_locks.result
@@ -51,13 +51,13 @@ connection con1;
CREATE OR REPLACE SEQUENCE seq1 START -28;
ERROR HY000: Sequence 'test.seq1' has out of range value for options
SET STATEMENT max_statement_time=10 FOR CREATE OR REPLACE SEQUENCE seq1 START 50;
-ERROR 70100: Query execution was interrupted (max_statement_time exceeded)
+ERROR 70100: Query was interrupted: execution time limit 10.0 sec exceeded
SET STATEMENT max_statement_time=10 FOR ALTER SEQUENCE IF EXISTS seq1 NOMAXVALUE;
-ERROR 70100: Query execution was interrupted (max_statement_time exceeded)
+ERROR 70100: Query was interrupted: execution time limit 10.0 sec exceeded
SET STATEMENT max_statement_time=10 FOR ALTER SEQUENCE IF EXISTS seq1 MAXVALUE 1000;
-ERROR 70100: Query execution was interrupted (max_statement_time exceeded)
+ERROR 70100: Query was interrupted: execution time limit 10.0 sec exceeded
SET STATEMENT max_statement_time=10 for rename table seq2 to seq3, seq3 to seq1;
-ERROR 70100: Query execution was interrupted (max_statement_time exceeded)
+ERROR 70100: Query was interrupted: execution time limit 10.0 sec exceeded
connection default;
backup unlock;
drop table seq1,seq2;
diff --git a/mysql-test/main/backup_locks.test b/mysql-test/main/backup_locks.test
index 6a1fe9f609406..c2618cbbadbde 100644
--- a/mysql-test/main/backup_locks.test
+++ b/mysql-test/main/backup_locks.test
@@ -5,6 +5,7 @@
--source include/long_test.inc
--source include/have_innodb.inc
--source include/have_metadata_lock_info.inc
+--source include/have_profiling.inc
--source include/not_embedded.inc
--source include/no_view_protocol.inc
diff --git a/mysql-test/main/backup_priv.result b/mysql-test/main/backup_priv.result
index 4169f58f40fa0..cd7f2c1dd3239 100644
--- a/mysql-test/main/backup_priv.result
+++ b/mysql-test/main/backup_priv.result
@@ -13,6 +13,7 @@ BACKUP STAGE FLUSH;
SELECT lock_mode FROM information_schema.metadata_lock_info WHERE lock_type='Backup lock';
lock_mode
MDL_BACKUP_FLUSH
+change_user user2,,;
SELECT lock_mode FROM information_schema.metadata_lock_info WHERE lock_type='Backup lock';
lock_mode
disconnect con1;
diff --git a/mysql-test/main/backup_priv.test b/mysql-test/main/backup_priv.test
index c77075c239356..a446e85b31f84 100644
--- a/mysql-test/main/backup_priv.test
+++ b/mysql-test/main/backup_priv.test
@@ -22,7 +22,6 @@ SELECT lock_mode FROM information_schema.metadata_lock_info WHERE lock_type='Bac
change_user user2;
SELECT lock_mode FROM information_schema.metadata_lock_info WHERE lock_type='Backup lock';
--disconnect con1
---source include/wait_until_disconnected.inc
--connection default
--echo # A very low privileged user (-> con4) cannot acquire the backup lock
@@ -39,7 +38,6 @@ BACKUP STAGE BLOCK_COMMIT;
--error ER_SPECIFIC_ACCESS_DENIED_ERROR
BACKUP STAGE END;
--disconnect con1
---source include/wait_until_disconnected.inc
--connection default
DROP USER user1@localhost, user2@localhost;
diff --git a/mysql-test/main/backup_stages.test b/mysql-test/main/backup_stages.test
index 1f5fb2d682823..d1d30e2b04c84 100644
--- a/mysql-test/main/backup_stages.test
+++ b/mysql-test/main/backup_stages.test
@@ -6,11 +6,9 @@
# A transactional engine
--source include/have_innodb.inc
--source include/have_metadata_lock_info.inc
+--source include/no_view_protocol.inc
# As non transactional engine we have MyISAM anyway.
-# Save the initial number of concurrent sessions.
---source include/count_sessions.inc
-
let $old_lock_wait_timeout = `SELECT @@global.lock_wait_timeout`;
--echo #-----------------------------------------------------------------------
@@ -384,4 +382,3 @@ SET GLOBAL lock_wait_timeout = $old_lock_wait_timeout;
--disconnect backup
--connection default
---source include/wait_until_count_sessions.inc
diff --git a/mysql-test/main/binary_to_hex.result b/mysql-test/main/binary_to_hex.result
index 3918021f3e65a..c24f91eef63a1 100644
--- a/mysql-test/main/binary_to_hex.result
+++ b/mysql-test/main/binary_to_hex.result
@@ -1,5 +1,3 @@
-USE test;
-DROP TABLE IF EXISTS t1, t2;
CREATE TABLE t1 (c1 TINYBLOB,
c2 BLOB,
c3 MEDIUMBLOB,
diff --git a/mysql-test/main/binary_to_hex.test b/mysql-test/main/binary_to_hex.test
index be4fb301e4033..bd7397313fbe8 100644
--- a/mysql-test/main/binary_to_hex.test
+++ b/mysql-test/main/binary_to_hex.test
@@ -8,15 +8,8 @@
# CLIENT (CONTRIBUTION)
#
-# Save the initial number of concurrent sessions
---source include/count_sessions.inc
--source include/not_embedded.inc
-USE test;
---disable_warnings
-DROP TABLE IF EXISTS t1, t2;
---enable_warnings
-
CREATE TABLE t1 (c1 TINYBLOB,
c2 BLOB,
c3 MEDIUMBLOB,
@@ -91,6 +84,3 @@ remove_file $MYSQLTEST_VARDIR/tmp/mdev-14593.sql;
#Cleanup
DROP TABLE t1;
-
-# Wait till all disconnects are completed
- --source include/wait_until_count_sessions.inc
diff --git a/mysql-test/main/bool_innodb.result b/mysql-test/main/bool_innodb.result
new file mode 100644
index 0000000000000..c08bc52a1b779
--- /dev/null
+++ b/mysql-test/main/bool_innodb.result
@@ -0,0 +1,10 @@
+#
+# MDEV-35288: Assertion `!is_cond()' failed in
+# virtual longlong Item_bool_func::val_int()
+#
+CREATE TABLE t (a INT) ENGINE=INNODB;
+SELECT SUM(a), ROWNUM() AS r FROM t HAVING r=1;
+SUM(a) r
+NULL 1
+DROP TABLE t;
+# End of 10.5 tests
diff --git a/mysql-test/main/bool_innodb.test b/mysql-test/main/bool_innodb.test
new file mode 100644
index 0000000000000..744311990cfdc
--- /dev/null
+++ b/mysql-test/main/bool_innodb.test
@@ -0,0 +1,15 @@
+--source include/have_innodb.inc
+
+--echo #
+--echo # MDEV-35288: Assertion `!is_cond()' failed in
+--echo # virtual longlong Item_bool_func::val_int()
+--echo #
+
+CREATE TABLE t (a INT) ENGINE=INNODB;
+SELECT SUM(a), ROWNUM() AS r FROM t HAVING r=1;
+
+# Cleanup
+DROP TABLE t;
+
+
+--echo # End of 10.5 tests
diff --git a/mysql-test/main/bug39022.test b/mysql-test/main/bug39022.test
index 81dd6f14bed1c..bceb7229cba0a 100644
--- a/mysql-test/main/bug39022.test
+++ b/mysql-test/main/bug39022.test
@@ -52,11 +52,9 @@ connection thread2;
REAP;
disconnect thread2;
---source include/wait_until_disconnected.inc
connection thread1;
disconnect thread1;
---source include/wait_until_disconnected.inc
connection default;
diff --git a/mysql-test/main/chained_ssl_certificates.opt b/mysql-test/main/chained_ssl_certificates.opt
new file mode 100644
index 0000000000000..bb2f8e1d88341
--- /dev/null
+++ b/mysql-test/main/chained_ssl_certificates.opt
@@ -0,0 +1,3 @@
+--ssl-ca=$MYSQL_TEST_DIR/std_data/cachain/root.crt
+--ssl-key=$MYSQL_TEST_DIR/std_data/cachain/server.key
+--ssl-cert=$MYSQL_TEST_DIR/std_data/cachain/server.cachain
diff --git a/mysql-test/main/chained_ssl_certificates.result b/mysql-test/main/chained_ssl_certificates.result
new file mode 100644
index 0000000000000..08911b0c936cb
--- /dev/null
+++ b/mysql-test/main/chained_ssl_certificates.result
@@ -0,0 +1,12 @@
+call mtr.add_suppression("Server SSL certificate doesn't verify");
+CREATE USER 'user1'@'%' REQUIRE SSL;
+Variable_name Value
+Ssl_version TLS
+
+Restart server and provide ssl-ca comprising intermediate_ca1 in addition to the root ca.
+Variable_name Value
+Ssl_version TLS
+
+Restart server and provide unrelated ssl-ca at server startup
+ERROR 2026 (HY000): TLS/SSL error:
+DROP USER 'user1';
diff --git a/mysql-test/main/chained_ssl_certificates.test b/mysql-test/main/chained_ssl_certificates.test
new file mode 100644
index 0000000000000..9d315e9480796
--- /dev/null
+++ b/mysql-test/main/chained_ssl_certificates.test
@@ -0,0 +1,74 @@
+# These tests are inspired from the following commit from MySQL Server
+# https://github.com/mysql/mysql-server/commit/969afef933f1872c5f38ea93047ef05c4509c335
+
+# Credits to salman.s.khan@oracle.com
+
+#####################################################################################
+# This test verifies MariaDB can handle chained ssl certificate
+# This test uses chained ssl certificates which is depicted as
+# below:-
+#
+# +---------+
+# | Root CA |
+# +---------+
+# |
+# /------------+-----------\
+# | |
+# +------------------+ +------------------+
+# | Intermediate CA1 | | Intermediate CA2 |
+# +------------------+ +------------------+
+# | |
+# +-------------+ +-------------+
+# | Server | | Client |
+# | certificate | | certificate |
+# +-------------+ +-------------+
+#
+# certificates that may be helpful for chain construction.
+# In order to validate server cert correctly, we need to
+# provide the trusted root certificate and the untrusted
+# intermediate certificates as part of ssl-ca. Hence
+# root_intermediate_ca1.crt (trusted root certificate +
+# untrusted intermediate ca1 certificate) is passed as with
+# --ssl-ca option
+
+--source include/not_embedded.inc
+--source include/have_ssl_communication.inc
+
+#Suppress warning by the server certificate verification check: unrelated CA
+call mtr.add_suppression("Server SSL certificate doesn't verify");
+
+CREATE USER 'user1'@'%' REQUIRE SSL;
+
+--replace_result TLSv1.3 TLS TLSv1.2 TLS
+--exec $MYSQL --host=localhost -P $MASTER_MYPORT --user=user1 --ssl-verify-server-cert --ssl-ca=$MYSQL_TEST_DIR/std_data/cachain/root.crt --ssl-cert=$MYSQL_TEST_DIR/std_data/cachain/client.cachain --ssl-key=$MYSQL_TEST_DIR/std_data/cachain/client.key -e "SHOW STATUS LIKE 'ssl_version'"
+
+--echo
+--echo Restart server and provide ssl-ca comprising intermediate_ca1 in addition to the root ca.
+--write_line wait $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+--shutdown_server
+--source include/wait_until_disconnected.inc
+
+--write_line "restart:--ssl-ca=$MYSQL_TEST_DIR/std_data/cachain/root_intermediate_ca1.crt --ssl-key=$MYSQL_TEST_DIR/std_data/cachain/server.key --ssl-cert=$MYSQL_TEST_DIR/std_data/cachain/server.cachain" $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+
+--replace_result TLSv1.3 TLS TLSv1.2 TLS
+--exec $MYSQL --host=localhost -P $MASTER_MYPORT --user=user1 --ssl-verify-server-cert --ssl-ca=$MYSQL_TEST_DIR/std_data/cachain/root.crt --ssl-cert=$MYSQL_TEST_DIR/std_data/cachain/client.cachain --ssl-key=$MYSQL_TEST_DIR/std_data/cachain/client.key -e "SHOW STATUS LIKE 'ssl_version'"
+
+--echo
+--echo Restart server and provide unrelated ssl-ca at server startup
+--write_line wait $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+--shutdown_server
+--source include/wait_until_disconnected.inc
+
+--write_line "restart:--ssl-ca=$MYSQL_TEST_DIR/std_data/cachain/unrelated_root.crt --ssl-key=$MYSQL_TEST_DIR/std_data/cachain/server.key --ssl-cert=$MYSQL_TEST_DIR/std_data/cachain/server.cachain" $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+
+--replace_regex /(ERROR 2026 \(HY000\): TLS\/SSL error:).*/\1/
+--error 1
+--exec $MYSQL --host=localhost -P $MASTER_MYPORT --user=user1 --ssl-verify-server-cert --ssl-ca=$MYSQL_TEST_DIR/std_data/cachain/unrelated_root.crt --ssl-cert=$MYSQL_TEST_DIR/std_data/cachain/client.cachain --ssl-key=$MYSQL_TEST_DIR/std_data/cachain/client.key -e "SHOW STATUS LIKE 'ssl_version'" 2>&1
+--echo
+
+# Cleanup
+DROP USER 'user1';
diff --git a/mysql-test/main/change_master_default.result b/mysql-test/main/change_master_default.result
new file mode 100644
index 0000000000000..9178c395339fb
--- /dev/null
+++ b/mysql-test/main/change_master_default.result
@@ -0,0 +1,266 @@
+# Start of main.change_master_default
+CREATE PROCEDURE show_defaultable_fields()
+SELECT connection_name,
+connect_retry,
+master_ssl_allowed,
+master_ssl_ca_file,
+master_ssl_ca_path,
+master_ssl_cert,
+master_ssl_cipher,
+master_ssl_key,
+master_ssl_verify_server_cert,
+master_ssl_crl,
+master_ssl_crlpath,
+using_gtid,
+master_retry_count,
+slave_heartbeat_period
+FROM information_schema.slave_status ORDER BY connection_name;
+CHANGE MASTER 'unset' TO master_host='127.0.1.1';
+CHANGE MASTER 'defaulted' TO
+master_connect_retry= DEFAULT,
+master_ssl= DEFAULT,
+master_ssl_ca= DEFAULT,
+master_ssl_capath= DEFAULT,
+master_ssl_cert= DEFAULT,
+master_ssl_cipher= DEFAULT,
+master_ssl_key= DEFAULT,
+master_ssl_verify_server_cert= DEFAULT,
+master_ssl_crl= DEFAULT,
+master_ssl_crlpath= DEFAULT,
+master_use_gtid= DEFAULT,
+master_retry_count= DEFAULT,
+master_heartbeat_period= DEFAULT,
+master_host= '127.0.1.2';
+CHANGE MASTER TO # Default master does not replace named masters
+master_connect_retry= 90,
+master_ssl= FALSE,
+master_ssl_ca= 'specified_ca',
+master_ssl_capath= 'specified_capath',
+master_ssl_cert= 'specified_cert',
+master_ssl_cipher= 'specified_cipher',
+master_ssl_key= 'specified_key',
+master_ssl_verify_server_cert= FALSE,
+master_ssl_crl= 'specified_crl',
+master_ssl_crlpath= 'specified_crlpath',
+master_use_gtid= NO,
+master_retry_count= 150000,
+master_heartbeat_period= 45,
+master_host='127.0.0.1';
+CALL show_defaultable_fields();
+connection_name
+connect_retry 90
+master_ssl_allowed No
+master_ssl_ca_file specified_ca
+master_ssl_ca_path specified_capath
+master_ssl_cert specified_cert
+master_ssl_cipher specified_cipher
+master_ssl_key specified_key
+master_ssl_verify_server_cert No
+master_ssl_crl specified_crl
+master_ssl_crlpath specified_crlpath
+using_gtid No
+master_retry_count 150000
+slave_heartbeat_period 45.000
+connection_name defaulted
+connect_retry 60
+master_ssl_allowed Yes
+master_ssl_ca_file
+master_ssl_ca_path
+master_ssl_cert
+master_ssl_cipher
+master_ssl_key
+master_ssl_verify_server_cert Yes
+master_ssl_crl
+master_ssl_crlpath
+using_gtid Slave_Pos
+master_retry_count 100000
+slave_heartbeat_period 60.000
+connection_name unset
+connect_retry 60
+master_ssl_allowed Yes
+master_ssl_ca_file
+master_ssl_ca_path
+master_ssl_cert
+master_ssl_cipher
+master_ssl_key
+master_ssl_verify_server_cert Yes
+master_ssl_crl
+master_ssl_crlpath
+using_gtid Slave_Pos
+master_retry_count 100000
+slave_heartbeat_period 60.000
+# Those set or left as `DEFAULT` should pick up changes to defaults.
+# restart: --skip-slave-start --master-connect-retry=30 --skip-master-ssl --master-ssl-ca=default_ca --master-ssl-capath=default_capath --master-ssl-cert=default_cert --master-ssl-cipher=default_cipher --master-ssl-key=default_key --skip-master-ssl-verify-server-cert --master-ssl-crl=default_crl --master-ssl-crlpath=default_crlpath --master-use-gtid=CURRENT_POS --master-retry-count=50000 --master-heartbeat-period=15
+CALL show_defaultable_fields();
+connection_name
+connect_retry 90
+master_ssl_allowed No
+master_ssl_ca_file specified_ca
+master_ssl_ca_path specified_capath
+master_ssl_cert specified_cert
+master_ssl_cipher specified_cipher
+master_ssl_key specified_key
+master_ssl_verify_server_cert No
+master_ssl_crl specified_crl
+master_ssl_crlpath specified_crlpath
+using_gtid No
+master_retry_count 150000
+slave_heartbeat_period 45.000
+connection_name defaulted
+connect_retry 30
+master_ssl_allowed No
+master_ssl_ca_file default_ca
+master_ssl_ca_path default_capath
+master_ssl_cert default_cert
+master_ssl_cipher default_cipher
+master_ssl_key default_key
+master_ssl_verify_server_cert No
+master_ssl_crl default_crl
+master_ssl_crlpath default_crlpath
+using_gtid Current_Pos
+master_retry_count 50000
+slave_heartbeat_period 15.000
+connection_name unset
+connect_retry 30
+master_ssl_allowed No
+master_ssl_ca_file default_ca
+master_ssl_ca_path default_capath
+master_ssl_cert default_cert
+master_ssl_cipher default_cipher
+master_ssl_key default_key
+master_ssl_verify_server_cert No
+master_ssl_crl default_crl
+master_ssl_crlpath default_crlpath
+using_gtid Current_Pos
+master_retry_count 50000
+slave_heartbeat_period 15.000
+SET @@GLOBAL.slave_net_timeout= 100;
+SELECT connection_name, slave_heartbeat_period
+FROM information_schema.slave_status ORDER BY connection_name;
+connection_name slave_heartbeat_period
+ 45.000
+defaulted 15.000
+unset 15.000
+CHANGE MASTER TO
+master_connect_retry= DEFAULT,
+master_ssl= DEFAULT,
+master_ssl_ca= DEFAULT,
+master_ssl_capath= DEFAULT,
+master_ssl_cert= DEFAULT,
+master_ssl_cipher= DEFAULT,
+master_ssl_key= DEFAULT,
+master_ssl_verify_server_cert= DEFAULT,
+master_ssl_crl= DEFAULT,
+master_ssl_crlpath= DEFAULT,
+master_use_gtid= DEFAULT,
+master_retry_count= DEFAULT,
+master_heartbeat_period= DEFAULT;
+CALL show_defaultable_fields();
+connection_name
+connect_retry 30
+master_ssl_allowed No
+master_ssl_ca_file default_ca
+master_ssl_ca_path default_capath
+master_ssl_cert default_cert
+master_ssl_cipher default_cipher
+master_ssl_key default_key
+master_ssl_verify_server_cert No
+master_ssl_crl default_crl
+master_ssl_crlpath default_crlpath
+using_gtid Current_Pos
+master_retry_count 50000
+slave_heartbeat_period 15.000
+connection_name defaulted
+connect_retry 30
+master_ssl_allowed No
+master_ssl_ca_file default_ca
+master_ssl_ca_path default_capath
+master_ssl_cert default_cert
+master_ssl_cipher default_cipher
+master_ssl_key default_key
+master_ssl_verify_server_cert No
+master_ssl_crl default_crl
+master_ssl_crlpath default_crlpath
+using_gtid Current_Pos
+master_retry_count 50000
+slave_heartbeat_period 15.000
+connection_name unset
+connect_retry 30
+master_ssl_allowed No
+master_ssl_ca_file default_ca
+master_ssl_ca_path default_capath
+master_ssl_cert default_cert
+master_ssl_cipher default_cipher
+master_ssl_key default_key
+master_ssl_verify_server_cert No
+master_ssl_crl default_crl
+master_ssl_crlpath default_crlpath
+using_gtid Current_Pos
+master_retry_count 50000
+slave_heartbeat_period 15.000
+RESET REPLICA 'unset' ALL;
+CHANGE MASTER 'unset' TO master_host='127.0.1.3';
+# Validate command line options
+# restart_abort: --master-heartbeat-period=''
+# restart_abort: --master-heartbeat-period=123abc
+# restart_abort: --master-heartbeat-period=-1
+# restart_abort: --master-heartbeat-period=4294967.296
+# restart: --skip-slave-start --master-heartbeat-period=0.000499
+SELECT connection_name, slave_heartbeat_period
+FROM information_schema.slave_status ORDER BY connection_name;
+connection_name slave_heartbeat_period
+ 0.000
+defaulted 0.000
+unset 0.000
+CALL mtr.add_suppression('.*master-heartbeat-period.+0.*disabl.+');
+FOUND 1 /\[Warning\] .*master-heartbeat-period.+0.*disabl.+/ in mysqld.1.err
+# restart: --skip-slave-start --skip-master-ssl --master-ssl --skip-master-ssl-verify-server-cert --master-ssl-verify-server-cert --master-use-gtid=NO --autoset-master-use-gtid --master-heartbeat-period=45 --autoset-master-heartbeat-period
+CALL show_defaultable_fields();
+connection_name
+connect_retry 60
+master_ssl_allowed Yes
+master_ssl_ca_file
+master_ssl_ca_path
+master_ssl_cert
+master_ssl_cipher
+master_ssl_key
+master_ssl_verify_server_cert Yes
+master_ssl_crl
+master_ssl_crlpath
+using_gtid Slave_Pos
+master_retry_count 100000
+slave_heartbeat_period 60.000
+connection_name defaulted
+connect_retry 60
+master_ssl_allowed Yes
+master_ssl_ca_file
+master_ssl_ca_path
+master_ssl_cert
+master_ssl_cipher
+master_ssl_key
+master_ssl_verify_server_cert Yes
+master_ssl_crl
+master_ssl_crlpath
+using_gtid Slave_Pos
+master_retry_count 100000
+slave_heartbeat_period 60.000
+connection_name unset
+connect_retry 60
+master_ssl_allowed Yes
+master_ssl_ca_file
+master_ssl_ca_path
+master_ssl_cert
+master_ssl_cipher
+master_ssl_key
+master_ssl_verify_server_cert Yes
+master_ssl_crl
+master_ssl_crlpath
+using_gtid Slave_Pos
+master_retry_count 100000
+slave_heartbeat_period 60.000
+# Clean-up
+DROP PROCEDURE show_defaultable_fields;
+RESET REPLICA 'unset' ALL;
+RESET REPLICA 'defaulted' ALL;
+RESET REPLICA ALL;
+# End of main.change_master_default
diff --git a/mysql-test/main/change_master_default.test b/mysql-test/main/change_master_default.test
new file mode 100644
index 0000000000000..a4e25c8d86992
--- /dev/null
+++ b/mysql-test/main/change_master_default.test
@@ -0,0 +1,149 @@
+--echo # Start of main.change_master_default
+
+# MDEV-28302: Test how `CHANGE MASTER [named]` reads server
+# options for its default values and the lack of those options.
+# The test creates multiple CHANGE MASTER connections,
+# where the defaultable fields of a connection are:
+# * left unset
+# * set to `DEFAULT`
+# * configured with values
+
+# only need CHANGE MASTER and IS.slave_status
+--source include/have_binlog_format_mixed.inc
+
+CREATE PROCEDURE show_defaultable_fields()
+SELECT connection_name,
+ connect_retry,
+ master_ssl_allowed,
+ master_ssl_ca_file,
+ master_ssl_ca_path,
+ master_ssl_cert,
+ master_ssl_cipher,
+ master_ssl_key,
+ master_ssl_verify_server_cert,
+ master_ssl_crl,
+ master_ssl_crlpath,
+ using_gtid,
+ master_retry_count,
+ slave_heartbeat_period
+FROM information_schema.slave_status ORDER BY connection_name;
+
+CHANGE MASTER 'unset' TO master_host='127.0.1.1';
+
+CHANGE MASTER 'defaulted' TO
+ master_connect_retry= DEFAULT,
+ master_ssl= DEFAULT,
+ master_ssl_ca= DEFAULT,
+ master_ssl_capath= DEFAULT,
+ master_ssl_cert= DEFAULT,
+ master_ssl_cipher= DEFAULT,
+ master_ssl_key= DEFAULT,
+ master_ssl_verify_server_cert= DEFAULT,
+ master_ssl_crl= DEFAULT,
+ master_ssl_crlpath= DEFAULT,
+ master_use_gtid= DEFAULT,
+ master_retry_count= DEFAULT,
+ master_heartbeat_period= DEFAULT,
+ master_host= '127.0.1.2';
+
+CHANGE MASTER TO # Default master does not replace named masters
+ master_connect_retry= 90,
+ master_ssl= FALSE,
+ master_ssl_ca= 'specified_ca',
+ master_ssl_capath= 'specified_capath',
+ master_ssl_cert= 'specified_cert',
+ master_ssl_cipher= 'specified_cipher',
+ master_ssl_key= 'specified_key',
+ master_ssl_verify_server_cert= FALSE,
+ master_ssl_crl= 'specified_crl',
+ master_ssl_crlpath= 'specified_crlpath',
+ master_use_gtid= NO,
+ master_retry_count= 150000,
+ master_heartbeat_period= 45,
+ master_host='127.0.0.1';
+
+# Show freshly created configurations
+--query_vertical CALL show_defaultable_fields()
+
+
+--echo # Those set or left as `DEFAULT` should pick up changes to defaults.
+
+--let $restart_parameters= --skip-slave-start --master-connect-retry=30 --skip-master-ssl --master-ssl-ca=default_ca --master-ssl-capath=default_capath --master-ssl-cert=default_cert --master-ssl-cipher=default_cipher --master-ssl-key=default_key --skip-master-ssl-verify-server-cert --master-ssl-crl=default_crl --master-ssl-crlpath=default_crlpath --master-use-gtid=CURRENT_POS --master-retry-count=50000 --master-heartbeat-period=15
+--source include/restart_mysqld.inc # not_embedded
+--query_vertical CALL show_defaultable_fields()
+
+# The `DEFAULT` of `master_heartbeat_period` changes with `@@slave_net_timeout`.
+SET @@GLOBAL.slave_net_timeout= 100;
+SELECT connection_name, slave_heartbeat_period
+FROM information_schema.slave_status ORDER BY connection_name;
+
+# `DEFAULT` overwrites the existing configs for only the CHANGEd connection.
+CHANGE MASTER TO
+ master_connect_retry= DEFAULT,
+ master_ssl= DEFAULT,
+ master_ssl_ca= DEFAULT,
+ master_ssl_capath= DEFAULT,
+ master_ssl_cert= DEFAULT,
+ master_ssl_cipher= DEFAULT,
+ master_ssl_key= DEFAULT,
+ master_ssl_verify_server_cert= DEFAULT,
+ master_ssl_crl= DEFAULT,
+ master_ssl_crlpath= DEFAULT,
+ master_use_gtid= DEFAULT,
+ master_retry_count= DEFAULT,
+ master_heartbeat_period= DEFAULT;
+--query_vertical CALL show_defaultable_fields()
+
+# Recreate 'unset' to see later that it saves `DEFAULT`, not the options' values
+--disable_warnings
+ RESET REPLICA 'unset' ALL;
+--enable_warnings
+CHANGE MASTER 'unset' TO master_host='127.0.1.3';
+
+
+--echo # Validate command line options
+
+# Invalid `--master-heartbeat-period` values should abort the server
+# (`restart_abort` includes a wait for the server to exit on its own,
+# e.g., due to a startup error.)
+--source include/shutdown_mysqld.inc
+--let $restart_parameters= restart_abort: --master-heartbeat-period=''
+--echo # $restart_parameters
+--write_line "$restart_parameters" $_expect_file_name
+--let $restart_parameters= restart_abort: --master-heartbeat-period=123abc
+--echo # $restart_parameters
+--write_line "$restart_parameters" $_expect_file_name
+--let $restart_parameters= restart_abort: --master-heartbeat-period=-1
+--echo # $restart_parameters
+--write_line "$restart_parameters" $_expect_file_name
+--let $restart_parameters= restart_abort: --master-heartbeat-period=4294967.296
+--echo # $restart_parameters
+--write_line "$restart_parameters" $_expect_file_name
+
+# Numbers between 0 and 0.5 exclusive should warn about rounding to 0 (disabled)
+--let $restart_parameters= --skip-slave-start --master-heartbeat-period=0.000499
+--source include/start_mysqld.inc
+SELECT connection_name, slave_heartbeat_period
+FROM information_schema.slave_status ORDER BY connection_name;
+--let $regexp= .*master-heartbeat-period.+0.*disabl.+
+--eval CALL mtr.add_suppression('$regexp')
+--let SEARCH_FILE= `SELECT @@log_error`
+--let SEARCH_PATTERN= \[Warning\] $regexp
+--source include/search_pattern_in_file.inc
+
+# Test prefixes: adding `auto-` and omitting `skip-`
+--let $restart_parameters= --skip-slave-start --skip-master-ssl --master-ssl --skip-master-ssl-verify-server-cert --master-ssl-verify-server-cert --master-use-gtid=NO --autoset-master-use-gtid --master-heartbeat-period=45 --autoset-master-heartbeat-period
+--source include/restart_mysqld.inc
+
+--query_vertical CALL show_defaultable_fields()
+
+
+--echo # Clean-up
+
+DROP PROCEDURE show_defaultable_fields;
+
+RESET REPLICA 'unset' ALL;
+RESET REPLICA 'defaulted' ALL;
+RESET REPLICA ALL;
+
+--echo # End of main.change_master_default
diff --git a/mysql-test/main/change_user.result b/mysql-test/main/change_user.result
index d9bbb34b6c295..3b7d668947dbb 100644
--- a/mysql-test/main/change_user.result
+++ b/mysql-test/main/change_user.result
@@ -1,7 +1,4 @@
connect old,localhost,root,,,,,auth=mysql_old_password:mysql_native_password;
-set global secure_auth=0;
-Warnings:
-Warning 1287 '@@secure_auth' is deprecated and will be removed in a future release
create user test_nopw;
grant select on test.* to test_nopw;
create user test_oldpw identified by password "09301740536db389";
@@ -11,27 +8,27 @@ grant select on test.* to test_newpw;
select concat('<', user(), '>'), concat('<', current_user(), '>'), database();
concat('<', user(), '>') concat('<', current_user(), '>') database()
test
+change_user test_nopw,,;
select concat('<', user(), '>'), concat('<', current_user(), '>'), database();
concat('<', user(), '>') concat('<', current_user(), '>') database()
NULL
-select concat('<', user(), '>'), concat('<', current_user(), '>'), database();
-concat('<', user(), '>') concat('<', current_user(), '>') database()
- NULL
+change_user test_newpw,newpw,;
select concat('<', user(), '>'), concat('<', current_user(), '>'), database();
concat('<', user(), '>') concat('<', current_user(), '>') database()
NULL
+change_user root,,;
select concat('<', user(), '>'), concat('<', current_user(), '>'), database();
concat('<', user(), '>') concat('<', current_user(), '>') database()
NULL
+change_user test_nopw,,test;
select concat('<', user(), '>'), concat('<', current_user(), '>'), database();
concat('<', user(), '>') concat('<', current_user(), '>') database()
test
-select concat('<', user(), '>'), concat('<', current_user(), '>'), database();
-concat('<', user(), '>') concat('<', current_user(), '>') database()
- test
+change_user test_newpw,newpw,test;
select concat('<', user(), '>'), concat('<', current_user(), '>'), database();
concat('<', user(), '>') concat('<', current_user(), '>') database()
test
+change_user root,,test;
select concat('<', user(), '>'), concat('<', current_user(), '>'), database();
concat('<', user(), '>') concat('<', current_user(), '>') database()
test
@@ -45,7 +42,7 @@ SELECT @@session.sql_big_selects;
SELECT @@global.max_join_size;
@@global.max_join_size
HA_POS_ERROR
-change_user
+change_user root,,test;
SELECT @@session.sql_big_selects;
@@session.sql_big_selects
1
@@ -54,13 +51,13 @@ SELECT @@global.max_join_size;
HA_POS_ERROR
SET @@global.max_join_size = 10000;
SET @@session.max_join_size = default;
-change_user
+change_user root,,test;
SELECT @@session.sql_big_selects;
@@session.sql_big_selects
0
SET @@global.max_join_size = 18446744073709551615;
SET @@session.max_join_size = default;
-change_user
+change_user root,,test;
SELECT @@session.sql_big_selects;
@@session.sql_big_selects
1
@@ -83,7 +80,7 @@ GET_LOCK('bug31418', 1)
SELECT IS_USED_LOCK('bug31418') = CONNECTION_ID();
IS_USED_LOCK('bug31418') = CONNECTION_ID()
1
-change_user
+change_user root,,test;
SELECT IS_FREE_LOCK('bug31418');
IS_FREE_LOCK('bug31418')
1
@@ -91,10 +88,8 @@ SELECT IS_USED_LOCK('bug31418');
IS_USED_LOCK('bug31418')
NULL
FLUSH STATUS;
+change_user root,,test;
Value of com_select did not change
-set global secure_auth=default;
-Warnings:
-Warning 1287 '@@secure_auth' is deprecated and will be removed in a future release
set timestamp=unix_timestamp('2010-10-10 10:10:10');
select now();
now()
@@ -102,7 +97,7 @@ now()
select year(now()) > 2011;
year(now()) > 2011
0
-change_user
+change_user root,,test;
select year(now()) > 2011;
year(now()) > 2011
1
diff --git a/mysql-test/main/change_user.test b/mysql-test/main/change_user.test
index 5f7d5a21915b0..d891ce4ea962c 100644
--- a/mysql-test/main/change_user.test
+++ b/mysql-test/main/change_user.test
@@ -1,10 +1,8 @@
-# This test is checking that old password authentication works
--disable_service_connection
# connect with mysql_old_password enabled
connect old,localhost,root,,,,,auth=mysql_old_password:mysql_native_password;
-set global secure_auth=0;
#
# functional change user tests
#
@@ -27,19 +25,6 @@ change_user test_nopw;
--replace_result <@> @> @localhost>
select concat('<', user(), '>'), concat('<', current_user(), '>'), database();
-#
-# embedded with enabled privilege control cannot do plugin negotiation.
-# that is, it cannot try to authenticate with a new scramble, receive a request
-# to switch to an old scramble, and retry with an old scramble.
-# As a result, it cannot change to a user that has old scramble and
-# and it stays logged as a previous user - test_nopw in this test file.
-# For the embedded with auth we replace nopw with oldpw in the results.
-#
-let $repl = `select if(version() like '%embedded%' and user() like '%nopw%', 'nopw', 'oldpw')`;
-
-change_user test_oldpw, oldpw;
---replace_result <@> @> @localhost> $repl oldpw
-select concat('<', user(), '>'), concat('<', current_user(), '>'), database();
change_user test_newpw, newpw;
--replace_result <@> @> @localhost>
select concat('<', user(), '>'), concat('<', current_user(), '>'), database();
@@ -50,9 +35,6 @@ select concat('<', user(), '>'), concat('<', current_user(), '>'), database();
change_user test_nopw,,test;
--replace_result <@> @> @localhost>
select concat('<', user(), '>'), concat('<', current_user(), '>'), database();
-change_user test_oldpw,oldpw,test;
---replace_result <@> @> @localhost> $repl oldpw
-select concat('<', user(), '>'), concat('<', current_user(), '>'), database();
change_user test_newpw,newpw,test;
--replace_result <@> @> @localhost>
select concat('<', user(), '>'), concat('<', current_user(), '>'), database();
@@ -74,7 +56,6 @@ SELECT @@session.sql_big_selects;
# The exact value depends on the server build flags
--replace_result 18446744073709551615 HA_POS_ERROR 4294967295 HA_POS_ERROR
SELECT @@global.max_join_size;
---echo change_user
--change_user
SELECT @@session.sql_big_selects;
# The exact value depends on the server build flags
@@ -82,7 +63,6 @@ SELECT @@session.sql_big_selects;
SELECT @@global.max_join_size;
SET @@global.max_join_size = 10000;
SET @@session.max_join_size = default;
---echo change_user
--change_user
SELECT @@session.sql_big_selects;
# On some machines the following will result into a warning
@@ -90,7 +70,6 @@ SELECT @@session.sql_big_selects;
SET @@global.max_join_size = 18446744073709551615;
--enable_warnings
SET @@session.max_join_size = default;
---echo change_user
--change_user
SELECT @@session.sql_big_selects;
--replace_result 4294967295 18446744073709551615
@@ -107,7 +86,6 @@ SELECT IS_FREE_LOCK('bug31418');
SELECT IS_USED_LOCK('bug31418');
SELECT GET_LOCK('bug31418', 1);
SELECT IS_USED_LOCK('bug31418') = CONNECTION_ID();
---echo change_user
--change_user
SELECT IS_FREE_LOCK('bug31418');
SELECT IS_USED_LOCK('bug31418');
@@ -146,12 +124,9 @@ if ($after != $before){
}
echo Value of com_select did not change;
-set global secure_auth=default;
-
set timestamp=unix_timestamp('2010-10-10 10:10:10');
select now();
select year(now()) > 2011;
---echo change_user
--change_user
select year(now()) > 2011;
--enable_service_connection
diff --git a/mysql-test/main/change_user_notembedded.result b/mysql-test/main/change_user_notembedded.result
index fbdd15377c77e..61fdf2b1f6ca0 100644
--- a/mysql-test/main/change_user_notembedded.result
+++ b/mysql-test/main/change_user_notembedded.result
@@ -1,9 +1,15 @@
connect test,localhost,root,,;
connection test;
+change_user foo,bar,;
ERROR 28000: Access denied for user 'foo'@'localhost' (using password: YES)
+change_user foo,,;
ERROR 28000: Access denied for user 'foo'@'localhost' (using password: NO)
+change_user root,,test;
+change_user foo,bar,;
ERROR 28000: Access denied for user 'foo'@'localhost' (using password: YES)
+change_user foo,bar,;
ERROR 08S01: Unknown command
+change_user root,,test;
ERROR 08S01: Unknown command
disconnect test;
connection default;
@@ -12,6 +18,7 @@ connection default;
# MDEV-36405 Session tracking does not report changes from COM_CHANGE_USER
#
change_user
+change_user root,,test;
-- Tracker : SESSION_TRACK_SYSTEM_VARIABLES
-- autocommit: ON
-- character_set_client: latin1
diff --git a/mysql-test/main/check.result b/mysql-test/main/check.result
index e7d26778e88ad..13219415a908a 100644
--- a/mysql-test/main/check.result
+++ b/mysql-test/main/check.result
@@ -1,8 +1,6 @@
connect con1,localhost,root,,;
connect con2,localhost,root,,;
connection con1;
-drop table if exists t1,t2;
-drop view if exists v1;
create table t1(n int not null, key(n), key(n), key(n), key(n));
Warnings:
Note 1831 Duplicate index `n_2`. This is deprecated and will be disallowed in a future release
@@ -18,6 +16,7 @@ connection default;
disconnect con1;
disconnect con2;
drop table t1;
+# End of 4.1 tests
Create table t1(f1 int);
Create table t2(f1 int);
Create view v1 as Select * from t1;
@@ -39,7 +38,6 @@ DROP TABLE t1;
# Bug#56422 CHECK TABLE run when the table is locked reports corruption
# along with timeout
#
-DROP TABLE IF EXISTS t1;
CREATE TABLE t1(a INT);
LOCK TABLE t1 WRITE;
connect con1, localhost, root;
@@ -53,52 +51,24 @@ UNLOCK TABLES;
DROP TABLE t1;
disconnect con1;
#
-# MDEV-15338
-# Assertion `!table || (!table->read_set ||
-# bitmap_is_set(table->read_set, field_index))'
-# failed on dropping column with CHECK
+# MDEV-37971 CHECK TABLE command can be executed by users with the table-level CREATE but not with global CREATE
#
-CREATE TABLE t1 (a INT, b INT, CHECK (a>0)) ENGINE=MyISAM;
-INSERT INTO t1 VALUES (1,2),(3,4);
-ALTER TABLE t1 DROP COLUMN a;
-CREATE OR REPLACE TABLE t1 (a INT, b INT, CHECK (a>0)) ENGINE=MyISAM;
-ALTER TABLE t1 DROP COLUMN b;
-CREATE OR REPLACE TABLE t1 (a INT, b INT, c INT, CHECK (a+b>0)) ENGINE=MyISAM;
-ALTER TABLE t1 DROP COLUMN b;
-ERROR 42S22: Unknown column 'b' in 'CHECK'
-ALTER TABLE t1 DROP COLUMN a, DROP COLUMN b;
-CREATE OR REPLACE TABLE t1 (a INT, b INT, c INT, CHECK (a+b>0)) ENGINE=MyISAM;
-ALTER TABLE t1 DROP CONSTRAINT `CONSTRAINT_1`;
-SHOW CREATE TABLE t1;
-Table Create Table
-t1 CREATE TABLE `t1` (
- `a` int(11) DEFAULT NULL,
- `b` int(11) DEFAULT NULL,
- `c` int(11) DEFAULT NULL
-) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci
-CREATE OR REPLACE TABLE t1 (a INT, b INT, c INT, CHECK (a+b>0)) ENGINE=MyISAM;
-ALTER TABLE t1 DROP COLUMN b, DROP CONSTRAINT `CONSTRAINT_1`;
-SHOW CREATE TABLE t1;
-Table Create Table
-t1 CREATE TABLE `t1` (
- `a` int(11) DEFAULT NULL,
- `c` int(11) DEFAULT NULL
-) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci
-DROP TABLE t1;
-create temporary table t1 (
-id int not null auto_increment primary key,
-f int not null default 0
-);
-insert into t1 () values ();
-alter ignore table t1 add constraint check (f > 0);
-Warnings:
-Warning 4025 CONSTRAINT `CONSTRAINT_1` failed for `test`.`t1`
-alter table t1;
-drop table t1;
-create temporary table t1 (a int default 0, check (a > 0));
-alter table t1 drop constraint if exists non_existing_constraint;
-Warnings:
-Note 1091 Can't DROP CONSTRAINT `non_existing_constraint`; check that it exists
-insert into t1 () values ();
-ERROR 23000: CONSTRAINT `CONSTRAINT_1` failed for `test`.`t1`
+create table t1 (a int);
+create user table_level_priv;
+create user global_level_priv;
+grant create on *.* to global_level_priv;
+grant create on test.t1 to table_level_priv;
+connect g,localhost,global_level_priv;
+check table test.t1;
+Table Op Msg_type Msg_text
+test.t1 check status OK
+connect t,localhost,table_level_priv;
+check table test.t1;
+Table Op Msg_type Msg_text
+test.t1 check status OK
+disconnect g;
+disconnect t;
+connection default;
drop table t1;
+drop user table_level_priv, global_level_priv;
+# End of 10.11 tests
diff --git a/mysql-test/main/check.test b/mysql-test/main/check.test
index 29587a9f62313..2f48fe8543dce 100644
--- a/mysql-test/main/check.test
+++ b/mysql-test/main/check.test
@@ -1,13 +1,6 @@
-# Save the initial number of concurrent sessions
---source include/count_sessions.inc
-
connect (con1,localhost,root,,);
connect (con2,localhost,root,,);
connection con1;
---disable_warnings
-drop table if exists t1,t2;
-drop view if exists v1;
---enable_warnings
# Add a lot of keys to slow down check
create table t1(n int not null, key(n), key(n), key(n), key(n));
@@ -32,7 +25,7 @@ disconnect con2;
drop table t1;
-# End of 4.1 tests
+--echo # End of 4.1 tests
#
# Bug#9897 Views: 'Check Table' crashes MySQL, with a view and a table
@@ -60,10 +53,6 @@ DROP TABLE t1;
--echo # along with timeout
--echo #
---disable_warnings
-DROP TABLE IF EXISTS t1;
---enable_warnings
-
CREATE TABLE t1(a INT);
LOCK TABLE t1 WRITE;
@@ -76,51 +65,24 @@ UNLOCK TABLES;
DROP TABLE t1;
disconnect con1;
-
-# Wait till we reached the initial number of concurrent sessions
---source include/wait_until_count_sessions.inc
-
--echo #
---echo # MDEV-15338
---echo # Assertion `!table || (!table->read_set ||
---echo # bitmap_is_set(table->read_set, field_index))'
---echo # failed on dropping column with CHECK
+--echo # MDEV-37971 CHECK TABLE command can be executed by users with the table-level CREATE but not with global CREATE
--echo #
-
-CREATE TABLE t1 (a INT, b INT, CHECK (a>0)) ENGINE=MyISAM;
-INSERT INTO t1 VALUES (1,2),(3,4);
-ALTER TABLE t1 DROP COLUMN a;
-CREATE OR REPLACE TABLE t1 (a INT, b INT, CHECK (a>0)) ENGINE=MyISAM;
-ALTER TABLE t1 DROP COLUMN b;
-CREATE OR REPLACE TABLE t1 (a INT, b INT, c INT, CHECK (a+b>0)) ENGINE=MyISAM;
---error ER_BAD_FIELD_ERROR
-ALTER TABLE t1 DROP COLUMN b;
-ALTER TABLE t1 DROP COLUMN a, DROP COLUMN b;
-CREATE OR REPLACE TABLE t1 (a INT, b INT, c INT, CHECK (a+b>0)) ENGINE=MyISAM;
-ALTER TABLE t1 DROP CONSTRAINT `CONSTRAINT_1`;
-SHOW CREATE TABLE t1;
-CREATE OR REPLACE TABLE t1 (a INT, b INT, c INT, CHECK (a+b>0)) ENGINE=MyISAM;
-ALTER TABLE t1 DROP COLUMN b, DROP CONSTRAINT `CONSTRAINT_1`;
-SHOW CREATE TABLE t1;
-DROP TABLE t1;
-
-#
-# MDEV-16903 Assertion `!auto_increment_field_not_null' failed in TABLE::init after unsuccessful attempt to add CHECK constraint on temporary table
-#
-create temporary table t1 (
- id int not null auto_increment primary key,
- f int not null default 0
-);
-insert into t1 () values ();
-alter ignore table t1 add constraint check (f > 0);
-alter table t1;
+create table t1 (a int);
+create user table_level_priv;
+create user global_level_priv;
+grant create on *.* to global_level_priv;
+grant create on test.t1 to table_level_priv;
+
+connect g,localhost,global_level_priv;
+check table test.t1;
+
+connect t,localhost,table_level_priv;
+check table test.t1;
+disconnect g;
+disconnect t;
+connection default;
drop table t1;
+drop user table_level_priv, global_level_priv;
-#
-# MDEV-16905 ASAN heap-use-after-free in __interceptor_strnlen / ... / TABLE::verify_constraints upon INSERT into temporary table with CHECK constraint
-#
-create temporary table t1 (a int default 0, check (a > 0));
-alter table t1 drop constraint if exists non_existing_constraint;
---error ER_CONSTRAINT_FAILED
-insert into t1 () values ();
-drop table t1;
+--echo # End of 10.11 tests
diff --git a/mysql-test/main/check_constraint.result b/mysql-test/main/check_constraint.result
index 830fff3243f78..fbec0c6839806 100644
--- a/mysql-test/main/check_constraint.result
+++ b/mysql-test/main/check_constraint.result
@@ -131,17 +131,29 @@ t1 CREATE TABLE `t1` (
CONSTRAINT `CONSTRAINT_2` CHECK (`a` > `b`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci
drop table t1;
+#
+# MDEV-10370 Check constraints on virtual columns fails on INSERT when column not specified
+#
create table t1(c1 int, c2 int as (c1 + 1), check (c2 > 2));
insert into t1(c1) values(1);
ERROR 23000: CONSTRAINT `CONSTRAINT_1` failed for `test`.`t1`
insert into t1(c1) values(2);
drop table t1;
+#
+# MDEV-11117 CHECK constraint fails on intermediate step of ALTER
+#
create or replace table t1( c1 int auto_increment primary key, check( c1 > 0 or c1 is null ) );
ERROR HY000: Function or expression 'AUTO_INCREMENT' cannot be used in the CHECK clause of `c1`
+#
+# MDEV-12421 Check constraint with query crashes server and renders DB unusable
+#
create table t1 (a int check (@b in (select user from mysql.user)));
ERROR 42000: CHECK does not support subqueries or stored functions
create table t1 (a int check (a > @b));
ERROR HY000: Function or expression '@b' cannot be used in the CHECK clause of `a`
+#
+# MDEV-13596 CHECK constraints disallow NULL to pass through, violating SQL
+#
create table t1 (a int check (a = 1));
insert t1 values (1);
insert t1 values (2);
@@ -152,10 +164,16 @@ a
1
NULL
drop table t1;
+#
+# MDEV-15141 Check constraint validation on a datetime field crashes the process
+#
create table t1 (id int auto_increment primary key, datecol datetime, check (datecol>'0001-01-01 00:00:00'));
insert into t1 (datecol) values (now());
insert into t1 (datecol) values (now());
drop table t1;
+#
+# MDEV-15461 Check Constraints with binary logging makes insert inconsistent
+#
CREATE TABLE t1 (
EmployeeID SMALLINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
FirstName VARCHAR(30) NOT NULL CHECK (CHAR_LENGTH(FirstName > 2))
@@ -198,8 +216,7 @@ EmployeeID FirstName
6 Brian
drop table t1;
#
-# MDEV-16630: Ambiguous error message when check constraint
-# matches table name
+# MDEV-16630: Ambiguous error message when check constraint matches table name
#
use test;
drop table if exists t;
@@ -279,8 +296,59 @@ Warning 1265 Data truncated for column 'v1' at row 1
Warning 1292 Truncated incorrect INTEGER value: 'x'
drop table t1;
#
-# End of 10.2 tests
+# MDEV-15338 Assertion `!table || (!table->read_set || bitmap_is_set(table->read_set, field_index))' failed on dropping column with CHECK
+#
+CREATE TABLE t1 (a INT, b INT, CHECK (a>0)) ENGINE=MyISAM;
+INSERT INTO t1 VALUES (1,2),(3,4);
+ALTER TABLE t1 DROP COLUMN a;
+CREATE OR REPLACE TABLE t1 (a INT, b INT, CHECK (a>0)) ENGINE=MyISAM;
+ALTER TABLE t1 DROP COLUMN b;
+CREATE OR REPLACE TABLE t1 (a INT, b INT, c INT, CHECK (a+b>0)) ENGINE=MyISAM;
+ALTER TABLE t1 DROP COLUMN b;
+ERROR 42S22: Unknown column 'b' in 'CHECK'
+ALTER TABLE t1 DROP COLUMN a, DROP COLUMN b;
+CREATE OR REPLACE TABLE t1 (a INT, b INT, c INT, CHECK (a+b>0)) ENGINE=MyISAM;
+ALTER TABLE t1 DROP CONSTRAINT `CONSTRAINT_1`;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) DEFAULT NULL,
+ `c` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci
+CREATE OR REPLACE TABLE t1 (a INT, b INT, c INT, CHECK (a+b>0)) ENGINE=MyISAM;
+ALTER TABLE t1 DROP COLUMN b, DROP CONSTRAINT `CONSTRAINT_1`;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `c` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci
+DROP TABLE t1;
+#
+# MDEV-16903 Assertion `!auto_increment_field_not_null' failed in TABLE::init after unsuccessful attempt to add CHECK constraint on temporary table
+#
+create temporary table t1 (
+id int not null auto_increment primary key,
+f int not null default 0
+);
+insert into t1 () values ();
+alter ignore table t1 add constraint check (f > 0);
+Warnings:
+Warning 4025 CONSTRAINT `CONSTRAINT_1` failed for `test`.`t1`
+alter table t1;
+drop table t1;
#
+# MDEV-16905 ASAN heap-use-after-free in __interceptor_strnlen / ... / TABLE::verify_constraints upon INSERT into temporary table with CHECK constraint
+#
+create temporary table t1 (a int default 0, check (a > 0));
+alter table t1 drop constraint if exists non_existing_constraint;
+Warnings:
+Note 1091 Can't DROP CONSTRAINT `non_existing_constraint`; check that it exists
+insert into t1 () values ();
+ERROR 23000: CONSTRAINT `CONSTRAINT_1` failed for `test`.`t1`
+drop table t1;
+# End of 10.2 tests
#
# MDEV-26061 MariaDB server crash at Field::set_default
#
@@ -292,10 +360,8 @@ t1 CREATE TABLE `t1` (
`1` int(1) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci
drop table t1;
-#
# End of 10.3 tests
#
-#
# MDEV-24274 ALTER TABLE with CHECK CONSTRAINTS gives "Out of Memory" error
#
create table t1 (id varchar(2), constraint id check (id regexp '[a-z]'));
diff --git a/mysql-test/main/check_constraint.test b/mysql-test/main/check_constraint.test
index 81fe6d162dc31..e62f7c2cc1abc 100644
--- a/mysql-test/main/check_constraint.test
+++ b/mysql-test/main/check_constraint.test
@@ -69,32 +69,32 @@ create or replace table t1 (a int, b int,
show create table t1;
drop table t1;
-#
-# MDEV-10370 Check constraints on virtual columns fails on INSERT when column not specified
-#
+--echo #
+--echo # MDEV-10370 Check constraints on virtual columns fails on INSERT when column not specified
+--echo #
create table t1(c1 int, c2 int as (c1 + 1), check (c2 > 2));
--error ER_CONSTRAINT_FAILED
insert into t1(c1) values(1);
insert into t1(c1) values(2);
drop table t1;
-#
-# MDEV-11117 CHECK constraint fails on intermediate step of ALTER
-#
+--echo #
+--echo # MDEV-11117 CHECK constraint fails on intermediate step of ALTER
+--echo #
-- error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
create or replace table t1( c1 int auto_increment primary key, check( c1 > 0 or c1 is null ) );
-#
-# MDEV-12421 Check constraint with query crashes server and renders DB unusable
-#
+--echo #
+--echo # MDEV-12421 Check constraint with query crashes server and renders DB unusable
+--echo #
--error ER_SUBQUERIES_NOT_SUPPORTED
create table t1 (a int check (@b in (select user from mysql.user)));
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
create table t1 (a int check (a > @b));
-#
-# MDEV-13596 CHECK constraints disallow NULL to pass through, violating SQL
-#
+--echo #
+--echo # MDEV-13596 CHECK constraints disallow NULL to pass through, violating SQL
+--echo #
create table t1 (a int check (a = 1));
insert t1 values (1);
--error ER_CONSTRAINT_FAILED
@@ -103,17 +103,17 @@ insert t1 values (NULL);
select * from t1;
drop table t1;
-#
-# MDEV-15141 Check constraint validation on a datetime field crashes the process
-#
+--echo #
+--echo # MDEV-15141 Check constraint validation on a datetime field crashes the process
+--echo #
create table t1 (id int auto_increment primary key, datecol datetime, check (datecol>'0001-01-01 00:00:00'));
insert into t1 (datecol) values (now());
insert into t1 (datecol) values (now());
drop table t1;
-#
-# MDEV-15461 Check Constraints with binary logging makes insert inconsistent
-#
+--echo #
+--echo # MDEV-15461 Check Constraints with binary logging makes insert inconsistent
+--echo #
CREATE TABLE t1 (
EmployeeID SMALLINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
@@ -136,8 +136,7 @@ select * from t1;
drop table t1;
--echo #
---echo # MDEV-16630: Ambiguous error message when check constraint
---echo # matches table name
+--echo # MDEV-16630: Ambiguous error message when check constraint matches table name
--echo #
use test;
@@ -208,8 +207,48 @@ insert ignore into t1 values ( 'x' , 'x' ) ;
drop table t1;
--echo #
---echo # End of 10.2 tests
+--echo # MDEV-15338 Assertion `!table || (!table->read_set || bitmap_is_set(table->read_set, field_index))' failed on dropping column with CHECK
+--echo #
+
+CREATE TABLE t1 (a INT, b INT, CHECK (a>0)) ENGINE=MyISAM;
+INSERT INTO t1 VALUES (1,2),(3,4);
+ALTER TABLE t1 DROP COLUMN a;
+CREATE OR REPLACE TABLE t1 (a INT, b INT, CHECK (a>0)) ENGINE=MyISAM;
+ALTER TABLE t1 DROP COLUMN b;
+CREATE OR REPLACE TABLE t1 (a INT, b INT, c INT, CHECK (a+b>0)) ENGINE=MyISAM;
+--error ER_BAD_FIELD_ERROR
+ALTER TABLE t1 DROP COLUMN b;
+ALTER TABLE t1 DROP COLUMN a, DROP COLUMN b;
+CREATE OR REPLACE TABLE t1 (a INT, b INT, c INT, CHECK (a+b>0)) ENGINE=MyISAM;
+ALTER TABLE t1 DROP CONSTRAINT `CONSTRAINT_1`;
+SHOW CREATE TABLE t1;
+CREATE OR REPLACE TABLE t1 (a INT, b INT, c INT, CHECK (a+b>0)) ENGINE=MyISAM;
+ALTER TABLE t1 DROP COLUMN b, DROP CONSTRAINT `CONSTRAINT_1`;
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+
+--echo #
+--echo # MDEV-16903 Assertion `!auto_increment_field_not_null' failed in TABLE::init after unsuccessful attempt to add CHECK constraint on temporary table
+--echo #
+create temporary table t1 (
+ id int not null auto_increment primary key,
+ f int not null default 0
+);
+insert into t1 () values ();
+alter ignore table t1 add constraint check (f > 0);
+alter table t1;
+drop table t1;
+
--echo #
+--echo # MDEV-16905 ASAN heap-use-after-free in __interceptor_strnlen / ... / TABLE::verify_constraints upon INSERT into temporary table with CHECK constraint
+--echo #
+create temporary table t1 (a int default 0, check (a > 0));
+alter table t1 drop constraint if exists non_existing_constraint;
+--error ER_CONSTRAINT_FAILED
+insert into t1 () values ();
+drop table t1;
+
+--echo # End of 10.2 tests
--echo #
--echo # MDEV-26061 MariaDB server crash at Field::set_default
@@ -219,9 +258,7 @@ create table t1 (d timestamp not null default now() check (default (d) is true))
show create table t1;
drop table t1;
---echo #
--echo # End of 10.3 tests
---echo #
--echo #
--echo # MDEV-24274 ALTER TABLE with CHECK CONSTRAINTS gives "Out of Memory" error
diff --git a/mysql-test/main/client_xml.result b/mysql-test/main/client_xml.result
index 6f91c18318cf3..1c090300f19c7 100644
--- a/mysql-test/main/client_xml.result
+++ b/mysql-test/main/client_xml.result
@@ -1,6 +1,5 @@
set @old_concurrent_insert= @@global.concurrent_insert;
set @@global.concurrent_insert= 0;
-drop table if exists t1;
create table t1 (
`a&b` int,
`a= 100000, so reversed comments with version
+# <= current should NOT execute (server is not older than that version).
+SELECT 1 /*!!50101 +1 */;
+1
+1
+SELECT 1 /*!!100000 +1 */;
+1
+1
+# Reversed comment with version higher than current SHOULD execute.
+SELECT 1 /*!!999999 +1 */;
+1 +1
+2
+# MariaDB-specific reversed executable comments
+SELECT 1 /*M!!50101 +1 */;
+1
+1
+SELECT 1 /*M!!999999 +1 */;
+1 +1
+2
+# Without version number (just /*!! with no digits) should still work
+# as a regular executable comment expanding the content.
+SELECT 1 /*!! +1 */;
+1 +1
+2
+SELECT 1 /*M!! +1 */;
+1 +1
+2
+# Combined forward and reversed in the same statement (MDEV-7381 use case).
+# On this server (>= 10.0.0): /*!100000 OR REPLACE */ executes,
+# /*!!100000 IF NOT EXISTS */ is skipped.
+# Effective statement: CREATE OR REPLACE TABLE t1 (a INT);
+CREATE /*!100000 OR REPLACE */ TABLE /*!!100000 IF NOT EXISTS */ t1 (a INT);
+INSERT INTO t1 VALUES (1);
+# Run again. OR REPLACE should drop and recreate the table, losing the row.
+CREATE /*!100000 OR REPLACE */ TABLE /*!!100000 IF NOT EXISTS */ t1 (a INT);
+# Table should be empty, proving OR REPLACE was used (not IF NOT EXISTS).
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+0
+DROP TABLE t1;
diff --git a/mysql-test/main/comments.test b/mysql-test/main/comments.test
index 671e5d6583555..49d18c332f928 100644
--- a/mysql-test/main/comments.test
+++ b/mysql-test/main/comments.test
@@ -101,3 +101,36 @@ prepare bar from "DELETE FROM table_28779 WHERE a = 7 OR 1=1/*!998765' AND b = '
drop table table_28779;
+
+--echo #
+--echo # MDEV-7381: Reversed executable comments
+--echo #
+
+--echo # Server version is >= 100000, so reversed comments with version
+--echo # <= current should NOT execute (server is not older than that version).
+SELECT 1 /*!!50101 +1 */;
+SELECT 1 /*!!100000 +1 */;
+
+--echo # Reversed comment with version higher than current SHOULD execute.
+SELECT 1 /*!!999999 +1 */;
+
+--echo # MariaDB-specific reversed executable comments
+SELECT 1 /*M!!50101 +1 */;
+SELECT 1 /*M!!999999 +1 */;
+
+--echo # Without version number (just /*!! with no digits) should still work
+--echo # as a regular executable comment expanding the content.
+SELECT 1 /*!! +1 */;
+SELECT 1 /*M!! +1 */;
+
+--echo # Combined forward and reversed in the same statement (MDEV-7381 use case).
+--echo # On this server (>= 10.0.0): /*!100000 OR REPLACE */ executes,
+--echo # /*!!100000 IF NOT EXISTS */ is skipped.
+--echo # Effective statement: CREATE OR REPLACE TABLE t1 (a INT);
+CREATE /*!100000 OR REPLACE */ TABLE /*!!100000 IF NOT EXISTS */ t1 (a INT);
+INSERT INTO t1 VALUES (1);
+--echo # Run again. OR REPLACE should drop and recreate the table, losing the row.
+CREATE /*!100000 OR REPLACE */ TABLE /*!!100000 IF NOT EXISTS */ t1 (a INT);
+--echo # Table should be empty, proving OR REPLACE was used (not IF NOT EXISTS).
+SELECT COUNT(*) FROM t1;
+DROP TABLE t1;
diff --git a/mysql-test/main/compress.test b/mysql-test/main/compress.test
index daa133ebdc7cf..f48919d264dcc 100644
--- a/mysql-test/main/compress.test
+++ b/mysql-test/main/compress.test
@@ -9,10 +9,6 @@
# Slow test, don't run during staging part
-- source include/not_staging.inc
-# Save the initial number of concurrent sessions
---source include/count_sessions.inc
-
-
connect (comp_con,localhost,root,,,,,COMPRESS);
# Check compression turned on
@@ -27,7 +23,3 @@ SHOW STATUS LIKE 'Compression';
connection default;
disconnect comp_con;
-
-# Wait till all disconnects are completed
---source include/wait_until_count_sessions.inc
-
diff --git a/mysql-test/main/connect.result b/mysql-test/main/connect.result
index 4ce32842a0051..b6e02d1b88fcb 100644
--- a/mysql-test/main/connect.result
+++ b/mysql-test/main/connect.result
@@ -1,6 +1,3 @@
-SET global secure_auth=0;
-Warnings:
-Warning 1287 '@@secure_auth' is deprecated and will be removed in a future release
connect con1,localhost,root,,mysql;
show tables;
Tables_in_mysql
@@ -102,63 +99,6 @@ connect(localhost,test,zorro,test,MASTER_PORT,MASTER_SOCKET);
connect fail_con,localhost,test,zorro,;
ERROR 28000: Access denied for user 'test'@'localhost' (using password: YES)
# switching from mysql.global_priv to mysql.user
-update mysql.user set plugin="", authentication_string="", password=old_password("gambling2") where user=_binary"test";
-flush privileges;
-show grants for test@localhost;
-Grants for test@localhost
-GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, BINLOG MONITOR, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER, CREATE TABLESPACE, DELETE HISTORY, SET USER, FEDERATED ADMIN, CONNECTION ADMIN, READ_ONLY ADMIN, REPLICATION SLAVE ADMIN, REPLICATION MASTER ADMIN, BINLOG ADMIN, BINLOG REPLAY, SLAVE MONITOR ON *.* TO `test`@`localhost` IDENTIFIED BY PASSWORD '2f27438961437573'
-update mysql.user set plugin='mysql_old_password' where user='test';
-flush privileges;
-show grants for test@localhost;
-Grants for test@localhost
-GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, BINLOG MONITOR, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER, CREATE TABLESPACE, DELETE HISTORY, SET USER, FEDERATED ADMIN, CONNECTION ADMIN, READ_ONLY ADMIN, REPLICATION SLAVE ADMIN, REPLICATION MASTER ADMIN, BINLOG ADMIN, BINLOG REPLAY, SLAVE MONITOR ON *.* TO `test`@`localhost` IDENTIFIED BY PASSWORD '2f27438961437573'
-connect con10,localhost,test,gambling2,,,,auth=mysql_old_password:mysql_native_password;
-connect con5,localhost,test,gambling2,mysql,,,auth=mysql_old_password:mysql_native_password;
-set password="";
-set password='gambling3';
-ERROR HY000: Password hash should be a 41-digit hexadecimal number
-set password=old_password('gambling3');
-show tables;
-Tables_in_mysql
-column_stats
-columns_priv
-db
-event
-func
-general_log
-global_priv_bak
-gtid_slave_pos
-help_category
-help_keyword
-help_relation
-help_topic
-index_stats
-innodb_index_stats
-innodb_table_stats
-plugin
-proc
-procs_priv
-proxies_priv
-roles_mapping
-servers
-slow_log
-table_stats
-tables_priv
-time_zone
-time_zone_leap_second
-time_zone_name
-time_zone_transition
-time_zone_transition_type
-transaction_registry
-user
-user_bak
-connect con6,localhost,test,gambling3,test,,,auth=mysql_old_password:mysql_native_password;
-show tables;
-Tables_in_test
-connection default;
-disconnect con10;
-disconnect con5;
-disconnect con6;
connect(localhost,test,,test2,MASTER_PORT,MASTER_SOCKET);
connect fail_con,localhost,test,,test2,,,auth=mysql_old_password:mysql_native_password;
ERROR 28000: Access denied for user 'test'@'localhost' (using password: NO)
@@ -277,8 +217,6 @@ disconnect tmp_con7;
# -- Restoring default connection...
connect default,localhost,root,,test;
-# -- Waiting for connections to close...
-
DROP USER mysqltest_u1@localhost;
# -- End of Bug#33507.
@@ -343,7 +281,6 @@ disconnect extracon;
disconnect extracon2;
connection default;
CREATE USER mysqltest_up1 IDENTIFIED VIA mysql_native_password using '*E8D46CE25265E545D225A8A6F1BAF642FEBEE5CB';
-CREATE USER mysqltest_up2 IDENTIFIED VIA mysql_old_password using '09301740536db389';
connect(localhost,mysqltest_up1,foo,test,MASTER_PORT,MASTER_SOCKET);
connect pcon1,localhost,mysqltest_up1,foo,,$MASTER_MYPORT,;
ERROR 28000: Access denied for user 'mysqltest_up1'@'localhost' (using password: YES)
@@ -352,14 +289,6 @@ select user(), current_user();
user() current_user()
mysqltest_up1@localhost mysqltest_up1@%
disconnect pcon2;
-connect(localhost,mysqltest_up2,newpw,test,MASTER_PORT,MASTER_SOCKET);
-connect pcon3,localhost,mysqltest_up2,newpw,,$MASTER_MYPORT,,auth=mysql_old_password:mysql_native_password;
-ERROR 28000: Access denied for user 'mysqltest_up2'@'localhost' (using password: YES)
-connect pcon4,localhost,mysqltest_up2,oldpw,,$MASTER_MYPORT,,auth=mysql_old_password:mysql_native_password;
-select user(), current_user();
-user() current_user()
-mysqltest_up2@localhost mysqltest_up2@%
-disconnect pcon4;
connect(localhost,mysqltest_nouser,newpw,test,MASTER_PORT,MASTER_SOCKET);
connect pcon5,localhost,mysqltest_nouser,newpw,,$MASTER_MYPORT,;
ERROR 28000: Access denied for user 'mysqltest_nouser'@'localhost' (using password: YES)
@@ -369,27 +298,19 @@ ERROR 28000: Access denied for user 'mysqltest_nouser'@'localhost' (using passwo
connection default;
# switching from mysql.global_priv to mysql.user
update mysql.user set plugin='mysql_native_password' where user = 'mysqltest_up1';
-update mysql.user set plugin='mysql_old_password' where user = 'mysqltest_up2';
select user, password, plugin, authentication_string from mysql.user
where user like 'mysqltest_up_';
user password plugin authentication_string
mysqltest_up1 *E8D46CE25265E545D225A8A6F1BAF642FEBEE5CB mysql_native_password *E8D46CE25265E545D225A8A6F1BAF642FEBEE5CB
-mysqltest_up2 09301740536db389 mysql_old_password 09301740536db389
flush privileges;
connect pcon6,localhost,mysqltest_up1,bar,,$MASTER_MYPORT,;
select user(), current_user();
user() current_user()
mysqltest_up1@localhost mysqltest_up1@%
disconnect pcon6;
-connect pcon7,localhost,mysqltest_up2,oldpw,,$MASTER_MYPORT,,auth=mysql_old_password:mysql_native_password;
-select user(), current_user();
-user() current_user()
-mysqltest_up2@localhost mysqltest_up2@%
-disconnect pcon7;
connection default;
# switching back from mysql.user to mysql.global_priv
DROP USER mysqltest_up1@'%';
-DROP USER mysqltest_up2@'%';
#
# BUG#1010351: New "via" keyword in 5.2+ can't be used as identifier anymore
#
@@ -413,9 +334,6 @@ test
test
test
drop procedure p1;
-SET global secure_auth=default;
-Warnings:
-Warning 1287 '@@secure_auth' is deprecated and will be removed in a future release
#
# MDEV-19282: Log more specific warning with log_warnings=2 if
# connection is aborted prior to authentication
@@ -477,6 +395,4 @@ Connection_errors_peer_address 0
Connection_errors_select 0
Connection_errors_tcpwrap 0
set global max_connections= @max_con.save;
-#
# End of 10.5 tests
-#
diff --git a/mysql-test/main/connect.test b/mysql-test/main/connect.test
index 8f95712d61a06..69acb71a119c3 100644
--- a/mysql-test/main/connect.test
+++ b/mysql-test/main/connect.test
@@ -9,11 +9,6 @@
# of the log tables (which are CSV-based). By connect mysql; show tables;
--source include/have_csv.inc
-# Save the initial number of concurrent sessions
---source include/count_sessions.inc
-
-SET global secure_auth=0;
-
#connect (con1,localhost,root,,"");
#show tables;
connect (con1,localhost,root,,mysql);
@@ -61,29 +56,7 @@ connect (fail_con,localhost,test,zorro,test2);
--error ER_ACCESS_DENIED_ERROR
connect (fail_con,localhost,test,zorro,);
-# check if old password version also works
source include/switch_to_mysql_user.inc;
-update mysql.user set plugin="", authentication_string="", password=old_password("gambling2") where user=_binary"test";
-flush privileges;
-show grants for test@localhost;
-update mysql.user set plugin='mysql_old_password' where user='test';
-flush privileges;
-show grants for test@localhost;
-
-connect con10,localhost,test,gambling2,,,,auth=mysql_old_password:mysql_native_password;
-connect con5,localhost,test,gambling2,mysql,,,auth=mysql_old_password:mysql_native_password;
-set password="";
---error ER_PASSWD_LENGTH
-set password='gambling3';
-set password=old_password('gambling3');
-show tables;
-connect (con6,localhost,test,gambling3,test,,,auth=mysql_old_password:mysql_native_password);
-show tables;
-
-connection default;
-disconnect con10;
-disconnect con5;
-disconnect con6;
--replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_MYPORT MASTER_PORT
--error ER_ACCESS_DENIED_ERROR
@@ -250,11 +223,6 @@ let $wait_condition =
--echo # -- Restoring default connection...
--connect (default,localhost,root,,test)
---echo
---echo # -- Waiting for connections to close...
-let $count_sessions=1;
---source include/wait_until_count_sessions.inc
-
--echo
DROP USER mysqltest_u1@localhost;
@@ -267,6 +235,9 @@ DROP USER mysqltest_u1@localhost;
--echo # -- Bug#35074: max_used_connections is not correct.
--echo
+let $count_sessions=1;
+--source include/wait_until_count_sessions.inc
+
FLUSH GLOBAL STATUS;
--echo
@@ -368,7 +339,6 @@ FLUSH PRIVILEGES;
# A couple of plugin tests - for builtin plugins only
#
CREATE USER mysqltest_up1 IDENTIFIED VIA mysql_native_password using '*E8D46CE25265E545D225A8A6F1BAF642FEBEE5CB';
-CREATE USER mysqltest_up2 IDENTIFIED VIA mysql_old_password using '09301740536db389';
--replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_MYPORT MASTER_PORT
--error ER_ACCESS_DENIED_ERROR
@@ -377,13 +347,6 @@ connect(pcon2,localhost,mysqltest_up1,bar,,$MASTER_MYPORT,);
select user(), current_user();
disconnect pcon2;
---replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_MYPORT MASTER_PORT
---error ER_ACCESS_DENIED_ERROR
-connect(pcon3,localhost,mysqltest_up2,newpw,,$MASTER_MYPORT,,auth=mysql_old_password:mysql_native_password);
-connect(pcon4,localhost,mysqltest_up2,oldpw,,$MASTER_MYPORT,,auth=mysql_old_password:mysql_native_password);
-select user(), current_user();
-disconnect pcon4;
-
#
# lp:683112 Maria 5.2 incorrectly reports "(using password: NO)"
# even when password is specified
@@ -406,7 +369,6 @@ connection default;
#
source include/switch_to_mysql_user.inc;
update mysql.user set plugin='mysql_native_password' where user = 'mysqltest_up1';
-update mysql.user set plugin='mysql_old_password' where user = 'mysqltest_up2';
select user, password, plugin, authentication_string from mysql.user
where user like 'mysqltest_up_';
flush privileges;
@@ -415,18 +377,11 @@ connect(pcon6,localhost,mysqltest_up1,bar,,$MASTER_MYPORT,);
select user(), current_user();
disconnect pcon6;
-connect(pcon7,localhost,mysqltest_up2,oldpw,,$MASTER_MYPORT,,auth=mysql_old_password:mysql_native_password);
-select user(), current_user();
-disconnect pcon7;
connection default;
source include/switch_to_mysql_global_priv.inc;
DROP USER mysqltest_up1@'%';
-DROP USER mysqltest_up2@'%';
-
-# Wait till all disconnects are completed
---source include/wait_until_count_sessions.inc
--echo #
--echo # BUG#1010351: New "via" keyword in 5.2+ can't be used as identifier anymore
@@ -453,8 +408,6 @@ delimiter ;|
call p1(2);
drop procedure p1;
-SET global secure_auth=default;
-
--echo #
--echo # MDEV-19282: Log more specific warning with log_warnings=2 if
--echo # connection is aborted prior to authentication
@@ -557,6 +510,4 @@ let $status_var_value= 1;
show global status like 'Connection_errors%';
set global max_connections= @max_con.save;
---echo #
--echo # End of 10.5 tests
---echo #
diff --git a/mysql-test/main/consistent_snapshot.result b/mysql-test/main/consistent_snapshot.result
index b978f1dd9d27f..ac9bc3188ee17 100644
--- a/mysql-test/main/consistent_snapshot.result
+++ b/mysql-test/main/consistent_snapshot.result
@@ -1,4 +1,3 @@
-DROP TABLE IF EXISTS t1;
connect con1,localhost,root,,;
connect con2,localhost,root,,;
### Test 1:
@@ -42,3 +41,4 @@ connection default;
disconnect con1;
disconnect con2;
DROP TABLE t1;
+# End of 4.1 tests
diff --git a/mysql-test/main/consistent_snapshot.test b/mysql-test/main/consistent_snapshot.test
index a481e757bed1a..71ec59d02091e 100644
--- a/mysql-test/main/consistent_snapshot.test
+++ b/mysql-test/main/consistent_snapshot.test
@@ -1,12 +1,5 @@
--source include/have_innodb.inc
-# Save the initial number of concurrent sessions
---source include/count_sessions.inc
-
---disable_warnings
-DROP TABLE IF EXISTS t1;
---enable_warnings
-
connect (con1,localhost,root,,);
connect (con2,localhost,root,,);
@@ -62,8 +55,4 @@ disconnect con1;
disconnect con2;
DROP TABLE t1;
-# End of 4.1 tests
-
-# Wait till all disconnects are completed
---source include/wait_until_count_sessions.inc
-
+--echo # End of 4.1 tests
diff --git a/mysql-test/main/costs.result b/mysql-test/main/costs.result
index b8ee34cb1c1cb..f7b2b4a036f05 100644
--- a/mysql-test/main/costs.result
+++ b/mysql-test/main/costs.result
@@ -124,3 +124,77 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range l_suppkey l_suppkey 10 NULL 1 Using where; Using index
drop table t1;
set global InnoDB.optimizer_disk_read_ratio=@save;
+#
+# MDEV-37723 In MDEV-36861, analyze Q4
+# Alter disk based tmp table lookup cost formula
+#
+create table t1 (a int primary key,
+b date, c char(15),
+d blob,
+key t1_ix1 (b)) ENGINE= InnoDB;
+create table t2 (e int not null,
+f int not null,
+g date, h date,
+primary key (e, f)) ENGINE= InnoDB;
+insert into t1 select seq, date('1993-06-01') + interval seq second,
+chr(65+mod(seq, 4)), NULL from seq_1_to_7000;
+insert into t2 select a.seq, b.seq, date('1993-06-01') + interval b.seq day,
+if (mod(a.seq,2), date('1993-06-01') + interval b.seq+1 day,
+date('1993-06-01') - interval b.seq-1 day)
+from seq_1_to_7000 a, seq_1_to_3 b;
+set
+@save_mhts= @@max_heap_table_size,
+@@max_heap_table_size=16384;
+# This should use "t1, FirstMatch(t2)". Not "t1, SJ-Materialization(t2)".
+explain format=json
+select c, count(*) as dc
+from t1
+where
+b >= date '1993-06-01' and b < date '1993-06-01' + interval '3' month and
+exists (select * from t2 where e = t1.a and g < h)
+group by c;
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "cost": 12.53886553,
+ "filesort": {
+ "sort_key": "t1.c",
+ "temporary_table": {
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "possible_keys": ["PRIMARY", "t1_ix1"],
+ "loops": 1,
+ "rows": 7000,
+ "cost": 1.1518548,
+ "filtered": 100,
+ "attached_condition": "t1.b >= DATE'1993-06-01' and t1.b < (DATE'1993-06-01' + interval '3' month)"
+ }
+ },
+ {
+ "table": {
+ "table_name": "t2",
+ "access_type": "ref",
+ "possible_keys": ["PRIMARY"],
+ "key": "PRIMARY",
+ "key_length": "4",
+ "used_key_parts": ["e"],
+ "ref": ["test.t1.a"],
+ "loops": 7000,
+ "rows": 1,
+ "cost": 6.7528092,
+ "filtered": 100,
+ "attached_condition": "t2.g < t2.h",
+ "first_match": "t1"
+ }
+ }
+ ]
+ }
+ }
+ }
+}
+set max_heap_table_size=@save_mhts;
+drop table t1, t2;
diff --git a/mysql-test/main/costs.test b/mysql-test/main/costs.test
index c425390e17dd5..5de334c67d396 100644
--- a/mysql-test/main/costs.test
+++ b/mysql-test/main/costs.test
@@ -7,6 +7,7 @@
--source include/have_sequence.inc
--source include/have_innodb.inc
+--source include/innodb_stable_estimates.inc
create table t1 (a int primary key, b int, c int, d int, e int, key ba (b,a), key bda (b,d,a), key cba (c,b,a), key cb (c,b), key d (d)) engine=aria;
insert into t1 select seq,seq,seq,seq,seq from seq_1_to_10;
@@ -114,3 +115,41 @@ explain select count(*) from test.t1 force index (l_suppkey) where l_suppkey >=
drop table t1;
set global InnoDB.optimizer_disk_read_ratio=@save;
+
+--echo #
+--echo # MDEV-37723 In MDEV-36861, analyze Q4
+--echo # Alter disk based tmp table lookup cost formula
+--echo #
+
+create table t1 (a int primary key,
+ b date, c char(15),
+ d blob,
+ key t1_ix1 (b)) ENGINE= InnoDB;
+create table t2 (e int not null,
+ f int not null,
+ g date, h date,
+ primary key (e, f)) ENGINE= InnoDB;
+--disable_warnings
+insert into t1 select seq, date('1993-06-01') + interval seq second,
+ chr(65+mod(seq, 4)), NULL from seq_1_to_7000;
+insert into t2 select a.seq, b.seq, date('1993-06-01') + interval b.seq day,
+ if (mod(a.seq,2), date('1993-06-01') + interval b.seq+1 day,
+ date('1993-06-01') - interval b.seq-1 day)
+ from seq_1_to_7000 a, seq_1_to_3 b;
+
+set
+ @save_mhts= @@max_heap_table_size,
+ @@max_heap_table_size=16384;
+
+
+--echo # This should use "t1, FirstMatch(t2)". Not "t1, SJ-Materialization(t2)".
+explain format=json
+select c, count(*) as dc
+from t1
+where
+ b >= date '1993-06-01' and b < date '1993-06-01' + interval '3' month and
+ exists (select * from t2 where e = t1.a and g < h)
+group by c;
+
+set max_heap_table_size=@save_mhts;
+drop table t1, t2;
diff --git a/mysql-test/main/create-big.test b/mysql-test/main/create-big.test
index a501d4c5e4480..3b14d14c5bef7 100644
--- a/mysql-test/main/create-big.test
+++ b/mysql-test/main/create-big.test
@@ -12,8 +12,6 @@
# Some of tests below also use binlog to check that statements are
# executed and logged in correct order
--source include/have_binlog_format_mixed_or_statement.inc
-# Save the initial number of concurrent sessions.
---source include/count_sessions.inc
# Create auxiliary connections
connect (addconroot1, localhost, root,,);
@@ -547,6 +545,3 @@ disconnect addconroot3;
set debug_sync='RESET';
source include/show_binlog_events.inc;
-# Check that all connections opened by test cases in this file are really
-# gone so execution of other tests won't be affected by their presence.
---source include/wait_until_count_sessions.inc
diff --git a/mysql-test/main/create_drop_binlog.result b/mysql-test/main/create_drop_binlog.result
index dc8f217fd6fd9..eaf8b8da3417a 100644
--- a/mysql-test/main/create_drop_binlog.result
+++ b/mysql-test/main/create_drop_binlog.result
@@ -338,16 +338,16 @@ Log_name Pos Event_type Server_id End_log_pos Info
RESET MASTER;
RESET MASTER;
SHOW MASTER STATUS;
-File Position Binlog_Do_DB Binlog_Ignore_DB
-master-bin.000001
+File Position Binlog_Do_DB Binlog_Ignore_DB Gtid_Binlog_Pos
+master-bin.000001
RESET MASTER TO 100;
SHOW MASTER STATUS;
-File Position Binlog_Do_DB Binlog_Ignore_DB
-master-bin.000100
+File Position Binlog_Do_DB Binlog_Ignore_DB Gtid_Binlog_Pos
+master-bin.000100
RESET MASTER;
SHOW MASTER STATUS;
-File Position Binlog_Do_DB Binlog_Ignore_DB
-master-bin.000001
+File Position Binlog_Do_DB Binlog_Ignore_DB Gtid_Binlog_Pos
+master-bin.000001
CREATE TABLE t1(a INT, b INT);
CREATE TABLE IF NOT EXISTS t1(a INT, b INT);
Warnings:
diff --git a/mysql-test/main/create_drop_function.result b/mysql-test/main/create_drop_function.result
index d6bee4da33900..de74de05f71d2 100644
--- a/mysql-test/main/create_drop_function.result
+++ b/mysql-test/main/create_drop_function.result
@@ -3,8 +3,8 @@ CREATE FUNCTION f1(str char(20))
RETURNS CHAR(100)
RETURN CONCAT('Hello, ', str, '!');
SELECT * FROM mysql.proc WHERE name like 'f1';
-db name type specific_name language sql_data_access is_deterministic security_type param_list returns body definer created modified sql_mode comment character_set_client collation_connection db_collation body_utf8 aggregate
-test f1 FUNCTION f1 SQL CONTAINS_SQL NO DEFINER str char(20) char(100) CHARSET utf8mb4 COLLATE utf8mb4_uca1400_ai_ci RETURN CONCAT('Hello, ', str, '!') root@localhost 2014-09-30 08:00:00 2014-09-30 08:00:00 STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION latin1 latin1_swedish_ci utf8mb4_uca1400_ai_ci RETURN CONCAT('Hello, ', str, '!') NONE
+db name type specific_name language sql_data_access is_deterministic security_type param_list returns body definer created modified sql_mode comment character_set_client collation_connection db_collation body_utf8 aggregate path
+test f1 FUNCTION f1 SQL CONTAINS_SQL NO DEFINER str char(20) char(100) CHARSET utf8mb4 COLLATE utf8mb4_uca1400_ai_ci RETURN CONCAT('Hello, ', str, '!') root@localhost 2014-09-30 08:00:00 2014-09-30 08:00:00 STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION latin1 latin1_swedish_ci utf8mb4_uca1400_ai_ci RETURN CONCAT('Hello, ', str, '!') NONE CURRENT_SCHEMA
SELECT f1('world');
f1('world')
Hello, world!
diff --git a/mysql-test/main/create_drop_role.result b/mysql-test/main/create_drop_role.result
index e3c893aaacfe6..ee8243aa4fddf 100644
--- a/mysql-test/main/create_drop_role.result
+++ b/mysql-test/main/create_drop_role.result
@@ -76,6 +76,7 @@ Warnings:
Note 1976 Can't drop role 'role_1'; it doesn't exist
DROP ROLE role_1;
ERROR HY000: Operation DROP ROLE failed for 'role_1'
+disconnect user_a;
DROP USER u1@localhost;
CREATE ROLE r;
GRANT SHOW DATABASES ON *.* TO r;
diff --git a/mysql-test/main/create_drop_role.test b/mysql-test/main/create_drop_role.test
index 808461ed3441c..e4890851bebe0 100644
--- a/mysql-test/main/create_drop_role.test
+++ b/mysql-test/main/create_drop_role.test
@@ -54,6 +54,7 @@ DROP ROLE IF EXISTS role_1;
--error ER_CANNOT_USER
DROP ROLE role_1;
+disconnect user_a;
DROP USER u1@localhost;
# MDEV-17942
diff --git a/mysql-test/main/create_drop_user.result b/mysql-test/main/create_drop_user.result
index 67717f3e4e05d..4a72a4b089152 100644
--- a/mysql-test/main/create_drop_user.result
+++ b/mysql-test/main/create_drop_user.result
@@ -41,3 +41,80 @@ Warnings:
Note 1974 Can't drop user 'u1'@'%'; it doesn't exist
DROP USER u2;
ERROR HY000: Operation DROP USER failed for 'u2'@'%'
+#
+# MDEV-35617: DROP USER should leave no active session for that user
+#
+CREATE USER u1;
+CREATE USER u2;
+CREATE USER u3;
+GRANT ALL on test.* to u1;
+GRANT ALL on test.* to u2;
+GRANT ALL on test.* to u3;
+# Establish two connections on behalf the users u1, u3
+# A connection on behalf the user u2 isn't established intentionally
+connect con1, localhost, u1, , test;
+connect con3, localhost, u3, , test;
+# Drop the users u1, u2, u3. Since the users u1 and u3 have active
+# connections to the server, the warning about it will be output
+connection default;
+DROP USER u1, u2, u3;
+Warnings:
+Note 4227 Dropped users 'u1'@'%','u3'@'%' have active connections. Use KILL CONNECTION if they should not be used anymore.
+# None of the users u1, u2, u3 should be present in the system
+SELECT User, Host FROM mysql.user WHERE user IN ('u1', 'u2', 'u3');
+User Host
+disconnect con1;
+disconnect con3;
+# Check behaviour of the DROP USER statement in
+# oracle compatibility mode
+SET @save_sql_mode = @@sql_mode;
+SET sql_mode="oracle";
+CREATE USER u1;
+CREATE USER u2;
+CREATE USER u3;
+GRANT ALL on test.* to u1;
+GRANT ALL on test.* to u2;
+GRANT ALL on test.* to u3;
+# Established two connections on behalf the users u1, u3;
+# A connection on behalf the user u2 isn't established intentionally
+connect con1, localhost, u1, , test;
+connect con3, localhost, u3, , test;
+connection default;
+# In oracle compatibility mode, DROP USER fails in case
+# there are connections on behalf the users being dropped.
+DROP USER u1, u2, u3;
+ERROR HY000: Operation DROP USER failed for 'u1'@'%','u3'@'%'
+# It is expected to see two users in output of the query: u1 and u3,
+# u2 should be dropped since it doesn't have active connection at the moment
+SELECT User, Host FROM mysql.user WHERE user IN ('u1', 'u2', 'u3');
+User Host
+u1 %
+u3 %
+SET sql_mode= @save_sql_mode;
+disconnect con1;
+disconnect con3;
+# Clean up
+# Clean up
+DROP USER u1, u3;
+CREATE USER u@localhost;
+CREATE USER u@'%';
+connect u,localhost,u;
+connection default;
+DROP USER u@'%';
+disconnect u;
+DROP USER u@localhost;
+CREATE USER u@localhost;
+SET sql_mode=oracle;
+connect u,localhost,u;
+connection default;
+DROP USER u@'%';
+ERROR HY000: Operation DROP USER failed for 'u'@'%'
+disconnect u;
+connect u,localhost,u;
+SELECT user(), current_user();
+user() current_user()
+u@localhost u@localhost
+disconnect u;
+connection default;
+# Clean up
+DROP USER u@localhost;
diff --git a/mysql-test/main/create_drop_user.test b/mysql-test/main/create_drop_user.test
index 234383fb4ca06..eeefa63c1b455 100644
--- a/mysql-test/main/create_drop_user.test
+++ b/mysql-test/main/create_drop_user.test
@@ -44,3 +44,94 @@ DROP USER IF EXISTS u1, u2;
--error ER_CANNOT_USER
DROP USER u2;
+
+--echo #
+--echo # MDEV-35617: DROP USER should leave no active session for that user
+--echo #
+
+CREATE USER u1;
+CREATE USER u2;
+CREATE USER u3;
+
+GRANT ALL on test.* to u1;
+GRANT ALL on test.* to u2;
+GRANT ALL on test.* to u3;
+
+--echo # Establish two connections on behalf the users u1, u3
+--echo # A connection on behalf the user u2 isn't established intentionally
+--connect (con1, localhost, u1, , test)
+--connect (con3, localhost, u3, , test)
+
+--echo # Drop the users u1, u2, u3. Since the users u1 and u3 have active
+--echo # connections to the server, the warning about it will be output
+--connection default
+DROP USER u1, u2, u3;
+
+--echo # None of the users u1, u2, u3 should be present in the system
+SELECT User, Host FROM mysql.user WHERE user IN ('u1', 'u2', 'u3');
+
+--disconnect con1
+--disconnect con3
+
+--echo # Check behaviour of the DROP USER statement in
+--echo # oracle compatibility mode
+SET @save_sql_mode = @@sql_mode;
+SET sql_mode="oracle";
+CREATE USER u1;
+CREATE USER u2;
+CREATE USER u3;
+
+GRANT ALL on test.* to u1;
+GRANT ALL on test.* to u2;
+GRANT ALL on test.* to u3;
+
+--echo # Established two connections on behalf the users u1, u3;
+--echo # A connection on behalf the user u2 isn't established intentionally
+--connect (con1, localhost, u1, , test)
+--connect (con3, localhost, u3, , test)
+
+--connection default
+--echo # In oracle compatibility mode, DROP USER fails in case
+--echo # there are connections on behalf the users being dropped.
+--error ER_CANNOT_USER
+DROP USER u1, u2, u3;
+
+--echo # It is expected to see two users in output of the query: u1 and u3,
+--echo # u2 should be dropped since it doesn't have active connection at the moment
+SELECT User, Host FROM mysql.user WHERE user IN ('u1', 'u2', 'u3');
+SET sql_mode= @save_sql_mode;
+
+--disconnect con1
+--disconnect con3
+--echo # Clean up
+--disable_warnings
+--echo # Clean up
+DROP USER u1, u3;
+--enable_warnings
+
+CREATE USER u@localhost;
+CREATE USER u@'%';
+--connect u,localhost,u
+--connection default
+DROP USER u@'%';
+
+--disconnect u
+--disable_warnings
+DROP USER u@localhost;
+--enable_warnings
+
+CREATE USER u@localhost;
+SET sql_mode=oracle;
+--connect u,localhost,u
+--connection default
+--error ER_CANNOT_USER
+DROP USER u@'%';
+--disconnect u
+
+--connect u,localhost,u
+SELECT user(), current_user();
+
+--disconnect u
+--connection default
+--echo # Clean up
+DROP USER u@localhost;
diff --git a/mysql-test/main/create_or_replace.test b/mysql-test/main/create_or_replace.test
index 05af75b61b73c..736713183ef1c 100644
--- a/mysql-test/main/create_or_replace.test
+++ b/mysql-test/main/create_or_replace.test
@@ -239,6 +239,7 @@ select LOCK_MODE,LOCK_TYPE, TABLE_SCHEMA,TABLE_NAME from information_schema.meta
--error ER_DUP_FIELDNAME
create or replace table test.t1 (a int) select 1 as 'a', 2 as 'a';
show tables;
+--sorted_result
select LOCK_MODE,LOCK_TYPE, TABLE_SCHEMA,TABLE_NAME from information_schema.metadata_lock_info;
--sorted_result
select LOCK_MODE,LOCK_TYPE, TABLE_SCHEMA,TABLE_NAME from information_schema.metadata_lock_info;
diff --git a/mysql-test/main/create_or_replace_permission.result b/mysql-test/main/create_or_replace_permission.result
index 1ea15d9621b16..8888fb04ed4ae 100644
--- a/mysql-test/main/create_or_replace_permission.result
+++ b/mysql-test/main/create_or_replace_permission.result
@@ -44,13 +44,10 @@ ERROR 42000: Access denied; you need (at least one of) the CREATE USER privilege
CREATE OR REPLACE ROLE developer;
ERROR 42000: Access denied; you need (at least one of) the CREATE USER privilege(s) for this operation
connection default;
+disconnect user_a;
SELECT CURRENT_USER;
CURRENT_USER
root@localhost
-REVOKE ALL ON db1.* FROM mysqltest_1@localhost;
-DROP DATABASE IF EXISTS db2;
-Warnings:
-Note 1008 Can't drop database 'db2'; database doesn't exist
DROP DATABASE db1;
DROP USER mysqltest_1@localhost;
set global sql_mode=default;
diff --git a/mysql-test/main/create_or_replace_permission.test b/mysql-test/main/create_or_replace_permission.test
index 0e833a125bd9e..66cd96bc6feed 100644
--- a/mysql-test/main/create_or_replace_permission.test
+++ b/mysql-test/main/create_or_replace_permission.test
@@ -61,11 +61,9 @@ CREATE OR REPLACE USER u1@localhost;
CREATE OR REPLACE ROLE developer;
connection default;
+disconnect user_a;
SELECT CURRENT_USER;
-REVOKE ALL ON db1.* FROM mysqltest_1@localhost;
-DROP DATABASE IF EXISTS db2;
DROP DATABASE db1;
DROP USER mysqltest_1@localhost;
-
set global sql_mode=default;
diff --git a/mysql-test/main/create_or_replace_pfs.result b/mysql-test/main/create_or_replace_pfs.result
new file mode 100644
index 0000000000000..24e40ea3b317d
--- /dev/null
+++ b/mysql-test/main/create_or_replace_pfs.result
@@ -0,0 +1,27 @@
+#
+# MDEV-23298 Assertion `table_list->prelocking_placeholder ==
+# TABLE_LIST::PRELOCK_NONE' failed in check_lock_and_start_stmt on
+# CREATE OR REPLACE TABLE
+#
+create table t2 (a int);
+insert into t2 values(1),(2);
+CREATE TABLE t1 (a INT);
+CREATE OR REPLACE TABLE t1 AS SELECT sys.format_statement('SELECT 1') AS q;
+drop table t1;
+CREATE TABLE t1 (a INT);
+CREATE OR REPLACE TABLE t1 AS SELECT sys.format_statement('SELECT 1') AS q, t2.a from t2;
+SELECT * from t1;
+q a
+SELECT 1 1
+SELECT 1 2
+drop table t1;
+CREATE TABLE t1 (a INT);
+lock table t1 write,t2 read, sys.sys_config read;
+CREATE OR REPLACE TABLE t1 AS SELECT sys.format_statement('SELECT 1') AS q, t2.a from t2;
+unlock tables;
+select * from t1;
+q a
+SELECT 1 1
+SELECT 1 2
+drop table t1,t2;
+# End of 10.6 tests
diff --git a/mysql-test/main/create_or_replace_pfs.test b/mysql-test/main/create_or_replace_pfs.test
new file mode 100644
index 0000000000000..d7ad6d323365d
--- /dev/null
+++ b/mysql-test/main/create_or_replace_pfs.test
@@ -0,0 +1,28 @@
+#
+# Check CREATE OR REPLACE TABLE
+#
+--source include/have_perfschema.inc
+
+--echo #
+--echo # MDEV-23298 Assertion `table_list->prelocking_placeholder ==
+--echo # TABLE_LIST::PRELOCK_NONE' failed in check_lock_and_start_stmt on
+--echo # CREATE OR REPLACE TABLE
+--echo #
+
+create table t2 (a int);
+insert into t2 values(1),(2);
+CREATE TABLE t1 (a INT);
+CREATE OR REPLACE TABLE t1 AS SELECT sys.format_statement('SELECT 1') AS q;
+drop table t1;
+CREATE TABLE t1 (a INT);
+CREATE OR REPLACE TABLE t1 AS SELECT sys.format_statement('SELECT 1') AS q, t2.a from t2;
+SELECT * from t1;
+drop table t1;
+CREATE TABLE t1 (a INT);
+lock table t1 write,t2 read, sys.sys_config read;
+CREATE OR REPLACE TABLE t1 AS SELECT sys.format_statement('SELECT 1') AS q, t2.a from t2;
+unlock tables;
+select * from t1;
+drop table t1,t2;
+
+--echo # End of 10.6 tests
diff --git a/mysql-test/main/create_select.result b/mysql-test/main/create_select.result
index 2fe9bba9872e4..bd78e2193aa96 100644
--- a/mysql-test/main/create_select.result
+++ b/mysql-test/main/create_select.result
@@ -56,6 +56,22 @@ t1 CREATE TABLE `t1` (
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci WITH SYSTEM VERSIONING
drop table t1;
set sql_mode=default;
-#
# End of 10.4 tests
#
+# MDEV-37998 (Column) CHECK constraints can cause CREATE TABLE (SELECT) queries to fail
+#
+create table t1(
+i int not null check(i > 0),
+j int default (i+1),
+primary key(i),
+check (2*i>1)
+);
+create table t2 (select i as a,j from t1);
+show create table t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `a` int(11) NOT NULL,
+ `j` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci
+drop table t1, t2;
+# End of 12.1 tests
diff --git a/mysql-test/main/create_select.test b/mysql-test/main/create_select.test
index d91f71133a0de..c464744390bd4 100644
--- a/mysql-test/main/create_select.test
+++ b/mysql-test/main/create_select.test
@@ -63,6 +63,19 @@ show create table t1;
drop table t1;
set sql_mode=default;
---echo #
--echo # End of 10.4 tests
+
+--echo #
+--echo # MDEV-37998 (Column) CHECK constraints can cause CREATE TABLE (SELECT) queries to fail
--echo #
+create table t1(
+ i int not null check(i > 0),
+ j int default (i+1),
+ primary key(i),
+ check (2*i>1)
+);
+create table t2 (select i as a,j from t1);
+show create table t2;
+drop table t1, t2;
+
+--echo # End of 12.1 tests
diff --git a/mysql-test/main/create_w_max_indexes_128.result b/mysql-test/main/create_w_max_indexes_128.result
index 112df1b7c4131..e54c27b827048 100644
--- a/mysql-test/main/create_w_max_indexes_128.result
+++ b/mysql-test/main/create_w_max_indexes_128.result
@@ -470,7 +470,7 @@ t1 CREATE TABLE `t1` (
KEY `a126_long_123456789_123456789_123456789_123456789_123456789_1234` (`c1`,`c2`,`c3`,`c4`,`c5`,`c6`,`c7`,`c8`,`c9`,`c10`,`c11`,`c12`,`c13`,`c14`,`c15`,`c16`),
KEY `a127_long_123456789_123456789_123456789_123456789_123456789_1234` (`c1`,`c2`,`c3`,`c4`,`c5`,`c6`,`c7`,`c8`,`c9`,`c10`,`c11`,`c12`,`c13`,`c14`,`c15`,`c16`),
KEY `a128_long_123456789_123456789_123456789_123456789_123456789_1234` (`c1`,`c2`,`c3`,`c4`,`c5`,`c6`,`c7`,`c8`,`c9`,`c10`,`c11`,`c12`,`c13`,`c14`,`c15`,`c16`)
-) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
+) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci
flush tables;
show create table t1;
Table Create Table
@@ -619,7 +619,7 @@ t1 CREATE TABLE `t1` (
KEY `a126_long_123456789_123456789_123456789_123456789_123456789_1234` (`c1`,`c2`,`c3`,`c4`,`c5`,`c6`,`c7`,`c8`,`c9`,`c10`,`c11`,`c12`,`c13`,`c14`,`c15`,`c16`),
KEY `a127_long_123456789_123456789_123456789_123456789_123456789_1234` (`c1`,`c2`,`c3`,`c4`,`c5`,`c6`,`c7`,`c8`,`c9`,`c10`,`c11`,`c12`,`c13`,`c14`,`c15`,`c16`),
KEY `a128_long_123456789_123456789_123456789_123456789_123456789_1234` (`c1`,`c2`,`c3`,`c4`,`c5`,`c6`,`c7`,`c8`,`c9`,`c10`,`c11`,`c12`,`c13`,`c14`,`c15`,`c16`)
-) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
+) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci
drop table t1;
create table t1 (c1 int, c2 int, c3 int, c4 int, c5 int, c6 int, c7 int,
c8 int, c9 int, c10 int, c11 int, c12 int, c13 int, c14 int, c15 int, c16 int);
@@ -1092,7 +1092,7 @@ t1 CREATE TABLE `t1` (
KEY `a126_long_123456789_123456789_123456789_123456789_123456789_1234` (`c1`,`c2`,`c3`,`c4`,`c5`,`c6`,`c7`,`c8`,`c9`,`c10`,`c11`,`c12`,`c13`,`c14`,`c15`,`c16`),
KEY `a127_long_123456789_123456789_123456789_123456789_123456789_1234` (`c1`,`c2`,`c3`,`c4`,`c5`,`c6`,`c7`,`c8`,`c9`,`c10`,`c11`,`c12`,`c13`,`c14`,`c15`,`c16`),
KEY `a128_long_123456789_123456789_123456789_123456789_123456789_1234` (`c1`,`c2`,`c3`,`c4`,`c5`,`c6`,`c7`,`c8`,`c9`,`c10`,`c11`,`c12`,`c13`,`c14`,`c15`,`c16`)
-) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
+) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci
flush tables;
show create table t1;
Table Create Table
@@ -1241,7 +1241,7 @@ t1 CREATE TABLE `t1` (
KEY `a126_long_123456789_123456789_123456789_123456789_123456789_1234` (`c1`,`c2`,`c3`,`c4`,`c5`,`c6`,`c7`,`c8`,`c9`,`c10`,`c11`,`c12`,`c13`,`c14`,`c15`,`c16`),
KEY `a127_long_123456789_123456789_123456789_123456789_123456789_1234` (`c1`,`c2`,`c3`,`c4`,`c5`,`c6`,`c7`,`c8`,`c9`,`c10`,`c11`,`c12`,`c13`,`c14`,`c15`,`c16`),
KEY `a128_long_123456789_123456789_123456789_123456789_123456789_1234` (`c1`,`c2`,`c3`,`c4`,`c5`,`c6`,`c7`,`c8`,`c9`,`c10`,`c11`,`c12`,`c13`,`c14`,`c15`,`c16`)
-) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
+) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci
alter table t1 add key
a129_long_123456789_123456789_123456789_123456789_123456789_1234 (
c1,c2,c3,c4,c5,c6,c7,c8,c9,c10,c11,c12,c13,c14,c15,c16);
diff --git a/mysql-test/main/cte_grant.result b/mysql-test/main/cte_grant.result
index 7a982fcee9af6..c88fca86454bb 100644
--- a/mysql-test/main/cte_grant.result
+++ b/mysql-test/main/cte_grant.result
@@ -60,7 +60,7 @@ c d
1 30
1 30
connection root;
-revoke all privileges on mysqltest.v1 from mysqltest_1@localhost;
+disconnect user1;
drop user mysqltest_1@localhost;
drop database mysqltest;
#
diff --git a/mysql-test/main/cte_grant.test b/mysql-test/main/cte_grant.test
index 3e6d50095693d..c9330de7a1960 100644
--- a/mysql-test/main/cte_grant.test
+++ b/mysql-test/main/cte_grant.test
@@ -1,16 +1,10 @@
# Can't test with embedded server
-- source include/not_embedded.inc
-# Save the initial number of concurrent sessions
---source include/count_sessions.inc
-
connect (root,localhost,root,,test);
connection root;
---disable_warnings
create database mysqltest;
---enable_warnings
-
create user mysqltest_1@localhost;
connect (user1,localhost,mysqltest_1,,"*NO-ONE*");
connection user1;
@@ -74,7 +68,7 @@ connection user1;
select * from mysqltest.v3;
connection root;
-revoke all privileges on mysqltest.v1 from mysqltest_1@localhost;
+disconnect user1;
drop user mysqltest_1@localhost;
drop database mysqltest;
diff --git a/mysql-test/main/cte_nonrecursive.result b/mysql-test/main/cte_nonrecursive.result
index 3ac342fb560ca..992c218a10eed 100644
--- a/mysql-test/main/cte_nonrecursive.result
+++ b/mysql-test/main/cte_nonrecursive.result
@@ -1676,6 +1676,7 @@ use test;
# THD::create_tmp_table_def_key
#
connect con1,localhost,root,,;
+change_user root,,;
CREATE TEMPORARY TABLE test.t (a INT);
WITH cte AS (SELECT 1) SELECT * FROM cte;
1
diff --git a/mysql-test/main/cte_recursive.result b/mysql-test/main/cte_recursive.result
index 42c77be5ca296..4bb99195e983d 100644
--- a/mysql-test/main/cte_recursive.result
+++ b/mysql-test/main/cte_recursive.result
@@ -6052,3 +6052,188 @@ b rank() over (order by c)
drop view v1;
drop table t1;
# End of 10.4 tests
+#
+# MDEV-32308: Server crash on cleanup of
+# non-fully-constructed-due-to-an-error CTE
+#
+SELECT ( WITH RECURSIVE x AS ( WITH x AS ( SELECT 1 FROM t14 ) SELECT x ) , t14 AS ( SELECT 1 UNION SELECT 'x' FROM x ) SELECT x FROM x WHERE ( SELECT x FROM x ) ) ;
+ERROR 42S22: Unknown column 'x' in 'SELECT'
+#
+# MDEV-32299 Segfault when preparing unreferenced select in recursive CTE
+#
+SELECT ( WITH RECURSIVE x AS ( SELECT * FROM ( SELECT UTC_TIMESTAMP FROM ( SELECT ( WITH x AS ( WITH x AS ( SELECT * FROM x ) SELECT 1 ) SELECT 1 ) ) x ) x UNION SELECT NULL ) ( SELECT x FROM x ) ) ;
+ERROR 42S22: Unknown column 'x' in 'SELECT'
+select (
+with recursive x as (
+select * from (
+select utc_timestamp
+from (
+select (
+with x as (
+with x as (
+select * from x
+)
+select 1
+)
+select 1
+) s
+) y
+) z
+union
+select null
+)
+(select x from x)
+);
+ERROR 42S22: Unknown column 'x' in 'SELECT'
+select (
+with recursive r as (
+select * from (
+with a as (
+select * from r
+)
+select 1
+) y
+union
+select 1
+)
+(select * from r)
+);
+(
+with recursive r as (
+select * from (
+with a as (
+select * from r
+)
+select 1
+) y
+union
+select 1
+)
+(select * from r)
+)
+1
+create table t1 (x int);
+with recursive r as (
+select f1 from (
+with a as (
+select x from t1
+)
+select 1 as f1
+) y
+union
+select null
+)
+(select * from r);
+f1
+1
+NULL
+with recursive r as (
+select f1 from (
+with a as (
+select f2 from t1
+)
+select 1 as f1
+) y
+union
+select null
+)
+(select * from r);
+ERROR 42S22: Unknown column 'f2' in 'SELECT'
+drop table t1;
+with recursive r as (
+select 1 as f1
+union
+select f1 from (
+with a as (
+select f1 from r
+)
+select 1 as f1
+) y
+)
+(select f1 from r);
+f1
+1
+with recursive r as (
+select 1 as f1
+union
+select f1 from (
+with a as (
+select f2 from r
+)
+select 1 as f1
+) y
+)
+(select f1 from r);
+ERROR 42S22: Unknown column 'f2' in 'SELECT'
+# End of 10.6 tests
+#
+# MDEV-32724 Segmentation fault due to Deep Recursion in table.cc and sql_lex.cc
+#
+with recursive r (y) as (
+with r (z) as (select 1 from r) select 1 from r
+union all
+select y from r)
+select y from r;
+ERROR HY000: No anchors for recursive WITH element 'r'
+# r2 CTE is the anchor for r (original behavior):
+with recursive r (y) as (
+with recursive r2 (z) as (
+select z + 1 from r2 where z < 2
+union all
+select 1)
+select z from r2
+union all
+select y * 2 from r where y < 10)
+select y from r;
+y
+1
+2
+2
+4
+4
+8
+8
+16
+16
+# It is different with the name clash,
+# select y * 2 from r is attached to inner r:
+with recursive r (y) as (
+with recursive r (z) as (
+select z + 1 from r where z < 2
+union all
+select 1)
+select z from r
+union all
+select y * 2 from r where y < 10)
+select y from r;
+ERROR 42S22: Unknown column 'y' in 'SELECT'
+# The whole set of SELECTs is attached to CTE:
+with recursive r (z) as (
+select z + 1 from r where z < 2
+union all
+select 1)
+select z from r
+union all
+select z * 2 from r where z < 10;
+z
+1
+2
+2
+4
+# In this case no outer recursion can occur as every r
+# is taken by the inner recursive CTE:
+with recursive r (y) as (
+with recursive r (z) as (
+select z + 1 from r where z < 2
+union all
+select 1)
+select z from r
+union all
+select z * 2 from r where z < 10)
+select y from r;
+y
+1
+2
+2
+4
+# End of 10.11 tests
diff --git a/mysql-test/main/cte_recursive.test b/mysql-test/main/cte_recursive.test
index f3e6cd78a5449..5f10d92b5cc5c 100644
--- a/mysql-test/main/cte_recursive.test
+++ b/mysql-test/main/cte_recursive.test
@@ -3,6 +3,8 @@
--source include/no_msan_without_big.inc
--source include/not_valgrind.inc
--source include/have_innodb.inc
+# --view-protocol fails due to MDEV-37119 for MDEV-32299
+--source include/no_view_protocol.inc
create table t1 (a int, b varchar(32));
insert into t1 values
@@ -4058,3 +4060,186 @@ drop view v1;
drop table t1;
--echo # End of 10.4 tests
+
+--echo #
+--echo # MDEV-32308: Server crash on cleanup of
+--echo # non-fully-constructed-due-to-an-error CTE
+--echo #
+--error ER_BAD_FIELD_ERROR
+SELECT ( WITH RECURSIVE x AS ( WITH x AS ( SELECT 1 FROM t14 ) SELECT x ) , t14 AS ( SELECT 1 UNION SELECT 'x' FROM x ) SELECT x FROM x WHERE ( SELECT x FROM x ) ) ;
+
+--echo #
+--echo # MDEV-32299 Segfault when preparing unreferenced select in recursive CTE
+--echo #
+
+# As in bug report
+--error ER_BAD_FIELD_ERROR
+SELECT ( WITH RECURSIVE x AS ( SELECT * FROM ( SELECT UTC_TIMESTAMP FROM ( SELECT ( WITH x AS ( WITH x AS ( SELECT * FROM x ) SELECT 1 ) SELECT 1 ) ) x ) x UNION SELECT NULL ) ( SELECT x FROM x ) ) ;
+
+#0 0x00005555569dff7b in TABLE_LIST::reset_const_table (this=0x7fffe0019938) at ../src/sql/table.cc:9615
+#1 0x00005555569dffd4 in TABLE_LIST::reset_const_table (this=0x7fffe001a8c0) at ../src/sql/table.cc:9622
+--error ER_BAD_FIELD_ERROR
+select (
+ with recursive x as (
+ select * from (
+ select utc_timestamp
+ from (
+ select (
+ with x as (
+ with x as (
+ select * from x
+ )
+ select 1
+ )
+ select 1
+ ) s
+ ) y
+ ) z
+
+ union
+
+ select null
+ )
+ (select x from x)
+);
+
+#6 0x00007ffff7639206 in __assert_fail (assertion=0x555555e121b6 "table_ref->table || table_ref->view", file=0x555555cdf138 "../src/sql/table.cc", line=7305, function=0x555555e30e24 "void Field_iterator_table_ref::set_field_iterator()") at ./assert/assert.c:101
+#7 0x00005555569da013 in Field_iterator_table_ref::set_field_iterator (this=0x7ffff0a9afc0) at ../src/sql/table.cc:7305
+select (
+ with recursive r as (
+ select * from (
+ with a as (
+ select * from r
+ )
+ select 1
+ ) y
+
+ union
+
+ select 1
+ )
+ (select * from r)
+);
+
+# Field resolution in unreferenced:
+create table t1 (x int);
+
+with recursive r as (
+ select f1 from (
+ with a as (
+ select x from t1
+ )
+ select 1 as f1
+ ) y
+
+ union
+
+ select null
+)
+(select * from r);
+
+--error ER_BAD_FIELD_ERROR
+with recursive r as (
+ select f1 from (
+ with a as (
+ select f2 from t1
+ )
+ select 1 as f1
+ ) y
+
+ union
+
+ select null
+)
+(select * from r);
+
+drop table t1;
+
+with recursive r as (
+ select 1 as f1
+
+ union
+
+ select f1 from (
+ with a as (
+ select f1 from r
+ )
+ select 1 as f1
+ ) y
+)
+(select f1 from r);
+
+--error ER_BAD_FIELD_ERROR
+with recursive r as (
+ select 1 as f1
+
+ union
+
+ select f1 from (
+ with a as (
+ select f2 from r
+ )
+ select 1 as f1
+ ) y
+)
+(select f1 from r);
+
+
+--echo # End of 10.6 tests
+
+--echo #
+--echo # MDEV-32724 Segmentation fault due to Deep Recursion in table.cc and sql_lex.cc
+--echo #
+--error ER_RECURSIVE_WITHOUT_ANCHORS
+with recursive r (y) as (
+ with r (z) as (select 1 from r) select 1 from r
+ union all
+ select y from r)
+select y from r;
+
+--echo # r2 CTE is the anchor for r (original behavior):
+with recursive r (y) as (
+ with recursive r2 (z) as (
+ select z + 1 from r2 where z < 2
+ union all
+ select 1)
+ select z from r2
+ union all
+ select y * 2 from r where y < 10)
+select y from r;
+
+--echo # It is different with the name clash,
+--echo # select y * 2 from r is attached to inner r:
+--error ER_BAD_FIELD_ERROR
+with recursive r (y) as (
+ with recursive r (z) as (
+ select z + 1 from r where z < 2
+ union all
+ select 1)
+ select z from r
+ union all
+ select y * 2 from r where y < 10)
+select y from r;
+
+--echo # The whole set of SELECTs is attached to CTE:
+with recursive r (z) as (
+ select z + 1 from r where z < 2
+ union all
+ select 1)
+select z from r
+union all
+select z * 2 from r where z < 10;
+
+--echo # In this case no outer recursion can occur as every r
+--echo # is taken by the inner recursive CTE:
+with recursive r (y) as (
+ with recursive r (z) as (
+ select z + 1 from r where z < 2
+ union all
+ select 1)
+ select z from r
+ union all
+ select z * 2 from r where z < 10)
+select y from r;
+
+--echo # End of 10.11 tests
diff --git a/mysql-test/main/cte_update_delete.result b/mysql-test/main/cte_update_delete.result
new file mode 100644
index 0000000000000..6cda90fb9e2cd
--- /dev/null
+++ b/mysql-test/main/cte_update_delete.result
@@ -0,0 +1,1378 @@
+#
+# MDEV-37220 Allow UPDATE/DELETE to read from a CTE
+#
+create table t1
+(
+a int not null,
+b int,
+c int,
+d int,
+amount decimal,
+key t1_ix1 (a,b)
+);
+insert into t1 values (0, NULL, 0, NULL, 10.0000), (1, 1, 1, 1, 10.0000),
+(2, 2, 2, 2, 20.0000), (3, 3, 3, 3, 30.0000), (4, 4, 4, 4, 40.0000),
+(5, 5, 5, 5, NULL), (6, 6, 6, 6, NULL), (7, 7, 7, 7, 70.0000),
+(8, 8, 8, 8, 80.0000);
+create table t2
+(
+a int NOT NULL,
+b int,
+name varchar(50),
+key t2_ix1 (a,b)
+);
+insert into t2 values (0, NULL, 'a'), (1, NULL, 'A'), (2, 2, 'B'), (3,3, 'C'),
+(4,4, 'D'), (5,5, NULL), (6,6, NULL), (7,7, 'E'), (8,8, 'F'), (9,9, 'G'),
+(10,10,'H'), (11,11, NULL), (12,12, NULL);
+create table t3
+(
+a int,
+b int,
+description varchar(50)
+);
+create table t4 as select * from t1;
+create table t5 as select * from t2;
+insert into t3 values (1, 1, 'iron'),(2,2,'wood'),(0,NULL, 'gold'),
+(3, 3, 'silver'), (4, 4, 'lead'), (5, 5, 'tin'), (6, 6, 'platinum'),
+(7, 7, 'aluminium');
+select * from t3;
+a b description
+1 1 iron
+2 2 wood
+0 NULL gold
+3 3 silver
+4 4 lead
+5 5 tin
+6 6 platinum
+7 7 aluminium
+# update, single table syntax, subq in set
+explain with cte as (select * from t1 where c < 5),
+cte2 as (select * from t2 where b < 3)
+update t3
+set t3.a = (select a from cte where b in (select b from cte2) and d = t3.a);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t3 ALL NULL NULL NULL NULL 8
+4 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 9 Using where
+4 DEPENDENT SUBQUERY t2 index NULL t2_ix1 9 NULL 13 Using where; Using index; FirstMatch(t1); Using join buffer (flat, BNL join)
+with cte as (select * from t1 where c < 5),
+cte2 as (select * from t2 where b < 3)
+update t3
+set t3.a = (select a from cte where b in (select b from cte2) and d = t3.a);
+select * from t3;
+a b description
+NULL 1 iron
+2 2 wood
+NULL NULL gold
+NULL 3 silver
+NULL 4 lead
+NULL 5 tin
+NULL 6 platinum
+NULL 7 aluminium
+truncate t3;
+insert into t3 values (1, 1, 'iron'),(2,2,'wood'),(0,NULL, 'gold'),
+(3, 3, 'silver'), (4, 4, 'lead'), (5, 5, 'tin'), (6, 6, 'platinum'),
+(7, 7, 'aluminium');
+create procedure p() with cte as (select * from t1 where c < 5),
+cte2 as (select * from t2 where b < 3)
+update t3
+set t3.a = (select a from cte where b in (select b from cte2) and d = t3.a);
+call p();
+drop procedure p;
+select * from t3;
+a b description
+NULL 1 iron
+2 2 wood
+NULL NULL gold
+NULL 3 silver
+NULL 4 lead
+NULL 5 tin
+NULL 6 platinum
+NULL 7 aluminium
+truncate t3;
+insert into t3 values (1, 1, 'iron'),(2,2,'wood'),(0,NULL, 'gold'),
+(3, 3, 'silver'), (4, 4, 'lead'), (5, 5, 'tin'), (6, 6, 'platinum'),
+(7, 7, 'aluminium');
+prepare s from 'with cte as (select * from t1 where c < 5),
+cte2 as (select * from t2 where b < 3)
+update t3
+set t3.a = (select a from cte where b in (select b from cte2) and d = t3.a)';
+execute s;
+select * from t3;
+a b description
+NULL 1 iron
+2 2 wood
+NULL NULL gold
+NULL 3 silver
+NULL 4 lead
+NULL 5 tin
+NULL 6 platinum
+NULL 7 aluminium
+truncate t3;
+insert into t3 values (1, 1, 'iron'),(2,2,'wood'),(0,NULL, 'gold'),
+(3, 3, 'silver'), (4, 4, 'lead'), (5, 5, 'tin'), (6, 6, 'platinum'),
+(7, 7, 'aluminium');
+execute s;
+select * from t3;
+a b description
+NULL 1 iron
+2 2 wood
+NULL NULL gold
+NULL 3 silver
+NULL 4 lead
+NULL 5 tin
+NULL 6 platinum
+NULL 7 aluminium
+truncate t3;
+insert into t3 values (1, 1, 'iron'),(2,2,'wood'),(0,NULL, 'gold'),
+(3, 3, 'silver'), (4, 4, 'lead'), (5, 5, 'tin'), (6, 6, 'platinum'),
+(7, 7, 'aluminium');
+drop prepare s;
+# update, single table syntax, subq in set, cte used twice
+explain with cte as (select * from t1 where c < 5),
+cte2 as (select * from t2 where b < 3)
+update t3
+set t3.a = (select a from cte
+where
+(b in (select b from cte2 where cte2.a = cte.a) or
+b in (select b from cte2 where cte2.b = cte.a)) and
+d = t3.a
+);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t3 ALL NULL NULL NULL NULL 8
+4 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 9 Using where
+6 DEPENDENT SUBQUERY t2 index t2_ix1 t2_ix1 9 NULL 13 Using where; Using index
+5 DEPENDENT SUBQUERY t2 ref t2_ix1 t2_ix1 9 test.t1.a,func 1 Using where; Using index
+with cte as (select * from t1 where c < 5),
+cte2 as (select * from t2 where b < 3)
+update t3
+set t3.a = (select a from cte
+where
+(b in (select b from cte2 where cte2.a = cte.a) or
+b in (select b from cte2 where cte2.b = cte.a)) and
+d = t3.a
+);
+select * from t3;
+a b description
+NULL 1 iron
+2 2 wood
+NULL NULL gold
+NULL 3 silver
+NULL 4 lead
+NULL 5 tin
+NULL 6 platinum
+NULL 7 aluminium
+truncate t3;
+insert into t3 values (1, 1, 'iron'),(2,2,'wood'),(0,NULL, 'gold'),
+(3, 3, 'silver'), (4, 4, 'lead'), (5, 5, 'tin'), (6, 6, 'platinum'),
+(7, 7, 'aluminium');
+create procedure p() with cte as (select * from t1 where c < 5),
+cte2 as (select * from t2 where b < 3)
+update t3
+set t3.a = (select a from cte
+where
+(b in (select b from cte2 where cte2.a = cte.a) or
+b in (select b from cte2 where cte2.b = cte.a)) and
+d = t3.a
+);
+call p();
+drop procedure p;
+select * from t3;
+a b description
+NULL 1 iron
+2 2 wood
+NULL NULL gold
+NULL 3 silver
+NULL 4 lead
+NULL 5 tin
+NULL 6 platinum
+NULL 7 aluminium
+truncate t3;
+insert into t3 values (1, 1, 'iron'),(2,2,'wood'),(0,NULL, 'gold'),
+(3, 3, 'silver'), (4, 4, 'lead'), (5, 5, 'tin'), (6, 6, 'platinum'),
+(7, 7, 'aluminium');
+prepare s from 'with cte as (select * from t1 where c < 5),
+cte2 as (select * from t2 where b < 3)
+update t3
+set t3.a = (select a from cte
+where
+(b in (select b from cte2 where cte2.a = cte.a) or
+b in (select b from cte2 where cte2.b = cte.a)) and
+d = t3.a
+)';
+execute s;
+select * from t3;
+a b description
+NULL 1 iron
+2 2 wood
+NULL NULL gold
+NULL 3 silver
+NULL 4 lead
+NULL 5 tin
+NULL 6 platinum
+NULL 7 aluminium
+truncate t3;
+insert into t3 values (1, 1, 'iron'),(2,2,'wood'),(0,NULL, 'gold'),
+(3, 3, 'silver'), (4, 4, 'lead'), (5, 5, 'tin'), (6, 6, 'platinum'),
+(7, 7, 'aluminium');
+execute s;
+select * from t3;
+a b description
+NULL 1 iron
+2 2 wood
+NULL NULL gold
+NULL 3 silver
+NULL 4 lead
+NULL 5 tin
+NULL 6 platinum
+NULL 7 aluminium
+truncate t3;
+insert into t3 values (1, 1, 'iron'),(2,2,'wood'),(0,NULL, 'gold'),
+(3, 3, 'silver'), (4, 4, 'lead'), (5, 5, 'tin'), (6, 6, 'platinum'),
+(7, 7, 'aluminium');
+drop prepare s;
+# multi table syntax, subq in set and where
+explain with cte as (select * from t1 where c < 5),
+cte2 as (select * from t2 where b < 3)
+update t3,cte
+set t3.a = cte.a+1 where cte.b in (select b from cte2) and d = t3.a;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t3 ALL NULL NULL NULL NULL 8 Using where
+1 PRIMARY ref key0 key0 5 test.t3.a 1 Using where
+1 PRIMARY t2 index NULL t2_ix1 9 NULL 13 Using where; Using index; FirstMatch()
+2 DERIVED t1 ALL NULL NULL NULL NULL 9 Using where
+with cte as (select * from t1 where c < 5),
+cte2 as (select * from t2 where b < 3)
+update t3,cte
+set t3.a = cte.a+1 where cte.b in (select b from cte2) and d = t3.a;
+select * from t3;
+a b description
+1 1 iron
+3 2 wood
+0 NULL gold
+3 3 silver
+4 4 lead
+5 5 tin
+6 6 platinum
+7 7 aluminium
+truncate t3;
+insert into t3 values (1, 1, 'iron'),(2,2,'wood'),(0,NULL, 'gold'),
+(3, 3, 'silver'), (4, 4, 'lead'), (5, 5, 'tin'), (6, 6, 'platinum'),
+(7, 7, 'aluminium');
+create procedure p() with cte as (select * from t1 where c < 5),
+cte2 as (select * from t2 where b < 3)
+update t3,cte
+set t3.a = cte.a+1 where cte.b in (select b from cte2) and d = t3.a;
+call p();
+drop procedure p;
+select * from t3;
+a b description
+1 1 iron
+3 2 wood
+0 NULL gold
+3 3 silver
+4 4 lead
+5 5 tin
+6 6 platinum
+7 7 aluminium
+truncate t3;
+insert into t3 values (1, 1, 'iron'),(2,2,'wood'),(0,NULL, 'gold'),
+(3, 3, 'silver'), (4, 4, 'lead'), (5, 5, 'tin'), (6, 6, 'platinum'),
+(7, 7, 'aluminium');
+# multi table syntax, subq in set and where, more complex CTEs
+explain with cte as (select t1.* from t1 left join t4 on t1.d = t4.d where t1.c < 5),
+cte2 as (select t2.* from t2, t5 where t2.b < 3 and t2.name = t5.name limit 1)
+update t3,cte, t4
+set t3.a = cte.a+1, t4.a = cte.a+2
+where cte.b in (select b from cte2) and cte.d = t3.a and cte.b = t4.a;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t3 ALL NULL NULL NULL NULL 8 Using where
+1 PRIMARY ref key0 key0 5 test.t3.a 8 Using where
+1 PRIMARY ref key0 key0 5 cte.b 1 FirstMatch()
+1 PRIMARY t4 ALL NULL NULL NULL NULL 9 Using where
+3 DERIVED t2 ALL NULL NULL NULL NULL 13 Using where
+3 DERIVED t5 ALL NULL NULL NULL NULL 13 Using where; Using join buffer (flat, BNL join)
+2 DERIVED t1 ALL NULL NULL NULL NULL 9 Using where
+2 DERIVED t4 ALL NULL NULL NULL NULL 9 Using where; Using join buffer (flat, BNL join)
+with cte as (select t1.* from t1 left join t4 on t1.d = t4.d where t1.c < 5),
+cte2 as (select t2.* from t2, t5 where t2.b < 3 and t2.name = t5.name limit 1)
+update t3,cte, t4
+set t3.a = cte.a+1, t4.a = cte.a+2
+where cte.b in (select b from cte2) and cte.d = t3.a and cte.b = t4.a;
+select * from t3;
+a b description
+1 1 iron
+3 2 wood
+0 NULL gold
+3 3 silver
+4 4 lead
+5 5 tin
+6 6 platinum
+7 7 aluminium
+select * from t4;
+a b c d amount
+0 NULL 0 NULL 10
+1 1 1 1 10
+4 2 2 2 20
+3 3 3 3 30
+4 4 4 4 40
+5 5 5 5 NULL
+6 6 6 6 NULL
+7 7 7 7 70
+8 8 8 8 80
+truncate t3;
+insert into t3 values (1, 1, 'iron'),(2,2,'wood'),(0,NULL, 'gold'),
+(3, 3, 'silver'), (4, 4, 'lead'), (5, 5, 'tin'), (6, 6, 'platinum'),
+(7, 7, 'aluminium');
+drop table t4;
+create table t4 as select * from t1;
+create procedure p() with cte as (select t1.* from t1 left join t4 on t1.d = t4.d where t1.c < 5),
+cte2 as (select t2.* from t2, t5 where t2.b < 3 and t2.name = t5.name limit 1)
+update t3,cte, t4
+set t3.a = cte.a+1, t4.a = cte.a+2
+where cte.b in (select b from cte2) and cte.d = t3.a and cte.b = t4.a;
+call p();
+drop procedure p;
+select * from t3;
+a b description
+1 1 iron
+3 2 wood
+0 NULL gold
+3 3 silver
+4 4 lead
+5 5 tin
+6 6 platinum
+7 7 aluminium
+select * from t4;
+a b c d amount
+0 NULL 0 NULL 10
+1 1 1 1 10
+4 2 2 2 20
+3 3 3 3 30
+4 4 4 4 40
+5 5 5 5 NULL
+6 6 6 6 NULL
+7 7 7 7 70
+8 8 8 8 80
+truncate t3;
+insert into t3 values (1, 1, 'iron'),(2,2,'wood'),(0,NULL, 'gold'),
+(3, 3, 'silver'), (4, 4, 'lead'), (5, 5, 'tin'), (6, 6, 'platinum'),
+(7, 7, 'aluminium');
+drop table t4;
+create table t4 as select * from t1;
+prepare s from 'with cte as (select t1.* from t1 left join t4 on t1.d = t4.d where t1.c < 5),
+cte2 as (select t2.* from t2, t5 where t2.b < 3 and t2.name = t5.name limit 1)
+update t3,cte, t4
+set t3.a = cte.a+1, t4.a = cte.a+2
+where cte.b in (select b from cte2) and cte.d = t3.a and cte.b = t4.a';
+execute s;
+select * from t3;
+a b description
+1 1 iron
+3 2 wood
+0 NULL gold
+3 3 silver
+4 4 lead
+5 5 tin
+6 6 platinum
+7 7 aluminium
+select * from t4;
+a b c d amount
+0 NULL 0 NULL 10
+1 1 1 1 10
+4 2 2 2 20
+3 3 3 3 30
+4 4 4 4 40
+5 5 5 5 NULL
+6 6 6 6 NULL
+7 7 7 7 70
+8 8 8 8 80
+truncate t3;
+insert into t3 values (1, 1, 'iron'),(2,2,'wood'),(0,NULL, 'gold'),
+(3, 3, 'silver'), (4, 4, 'lead'), (5, 5, 'tin'), (6, 6, 'platinum'),
+(7, 7, 'aluminium');
+drop table t4;
+create table t4 as select * from t1;
+execute s;
+select * from t3;
+a b description
+1 1 iron
+3 2 wood
+0 NULL gold
+3 3 silver
+4 4 lead
+5 5 tin
+6 6 platinum
+7 7 aluminium
+select * from t4;
+a b c d amount
+0 NULL 0 NULL 10
+1 1 1 1 10
+4 2 2 2 20
+3 3 3 3 30
+4 4 4 4 40
+5 5 5 5 NULL
+6 6 6 6 NULL
+7 7 7 7 70
+8 8 8 8 80
+truncate t3;
+insert into t3 values (1, 1, 'iron'),(2,2,'wood'),(0,NULL, 'gold'),
+(3, 3, 'silver'), (4, 4, 'lead'), (5, 5, 'tin'), (6, 6, 'platinum'),
+(7, 7, 'aluminium');
+drop prepare s;
+drop table t4;
+create table t4 as select * from t1;
+explain with cte as (select * from t1 where c < 5),
+cte2 as (select * from t2 where b < 3)
+update t3 left join cte on t3.b = cte.b
+set t3.a = cte.a+1 where cte.b in (select b from cte2) and d = t3.a;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t3 ALL NULL NULL NULL NULL 8 Using where
+1 PRIMARY ref key0 key0 10 test.t3.b,test.t3.a 1
+1 PRIMARY t2 index NULL t2_ix1 9 NULL 13 Using where; Using index; FirstMatch()
+2 DERIVED t1 ALL NULL NULL NULL NULL 9 Using where
+with cte as (select * from t1 where c < 5),
+cte2 as (select * from t2 where b < 3)
+update t3 left join cte on t3.b = cte.b
+set t3.a = cte.a+1 where cte.b in (select b from cte2) and d = t3.a;
+select * from t3;
+a b description
+1 1 iron
+3 2 wood
+0 NULL gold
+3 3 silver
+4 4 lead
+5 5 tin
+6 6 platinum
+7 7 aluminium
+truncate t3;
+insert into t3 values (1, 1, 'iron'),(2,2,'wood'),(0,NULL, 'gold'),
+(3, 3, 'silver'), (4, 4, 'lead'), (5, 5, 'tin'), (6, 6, 'platinum'),
+(7, 7, 'aluminium');
+explain with cte as (select * from t1 where c < 5),
+cte2 as (select * from t2 where b < 3)
+update t3, cte, cte2 set t3.a = cte.a+2 where cte.b = cte2.b and d = t3.a;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t3 ALL NULL NULL NULL NULL 8 Using where
+1 PRIMARY ref key0 key0 5 test.t3.a 1 Using where
+1 PRIMARY ref key0 key0 5 cte.b 1
+2 DERIVED t1 ALL NULL NULL NULL NULL 9 Using where
+3 DERIVED t2 ALL NULL NULL NULL NULL 13 Using where
+with cte as (select * from t1 where c < 5),
+cte2 as (select * from t2 where b < 3)
+update t3, cte, cte2 set t3.a = cte.a+2 where cte.b = cte2.b and d = t3.a;
+select * from t3;
+a b description
+1 1 iron
+4 2 wood
+0 NULL gold
+3 3 silver
+4 4 lead
+5 5 tin
+6 6 platinum
+7 7 aluminium
+truncate t3;
+insert into t3 values (1, 1, 'iron'),(2,2,'wood'),(0,NULL, 'gold'),
+(3, 3, 'silver'), (4, 4, 'lead'), (5, 5, 'tin'), (6, 6, 'platinum'),
+(7, 7, 'aluminium');
+explain with cte as (select * from t1 where c < 5),
+cte2 as (select * from t2 where b < 3)
+update cte, cte2, t3 set t3.a = cte.a+2 where cte.b = cte2.b and d = t3.a;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t3 ALL NULL NULL NULL NULL 8 Using where
+1 PRIMARY ref key1 key1 5 test.t3.a 1 Using where
+1 PRIMARY ref key0 key0 5 cte.b 1
+2 DERIVED t1 ALL NULL NULL NULL NULL 9 Using where
+3 DERIVED t2 ALL NULL NULL NULL NULL 13 Using where
+with cte as (select * from t1 where c < 5),
+cte2 as (select * from t2 where b < 3)
+update cte, cte2, t3 set t3.a = cte.a+2 where cte.b = cte2.b and d = t3.a;
+select * from t3;
+a b description
+1 1 iron
+4 2 wood
+0 NULL gold
+3 3 silver
+4 4 lead
+5 5 tin
+6 6 platinum
+7 7 aluminium
+truncate t3;
+insert into t3 values (1, 1, 'iron'),(2,2,'wood'),(0,NULL, 'gold'),
+(3, 3, 'silver'), (4, 4, 'lead'), (5, 5, 'tin'), (6, 6, 'platinum'),
+(7, 7, 'aluminium');
+explain with cte as (select * from t1 where c < 5 group by a),
+cte2 as (select * from t2 where b < 3 group by a)
+update cte, cte2, t3 set t3.a = cte.a+2 where cte.b = cte2.b and d = t3.a;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t3 ALL NULL NULL NULL NULL 8 Using where
+1 PRIMARY ref key1 key1 5 test.t3.a 1 Using where
+1 PRIMARY ref key0 key0 5 cte.b 1
+2 DERIVED t1 ALL NULL NULL NULL NULL 9 Using where; Using temporary; Using filesort
+3 DERIVED t2 ALL NULL NULL NULL NULL 13 Using where; Using temporary; Using filesort
+with cte as (select * from t1 where c < 5 group by a),
+cte2 as (select * from t2 where b < 3 group by a)
+update cte, cte2, t3 set t3.a = cte.a+2 where cte.b = cte2.b and d = t3.a;
+select * from t3;
+a b description
+1 1 iron
+4 2 wood
+0 NULL gold
+3 3 silver
+4 4 lead
+5 5 tin
+6 6 platinum
+7 7 aluminium
+truncate t3;
+insert into t3 values (1, 1, 'iron'),(2,2,'wood'),(0,NULL, 'gold'),
+(3, 3, 'silver'), (4, 4, 'lead'), (5, 5, 'tin'), (6, 6, 'platinum'),
+(7, 7, 'aluminium');
+create view v1 as select * from t1;
+explain with cte as (select * from v1 where c < 5 group by a),
+cte2 as (select * from t2 where b < 3 group by a)
+update cte, cte2, t3 set t3.a = cte.a+2 where cte.b = cte2.b and d = t3.a;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t3 ALL NULL NULL NULL NULL 8 Using where
+1 PRIMARY ref key1 key1 5 test.t3.a 1 Using where
+1 PRIMARY ref key0 key0 5 cte.b 1
+2 DERIVED t1 ALL NULL NULL NULL NULL 9 Using where; Using temporary; Using filesort
+3 DERIVED t2 ALL NULL NULL NULL NULL 13 Using where; Using temporary; Using filesort
+with cte as (select * from v1 where c < 5 group by a),
+cte2 as (select * from t2 where b < 3 group by a)
+update cte, cte2, t3 set t3.a = cte.a+2 where cte.b = cte2.b and d = t3.a;
+select * from t3;
+a b description
+1 1 iron
+4 2 wood
+0 NULL gold
+3 3 silver
+4 4 lead
+5 5 tin
+6 6 platinum
+7 7 aluminium
+truncate t3;
+insert into t3 values (1, 1, 'iron'),(2,2,'wood'),(0,NULL, 'gold'),
+(3, 3, 'silver'), (4, 4, 'lead'), (5, 5, 'tin'), (6, 6, 'platinum'),
+(7, 7, 'aluminium');
+with T as (select * from t1) update T set T.a=3;
+ERROR HY000: The target table T of the UPDATE is not updatable
+with T as (select * from v1) update T set T.a=3;
+ERROR HY000: The target table T of the UPDATE is not updatable
+with T as (select * from t1) delete from T where a=3;
+ERROR HY000: The target table T of the DELETE is not updatable
+with T as (select * from v1) delete from T where a=3;
+ERROR HY000: The target table T of the DELETE is not updatable
+drop view v1;
+create view v1 as select * from t1 where b IS NOT NULL limit 1;
+explain with cte as (select * from v1 where c < 5 group by a),
+cte2 as (select * from t2 where b < 3 group by a)
+update cte, cte2, t3 set t3.a = cte.a+2 where d = t3.a;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t3 ALL NULL NULL NULL NULL 8 Using where
+1 PRIMARY ref key0 key0 5 test.t3.a 1
+1 PRIMARY ALL NULL NULL NULL NULL 13
+2 DERIVED ALL NULL NULL NULL NULL 2 Using where; Using temporary; Using filesort
+4 DERIVED t1 ALL NULL NULL NULL NULL 9 Using where
+3 DERIVED t2 ALL NULL NULL NULL NULL 13 Using where; Using temporary; Using filesort
+with cte as (select * from v1 where c < 5 group by a),
+cte2 as (select * from t2 where b < 3 group by a)
+update cte, cte2, t3 set t3.a = cte.a+2 where d = t3.a;
+select * from t3;
+a b description
+3 1 iron
+2 2 wood
+0 NULL gold
+3 3 silver
+4 4 lead
+5 5 tin
+6 6 platinum
+7 7 aluminium
+truncate t3;
+insert into t3 values (1, 1, 'iron'),(2,2,'wood'),(0,NULL, 'gold'),
+(3, 3, 'silver'), (4, 4, 'lead'), (5, 5, 'tin'), (6, 6, 'platinum'),
+(7, 7, 'aluminium');
+drop view v1;
+CREATE FUNCTION f1 () RETURNS BLOB RETURN 1;
+CREATE TABLE tf (f1 DATE);
+INSERT INTO tf VALUES('2001-01-01');
+explain with cte as (select f1 as a, f1() as b, 2 as d from tf),
+cte2 as (select * from t2 where b < 3 group by a)
+update cte, cte2, t3 set t3.a = cte.a+2 where cte.b = cte2.b and d = t3.a;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY system NULL NULL NULL NULL 1
+1 PRIMARY ref key0 key0 5 const 1 Using where
+1 PRIMARY t3 ALL NULL NULL NULL NULL 8 Using where
+2 DERIVED tf system NULL NULL NULL NULL 1
+3 DERIVED t2 ALL NULL NULL NULL NULL 13 Using where; Using temporary; Using filesort
+with cte as (select f1 as a, f1() as b, 2 as d from tf),
+cte2 as (select * from t2 where b < 3 group by a)
+update cte, cte2, t3 set t3.a = cte.a+2 where cte.b = cte2.b and d = t3.a;
+select * from t3;
+a b description
+1 1 iron
+2 2 wood
+0 NULL gold
+3 3 silver
+4 4 lead
+5 5 tin
+6 6 platinum
+7 7 aluminium
+truncate t3;
+insert into t3 values (1, 1, 'iron'),(2,2,'wood'),(0,NULL, 'gold'),
+(3, 3, 'silver'), (4, 4, 'lead'), (5, 5, 'tin'), (6, 6, 'platinum'),
+(7, 7, 'aluminium');
+drop function f1;
+drop table tf;
+# delete single table syntax
+explain with cte as (select * from t1 where c < 5),
+cte2 as (select * from t2 where b < 3)
+delete from t3
+where t3.a = (select a from cte where b in (select b from cte2));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t3 ALL NULL NULL NULL NULL 8 Using where
+4 SUBQUERY t1 ALL NULL NULL NULL NULL 9 Using where
+4 SUBQUERY t2 index NULL t2_ix1 9 NULL 13 Using where; Using index; FirstMatch(t1); Using join buffer (flat, BNL join)
+with cte as (select * from t1 where c < 5),
+cte2 as (select * from t2 where b < 3)
+delete from t3
+where t3.a = (select a from cte where b in (select b from cte2));
+select * from t3;
+a b description
+1 1 iron
+0 NULL gold
+3 3 silver
+4 4 lead
+5 5 tin
+6 6 platinum
+7 7 aluminium
+truncate t3;
+insert into t3 values (1, 1, 'iron'),(2,2,'wood'),(0,NULL, 'gold'),
+(3, 3, 'silver'), (4, 4, 'lead'), (5, 5, 'tin'), (6, 6, 'platinum'),
+(7, 7, 'aluminium');
+create procedure p() with cte as (select * from t1 where c < 5),
+cte2 as (select * from t2 where b < 3)
+delete from t3
+where t3.a = (select a from cte where b in (select b from cte2));
+call p();
+drop procedure p;
+select * from t3;
+a b description
+1 1 iron
+0 NULL gold
+3 3 silver
+4 4 lead
+5 5 tin
+6 6 platinum
+7 7 aluminium
+truncate t3;
+insert into t3 values (1, 1, 'iron'),(2,2,'wood'),(0,NULL, 'gold'),
+(3, 3, 'silver'), (4, 4, 'lead'), (5, 5, 'tin'), (6, 6, 'platinum'),
+(7, 7, 'aluminium');
+# delete multi table syntax
+explain with cte as (select * from t1 where c < 5),
+cte2 as (select * from t2 where b < 3)
+delete from t3
+using t3, cte
+where t3.a = cte.a and cte.b in (select b from cte2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t3 ALL NULL NULL NULL NULL 8 Using where
+1 PRIMARY ref key0 key0 4 test.t3.a 1 Using where
+1 PRIMARY t2 index NULL t2_ix1 9 NULL 13 Using where; Using index; FirstMatch()
+2 DERIVED t1 ALL NULL NULL NULL NULL 9 Using where
+with cte as (select * from t1 where c < 5),
+cte2 as (select * from t2 where b < 3)
+delete from t3
+using t3, cte
+where t3.a = cte.a and cte.b in (select b from cte2);
+select * from t3;
+a b description
+1 1 iron
+0 NULL gold
+3 3 silver
+4 4 lead
+5 5 tin
+6 6 platinum
+7 7 aluminium
+truncate t3;
+insert into t3 values (1, 1, 'iron'),(2,2,'wood'),(0,NULL, 'gold'),
+(3, 3, 'silver'), (4, 4, 'lead'), (5, 5, 'tin'), (6, 6, 'platinum'),
+(7, 7, 'aluminium');
+create procedure p() with cte as (select * from t1 where c < 5),
+cte2 as (select * from t2 where b < 3)
+delete from t3
+using t3, cte
+where t3.a = cte.a and cte.b in (select b from cte2);
+call p();
+drop procedure p;
+select * from t3;
+a b description
+1 1 iron
+0 NULL gold
+3 3 silver
+4 4 lead
+5 5 tin
+6 6 platinum
+7 7 aluminium
+truncate t3;
+insert into t3 values (1, 1, 'iron'),(2,2,'wood'),(0,NULL, 'gold'),
+(3, 3, 'silver'), (4, 4, 'lead'), (5, 5, 'tin'), (6, 6, 'platinum'),
+(7, 7, 'aluminium');
+# delete multi table syntax, multi table delete
+explain with cte as (select * from t1 where c < 5),
+cte2 as (select * from t2 where b < 3)
+delete from t3, t4
+using t3, t4, cte
+where t3.a = cte.a and cte.b in (select b from cte2)
+and t4.a = t3.a;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t3 ALL NULL NULL NULL NULL 8 Using where
+1 PRIMARY ref key0 key0 4 test.t3.a 1 Using where
+1 PRIMARY t2 index NULL t2_ix1 9 NULL 13 Using where; Using index; FirstMatch()
+1 PRIMARY t4 ALL NULL NULL NULL NULL 9 Using where
+2 DERIVED t1 ALL NULL NULL NULL NULL 9 Using where
+with cte as (select * from t1 where c < 5),
+cte2 as (select * from t2 where b < 3)
+delete from t3, t4
+using t3, t4, cte
+where t3.a = cte.a and cte.b in (select b from cte2)
+and t4.a = t3.a;
+select * from t3;
+a b description
+1 1 iron
+0 NULL gold
+3 3 silver
+4 4 lead
+5 5 tin
+6 6 platinum
+7 7 aluminium
+select * from t4;
+a b c d amount
+0 NULL 0 NULL 10
+1 1 1 1 10
+3 3 3 3 30
+4 4 4 4 40
+5 5 5 5 NULL
+6 6 6 6 NULL
+7 7 7 7 70
+8 8 8 8 80
+truncate t3;
+insert into t3 values (1, 1, 'iron'),(2,2,'wood'),(0,NULL, 'gold'),
+(3, 3, 'silver'), (4, 4, 'lead'), (5, 5, 'tin'), (6, 6, 'platinum'),
+(7, 7, 'aluminium');
+create procedure p() with cte as (select * from t1 where c < 5),
+cte2 as (select * from t2 where b < 3)
+delete from t3, t4
+using t3, t4, cte
+where t3.a = cte.a and cte.b in (select b from cte2)
+and t4.a = t3.a;
+call p();
+drop procedure p;
+select * from t3;
+a b description
+1 1 iron
+2 2 wood
+0 NULL gold
+3 3 silver
+4 4 lead
+5 5 tin
+6 6 platinum
+7 7 aluminium
+truncate t3;
+insert into t3 values (1, 1, 'iron'),(2,2,'wood'),(0,NULL, 'gold'),
+(3, 3, 'silver'), (4, 4, 'lead'), (5, 5, 'tin'), (6, 6, 'platinum'),
+(7, 7, 'aluminium');
+# delete multi table syntax, multi table CTEs
+explain with cte as (select t1.* from t1 left join t4 on t1.d = t4.d where t1.c < 5),
+cte2 as (select t2.* from t2, t5 where t2.b < 3 and t2.name = t5.name limit 1)
+delete from t3
+using t3, cte
+where t3.a = cte.a and cte.b in (select b from cte2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t3 ALL NULL NULL NULL NULL 8 Using where
+1 PRIMARY ref key0 key0 4 test.t3.a 8 Using where
+1 PRIMARY ref key0 key0 5 cte.b 1 FirstMatch()
+3 DERIVED t2 ALL NULL NULL NULL NULL 13 Using where
+3 DERIVED t5 ALL NULL NULL NULL NULL 13 Using where; Using join buffer (flat, BNL join)
+2 DERIVED t1 ALL NULL NULL NULL NULL 9 Using where
+2 DERIVED t4 ALL NULL NULL NULL NULL 8 Using where; Using join buffer (flat, BNL join)
+with cte as (select t1.* from t1 left join t4 on t1.d = t4.d where t1.c < 5),
+cte2 as (select t2.* from t2, t5 where t2.b < 3 and t2.name = t5.name limit 1)
+delete from t3
+using t3, cte
+where t3.a = cte.a and cte.b in (select b from cte2);
+select * from t3;
+a b description
+1 1 iron
+0 NULL gold
+3 3 silver
+4 4 lead
+5 5 tin
+6 6 platinum
+7 7 aluminium
+truncate t3;
+insert into t3 values (1, 1, 'iron'),(2,2,'wood'),(0,NULL, 'gold'),
+(3, 3, 'silver'), (4, 4, 'lead'), (5, 5, 'tin'), (6, 6, 'platinum'),
+(7, 7, 'aluminium');
+create procedure p() with cte as (select t1.* from t1 left join t4 on t1.d = t4.d where t1.c < 5),
+cte2 as (select t2.* from t2, t5 where t2.b < 3 and t2.name = t5.name limit 1)
+delete from t3
+using t3, cte
+where t3.a = cte.a and cte.b in (select b from cte2);
+call p();
+drop procedure p;
+select * from t3;
+a b description
+1 1 iron
+0 NULL gold
+3 3 silver
+4 4 lead
+5 5 tin
+6 6 platinum
+7 7 aluminium
+truncate t3;
+insert into t3 values (1, 1, 'iron'),(2,2,'wood'),(0,NULL, 'gold'),
+(3, 3, 'silver'), (4, 4, 'lead'), (5, 5, 'tin'), (6, 6, 'platinum'),
+(7, 7, 'aluminium');
+prepare s from 'with cte as (select t1.* from t1 left join t4 on t1.d = t4.d where t1.c < 5),
+cte2 as (select t2.* from t2, t5 where t2.b < 3 and t2.name = t5.name limit 1)
+delete from t3
+using t3, cte
+where t3.a = cte.a and cte.b in (select b from cte2)';
+execute s;
+select * from t3;
+a b description
+1 1 iron
+0 NULL gold
+3 3 silver
+4 4 lead
+5 5 tin
+6 6 platinum
+7 7 aluminium
+truncate t3;
+insert into t3 values (1, 1, 'iron'),(2,2,'wood'),(0,NULL, 'gold'),
+(3, 3, 'silver'), (4, 4, 'lead'), (5, 5, 'tin'), (6, 6, 'platinum'),
+(7, 7, 'aluminium');
+execute s;
+select * from t3;
+a b description
+1 1 iron
+0 NULL gold
+3 3 silver
+4 4 lead
+5 5 tin
+6 6 platinum
+7 7 aluminium
+truncate t3;
+insert into t3 values (1, 1, 'iron'),(2,2,'wood'),(0,NULL, 'gold'),
+(3, 3, 'silver'), (4, 4, 'lead'), (5, 5, 'tin'), (6, 6, 'platinum'),
+(7, 7, 'aluminium');
+drop prepare s;
+# delete multi table syntax, limit clause in delete
+explain with cte as (select * from t1 where c < 5),
+cte2 as (select * from t2 where b < 3)
+delete from t3
+using t3, cte
+where t3.a = cte.a and cte.b in (select b from cte2) limit 1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t3 ALL NULL NULL NULL NULL 8 Using where
+1 PRIMARY ref key0 key0 4 test.t3.a 1 Using where
+1 PRIMARY t2 index NULL t2_ix1 9 NULL 13 Using where; Using index; FirstMatch()
+2 DERIVED t1 ALL NULL NULL NULL NULL 9 Using where
+with cte as (select * from t1 where c < 5),
+cte2 as (select * from t2 where b < 3)
+delete from t3
+using t3, cte
+where t3.a = cte.a and cte.b in (select b from cte2) limit 1;
+select * from t3;
+a b description
+1 1 iron
+0 NULL gold
+3 3 silver
+4 4 lead
+5 5 tin
+6 6 platinum
+7 7 aluminium
+truncate t3;
+insert into t3 values (1, 1, 'iron'),(2,2,'wood'),(0,NULL, 'gold'),
+(3, 3, 'silver'), (4, 4, 'lead'), (5, 5, 'tin'), (6, 6, 'platinum'),
+(7, 7, 'aluminium');
+create procedure p() with cte as (select * from t1 where c < 5),
+cte2 as (select * from t2 where b < 3)
+delete from t3
+using t3, cte
+where t3.a = cte.a and cte.b in (select b from cte2) limit 1;
+call p();
+drop procedure p;
+select * from t3;
+a b description
+1 1 iron
+0 NULL gold
+3 3 silver
+4 4 lead
+5 5 tin
+6 6 platinum
+7 7 aluminium
+truncate t3;
+insert into t3 values (1, 1, 'iron'),(2,2,'wood'),(0,NULL, 'gold'),
+(3, 3, 'silver'), (4, 4, 'lead'), (5, 5, 'tin'), (6, 6, 'platinum'),
+(7, 7, 'aluminium');
+prepare s from 'with cte as (select * from t1 where c < 5),
+cte2 as (select * from t2 where b < 3)
+delete from t3
+using t3, cte
+where t3.a = cte.a and cte.b in (select b from cte2) limit 1';
+execute s;
+select * from t3;
+a b description
+1 1 iron
+0 NULL gold
+3 3 silver
+4 4 lead
+5 5 tin
+6 6 platinum
+7 7 aluminium
+truncate t3;
+insert into t3 values (1, 1, 'iron'),(2,2,'wood'),(0,NULL, 'gold'),
+(3, 3, 'silver'), (4, 4, 'lead'), (5, 5, 'tin'), (6, 6, 'platinum'),
+(7, 7, 'aluminium');
+execute s;
+select * from t3;
+a b description
+1 1 iron
+0 NULL gold
+3 3 silver
+4 4 lead
+5 5 tin
+6 6 platinum
+7 7 aluminium
+truncate t3;
+insert into t3 values (1, 1, 'iron'),(2,2,'wood'),(0,NULL, 'gold'),
+(3, 3, 'silver'), (4, 4, 'lead'), (5, 5, 'tin'), (6, 6, 'platinum'),
+(7, 7, 'aluminium');
+drop prepare s;
+explain with cte as (select * from t1 where c < 5),
+cte2 as (select * from t2 where b < 3)
+delete from t3
+using t3, cte, cte2
+where t3.a = cte.a and cte.b = cte2.b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t3 ALL NULL NULL NULL NULL 8 Using where
+1 PRIMARY ref key0 key0 4 test.t3.a 1 Using where
+1 PRIMARY ref key0 key0 5 cte.b 1
+2 DERIVED t1 ALL NULL NULL NULL NULL 9 Using where
+3 DERIVED t2 ALL NULL NULL NULL NULL 13 Using where
+with cte as (select * from t1 where c < 5),
+cte2 as (select * from t2 where b < 3)
+delete from t3
+using t3, cte, cte2
+where t3.a = cte.a and cte.b = cte2.b;
+select * from t3;
+a b description
+1 1 iron
+0 NULL gold
+3 3 silver
+4 4 lead
+5 5 tin
+6 6 platinum
+7 7 aluminium
+truncate t3;
+insert into t3 values (1, 1, 'iron'),(2,2,'wood'),(0,NULL, 'gold'),
+(3, 3, 'silver'), (4, 4, 'lead'), (5, 5, 'tin'), (6, 6, 'platinum'),
+(7, 7, 'aluminium');
+# recursive CTE, test update on values 1 (NC), 2, 5, 6 from CTE
+explain with recursive cte_r(a, c) as
+(
+values (1,5)
+union
+values (2,6)
+union
+select t1.a, t1.b
+from t1, cte_r
+where t1.a = cte_r.a
+)
+update t3, cte_r
+set t3.a = 1
+where t3.b = c;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t3 ALL NULL NULL NULL NULL 8 Using where
+1 PRIMARY ref key1,distinct_key key1 5 test.t3.b 1
+2 DERIVED NULL NULL NULL NULL NULL NULL NULL No tables used
+3 UNION NULL NULL NULL NULL NULL NULL NULL No tables used
+4 RECURSIVE UNION t1 index t1_ix1 t1_ix1 9 NULL 9 Using index
+4 RECURSIVE UNION ref key0 key0 5 test.t1.a 1
+NULL UNION RESULT ALL NULL NULL NULL NULL NULL
+with recursive cte_r(a, c) as
+(
+values (1,5)
+union
+values (2,6)
+union
+select t1.a, t1.b
+from t1, cte_r
+where t1.a = cte_r.a
+)
+update t3, cte_r
+set t3.a = 1
+where t3.b = c;
+select * from t3;
+a b description
+1 1 iron
+1 2 wood
+0 NULL gold
+3 3 silver
+4 4 lead
+1 5 tin
+1 6 platinum
+7 7 aluminium
+truncate t3;
+insert into t3 values (1, 1, 'iron'),(2,2,'wood'),(0,NULL, 'gold'),
+(3, 3, 'silver'), (4, 4, 'lead'), (5, 5, 'tin'), (6, 6, 'platinum'),
+(7, 7, 'aluminium');
+create procedure p() with recursive cte_r(a, c) as
+(
+values (1,5)
+union
+values (2,6)
+union
+select t1.a, t1.b
+from t1, cte_r
+where t1.a = cte_r.a
+)
+update t3, cte_r
+set t3.a = 1
+where t3.b = c;
+call p();
+drop procedure p;
+select * from t3;
+a b description
+1 1 iron
+1 2 wood
+0 NULL gold
+3 3 silver
+4 4 lead
+1 5 tin
+1 6 platinum
+7 7 aluminium
+truncate t3;
+insert into t3 values (1, 1, 'iron'),(2,2,'wood'),(0,NULL, 'gold'),
+(3, 3, 'silver'), (4, 4, 'lead'), (5, 5, 'tin'), (6, 6, 'platinum'),
+(7, 7, 'aluminium');
+prepare s from 'with recursive cte_r(a, c) as
+(
+values (1,5)
+union
+values (2,6)
+union
+select t1.a, t1.b
+from t1, cte_r
+where t1.a = cte_r.a
+)
+update t3, cte_r
+set t3.a = 1
+where t3.b = c';
+execute s;
+select * from t3;
+a b description
+1 1 iron
+1 2 wood
+0 NULL gold
+3 3 silver
+4 4 lead
+1 5 tin
+1 6 platinum
+7 7 aluminium
+truncate t3;
+insert into t3 values (1, 1, 'iron'),(2,2,'wood'),(0,NULL, 'gold'),
+(3, 3, 'silver'), (4, 4, 'lead'), (5, 5, 'tin'), (6, 6, 'platinum'),
+(7, 7, 'aluminium');
+execute s;
+select * from t3;
+a b description
+1 1 iron
+1 2 wood
+0 NULL gold
+3 3 silver
+4 4 lead
+1 5 tin
+1 6 platinum
+7 7 aluminium
+truncate t3;
+insert into t3 values (1, 1, 'iron'),(2,2,'wood'),(0,NULL, 'gold'),
+(3, 3, 'silver'), (4, 4, 'lead'), (5, 5, 'tin'), (6, 6, 'platinum'),
+(7, 7, 'aluminium');
+drop prepare s;
+# recursive CTE, test delete, multi table syntax
+explain with recursive cte_r(a, c) as
+(
+values (1,5)
+union
+values (2,6)
+union
+select t1.a, t1.b
+from t1, cte_r
+where t1.a = cte_r.a
+)
+delete from t3
+using t3, cte_r
+where t3.b = c;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t3 ALL NULL NULL NULL NULL 8 Using where
+1 PRIMARY ref key1,distinct_key key1 5 test.t3.b 1
+2 DERIVED NULL NULL NULL NULL NULL NULL NULL No tables used
+3 UNION NULL NULL NULL NULL NULL NULL NULL No tables used
+4 RECURSIVE UNION t1 index t1_ix1 t1_ix1 9 NULL 9 Using index
+4 RECURSIVE UNION ref key0 key0 5 test.t1.a 1
+NULL UNION RESULT ALL NULL NULL NULL NULL NULL
+with recursive cte_r(a, c) as
+(
+values (1,5)
+union
+values (2,6)
+union
+select t1.a, t1.b
+from t1, cte_r
+where t1.a = cte_r.a
+)
+delete from t3
+using t3, cte_r
+where t3.b = c;
+select * from t3;
+a b description
+0 NULL gold
+3 3 silver
+4 4 lead
+7 7 aluminium
+truncate t3;
+insert into t3 values (1, 1, 'iron'),(2,2,'wood'),(0,NULL, 'gold'),
+(3, 3, 'silver'), (4, 4, 'lead'), (5, 5, 'tin'), (6, 6, 'platinum'),
+(7, 7, 'aluminium');
+create procedure p() with recursive cte_r(a, c) as
+(
+values (1,5)
+union
+values (2,6)
+union
+select t1.a, t1.b
+from t1, cte_r
+where t1.a = cte_r.a
+)
+delete from t3
+using t3, cte_r
+where t3.b = c;
+call p();
+drop procedure p;
+select * from t3;
+a b description
+0 NULL gold
+3 3 silver
+4 4 lead
+7 7 aluminium
+truncate t3;
+insert into t3 values (1, 1, 'iron'),(2,2,'wood'),(0,NULL, 'gold'),
+(3, 3, 'silver'), (4, 4, 'lead'), (5, 5, 'tin'), (6, 6, 'platinum'),
+(7, 7, 'aluminium');
+prepare s from 'with recursive cte_r(a, c) as
+(
+values (1,5)
+union
+values (2,6)
+union
+select t1.a, t1.b
+from t1, cte_r
+where t1.a = cte_r.a
+)
+delete from t3
+using t3, cte_r
+where t3.b = c';
+execute s;
+select * from t3;
+a b description
+0 NULL gold
+3 3 silver
+4 4 lead
+7 7 aluminium
+truncate t3;
+insert into t3 values (1, 1, 'iron'),(2,2,'wood'),(0,NULL, 'gold'),
+(3, 3, 'silver'), (4, 4, 'lead'), (5, 5, 'tin'), (6, 6, 'platinum'),
+(7, 7, 'aluminium');
+execute s;
+select * from t3;
+a b description
+0 NULL gold
+3 3 silver
+4 4 lead
+7 7 aluminium
+truncate t3;
+insert into t3 values (1, 1, 'iron'),(2,2,'wood'),(0,NULL, 'gold'),
+(3, 3, 'silver'), (4, 4, 'lead'), (5, 5, 'tin'), (6, 6, 'platinum'),
+(7, 7, 'aluminium');
+drop prepare s;
+# recursive CTE, test delete, single table syntax
+explain with recursive cte_r(a, c) as
+(
+values (1,5)
+union
+values (2,6)
+union
+select t1.a, t1.b
+from t1, cte_r
+where t1.a = cte_r.a
+),
+cte (a) as
+(
+select a from t2
+)
+delete from t3
+where t3.b in (select c from cte_r, cte where cte.a = cte_r.a );
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t3 ALL NULL NULL NULL NULL 8 Using where
+1 PRIMARY ref key1,distinct_key key1 5 test.t3.b 1 Using where
+1 PRIMARY t2 ref t2_ix1 t2_ix1 4 cte_r.a 2 Using index; FirstMatch(t3)
+2 DERIVED NULL NULL NULL NULL NULL NULL NULL No tables used
+3 UNION NULL NULL NULL NULL NULL NULL NULL No tables used
+4 RECURSIVE UNION t1 index t1_ix1 t1_ix1 9 NULL 9 Using index
+4 RECURSIVE UNION ref key0 key0 5 test.t1.a 1
+NULL UNION RESULT ALL NULL NULL NULL NULL NULL
+with recursive cte_r(a, c) as
+(
+values (1,5)
+union
+values (2,6)
+union
+select t1.a, t1.b
+from t1, cte_r
+where t1.a = cte_r.a
+),
+cte (a) as
+(
+select a from t2
+)
+delete from t3
+where t3.b in (select c from cte_r, cte where cte.a = cte_r.a );
+select * from t3;
+a b description
+0 NULL gold
+3 3 silver
+4 4 lead
+7 7 aluminium
+truncate t3;
+insert into t3 values (1, 1, 'iron'),(2,2,'wood'),(0,NULL, 'gold'),
+(3, 3, 'silver'), (4, 4, 'lead'), (5, 5, 'tin'), (6, 6, 'platinum'),
+(7, 7, 'aluminium');
+create procedure p() with recursive cte_r(a, c) as
+(
+values (1,5)
+union
+values (2,6)
+union
+select t1.a, t1.b
+from t1, cte_r
+where t1.a = cte_r.a
+),
+cte (a) as
+(
+select a from t2
+)
+delete from t3
+where t3.b in (select c from cte_r, cte where cte.a = cte_r.a );
+call p();
+drop procedure p;
+select * from t3;
+a b description
+0 NULL gold
+3 3 silver
+4 4 lead
+7 7 aluminium
+truncate t3;
+insert into t3 values (1, 1, 'iron'),(2,2,'wood'),(0,NULL, 'gold'),
+(3, 3, 'silver'), (4, 4, 'lead'), (5, 5, 'tin'), (6, 6, 'platinum'),
+(7, 7, 'aluminium');
+prepare s from 'with recursive cte_r(a, c) as
+(
+values (1,5)
+union
+values (2,6)
+union
+select t1.a, t1.b
+from t1, cte_r
+where t1.a = cte_r.a
+),
+cte (a) as
+(
+select a from t2
+)
+delete from t3
+where t3.b in (select c from cte_r, cte where cte.a = cte_r.a )';
+execute s;
+select * from t3;
+a b description
+0 NULL gold
+3 3 silver
+4 4 lead
+7 7 aluminium
+truncate t3;
+insert into t3 values (1, 1, 'iron'),(2,2,'wood'),(0,NULL, 'gold'),
+(3, 3, 'silver'), (4, 4, 'lead'), (5, 5, 'tin'), (6, 6, 'platinum'),
+(7, 7, 'aluminium');
+execute s;
+select * from t3;
+a b description
+0 NULL gold
+3 3 silver
+4 4 lead
+7 7 aluminium
+truncate t3;
+insert into t3 values (1, 1, 'iron'),(2,2,'wood'),(0,NULL, 'gold'),
+(3, 3, 'silver'), (4, 4, 'lead'), (5, 5, 'tin'), (6, 6, 'platinum'),
+(7, 7, 'aluminium');
+drop prepare s;
+#
+# MDEV-38258 No error thrown when CTE columns updated in updates set clause
+#
+with cte as (select * from t1 where c < 1)
+update cte set cte.a =(select a from cte);
+ERROR HY000: The target table cte of the UPDATE is not updatable
+with cte as (select a from t1)
+update cte set cte.a=(select a from cte limit 1);
+ERROR HY000: The target table cte of the UPDATE is not updatable
+with cte as (select a from t1),
+cte2 as (select a from t3)
+update t2, cte set cte.a=(select a from cte limit 1);
+ERROR HY000: The target table cte of the UPDATE is not updatable
+with cte as (select a from t1),
+cte2 as (select a from t3)
+update cte
+set cte.a=(select a from cte where cte.a in (select a from cte2) limit 1);
+ERROR HY000: The target table cte of the UPDATE is not updatable
+drop table t1, t2, t3, t4, t5;
+#
+# MDEV-38272 Sig11 in LEX::resolve_references_to_cte at sql/sql_cte.cc
+#
+create table t1(a int);
+insert into t1 values (1), (5), (10), (15), (20), (25);
+create view v1 as select * from t1 where a < 10;
+with cte as (select * from t1) delete from t1,cte where t1.a=cte.a;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'where t1.a=cte.a' at line 1
+with cte as (select * from t1) delete from t1 using t1,cte where t1.a=cte.a;
+#
+# MDEV-38272 Recursive CTE usage leaks memory when not used in a top level select
+#
+with recursive cte as (select a from t1 union select a from cte)
+update t1, cte set t1.o = 1;
+ERROR 42S22: Unknown column 't1.o' in 'SET'
+with recursive cte as (select a from t1 union select a from cte where a < 2)
+delete from cte where a = (select a from cte);
+ERROR HY000: The target table cte of the DELETE is not updatable
+with recursive cte as (select a from t1 union select a from cte where a < 2)
+delete from cte where a = 10;
+ERROR HY000: The target table cte of the DELETE is not updatable
+insert into t1 values (1), (5), (10), (15), (20), (25);
+with recursive cte as (select a from t1 union select a from cte where a < 2)
+delete from v1 using v1, cte where v1.a = cte.a;
+select * from t1 order by 1;
+a
+10
+15
+20
+25
+drop table t1;
+# End of 12.2 tests
diff --git a/mysql-test/main/cte_update_delete.test b/mysql-test/main/cte_update_delete.test
new file mode 100644
index 0000000000000..8ec964153c489
--- /dev/null
+++ b/mysql-test/main/cte_update_delete.test
@@ -0,0 +1,598 @@
+--source include/not_embedded.inc
+--echo #
+--echo # MDEV-37220 Allow UPDATE/DELETE to read from a CTE
+--echo #
+
+create table t1
+(
+ a int not null,
+ b int,
+ c int,
+ d int,
+ amount decimal,
+ key t1_ix1 (a,b)
+);
+
+insert into t1 values (0, NULL, 0, NULL, 10.0000), (1, 1, 1, 1, 10.0000),
+(2, 2, 2, 2, 20.0000), (3, 3, 3, 3, 30.0000), (4, 4, 4, 4, 40.0000),
+(5, 5, 5, 5, NULL), (6, 6, 6, 6, NULL), (7, 7, 7, 7, 70.0000),
+(8, 8, 8, 8, 80.0000);
+
+create table t2
+(
+ a int NOT NULL,
+ b int,
+ name varchar(50),
+ key t2_ix1 (a,b)
+);
+
+insert into t2 values (0, NULL, 'a'), (1, NULL, 'A'), (2, 2, 'B'), (3,3, 'C'),
+(4,4, 'D'), (5,5, NULL), (6,6, NULL), (7,7, 'E'), (8,8, 'F'), (9,9, 'G'),
+(10,10,'H'), (11,11, NULL), (12,12, NULL);
+
+create table t3
+(
+ a int,
+ b int,
+ description varchar(50)
+);
+
+let $empty_t3=
+truncate t3;
+let $fill_t3=
+insert into t3 values (1, 1, 'iron'),(2,2,'wood'),(0,NULL, 'gold'),
+(3, 3, 'silver'), (4, 4, 'lead'), (5, 5, 'tin'), (6, 6, 'platinum'),
+(7, 7, 'aluminium');
+
+create table t4 as select * from t1;
+create table t5 as select * from t2;
+
+eval $fill_t3;
+
+select * from t3;
+
+--echo # update, single table syntax, subq in set
+let $q=
+with cte as (select * from t1 where c < 5),
+ cte2 as (select * from t2 where b < 3)
+update t3
+ set t3.a = (select a from cte where b in (select b from cte2) and d = t3.a);
+eval explain $q;
+eval $q;
+select * from t3;
+eval $empty_t3;
+eval $fill_t3;
+eval create procedure p() $q;
+call p();
+drop procedure p;
+select * from t3;
+eval $empty_t3;
+eval $fill_t3;
+eval prepare s from '$q';
+execute s;
+select * from t3;
+eval $empty_t3;
+eval $fill_t3;
+execute s;
+select * from t3;
+eval $empty_t3;
+eval $fill_t3;
+drop prepare s;
+
+--echo # update, single table syntax, subq in set, cte used twice
+let $q=
+with cte as (select * from t1 where c < 5),
+ cte2 as (select * from t2 where b < 3)
+update t3
+ set t3.a = (select a from cte
+ where
+ (b in (select b from cte2 where cte2.a = cte.a) or
+ b in (select b from cte2 where cte2.b = cte.a)) and
+ d = t3.a
+ );
+eval explain $q;
+eval $q;
+select * from t3;
+eval $empty_t3;
+eval $fill_t3;
+eval create procedure p() $q;
+call p();
+drop procedure p;
+select * from t3;
+eval $empty_t3;
+eval $fill_t3;
+eval prepare s from '$q';
+execute s;
+select * from t3;
+eval $empty_t3;
+eval $fill_t3;
+execute s;
+select * from t3;
+eval $empty_t3;
+eval $fill_t3;
+drop prepare s;
+
+--echo # multi table syntax, subq in set and where
+let $q=
+with cte as (select * from t1 where c < 5),
+ cte2 as (select * from t2 where b < 3)
+update t3,cte
+ set t3.a = cte.a+1 where cte.b in (select b from cte2) and d = t3.a;
+eval explain $q;
+eval $q;
+select * from t3;
+eval $empty_t3;
+eval $fill_t3;
+eval create procedure p() $q;
+call p();
+drop procedure p;
+select * from t3;
+eval $empty_t3;
+eval $fill_t3;
+
+--echo # multi table syntax, subq in set and where, more complex CTEs
+let $q=
+with cte as (select t1.* from t1 left join t4 on t1.d = t4.d where t1.c < 5),
+ cte2 as (select t2.* from t2, t5 where t2.b < 3 and t2.name = t5.name limit 1)
+update t3,cte, t4
+ set t3.a = cte.a+1, t4.a = cte.a+2
+ where cte.b in (select b from cte2) and cte.d = t3.a and cte.b = t4.a;
+eval explain $q;
+eval $q;
+select * from t3;
+select * from t4;
+eval $empty_t3;
+eval $fill_t3;
+drop table t4;
+create table t4 as select * from t1;
+
+eval create procedure p() $q;
+call p();
+drop procedure p;
+select * from t3;
+select * from t4;
+eval $empty_t3;
+eval $fill_t3;
+drop table t4;
+create table t4 as select * from t1;
+eval prepare s from '$q';
+execute s;
+select * from t3;
+select * from t4;
+eval $empty_t3;
+eval $fill_t3;
+drop table t4;
+create table t4 as select * from t1;
+execute s;
+select * from t3;
+select * from t4;
+eval $empty_t3;
+eval $fill_t3;
+drop prepare s;
+
+drop table t4;
+create table t4 as select * from t1;
+
+let $q=
+with cte as (select * from t1 where c < 5),
+ cte2 as (select * from t2 where b < 3)
+update t3 left join cte on t3.b = cte.b
+ set t3.a = cte.a+1 where cte.b in (select b from cte2) and d = t3.a;
+eval explain $q;
+eval $q;
+select * from t3;
+eval $empty_t3;
+eval $fill_t3;
+
+let $q=
+with cte as (select * from t1 where c < 5),
+ cte2 as (select * from t2 where b < 3)
+update t3, cte, cte2 set t3.a = cte.a+2 where cte.b = cte2.b and d = t3.a;
+eval explain $q;
+eval $q;
+select * from t3;
+eval $empty_t3;
+eval $fill_t3;
+
+let $q=
+with cte as (select * from t1 where c < 5),
+ cte2 as (select * from t2 where b < 3)
+update cte, cte2, t3 set t3.a = cte.a+2 where cte.b = cte2.b and d = t3.a;
+eval explain $q;
+eval $q;
+select * from t3;
+eval $empty_t3;
+eval $fill_t3;
+
+let $q=
+with cte as (select * from t1 where c < 5 group by a),
+ cte2 as (select * from t2 where b < 3 group by a)
+update cte, cte2, t3 set t3.a = cte.a+2 where cte.b = cte2.b and d = t3.a;
+eval explain $q;
+eval $q;
+select * from t3;
+eval $empty_t3;
+eval $fill_t3;
+
+create view v1 as select * from t1;
+let $q=
+with cte as (select * from v1 where c < 5 group by a),
+ cte2 as (select * from t2 where b < 3 group by a)
+update cte, cte2, t3 set t3.a = cte.a+2 where cte.b = cte2.b and d = t3.a;
+eval explain $q;
+eval $q;
+select * from t3;
+eval $empty_t3;
+eval $fill_t3;
+
+--error 1288
+with T as (select * from t1) update T set T.a=3;
+
+--error 1288
+with T as (select * from v1) update T set T.a=3;
+
+--error 1288
+with T as (select * from t1) delete from T where a=3;
+
+--error 1288
+with T as (select * from v1) delete from T where a=3;
+
+drop view v1;
+
+create view v1 as select * from t1 where b IS NOT NULL limit 1;
+let $q=
+with cte as (select * from v1 where c < 5 group by a),
+ cte2 as (select * from t2 where b < 3 group by a)
+update cte, cte2, t3 set t3.a = cte.a+2 where d = t3.a;
+eval explain $q;
+eval $q;
+select * from t3;
+eval $empty_t3;
+eval $fill_t3;
+drop view v1;
+
+CREATE FUNCTION f1 () RETURNS BLOB RETURN 1;
+CREATE TABLE tf (f1 DATE);
+INSERT INTO tf VALUES('2001-01-01');
+let $q=
+with cte as (select f1 as a, f1() as b, 2 as d from tf),
+ cte2 as (select * from t2 where b < 3 group by a)
+update cte, cte2, t3 set t3.a = cte.a+2 where cte.b = cte2.b and d = t3.a;
+eval explain $q;
+eval $q;
+select * from t3;
+eval $empty_t3;
+eval $fill_t3;
+drop function f1;
+drop table tf;
+
+--echo # delete single table syntax
+let $q=
+with cte as (select * from t1 where c < 5),
+ cte2 as (select * from t2 where b < 3)
+delete from t3
+ where t3.a = (select a from cte where b in (select b from cte2));
+
+eval explain $q;
+eval $q;
+select * from t3;
+eval $empty_t3;
+eval $fill_t3;
+eval create procedure p() $q;
+call p();
+drop procedure p;
+select * from t3;
+eval $empty_t3;
+eval $fill_t3;
+
+
+--echo # delete multi table syntax
+let $q=
+with cte as (select * from t1 where c < 5),
+ cte2 as (select * from t2 where b < 3)
+delete from t3
+ using t3, cte
+ where t3.a = cte.a and cte.b in (select b from cte2);
+eval explain $q;
+eval $q;
+select * from t3;
+eval $empty_t3;
+eval $fill_t3;
+eval create procedure p() $q;
+call p();
+drop procedure p;
+select * from t3;
+eval $empty_t3;
+eval $fill_t3;
+
+--echo # delete multi table syntax, multi table delete
+let $q=
+with cte as (select * from t1 where c < 5),
+ cte2 as (select * from t2 where b < 3)
+delete from t3, t4
+ using t3, t4, cte
+ where t3.a = cte.a and cte.b in (select b from cte2)
+ and t4.a = t3.a;
+eval explain $q;
+eval $q;
+select * from t3;
+select * from t4;
+eval $empty_t3;
+eval $fill_t3;
+eval create procedure p() $q;
+call p();
+drop procedure p;
+select * from t3;
+eval $empty_t3;
+eval $fill_t3;
+
+--echo # delete multi table syntax, multi table CTEs
+let $q=
+with cte as (select t1.* from t1 left join t4 on t1.d = t4.d where t1.c < 5),
+ cte2 as (select t2.* from t2, t5 where t2.b < 3 and t2.name = t5.name limit 1)
+delete from t3
+ using t3, cte
+ where t3.a = cte.a and cte.b in (select b from cte2);
+eval explain $q;
+eval $q;
+select * from t3;
+eval $empty_t3;
+eval $fill_t3;
+eval create procedure p() $q;
+call p();
+drop procedure p;
+select * from t3;
+eval $empty_t3;
+eval $fill_t3;
+eval prepare s from '$q';
+execute s;
+select * from t3;
+eval $empty_t3;
+eval $fill_t3;
+execute s;
+select * from t3;
+eval $empty_t3;
+eval $fill_t3;
+drop prepare s;
+
+
+
+--echo # delete multi table syntax, limit clause in delete
+let $q=
+with cte as (select * from t1 where c < 5),
+ cte2 as (select * from t2 where b < 3)
+delete from t3
+ using t3, cte
+ where t3.a = cte.a and cte.b in (select b from cte2) limit 1;
+eval explain $q;
+eval $q;
+select * from t3;
+eval $empty_t3;
+eval $fill_t3;
+eval create procedure p() $q;
+call p();
+drop procedure p;
+select * from t3;
+eval $empty_t3;
+eval $fill_t3;
+eval prepare s from '$q';
+execute s;
+select * from t3;
+eval $empty_t3;
+eval $fill_t3;
+execute s;
+select * from t3;
+eval $empty_t3;
+eval $fill_t3;
+drop prepare s;
+
+let $q=
+with cte as (select * from t1 where c < 5),
+ cte2 as (select * from t2 where b < 3)
+delete from t3
+ using t3, cte, cte2
+ where t3.a = cte.a and cte.b = cte2.b;
+eval explain $q;
+eval $q;
+select * from t3;
+eval $empty_t3;
+eval $fill_t3;
+
+--echo # recursive CTE, test update on values 1 (NC), 2, 5, 6 from CTE
+let $q=
+with recursive cte_r(a, c) as
+ (
+ values (1,5)
+ union
+ values (2,6)
+ union
+ select t1.a, t1.b
+ from t1, cte_r
+ where t1.a = cte_r.a
+ )
+update t3, cte_r
+ set t3.a = 1
+ where t3.b = c;
+eval explain $q;
+eval $q;
+select * from t3;
+eval $empty_t3;
+eval $fill_t3;
+eval create procedure p() $q;
+call p();
+drop procedure p;
+select * from t3;
+eval $empty_t3;
+eval $fill_t3;
+eval prepare s from '$q';
+execute s;
+select * from t3;
+eval $empty_t3;
+eval $fill_t3;
+execute s;
+select * from t3;
+eval $empty_t3;
+eval $fill_t3;
+drop prepare s;
+
+--echo # recursive CTE, test delete, multi table syntax
+let $q=
+with recursive cte_r(a, c) as
+ (
+ values (1,5)
+ union
+ values (2,6)
+ union
+ select t1.a, t1.b
+ from t1, cte_r
+ where t1.a = cte_r.a
+ )
+delete from t3
+ using t3, cte_r
+ where t3.b = c;
+eval explain $q;
+eval $q;
+select * from t3;
+eval $empty_t3;
+eval $fill_t3;
+eval create procedure p() $q;
+call p();
+drop procedure p;
+select * from t3;
+eval $empty_t3;
+eval $fill_t3;
+eval prepare s from '$q';
+execute s;
+select * from t3;
+eval $empty_t3;
+eval $fill_t3;
+execute s;
+select * from t3;
+eval $empty_t3;
+eval $fill_t3;
+drop prepare s;
+
+--echo # recursive CTE, test delete, single table syntax
+let $q=
+with recursive cte_r(a, c) as
+ (
+ values (1,5)
+ union
+ values (2,6)
+ union
+ select t1.a, t1.b
+ from t1, cte_r
+ where t1.a = cte_r.a
+ ),
+ cte (a) as
+ (
+ select a from t2
+ )
+delete from t3
+ where t3.b in (select c from cte_r, cte where cte.a = cte_r.a );
+eval explain $q;
+eval $q;
+select * from t3;
+eval $empty_t3;
+eval $fill_t3;
+eval create procedure p() $q;
+call p();
+drop procedure p;
+select * from t3;
+eval $empty_t3;
+eval $fill_t3;
+eval prepare s from '$q';
+execute s;
+select * from t3;
+eval $empty_t3;
+eval $fill_t3;
+execute s;
+select * from t3;
+eval $empty_t3;
+eval $fill_t3;
+drop prepare s;
+
+--echo #
+--echo # MDEV-38258 No error thrown when CTE columns updated in updates set clause
+--echo #
+
+--error ER_NON_UPDATABLE_TABLE
+with cte as (select * from t1 where c < 1)
+ update cte set cte.a =(select a from cte);
+
+--error ER_NON_UPDATABLE_TABLE
+with cte as (select a from t1)
+ update cte set cte.a=(select a from cte limit 1);
+
+--error ER_NON_UPDATABLE_TABLE
+with cte as (select a from t1),
+ cte2 as (select a from t3)
+ update t2, cte set cte.a=(select a from cte limit 1);
+
+--error ER_NON_UPDATABLE_TABLE
+with cte as (select a from t1),
+ cte2 as (select a from t3)
+ update cte
+ set cte.a=(select a from cte where cte.a in (select a from cte2) limit 1);
+
+drop table t1, t2, t3, t4, t5;
+
+--echo #
+--echo # MDEV-38272 Sig11 in LEX::resolve_references_to_cte at sql/sql_cte.cc
+--echo #
+
+create table t1(a int);
+insert into t1 values (1), (5), (10), (15), (20), (25);
+create view v1 as select * from t1 where a < 10;
+--error ER_PARSE_ERROR
+with cte as (select * from t1) delete from t1,cte where t1.a=cte.a;
+with cte as (select * from t1) delete from t1 using t1,cte where t1.a=cte.a;
+
+--echo #
+--echo # MDEV-38272 Recursive CTE usage leaks memory when not used in a top level select
+--echo #
+
+--error ER_BAD_FIELD_ERROR
+with recursive cte as (select a from t1 union select a from cte)
+ update t1, cte set t1.o = 1;
+
+let $restart_file= $MYSQLTEST_VARDIR/tmp/mysqld.1.expect;
+--write_line wait $restart_file
+--shutdown_server
+--source include/wait_until_disconnected.inc
+--write_line "restart: " $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+-- enable_reconnect
+-- source include/wait_until_connected_again.inc
+
+--error ER_NON_UPDATABLE_TABLE
+with recursive cte as (select a from t1 union select a from cte where a < 2)
+ delete from cte where a = (select a from cte);
+
+let $restart_file= $MYSQLTEST_VARDIR/tmp/mysqld.1.expect;
+--write_line wait $restart_file
+--shutdown_server
+--source include/wait_until_disconnected.inc
+--write_line "restart: " $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+-- enable_reconnect
+-- source include/wait_until_connected_again.inc
+
+--error ER_NON_UPDATABLE_TABLE
+with recursive cte as (select a from t1 union select a from cte where a < 2)
+ delete from cte where a = 10;
+
+let $restart_file= $MYSQLTEST_VARDIR/tmp/mysqld.1.expect;
+--write_line wait $restart_file
+--shutdown_server
+--source include/wait_until_disconnected.inc
+--write_line "restart: " $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+-- enable_reconnect
+-- source include/wait_until_connected_again.inc
+
+insert into t1 values (1), (5), (10), (15), (20), (25);
+with recursive cte as (select a from t1 union select a from cte where a < 2)
+ delete from v1 using v1, cte where v1.a = cte.a;
+select * from t1 order by 1;
+
+drop table t1;
+
+--echo # End of 12.2 tests
diff --git a/mysql-test/main/ctype_binary.result b/mysql-test/main/ctype_binary.result
index ddb6828838625..794f25311db53 100644
--- a/mysql-test/main/ctype_binary.result
+++ b/mysql-test/main/ctype_binary.result
@@ -2038,20 +2038,6 @@ hex(concat(a)) a
30303030303030303030303030303030313030302E31 00000000000000001000.1
30303030303030303030303030303031303030302E31 00000000000000010000.1
drop table t1;
-create table t1 (a year(2));
-Warnings:
-Warning 1287 'YEAR(2)' is deprecated and will be removed in a future release. Please use 'YEAR(4)' instead
-insert into t1 values (1);
-select hex(concat(a)) from t1;
-hex(concat(a))
-3031
-create table t2 as select concat(a) from t1;
-show create table t2;
-Table Create Table
-t2 CREATE TABLE `t2` (
- `concat(a)` varbinary(2) DEFAULT NULL
-) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci
-drop table t1, t2;
create table t1 (a year);
insert into t1 values (1);
select hex(concat(a)) from t1;
@@ -2353,19 +2339,6 @@ hex(a)
30303030303030303030303030303031303030302E31
drop table t1;
drop view v1;
-create table t1 (a year(2));
-Warnings:
-Warning 1287 'YEAR(2)' is deprecated and will be removed in a future release. Please use 'YEAR(4)' instead
-insert into t1 values (1);
-create view v1(a) as select concat(a) from t1;
-show columns from v1;
-Field Type Null Key Default Extra
-a varbinary(2) YES NULL
-select hex(a) from v1;
-hex(a)
-3031
-drop table t1;
-drop view v1;
create table t1 (a year);
insert into t1 values (1);
create view v1(a) as select concat(a) from t1;
diff --git a/mysql-test/main/ctype_collate_implicit.result b/mysql-test/main/ctype_collate_implicit.result
index 2f9fe5723c35f..64082dbf63c4c 100644
--- a/mysql-test/main/ctype_collate_implicit.result
+++ b/mysql-test/main/ctype_collate_implicit.result
@@ -182,17 +182,17 @@ WHERE CHARACTER_SET_NAME='latin1';
CHARACTER_SET_NAME DEFAULT_COLLATE_NAME DESCRIPTION MAXLEN
latin1 latin1_bin cp1252 West European 1
SHOW COLLATION LIKE 'latin1%';
-Collation Charset Id Default Compiled Sortlen
-latin1_german1_ci latin1 5 Yes 1
-latin1_swedish_ci latin1 8 Yes 1
-latin1_danish_ci latin1 15 Yes 1
-latin1_german2_ci latin1 31 Yes 2
-latin1_bin latin1 47 Yes Yes 1
-latin1_general_ci latin1 48 Yes 1
-latin1_general_cs latin1 49 Yes 1
-latin1_spanish_ci latin1 94 Yes 1
-latin1_swedish_nopad_ci latin1 1032 Yes 1
-latin1_nopad_bin latin1 1071 Yes 1
+Collation Charset Id Default Compiled Sortlen Pad_attribute
+latin1_german1_ci latin1 5 Yes 1 PAD SPACE
+latin1_swedish_ci latin1 8 Yes 1 PAD SPACE
+latin1_danish_ci latin1 15 Yes 1 PAD SPACE
+latin1_german2_ci latin1 31 Yes 2 PAD SPACE
+latin1_bin latin1 47 Yes Yes 1 PAD SPACE
+latin1_general_ci latin1 48 Yes 1 PAD SPACE
+latin1_general_cs latin1 49 Yes 1 PAD SPACE
+latin1_spanish_ci latin1 94 Yes 1 PAD SPACE
+latin1_swedish_nopad_ci latin1 1032 Yes 1 NO PAD
+latin1_nopad_bin latin1 1071 Yes 1 NO PAD
SELECT COLLATION_NAME, IS_DEFAULT
FROM INFORMATION_SCHEMA.COLLATIONS
WHERE CHARACTER_SET_NAME LIKE 'latin1%';
@@ -229,8 +229,8 @@ WHERE CHARACTER_SET_NAME='utf8mb4';
CHARACTER_SET_NAME DEFAULT_COLLATE_NAME DESCRIPTION MAXLEN
utf8mb4 utf8mb4_uca1400_ai_ci UTF-8 Unicode 4
SHOW COLLATION LIKE '%uca1400_ai_ci%';
-Collation Charset Id Default Compiled Sortlen
-uca1400_ai_ci NULL NULL NULL Yes 8
+Collation Charset Id Default Compiled Sortlen Pad_attribute
+uca1400_ai_ci NULL NULL NULL Yes 8 PAD SPACE
SELECT COLLATION_NAME, IS_DEFAULT
FROM INFORMATION_SCHEMA.COLLATIONS
WHERE COLLATION_NAME LIKE '%uca1400_ai_ci%';
diff --git a/mysql-test/main/ctype_cp1250_ch.result b/mysql-test/main/ctype_cp1250_ch.result
index fb0373349fdfe..c65b3d260af10 100644
--- a/mysql-test/main/ctype_cp1250_ch.result
+++ b/mysql-test/main/ctype_cp1250_ch.result
@@ -1,8 +1,8 @@
drop table if exists t1;
DROP TABLE IF EXISTS t1;
SHOW COLLATION LIKE 'cp1250_czech_cs';
-Collation Charset Id Default Compiled Sortlen
-cp1250_czech_cs cp1250 34 Yes 2
+Collation Charset Id Default Compiled Sortlen Pad_attribute
+cp1250_czech_cs cp1250 34 Yes 2 PAD SPACE
SET @test_character_set= 'cp1250';
SET @test_collation= 'cp1250_general_ci';
SET @safe_character_set_server= @@character_set_server;
diff --git a/mysql-test/main/ctype_cp1251.result b/mysql-test/main/ctype_cp1251.result
index 9de7d0dd92232..8d67de36b6041 100644
--- a/mysql-test/main/ctype_cp1251.result
+++ b/mysql-test/main/ctype_cp1251.result
@@ -2450,20 +2450,6 @@ hex(concat(a)) a
30303030303030303030303030303030313030302E31 00000000000000001000.1
30303030303030303030303030303031303030302E31 00000000000000010000.1
drop table t1;
-create table t1 (a year(2));
-Warnings:
-Warning 1287 'YEAR(2)' is deprecated and will be removed in a future release. Please use 'YEAR(4)' instead
-insert into t1 values (1);
-select hex(concat(a)) from t1;
-hex(concat(a))
-3031
-create table t2 as select concat(a) from t1;
-show create table t2;
-Table Create Table
-t2 CREATE TABLE `t2` (
- `concat(a)` varchar(2) CHARACTER SET cp1251 COLLATE cp1251_general_ci DEFAULT NULL
-) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci
-drop table t1, t2;
create table t1 (a year);
insert into t1 values (1);
select hex(concat(a)) from t1;
@@ -2765,19 +2751,6 @@ hex(a)
30303030303030303030303030303031303030302E31
drop table t1;
drop view v1;
-create table t1 (a year(2));
-Warnings:
-Warning 1287 'YEAR(2)' is deprecated and will be removed in a future release. Please use 'YEAR(4)' instead
-insert into t1 values (1);
-create view v1(a) as select concat(a) from t1;
-show columns from v1;
-Field Type Null Key Default Extra
-a varchar(2) YES NULL
-select hex(a) from v1;
-hex(a)
-3031
-drop table t1;
-drop view v1;
create table t1 (a year);
insert into t1 values (1);
create view v1(a) as select concat(a) from t1;
diff --git a/mysql-test/main/ctype_latin1.result b/mysql-test/main/ctype_latin1.result
index 5c584ebec3c48..fb5337ee8ad0a 100644
--- a/mysql-test/main/ctype_latin1.result
+++ b/mysql-test/main/ctype_latin1.result
@@ -2759,20 +2759,6 @@ hex(concat(a)) a
30303030303030303030303030303030313030302E31 00000000000000001000.1
30303030303030303030303030303031303030302E31 00000000000000010000.1
drop table t1;
-create table t1 (a year(2));
-Warnings:
-Warning 1287 'YEAR(2)' is deprecated and will be removed in a future release. Please use 'YEAR(4)' instead
-insert into t1 values (1);
-select hex(concat(a)) from t1;
-hex(concat(a))
-3031
-create table t2 as select concat(a) from t1;
-show create table t2;
-Table Create Table
-t2 CREATE TABLE `t2` (
- `concat(a)` varchar(2) CHARACTER SET latin1 COLLATE latin1_swedish_ci DEFAULT NULL
-) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci
-drop table t1, t2;
create table t1 (a year);
insert into t1 values (1);
select hex(concat(a)) from t1;
@@ -3074,19 +3060,6 @@ hex(a)
30303030303030303030303030303031303030302E31
drop table t1;
drop view v1;
-create table t1 (a year(2));
-Warnings:
-Warning 1287 'YEAR(2)' is deprecated and will be removed in a future release. Please use 'YEAR(4)' instead
-insert into t1 values (1);
-create view v1(a) as select concat(a) from t1;
-show columns from v1;
-Field Type Null Key Default Extra
-a varchar(2) YES NULL
-select hex(a) from v1;
-hex(a)
-3031
-drop table t1;
-drop view v1;
create table t1 (a year);
insert into t1 values (1);
create view v1(a) as select concat(a) from t1;
@@ -8161,12 +8134,12 @@ SELECT * FROM t1 WHERE (a,a)=('2001-01-01x',DATE'2001-01-01');
a
2001-01-01x
Warnings:
-Warning 1292 Truncated incorrect date value: '2001-01-01x'
+Warning 1292 Incorrect date value: '2001-01-01x' for column `test`.`t1`.`a` at row 2
SELECT * FROM t1 WHERE (a,a)=(DATE'2001-01-01','2001-01-01x');
a
2001-01-01x
Warnings:
-Warning 1292 Truncated incorrect date value: '2001-01-01x'
+Warning 1292 Incorrect date value: '2001-01-01x' for column `test`.`t1`.`a` at row 2
SELECT * FROM t1 WHERE (a,a)=('2001-01-01',DATE'2001-01-01');
a
2001-01-01
@@ -8186,12 +8159,12 @@ SELECT * FROM t1 WHERE (a,a)=('2001-01-01x',DATE'2001-01-01');
a
2001-01-01x
Warnings:
-Warning 1292 Truncated incorrect date value: '2001-01-01x'
+Warning 1292 Incorrect date value: '2001-01-01x' for column `test`.`t1`.`a` at row 2
SELECT * FROM t1 WHERE (a,a)=(DATE'2001-01-01','2001-01-01x');
a
2001-01-01x
Warnings:
-Warning 1292 Truncated incorrect date value: '2001-01-01x'
+Warning 1292 Incorrect date value: '2001-01-01x' for column `test`.`t1`.`a` at row 2
SELECT * FROM t1 WHERE (a,a)=('2001-01-01',DATE'2001-01-01');
a
2001-01-01
diff --git a/mysql-test/main/ctype_ldml.result b/mysql-test/main/ctype_ldml.result
index 54d9dde354be4..c6bc0a3ab74f5 100644
--- a/mysql-test/main/ctype_ldml.result
+++ b/mysql-test/main/ctype_ldml.result
@@ -7,8 +7,8 @@ show variables like 'character_sets_dir%';
Variable_name Value
character_sets_dir MYSQL_TEST_DIR/std_data/ldml/
show collation like 'utf8mb3_phone_ci';
-Collation Charset Id Default Compiled Sortlen
-utf8mb3_phone_ci utf8mb3 352 8
+Collation Charset Id Default Compiled Sortlen Pad_attribute
+utf8mb3_phone_ci utf8mb3 352 8 PAD SPACE
CREATE TABLE t1 (
name VARCHAR(64),
phone VARCHAR(64) CHARACTER SET utf8 COLLATE utf8_phone_ci
@@ -39,8 +39,8 @@ name phone
Bar +7-912-800-80-01
DROP TABLE t1;
show collation like 'utf8mb3_test_ci';
-Collation Charset Id Default Compiled Sortlen
-utf8mb3_test_ci utf8mb3 353 8
+Collation Charset Id Default Compiled Sortlen Pad_attribute
+utf8mb3_test_ci utf8mb3 353 8 PAD SPACE
create table t1 (c1 char(1) character set utf8 collate utf8_test_ci);
insert into t1 values ('a');
select * from t1 where c1='b';
@@ -48,8 +48,8 @@ c1
a
drop table t1;
show collation like 'ucs2_test_ci';
-Collation Charset Id Default Compiled Sortlen
-ucs2_test_ci ucs2 358 8
+Collation Charset Id Default Compiled Sortlen Pad_attribute
+ucs2_test_ci ucs2 358 8 PAD SPACE
create table t1 (c1 char(1) character set ucs2 collate ucs2_test_ci);
insert into t1 values ('a');
select * from t1 where c1='b';
@@ -57,8 +57,8 @@ c1
a
drop table t1;
show collation like 'utf8mb4_test_ci';
-Collation Charset Id Default Compiled Sortlen
-utf8mb4_test_ci utf8mb4 326 8
+Collation Charset Id Default Compiled Sortlen Pad_attribute
+utf8mb4_test_ci utf8mb4 326 8 PAD SPACE
create table t1 (c1 char(1) character set utf8mb4 collate utf8mb4_test_ci);
insert into t1 values ('a');
select * from t1 where c1='b';
@@ -66,8 +66,8 @@ c1
a
drop table t1;
show collation like 'utf16_test_ci';
-Collation Charset Id Default Compiled Sortlen
-utf16_test_ci utf16 327 8
+Collation Charset Id Default Compiled Sortlen Pad_attribute
+utf16_test_ci utf16 327 8 PAD SPACE
create table t1 (c1 char(1) character set utf16 collate utf16_test_ci);
insert into t1 values ('a');
select * from t1 where c1='b';
@@ -75,8 +75,8 @@ c1
a
drop table t1;
show collation like 'utf32_test_ci';
-Collation Charset Id Default Compiled Sortlen
-utf32_test_ci utf32 391 8
+Collation Charset Id Default Compiled Sortlen Pad_attribute
+utf32_test_ci utf32 391 8 PAD SPACE
create table t1 (c1 char(1) character set utf32 collate utf32_test_ci);
insert into t1 values ('a');
select * from t1 where c1='b';
@@ -174,8 +174,8 @@ Warning 1265 Data truncated for column 'c1' at row 1
DROP TABLE t1;
Vietnamese experimental collation
show collation like 'ucs2_vn_ci';
-Collation Charset Id Default Compiled Sortlen
-ucs2_vn_ci ucs2 359 8
+Collation Charset Id Default Compiled Sortlen Pad_attribute
+ucs2_vn_ci ucs2 359 8 PAD SPACE
create table t1 (c1 char(1) character set ucs2 collate ucs2_vn_ci);
insert into t1 values (0x0061),(0x0041),(0x00E0),(0x00C0),(0x1EA3),(0x1EA2),
(0x00E3),(0x00C3),(0x00E1),(0x00C1),(0x1EA1),(0x1EA0);
@@ -449,69 +449,69 @@ drop table t1;
Bug#46448 trailing spaces are not ignored when user collation maps space != 0x20
set names latin1;
show collation like 'latin1_test';
-Collation Charset Id Default Compiled Sortlen
-latin1_test latin1 331 1
+Collation Charset Id Default Compiled Sortlen Pad_attribute
+latin1_test latin1 331 1 PAD SPACE
select "foo" = "foo " collate latin1_test;
"foo" = "foo " collate latin1_test
1
The following tests check that two-byte collation IDs work
select * from information_schema.collations where id>256 and is_compiled<>'Yes' order by id;
-COLLATION_NAME CHARACTER_SET_NAME ID IS_DEFAULT IS_COMPILED SORTLEN COMMENT
-ascii2_general_nopad_ci ascii2 318 1
-ascii2_bin2 ascii2 319 1
-ascii2_general_ci ascii2 320 Yes 1
-ascii2_bin ascii2 321 1
-ascii2_general_inherited_ci ascii2 322 1
-ascii2_general_inherited2_ci ascii2 323 1
-ascii2_badly_inherited_ci ascii2 324 1
-ascii2_nopad_bin ascii2 325 1
-utf8mb4_test_ci utf8mb4 326 8
-utf16_test_ci utf16 327 8
-utf8mb4_test_400_ci utf8mb4 328 8
-utf8mb4_test_520_nopad_ci utf8mb4 329 8
-utf8mb4_uca1400_test01_as_ci utf8mb4 330 4
-latin1_test latin1 331 1 cp1252 West European
-latin1_test2 latin1 332 1 cp1252 West European
-latin1_test2_cs latin1 333 1 cp1252 West European
-latin1_swedish_nopad2_ci latin1 334 1 cp1252 West European
-utf8mb3_bengali_standard_ci utf8mb3 336 8
-utf8mb3_bengali_traditional_ci utf8mb3 337 8
-utf8mb3_implicit_weights_ci utf8mb3 338 8
-utf8mb3_phone_ci utf8mb3 352 8
-utf8mb3_test_ci utf8mb3 353 8
-utf8mb3_5624_1 utf8mb3 354 8
-utf8mb3_5624_2 utf8mb3 355 8
-utf8mb3_5624_3 utf8mb3 356 8
-utf8mb3_5624_4 utf8mb3 357 8
-ucs2_test_ci ucs2 358 8
-ucs2_vn_ci ucs2 359 8
-ucs2_5624_1 ucs2 360 8
-utf8mb3_5624_5 utf8mb3 368 8
-utf8mb3_5624_5_bad utf8mb3 369 8
-utf8mb3_czech_test_w2 utf8mb3 370 4
-utf8mb3_czech_test_nopad_w2 utf8mb3 371 4
-utf8mb3_czech_test_bad_w2 utf8mb3 372 4
-utf32_test_ci utf32 391 8
-utf8mb3_maxuserid_ci utf8mb3 2047 8
+COLLATION_NAME CHARACTER_SET_NAME ID IS_DEFAULT IS_COMPILED SORTLEN PAD_ATTRIBUTE COMMENT
+ascii2_general_nopad_ci ascii2 318 1 NO PAD
+ascii2_bin2 ascii2 319 1 PAD SPACE
+ascii2_general_ci ascii2 320 Yes 1 PAD SPACE
+ascii2_bin ascii2 321 1 PAD SPACE
+ascii2_general_inherited_ci ascii2 322 1 PAD SPACE
+ascii2_general_inherited2_ci ascii2 323 1 PAD SPACE
+ascii2_badly_inherited_ci ascii2 324 1 PAD SPACE
+ascii2_nopad_bin ascii2 325 1 NO PAD
+utf8mb4_test_ci utf8mb4 326 8 PAD SPACE
+utf16_test_ci utf16 327 8 PAD SPACE
+utf8mb4_test_400_ci utf8mb4 328 8 PAD SPACE
+utf8mb4_test_520_nopad_ci utf8mb4 329 8 NO PAD
+utf8mb4_uca1400_test01_as_ci utf8mb4 330 4 PAD SPACE
+latin1_test latin1 331 1 PAD SPACE cp1252 West European
+latin1_test2 latin1 332 1 PAD SPACE cp1252 West European
+latin1_test2_cs latin1 333 1 PAD SPACE cp1252 West European
+latin1_swedish_nopad2_ci latin1 334 1 NO PAD cp1252 West European
+utf8mb3_bengali_standard_ci utf8mb3 336 8 PAD SPACE
+utf8mb3_bengali_traditional_ci utf8mb3 337 8 PAD SPACE
+utf8mb3_implicit_weights_ci utf8mb3 338 8 PAD SPACE
+utf8mb3_phone_ci utf8mb3 352 8 PAD SPACE
+utf8mb3_test_ci utf8mb3 353 8 PAD SPACE
+utf8mb3_5624_1 utf8mb3 354 8 PAD SPACE
+utf8mb3_5624_2 utf8mb3 355 8 PAD SPACE
+utf8mb3_5624_3 utf8mb3 356 8 PAD SPACE
+utf8mb3_5624_4 utf8mb3 357 8 PAD SPACE
+ucs2_test_ci ucs2 358 8 PAD SPACE
+ucs2_vn_ci ucs2 359 8 PAD SPACE
+ucs2_5624_1 ucs2 360 8 PAD SPACE
+utf8mb3_5624_5 utf8mb3 368 8 PAD SPACE
+utf8mb3_5624_5_bad utf8mb3 369 8 PAD SPACE
+utf8mb3_czech_test_w2 utf8mb3 370 4 PAD SPACE
+utf8mb3_czech_test_nopad_w2 utf8mb3 371 4 NO PAD
+utf8mb3_czech_test_bad_w2 utf8mb3 372 4 PAD SPACE
+utf32_test_ci utf32 391 8 PAD SPACE
+utf8mb3_maxuserid_ci utf8mb3 2047 8 PAD SPACE
show collation like '%test%';
-Collation Charset Id Default Compiled Sortlen
-latin1_test latin1 331 1
-latin1_test2 latin1 332 1
-latin1_test2_cs latin1 333 1
-utf8mb3_test_ci utf8mb3 353 8
-utf8mb3_czech_test_w2 utf8mb3 370 4
-utf8mb3_czech_test_nopad_w2 utf8mb3 371 4
-utf8mb3_czech_test_bad_w2 utf8mb3 372 4
-ucs2_test_ci ucs2 358 8
-utf8mb4_test_ci utf8mb4 326 8
-utf8mb4_test_400_ci utf8mb4 328 8
-utf8mb4_test_520_nopad_ci utf8mb4 329 8
-utf8mb4_uca1400_test01_as_ci utf8mb4 330 4
-utf16_test_ci utf16 327 8
-utf32_test_ci utf32 391 8
+Collation Charset Id Default Compiled Sortlen Pad_attribute
+latin1_test latin1 331 1 PAD SPACE
+latin1_test2 latin1 332 1 PAD SPACE
+latin1_test2_cs latin1 333 1 PAD SPACE
+utf8mb3_test_ci utf8mb3 353 8 PAD SPACE
+utf8mb3_czech_test_w2 utf8mb3 370 4 PAD SPACE
+utf8mb3_czech_test_nopad_w2 utf8mb3 371 4 NO PAD
+utf8mb3_czech_test_bad_w2 utf8mb3 372 4 PAD SPACE
+ucs2_test_ci ucs2 358 8 PAD SPACE
+utf8mb4_test_ci utf8mb4 326 8 PAD SPACE
+utf8mb4_test_400_ci utf8mb4 328 8 PAD SPACE
+utf8mb4_test_520_nopad_ci utf8mb4 329 8 NO PAD
+utf8mb4_uca1400_test01_as_ci utf8mb4 330 4 PAD SPACE
+utf16_test_ci utf16 327 8 PAD SPACE
+utf32_test_ci utf32 391 8 PAD SPACE
show collation like 'ucs2_vn_ci';
-Collation Charset Id Default Compiled Sortlen
-ucs2_vn_ci ucs2 359 8
+Collation Charset Id Default Compiled Sortlen Pad_attribute
+ucs2_vn_ci ucs2 359 8 PAD SPACE
create table t1 (c1 char(1) character set ucs2 collate ucs2_vn_ci);
insert into t1 values (0x0061);
set @@character_set_results=NULL;
@@ -530,8 +530,8 @@ b
DROP TABLE t1;
SET NAMES utf8 COLLATE utf8_phone_ci;
show collation like 'utf8mb3_phone_ci';
-Collation Charset Id Default Compiled Sortlen
-utf8mb3_phone_ci utf8mb3 352 8
+Collation Charset Id Default Compiled Sortlen Pad_attribute
+utf8mb3_phone_ci utf8mb3 352 8 PAD SPACE
SET NAMES utf8;
SELECT hex(weight_string(_utf8mb4'a' collate utf8mb4_test_400_ci)) as exp;
exp
@@ -3108,7 +3108,7 @@ DROP TABLE case_folding;
# MDEV-7947 my_charset_same: strcmp() takes 0.37% in OLTP RO
#
SHOW COLLATION LIKE 'latin1_test_replace';
-Collation Charset Id Default Compiled Sortlen
+Collation Charset Id Default Compiled Sortlen Pad_attribute
SELECT 'foo' = 'foo ' COLLATE latin1_test_replace;
ERROR HY000: Unknown collation: 'latin1_test_replace'
#
diff --git a/mysql-test/main/ctype_ucs.result b/mysql-test/main/ctype_ucs.result
index 84ee60e19bf78..595fba0b8158c 100644
--- a/mysql-test/main/ctype_ucs.result
+++ b/mysql-test/main/ctype_ucs.result
@@ -174,8 +174,8 @@ LPAD(_ucs2 X'0420',10,_ucs2 X'04210422')
SELECT LPAD(_ucs2 X'0420',10,_ucs2 X'042104220423');
LPAD(_ucs2 X'0420',10,_ucs2 X'042104220423')
-SELECT LPAD(_ucs2 X'0420042104220423042404250426042704280429042A042B',10,_ucs2 X'042104220423');
-LPAD(_ucs2 X'0420042104220423042404250426042704280429042A042B',10,_ucs2 X'042104220423')
+SELECT LPAD(_ucs2 X'0420042104220423042404250426042704280429042A042B',10,_ucs2 X'042104220423') AS res;
+res
SELECT RPAD(_ucs2 X'0420',10,_ucs2 X'0421');
RPAD(_ucs2 X'0420',10,_ucs2 X'0421')
@@ -186,8 +186,8 @@ RPAD(_ucs2 X'0420',10,_ucs2 X'04210422')
SELECT RPAD(_ucs2 X'0420',10,_ucs2 X'042104220423');
RPAD(_ucs2 X'0420',10,_ucs2 X'042104220423')
-SELECT RPAD(_ucs2 X'0420042104220423042404250426042704280429042A042B',10,_ucs2 X'042104220423');
-RPAD(_ucs2 X'0420042104220423042404250426042704280429042A042B',10,_ucs2 X'042104220423')
+SELECT RPAD(_ucs2 X'0420042104220423042404250426042704280429042A042B',10,_ucs2 X'042104220423') AS res;
+res
CREATE TABLE t1 SELECT
LPAD(_ucs2 X'0420',10,_ucs2 X'0421') l,
@@ -3641,20 +3641,6 @@ hex(concat(a)) a
00300030003000300030003000300030003000300030003000300030003000300031003000300030002E0031 00000000000000001000.1
00300030003000300030003000300030003000300030003000300030003000310030003000300030002E0031 00000000000000010000.1
drop table t1;
-create table t1 (a year(2));
-Warnings:
-Warning 1287 'YEAR(2)' is deprecated and will be removed in a future release. Please use 'YEAR(4)' instead
-insert into t1 values (1);
-select hex(concat(a)) from t1;
-hex(concat(a))
-00300031
-create table t2 as select concat(a) from t1;
-show create table t2;
-Table Create Table
-t2 CREATE TABLE `t2` (
- `concat(a)` varchar(2) CHARACTER SET ucs2 COLLATE ucs2_general_ci DEFAULT NULL
-) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci
-drop table t1, t2;
create table t1 (a year);
insert into t1 values (1);
select hex(concat(a)) from t1;
@@ -3956,19 +3942,6 @@ hex(a)
00300030003000300030003000300030003000300030003000300030003000310030003000300030002E0031
drop table t1;
drop view v1;
-create table t1 (a year(2));
-Warnings:
-Warning 1287 'YEAR(2)' is deprecated and will be removed in a future release. Please use 'YEAR(4)' instead
-insert into t1 values (1);
-create view v1(a) as select concat(a) from t1;
-show columns from v1;
-Field Type Null Key Default Extra
-a varchar(2) YES NULL
-select hex(a) from v1;
-hex(a)
-00300031
-drop table t1;
-drop view v1;
create table t1 (a year);
insert into t1 values (1);
create view v1(a) as select concat(a) from t1;
diff --git a/mysql-test/main/ctype_ucs.test b/mysql-test/main/ctype_ucs.test
index 03e6567820431..e9a7513231496 100644
--- a/mysql-test/main/ctype_ucs.test
+++ b/mysql-test/main/ctype_ucs.test
@@ -51,12 +51,12 @@ DROP TABLE t1;
SELECT LPAD(_ucs2 X'0420',10,_ucs2 X'0421');
SELECT LPAD(_ucs2 X'0420',10,_ucs2 X'04210422');
SELECT LPAD(_ucs2 X'0420',10,_ucs2 X'042104220423');
-SELECT LPAD(_ucs2 X'0420042104220423042404250426042704280429042A042B',10,_ucs2 X'042104220423');
+SELECT LPAD(_ucs2 X'0420042104220423042404250426042704280429042A042B',10,_ucs2 X'042104220423') AS res;
SELECT RPAD(_ucs2 X'0420',10,_ucs2 X'0421');
SELECT RPAD(_ucs2 X'0420',10,_ucs2 X'04210422');
SELECT RPAD(_ucs2 X'0420',10,_ucs2 X'042104220423');
-SELECT RPAD(_ucs2 X'0420042104220423042404250426042704280429042A042B',10,_ucs2 X'042104220423');
+SELECT RPAD(_ucs2 X'0420042104220423042404250426042704280429042A042B',10,_ucs2 X'042104220423') AS res;
CREATE TABLE t1 SELECT
LPAD(_ucs2 X'0420',10,_ucs2 X'0421') l,
@@ -118,6 +118,7 @@ SET NAMES koi8r;
SET character_set_connection=ucs2;
--source include/ctype_like.inc
+--disable_service_connection
CREATE TABLE t1 (a VARCHAR(10) CHARACTER SET ucs2);
INSERT INTO t1 VALUES (''),(''),(''),(''),(''),('');
INSERT INTO t1 VALUES (''),(''),(''),('');
@@ -127,6 +128,7 @@ SELECT * FROM t1 WHERE a LIKE '%
SELECT * FROM t1 WHERE a LIKE '%%';
SELECT * FROM t1 WHERE a LIKE '%';
SELECT * FROM t1 WHERE a LIKE '%' COLLATE ucs2_bin;
+--enable_service_connection
DROP TABLE t1;
#
diff --git a/mysql-test/main/ctype_utf8.result b/mysql-test/main/ctype_utf8.result
index 1182028c925bc..1c184e24ecd4c 100644
--- a/mysql-test/main/ctype_utf8.result
+++ b/mysql-test/main/ctype_utf8.result
@@ -4387,20 +4387,6 @@ hex(concat(a)) a
30303030303030303030303030303030313030302E31 00000000000000001000.1
30303030303030303030303030303031303030302E31 00000000000000010000.1
drop table t1;
-create table t1 (a year(2));
-Warnings:
-Warning 1287 'YEAR(2)' is deprecated and will be removed in a future release. Please use 'YEAR(4)' instead
-insert into t1 values (1);
-select hex(concat(a)) from t1;
-hex(concat(a))
-3031
-create table t2 as select concat(a) from t1;
-show create table t2;
-Table Create Table
-t2 CREATE TABLE `t2` (
- `concat(a)` varchar(2) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL
-) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci
-drop table t1, t2;
create table t1 (a year);
insert into t1 values (1);
select hex(concat(a)) from t1;
@@ -4702,19 +4688,6 @@ hex(a)
30303030303030303030303030303031303030302E31
drop table t1;
drop view v1;
-create table t1 (a year(2));
-Warnings:
-Warning 1287 'YEAR(2)' is deprecated and will be removed in a future release. Please use 'YEAR(4)' instead
-insert into t1 values (1);
-create view v1(a) as select concat(a) from t1;
-show columns from v1;
-Field Type Null Key Default Extra
-a varchar(2) YES NULL
-select hex(a) from v1;
-hex(a)
-3031
-drop table t1;
-drop view v1;
create table t1 (a year);
insert into t1 values (1);
create view v1(a) as select concat(a) from t1;
diff --git a/mysql-test/main/ctype_utf8mb4_0900.result b/mysql-test/main/ctype_utf8mb4_0900.result
index 5bb3123aab8dc..4e94f3d3f3339 100644
--- a/mysql-test/main/ctype_utf8mb4_0900.result
+++ b/mysql-test/main/ctype_utf8mb4_0900.result
@@ -47,51 +47,51 @@ utf8mb4_tr_0900_as_cs utf8mb4 utf8mb4_tr_0900_as_cs 288
utf8mb4_vi_0900_ai_ci utf8mb4 utf8mb4_vi_0900_ai_ci 277
utf8mb4_vi_0900_as_cs utf8mb4 utf8mb4_vi_0900_as_cs 300
select * from information_schema.COLLATIONS where collation_name like "%0900%";
-COLLATION_NAME CHARACTER_SET_NAME ID IS_DEFAULT IS_COMPILED SORTLEN COMMENT
-utf8mb4_0900_ai_ci utf8mb4 255 Yes 8 Alias for utf8mb4_uca1400_nopad_ai_ci
-utf8mb4_de_pb_0900_ai_ci utf8mb4 256 Yes 8 Alias for utf8mb4_uca1400_german2_nopad_ai_ci
-utf8mb4_is_0900_ai_ci utf8mb4 257 Yes 8 Alias for utf8mb4_uca1400_icelandic_nopad_ai_ci
-utf8mb4_lv_0900_ai_ci utf8mb4 258 Yes 8 Alias for utf8mb4_uca1400_latvian_nopad_ai_ci
-utf8mb4_ro_0900_ai_ci utf8mb4 259 Yes 8 Alias for utf8mb4_uca1400_romanian_nopad_ai_ci
-utf8mb4_sl_0900_ai_ci utf8mb4 260 Yes 8 Alias for utf8mb4_uca1400_slovenian_nopad_ai_ci
-utf8mb4_pl_0900_ai_ci utf8mb4 261 Yes 8 Alias for utf8mb4_uca1400_polish_nopad_ai_ci
-utf8mb4_et_0900_ai_ci utf8mb4 262 Yes 8 Alias for utf8mb4_uca1400_estonian_nopad_ai_ci
-utf8mb4_es_0900_ai_ci utf8mb4 263 Yes 8 Alias for utf8mb4_uca1400_spanish_nopad_ai_ci
-utf8mb4_sv_0900_ai_ci utf8mb4 264 Yes 8 Alias for utf8mb4_uca1400_swedish_nopad_ai_ci
-utf8mb4_tr_0900_ai_ci utf8mb4 265 Yes 8 Alias for utf8mb4_uca1400_turkish_nopad_ai_ci
-utf8mb4_cs_0900_ai_ci utf8mb4 266 Yes 8 Alias for utf8mb4_uca1400_czech_nopad_ai_ci
-utf8mb4_da_0900_ai_ci utf8mb4 267 Yes 8 Alias for utf8mb4_uca1400_danish_nopad_ai_ci
-utf8mb4_lt_0900_ai_ci utf8mb4 268 Yes 8 Alias for utf8mb4_uca1400_lithuanian_nopad_ai_ci
-utf8mb4_sk_0900_ai_ci utf8mb4 269 Yes 8 Alias for utf8mb4_uca1400_slovak_nopad_ai_ci
-utf8mb4_es_trad_0900_ai_ci utf8mb4 270 Yes 8 Alias for utf8mb4_uca1400_spanish2_nopad_ai_ci
-utf8mb4_la_0900_ai_ci utf8mb4 271 Yes 8 Alias for utf8mb4_uca1400_roman_nopad_ai_ci
-utf8mb4_eo_0900_ai_ci utf8mb4 273 Yes 8 Alias for utf8mb4_uca1400_esperanto_nopad_ai_ci
-utf8mb4_hu_0900_ai_ci utf8mb4 274 Yes 8 Alias for utf8mb4_uca1400_hungarian_nopad_ai_ci
-utf8mb4_hr_0900_ai_ci utf8mb4 275 Yes 8 Alias for utf8mb4_uca1400_croatian_nopad_ai_ci
-utf8mb4_vi_0900_ai_ci utf8mb4 277 Yes 8 Alias for utf8mb4_uca1400_vietnamese_nopad_ai_ci
-utf8mb4_0900_as_cs utf8mb4 278 Yes 8 Alias for utf8mb4_uca1400_nopad_as_cs
-utf8mb4_de_pb_0900_as_cs utf8mb4 279 Yes 8 Alias for utf8mb4_uca1400_german2_nopad_as_cs
-utf8mb4_is_0900_as_cs utf8mb4 280 Yes 8 Alias for utf8mb4_uca1400_icelandic_nopad_as_cs
-utf8mb4_lv_0900_as_cs utf8mb4 281 Yes 8 Alias for utf8mb4_uca1400_latvian_nopad_as_cs
-utf8mb4_ro_0900_as_cs utf8mb4 282 Yes 8 Alias for utf8mb4_uca1400_romanian_nopad_as_cs
-utf8mb4_sl_0900_as_cs utf8mb4 283 Yes 8 Alias for utf8mb4_uca1400_slovenian_nopad_as_cs
-utf8mb4_pl_0900_as_cs utf8mb4 284 Yes 8 Alias for utf8mb4_uca1400_polish_nopad_as_cs
-utf8mb4_et_0900_as_cs utf8mb4 285 Yes 8 Alias for utf8mb4_uca1400_estonian_nopad_as_cs
-utf8mb4_es_0900_as_cs utf8mb4 286 Yes 8 Alias for utf8mb4_uca1400_spanish_nopad_as_cs
-utf8mb4_sv_0900_as_cs utf8mb4 287 Yes 8 Alias for utf8mb4_uca1400_swedish_nopad_as_cs
-utf8mb4_tr_0900_as_cs utf8mb4 288 Yes 8 Alias for utf8mb4_uca1400_turkish_nopad_as_cs
-utf8mb4_cs_0900_as_cs utf8mb4 289 Yes 8 Alias for utf8mb4_uca1400_czech_nopad_as_cs
-utf8mb4_da_0900_as_cs utf8mb4 290 Yes 8 Alias for utf8mb4_uca1400_danish_nopad_as_cs
-utf8mb4_lt_0900_as_cs utf8mb4 291 Yes 8 Alias for utf8mb4_uca1400_lithuanian_nopad_as_cs
-utf8mb4_sk_0900_as_cs utf8mb4 292 Yes 8 Alias for utf8mb4_uca1400_slovak_nopad_as_cs
-utf8mb4_es_trad_0900_as_cs utf8mb4 293 Yes 8 Alias for utf8mb4_uca1400_spanish2_nopad_as_cs
-utf8mb4_la_0900_as_cs utf8mb4 294 Yes 8 Alias for utf8mb4_uca1400_roman_nopad_as_cs
-utf8mb4_eo_0900_as_cs utf8mb4 296 Yes 8 Alias for utf8mb4_uca1400_esperanto_nopad_as_cs
-utf8mb4_hu_0900_as_cs utf8mb4 297 Yes 8 Alias for utf8mb4_uca1400_hungarian_nopad_as_cs
-utf8mb4_hr_0900_as_cs utf8mb4 298 Yes 8 Alias for utf8mb4_uca1400_croatian_nopad_as_cs
-utf8mb4_vi_0900_as_cs utf8mb4 300 Yes 8 Alias for utf8mb4_uca1400_vietnamese_nopad_as_cs
-utf8mb4_0900_as_ci utf8mb4 305 Yes 8 Alias for utf8mb4_uca1400_nopad_as_ci
-utf8mb4_0900_bin utf8mb4 309 Yes 1 Alias for utf8mb4_nopad_bin
+COLLATION_NAME CHARACTER_SET_NAME ID IS_DEFAULT IS_COMPILED SORTLEN PAD_ATTRIBUTE COMMENT
+utf8mb4_0900_ai_ci utf8mb4 255 Yes 8 NO PAD Alias for utf8mb4_uca1400_nopad_ai_ci
+utf8mb4_de_pb_0900_ai_ci utf8mb4 256 Yes 8 NO PAD Alias for utf8mb4_uca1400_german2_nopad_ai_ci
+utf8mb4_is_0900_ai_ci utf8mb4 257 Yes 8 NO PAD Alias for utf8mb4_uca1400_icelandic_nopad_ai_ci
+utf8mb4_lv_0900_ai_ci utf8mb4 258 Yes 8 NO PAD Alias for utf8mb4_uca1400_latvian_nopad_ai_ci
+utf8mb4_ro_0900_ai_ci utf8mb4 259 Yes 8 NO PAD Alias for utf8mb4_uca1400_romanian_nopad_ai_ci
+utf8mb4_sl_0900_ai_ci utf8mb4 260 Yes 8 NO PAD Alias for utf8mb4_uca1400_slovenian_nopad_ai_ci
+utf8mb4_pl_0900_ai_ci utf8mb4 261 Yes 8 NO PAD Alias for utf8mb4_uca1400_polish_nopad_ai_ci
+utf8mb4_et_0900_ai_ci utf8mb4 262 Yes 8 NO PAD Alias for utf8mb4_uca1400_estonian_nopad_ai_ci
+utf8mb4_es_0900_ai_ci utf8mb4 263 Yes 8 NO PAD Alias for utf8mb4_uca1400_spanish_nopad_ai_ci
+utf8mb4_sv_0900_ai_ci utf8mb4 264 Yes 8 NO PAD Alias for utf8mb4_uca1400_swedish_nopad_ai_ci
+utf8mb4_tr_0900_ai_ci utf8mb4 265 Yes 8 NO PAD Alias for utf8mb4_uca1400_turkish_nopad_ai_ci
+utf8mb4_cs_0900_ai_ci utf8mb4 266 Yes 8 NO PAD Alias for utf8mb4_uca1400_czech_nopad_ai_ci
+utf8mb4_da_0900_ai_ci utf8mb4 267 Yes 8 NO PAD Alias for utf8mb4_uca1400_danish_nopad_ai_ci
+utf8mb4_lt_0900_ai_ci utf8mb4 268 Yes 8 NO PAD Alias for utf8mb4_uca1400_lithuanian_nopad_ai_ci
+utf8mb4_sk_0900_ai_ci utf8mb4 269 Yes 8 NO PAD Alias for utf8mb4_uca1400_slovak_nopad_ai_ci
+utf8mb4_es_trad_0900_ai_ci utf8mb4 270 Yes 8 NO PAD Alias for utf8mb4_uca1400_spanish2_nopad_ai_ci
+utf8mb4_la_0900_ai_ci utf8mb4 271 Yes 8 NO PAD Alias for utf8mb4_uca1400_roman_nopad_ai_ci
+utf8mb4_eo_0900_ai_ci utf8mb4 273 Yes 8 NO PAD Alias for utf8mb4_uca1400_esperanto_nopad_ai_ci
+utf8mb4_hu_0900_ai_ci utf8mb4 274 Yes 8 NO PAD Alias for utf8mb4_uca1400_hungarian_nopad_ai_ci
+utf8mb4_hr_0900_ai_ci utf8mb4 275 Yes 8 NO PAD Alias for utf8mb4_uca1400_croatian_nopad_ai_ci
+utf8mb4_vi_0900_ai_ci utf8mb4 277 Yes 8 NO PAD Alias for utf8mb4_uca1400_vietnamese_nopad_ai_ci
+utf8mb4_0900_as_cs utf8mb4 278 Yes 8 NO PAD Alias for utf8mb4_uca1400_nopad_as_cs
+utf8mb4_de_pb_0900_as_cs utf8mb4 279 Yes 8 NO PAD Alias for utf8mb4_uca1400_german2_nopad_as_cs
+utf8mb4_is_0900_as_cs utf8mb4 280 Yes 8 NO PAD Alias for utf8mb4_uca1400_icelandic_nopad_as_cs
+utf8mb4_lv_0900_as_cs utf8mb4 281 Yes 8 NO PAD Alias for utf8mb4_uca1400_latvian_nopad_as_cs
+utf8mb4_ro_0900_as_cs utf8mb4 282 Yes 8 NO PAD Alias for utf8mb4_uca1400_romanian_nopad_as_cs
+utf8mb4_sl_0900_as_cs utf8mb4 283 Yes 8 NO PAD Alias for utf8mb4_uca1400_slovenian_nopad_as_cs
+utf8mb4_pl_0900_as_cs utf8mb4 284 Yes 8 NO PAD Alias for utf8mb4_uca1400_polish_nopad_as_cs
+utf8mb4_et_0900_as_cs utf8mb4 285 Yes 8 NO PAD Alias for utf8mb4_uca1400_estonian_nopad_as_cs
+utf8mb4_es_0900_as_cs utf8mb4 286 Yes 8 NO PAD Alias for utf8mb4_uca1400_spanish_nopad_as_cs
+utf8mb4_sv_0900_as_cs utf8mb4 287 Yes 8 NO PAD Alias for utf8mb4_uca1400_swedish_nopad_as_cs
+utf8mb4_tr_0900_as_cs utf8mb4 288 Yes 8 NO PAD Alias for utf8mb4_uca1400_turkish_nopad_as_cs
+utf8mb4_cs_0900_as_cs utf8mb4 289 Yes 8 NO PAD Alias for utf8mb4_uca1400_czech_nopad_as_cs
+utf8mb4_da_0900_as_cs utf8mb4 290 Yes 8 NO PAD Alias for utf8mb4_uca1400_danish_nopad_as_cs
+utf8mb4_lt_0900_as_cs utf8mb4 291 Yes 8 NO PAD Alias for utf8mb4_uca1400_lithuanian_nopad_as_cs
+utf8mb4_sk_0900_as_cs utf8mb4 292 Yes 8 NO PAD Alias for utf8mb4_uca1400_slovak_nopad_as_cs
+utf8mb4_es_trad_0900_as_cs utf8mb4 293 Yes 8 NO PAD Alias for utf8mb4_uca1400_spanish2_nopad_as_cs
+utf8mb4_la_0900_as_cs utf8mb4 294 Yes 8 NO PAD Alias for utf8mb4_uca1400_roman_nopad_as_cs
+utf8mb4_eo_0900_as_cs utf8mb4 296 Yes 8 NO PAD Alias for utf8mb4_uca1400_esperanto_nopad_as_cs
+utf8mb4_hu_0900_as_cs utf8mb4 297 Yes 8 NO PAD Alias for utf8mb4_uca1400_hungarian_nopad_as_cs
+utf8mb4_hr_0900_as_cs utf8mb4 298 Yes 8 NO PAD Alias for utf8mb4_uca1400_croatian_nopad_as_cs
+utf8mb4_vi_0900_as_cs utf8mb4 300 Yes 8 NO PAD Alias for utf8mb4_uca1400_vietnamese_nopad_as_cs
+utf8mb4_0900_as_ci utf8mb4 305 Yes 8 NO PAD Alias for utf8mb4_uca1400_nopad_as_ci
+utf8mb4_0900_bin utf8mb4 309 Yes 1 NO PAD Alias for utf8mb4_nopad_bin
#
# MDEV-20912 Add support for utf8mb4_0900_* collations in MariaDB Server
#
diff --git a/mysql-test/main/ctype_utf8mb4_uca1400_ai_ci.result b/mysql-test/main/ctype_utf8mb4_uca1400_ai_ci.result
index f13fac20e43a7..1bfd04802d239 100644
--- a/mysql-test/main/ctype_utf8mb4_uca1400_ai_ci.result
+++ b/mysql-test/main/ctype_utf8mb4_uca1400_ai_ci.result
@@ -618,5 +618,10 @@ Warnings:
Note 1003 select `test`.`t1`.`c1` AS `c1` from `test`.`t1` where concat(`test`.`t1`.`c1`) = 'ä' and concat(`test`.`t1`.`c1`) like 'ae'
DROP TABLE IF EXISTS t1;
#
+# MDEV-38608 TO_DATE: Server crash in my_uca_strnncoll_multilevel_generic
+#
+CREATE TABLE t1 (f ENUM('foo','bar')) COLLATE uca1400_ai_cs;
+DROP TABLE t1;
+#
# End of 10.0 tests
#
diff --git a/mysql-test/main/ctype_utf8mb4_uca1400_ai_ci.test b/mysql-test/main/ctype_utf8mb4_uca1400_ai_ci.test
index 862053ed97717..83c630abb580d 100644
--- a/mysql-test/main/ctype_utf8mb4_uca1400_ai_ci.test
+++ b/mysql-test/main/ctype_utf8mb4_uca1400_ai_ci.test
@@ -47,6 +47,13 @@ SET NAMES utf8mb4 COLLATE uca1400_ai_ci;
--source include/ctype_like_cond_propagation.inc
--source include/ctype_like_cond_propagation_utf8_german.inc
+--echo #
+--echo # MDEV-38608 TO_DATE: Server crash in my_uca_strnncoll_multilevel_generic
+--echo #
+
+CREATE TABLE t1 (f ENUM('foo','bar')) COLLATE uca1400_ai_cs;
+DROP TABLE t1;
+
--echo #
--echo # End of 10.0 tests
--echo #
diff --git a/mysql-test/main/ddl_i18n_koi8r.result b/mysql-test/main/ddl_i18n_koi8r.result
index 3e6cd07c3117d..a1e3e45a8c4d8 100644
--- a/mysql-test/main/ddl_i18n_koi8r.result
+++ b/mysql-test/main/ddl_i18n_koi8r.result
@@ -2844,9 +2844,7 @@ Table Create Table
t2 CREATE TABLE `t2` (
`col1` varchar(10) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=cp1251 COLLATE=cp1251_general_cs
-connection con2;
disconnect con2;
-connection con3;
disconnect con3;
connection default;
USE test;
diff --git a/mysql-test/main/ddl_i18n_koi8r.test b/mysql-test/main/ddl_i18n_koi8r.test
index f80dab8a04125..e6dbb278536be 100644
--- a/mysql-test/main/ddl_i18n_koi8r.test
+++ b/mysql-test/main/ddl_i18n_koi8r.test
@@ -1110,12 +1110,8 @@ SHOW CREATE TABLE mysqltest2.t2|
#
delimiter ;|
---connection con2
--disconnect con2
---source include/wait_until_disconnected.inc
---connection con3
--disconnect con3
---source include/wait_until_disconnected.inc
--connection default
USE test;
DROP DATABASE mysqltest1;
diff --git a/mysql-test/main/ddl_i18n_utf8.result b/mysql-test/main/ddl_i18n_utf8.result
index ff31607c22d69..951717e178827 100644
--- a/mysql-test/main/ddl_i18n_utf8.result
+++ b/mysql-test/main/ddl_i18n_utf8.result
@@ -2844,9 +2844,7 @@ Table Create Table
t2 CREATE TABLE `t2` (
`col1` varchar(10) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=cp1251 COLLATE=cp1251_general_cs
-connection con2;
disconnect con2;
-connection con3;
disconnect con3;
connection default;
USE test;
diff --git a/mysql-test/main/ddl_i18n_utf8.test b/mysql-test/main/ddl_i18n_utf8.test
index a6ca726bb9e4c..a4ba10bd689ef 100644
--- a/mysql-test/main/ddl_i18n_utf8.test
+++ b/mysql-test/main/ddl_i18n_utf8.test
@@ -1113,12 +1113,8 @@ SHOW CREATE TABLE mysqltest2.t2|
#
delimiter ;|
---connection con2
--disconnect con2
---source include/wait_until_disconnected.inc
---connection con3
--disconnect con3
---source include/wait_until_disconnected.inc
--connection default
USE test;
DROP DATABASE mysqltest1;
diff --git a/mysql-test/main/deadlock_ftwrl.test b/mysql-test/main/deadlock_ftwrl.test
index fc943bcf95347..1114a16e41fc4 100644
--- a/mysql-test/main/deadlock_ftwrl.test
+++ b/mysql-test/main/deadlock_ftwrl.test
@@ -3,7 +3,7 @@
# Deadlock detector should resolve conflicts between FTWRL and user locks.
--source include/have_debug_sync.inc
---source include/count_sessions.inc
+--source include/no_view_protocol.inc
CREATE TABLE t1(a INT);
SELECT GET_LOCK("l1", 0);
@@ -32,5 +32,3 @@ UNLOCK TABLES;
DROP TABLE t1;
set debug_sync='reset';
-
---source include/wait_until_count_sessions.inc
diff --git a/mysql-test/main/debug_sync.result b/mysql-test/main/debug_sync.result
index 6bc2a5cbe245f..4c1711a6d6b3b 100644
--- a/mysql-test/main/debug_sync.result
+++ b/mysql-test/main/debug_sync.result
@@ -320,30 +320,3 @@ SHOW VARIABLES LIKE 'DEBUG_SYNC';
Variable_name Value
debug_sync ON - current signals: 's2,s7,s1,s5'
SET DEBUG_SYNC= 'RESET';
-#
-# MDEV-30364 Assertion MDL_EXCLUSIVE on DISCARD TABLESPACE in LOCK TABLE mode
-#
-create table t (c int) engine=innodb;
-connect con1,localhost,root;
-set debug_sync='get_schema_column WAIT_FOR go';
-select column_name from information_schema.columns
-where table_schema='test' and table_name='t';
-connection default;
-lock table t write;
-alter table t discard tablespace;
-connect con2,localhost,root;
-disconnect con2;
-connection default;
-ERROR 70100: Query execution was interrupted
-set debug_sync='now SIGNAL go';
-connection con1;
-column_name
-c
-disconnect con1;
-connection default;
-unlock tables;
-drop table t;
-set debug_sync= 'reset';
-#
-# End of 10.6 tests
-#
diff --git a/mysql-test/main/debug_sync.test b/mysql-test/main/debug_sync.test
index 1c8638832c139..4c39ed39bfe0b 100644
--- a/mysql-test/main/debug_sync.test
+++ b/mysql-test/main/debug_sync.test
@@ -448,43 +448,3 @@ SHOW VARIABLES LIKE 'DEBUG_SYNC';
# Otherwise signal would confuse the next test.
#
SET DEBUG_SYNC= 'RESET';
-
---echo #
---echo # MDEV-30364 Assertion MDL_EXCLUSIVE on DISCARD TABLESPACE in LOCK TABLE mode
---echo #
-create table t (c int) engine=innodb;
---connect con1,localhost,root
-set debug_sync='get_schema_column WAIT_FOR go';
-send select column_name from information_schema.columns
-where table_schema='test' and table_name='t';
-
---connection default
-let $wait_condition=select 1 from information_schema.processlist where state like 'debug sync point%';
---source include/wait_condition.inc
-let $connid=`select connection_id()`;
-lock table t write;
-send alter table t discard tablespace;
-
---connect con2,localhost,root
---disable_query_log
---eval kill query $connid
---enable_query_log
---disconnect con2
-
---connection default
---error ER_QUERY_INTERRUPTED
-reap;
-set debug_sync='now SIGNAL go';
-
---connection con1
-reap;
---disconnect con1
-
---connection default
-unlock tables;
-drop table t;
-set debug_sync= 'reset';
-
---echo #
---echo # End of 10.6 tests
---echo #
diff --git a/mysql-test/main/default.result b/mysql-test/main/default.result
index d1fa23369c3a6..a1437dfe622a3 100644
--- a/mysql-test/main/default.result
+++ b/mysql-test/main/default.result
@@ -3122,7 +3122,7 @@ create table t3 as select max(a), max(b), max(c) from t1;
show create table t2;
Table Create Table
t2 CREATE TABLE `t2` (
- `a` int(11) DEFAULT 5 CHECK (`a` > 10),
+ `a` int(11) DEFAULT 5,
`b` int(11) DEFAULT (5 + 5),
`c` int(11) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
diff --git a/mysql-test/main/delayed.result b/mysql-test/main/delayed.result
index 73e1ed40c6a58..30d8fe99ccd6e 100644
--- a/mysql-test/main/delayed.result
+++ b/mysql-test/main/delayed.result
@@ -420,3 +420,11 @@ CREATE TABLE t1 (c0 INT,UNIQUE (c0) USING HASH) ENGINE=MYISAM;
INSERT DELAYED INTO t1 VALUES (0);
INSERT DELAYED INTO t1 VALUES (0);
DROP TABLE t1;
+#
+# MDEV-38726: Assertion `table->default_field != dfield_ptr' failed in
+# bool parse_vcol_defs(THD *, MEM_ROOT *, TABLE *, bool *,
+# vcol_init_mode)
+#
+CREATE TABLE t_38726 (a TIMESTAMP ON UPDATE CURRENT_TIMESTAMP()) ENGINE=MYISAM;
+INSERT DELAYED INTO t_38726 VALUES ();
+DROP TABLE t_38726;
diff --git a/mysql-test/main/delayed.test b/mysql-test/main/delayed.test
index 36f2b6653c9e6..a578a76dbd4f8 100644
--- a/mysql-test/main/delayed.test
+++ b/mysql-test/main/delayed.test
@@ -534,12 +534,8 @@ INSERT DELAYED INTO t2 VALUES (8);
UNLOCK TABLES;
SET AUTOCOMMIT= 1;
-connection con2;
disconnect con2;
---source include/wait_until_disconnected.inc
-connection con1;
disconnect con1;
---source include/wait_until_disconnected.inc
connection default;
DROP TABLE t1, t2, t3;
@@ -585,7 +581,6 @@ connection con1;
--reap
disconnect con1;
---source include/wait_until_disconnected.inc
connection default;
drop tables tm, t1, t2;
@@ -637,3 +632,13 @@ INSERT DELAYED INTO t1 VALUES (0);
DROP TABLE t1;
--enable_view_protocol
+
+--echo #
+--echo # MDEV-38726: Assertion `table->default_field != dfield_ptr' failed in
+--echo # bool parse_vcol_defs(THD *, MEM_ROOT *, TABLE *, bool *,
+--echo # vcol_init_mode)
+--echo #
+
+CREATE TABLE t_38726 (a TIMESTAMP ON UPDATE CURRENT_TIMESTAMP()) ENGINE=MYISAM;
+INSERT DELAYED INTO t_38726 VALUES ();
+DROP TABLE t_38726;
diff --git a/mysql-test/main/delete.result b/mysql-test/main/delete.result
index ee1f00729d81e..f07dab64076a3 100644
--- a/mysql-test/main/delete.result
+++ b/mysql-test/main/delete.result
@@ -779,6 +779,22 @@ id
Warnings:
Warning 4207 Index hints are ignored because they are incompatible with RETURNING clause
drop table t2;
-#
# End of 11.4 test
#
+# MDEV-38068 Query doesn't delete all data it should after update to 11.8.4
+#
+create table t1 (id varchar(32), d1 char, key (id), key (d1)) engine=myisam;
+insert into t1 values ('1','A'), ('1','B'), ('1','C'), ('2','D'), ('2','E');
+select count(*) from t1;
+count(*)
+5
+need "range" below
+explain delete from t1 where id = '1';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range id id 131 NULL 3 Using where
+delete from t1 where id = '1';
+select count(*) from t1;
+count(*)
+2
+drop table t1;
+# End of 11.8 test
diff --git a/mysql-test/main/delete.test b/mysql-test/main/delete.test
index c6534f55f4941..99f05f327352d 100644
--- a/mysql-test/main/delete.test
+++ b/mysql-test/main/delete.test
@@ -825,6 +825,18 @@ DELETE FROM t2 ignore index(primary) ORDER BY (id) LIMIT 2 RETURNING id;
drop table t2;
---echo #
--echo # End of 11.4 test
+
--echo #
+--echo # MDEV-38068 Query doesn't delete all data it should after update to 11.8.4
+--echo #
+create table t1 (id varchar(32), d1 char, key (id), key (d1)) engine=myisam;
+insert into t1 values ('1','A'), ('1','B'), ('1','C'), ('2','D'), ('2','E');
+select count(*) from t1;
+--echo need "range" below
+explain delete from t1 where id = '1';
+delete from t1 where id = '1';
+select count(*) from t1;
+drop table t1;
+
+--echo # End of 11.8 test
diff --git a/mysql-test/main/derived.result b/mysql-test/main/derived.result
index 8a837b2ffde3c..1aa234e2aaba2 100644
--- a/mysql-test/main/derived.result
+++ b/mysql-test/main/derived.result
@@ -1,4 +1,3 @@
-drop table if exists t1,t2,t3;
ALTER DATABASE test CHARACTER SET latin1 COLLATE latin1_swedish_ci;
set @save_derived_optimizer_switch=@@optimizer_switch;
set optimizer_switch='derived_merge=off,derived_with_keys=off';
@@ -398,7 +397,6 @@ ID DATA FID
select t2.* from (select * from t1) as A inner join t2 on A.ID = t2.FID;
ID DATA FID
drop table t1, t2;
-connection con1;
disconnect con1;
connection default;
drop user mysqltest_1;
diff --git a/mysql-test/main/derived.test b/mysql-test/main/derived.test
index 1350aed6d73ea..c5c27c940c840 100644
--- a/mysql-test/main/derived.test
+++ b/mysql-test/main/derived.test
@@ -1,11 +1,6 @@
# Initialize
--source include/default_optimizer_switch.inc
--source include/have_sequence.inc
-
---disable_warnings
-drop table if exists t1,t2,t3;
---enable_warnings
-
--source include/test_db_charset_latin1.inc
set @save_derived_optimizer_switch=@@optimizer_switch;
@@ -290,9 +285,7 @@ select t2.* from ((select * from t1) as A inner join t2 on A.ID = t2.FID);
select t2.* from (select * from t1) as A inner join t2 on A.ID = t2.FID;
drop table t1, t2;
-connection con1;
disconnect con1;
---source include/wait_until_disconnected.inc
connection default;
drop user mysqltest_1;
@@ -1201,6 +1194,7 @@ drop table t1,t2,t3;
--echo # query includes a derived table containing unnamed column
--echo # (eg: `SELECT '' from t`).
--echo #
+--disable_view_protocol
--echo # Tests from the bug report
@@ -1301,6 +1295,7 @@ SELECT * FROM v6_t;
DROP VIEW v1_t, v2_t, v3_t, v4_t, v5_t, v6_t;
DROP TABLE t;
+--enable_view_protocol
--echo # End of 10.11 tests
diff --git a/mysql-test/main/derived_cond_pushdown.result b/mysql-test/main/derived_cond_pushdown.result
index 1f0d1514cb91d..8a03938837520 100644
--- a/mysql-test/main/derived_cond_pushdown.result
+++ b/mysql-test/main/derived_cond_pushdown.result
@@ -1930,7 +1930,7 @@ a b max_c avg_c a b c d
explain select * from v1,t2 where (v1.a=v1.b) and (v1.a=t2.a);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 9 Using where
-1 PRIMARY ref key0 key0 10 test.t2.a,test.t2.a 2
+1 PRIMARY ref key0 key0 10 test.t2.a,test.t2.a 1
2 DERIVED t1 ALL NULL NULL NULL NULL 20 Using where; Using temporary; Using filesort
explain format=json select * from v1,t2 where (v1.a=v1.b) and (v1.a=t2.a);
EXPLAIN
@@ -1960,7 +1960,7 @@ EXPLAIN
"used_key_parts": ["a", "b"],
"ref": ["test.t2.a", "test.t2.a"],
"loops": 9,
- "rows": 2,
+ "rows": 1,
"cost": "COST_REPLACED",
"filtered": 100,
"materialized": {
@@ -2993,7 +2993,7 @@ where t1.a>5 group by a,b having max_c < 707) v1,
t2 where (v1.a=t2.a) and (v1.max_c>300) and (v1.a=v1.b);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 9 Using where
-1 PRIMARY ref key0 key0 10 test.t2.a,test.t2.a 2 Using where
+1 PRIMARY ref key0 key0 10 test.t2.a,test.t2.a 1 Using where
2 DERIVED t1 ALL NULL NULL NULL NULL 20 Using where; Using temporary; Using filesort
explain format=json select * from
(select a, b, max(c) as max_c, avg(c) as avg_c from t1
@@ -3026,7 +3026,7 @@ EXPLAIN
"used_key_parts": ["a", "b"],
"ref": ["test.t2.a", "test.t2.a"],
"loops": 9,
- "rows": 2,
+ "rows": 1,
"cost": "COST_REPLACED",
"filtered": 100,
"attached_condition": "v1.max_c > 300",
@@ -3155,7 +3155,7 @@ a b max_c avg_c a b c d
explain select * from v1,t2 where (v1.a=t2.a) and (v1.b=t2.b);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 9 Using where
-1 PRIMARY ref key0 key0 10 test.t2.a,test.t2.b 2
+1 PRIMARY ref key0 key0 10 test.t2.a,test.t2.b 1
2 DERIVED t1 ALL NULL NULL NULL NULL 20 Using temporary; Using filesort
explain format=json select * from v1,t2 where (v1.a=t2.a) and (v1.b=t2.b);
EXPLAIN
@@ -3185,7 +3185,7 @@ EXPLAIN
"used_key_parts": ["a", "b"],
"ref": ["test.t2.a", "test.t2.b"],
"loops": 9,
- "rows": 2,
+ "rows": 1,
"cost": "COST_REPLACED",
"filtered": 100,
"materialized": {
@@ -4041,7 +4041,7 @@ explain select * from v1,v2,t2 where
(v1.a=t2.a) and (v1.a=v1.b) and (v1.a=v2.a) and (v2.max_c<300);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 9 Using where
-1 PRIMARY ref key1 key1 10 test.t2.a,test.t2.a 2
+1 PRIMARY ref key1 key1 10 test.t2.a,test.t2.a 1
1 PRIMARY ref key0 key0 5 test.t2.a 2 Using where
3 DERIVED t1 ALL NULL NULL NULL NULL 20 Using where; Using temporary; Using filesort
2 DERIVED t1 ALL NULL NULL NULL NULL 20 Using where; Using temporary; Using filesort
@@ -4074,7 +4074,7 @@ EXPLAIN
"used_key_parts": ["a", "b"],
"ref": ["test.t2.a", "test.t2.a"],
"loops": 9,
- "rows": 2,
+ "rows": 1,
"cost": "COST_REPLACED",
"filtered": 100,
"materialized": {
@@ -4113,7 +4113,7 @@ EXPLAIN
"key_length": "5",
"used_key_parts": ["a"],
"ref": ["test.t2.a"],
- "loops": 18,
+ "loops": 9,
"rows": 2,
"cost": "COST_REPLACED",
"filtered": 100,
@@ -8165,8 +8165,8 @@ a b min_c a b max_c avg_c
explain select * from v4,v2 where
(v4.a=v2.b) and (v4.a=v4.b) and (v4.min_c<100);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY ALL NULL NULL NULL NULL 20 Using where
-1 PRIMARY ref key0 key0 5 v4.a 2
+1 PRIMARY ALL NULL NULL NULL NULL 20 Using where
+1 PRIMARY ref key0 key0 10 v2.b,v2.b 1 Using where
4 DERIVED t1 ALL NULL NULL NULL NULL 20 Using where; Using temporary; Using filesort
2 DERIVED ALL NULL NULL NULL NULL 20 Using where; Using temporary; Using filesort
3 DERIVED t1 ALL NULL NULL NULL NULL 20 Using where; Using temporary; Using filesort
@@ -8180,56 +8180,31 @@ EXPLAIN
"nested_loop": [
{
"table": {
- "table_name": "",
+ "table_name": "",
"access_type": "ALL",
"loops": 1,
"rows": 20,
"cost": "COST_REPLACED",
"filtered": 100,
- "attached_condition": "v4.b = v4.a and v4.min_c < 100 and v4.a is not null",
+ "attached_condition": "v2.b is not null and v2.b is not null",
"materialized": {
"query_block": {
- "select_id": 2,
+ "select_id": 4,
"cost": "COST_REPLACED",
- "having_condition": "min_c < 100",
+ "having_condition": "max_c < 707",
"filesort": {
- "sort_key": "v1.a, v1.b",
+ "sort_key": "t1.a, t1.b",
"temporary_table": {
"nested_loop": [
{
"table": {
- "table_name": "",
+ "table_name": "t1",
"access_type": "ALL",
"loops": 1,
"rows": 20,
"cost": "COST_REPLACED",
"filtered": 100,
- "attached_condition": "v1.b = v1.a and v1.a < 15",
- "materialized": {
- "query_block": {
- "select_id": 3,
- "cost": "COST_REPLACED",
- "having_condition": "max_c < 707",
- "filesort": {
- "sort_key": "t1.a, t1.b",
- "temporary_table": {
- "nested_loop": [
- {
- "table": {
- "table_name": "t1",
- "access_type": "ALL",
- "loops": 1,
- "rows": 20,
- "cost": "COST_REPLACED",
- "filtered": 100,
- "attached_condition": "t1.b = t1.a and t1.a < 15"
- }
- }
- ]
- }
- }
- }
- }
+ "attached_condition": "t1.a > 5"
}
}
]
@@ -8241,35 +8216,61 @@ EXPLAIN
},
{
"table": {
- "table_name": "",
+ "table_name": "",
"access_type": "ref",
"possible_keys": ["key0"],
"key": "key0",
- "key_length": "5",
- "used_key_parts": ["b"],
- "ref": ["v4.a"],
+ "key_length": "10",
+ "used_key_parts": ["a", "b"],
+ "ref": ["v2.b", "v2.b"],
"loops": 20,
- "rows": 2,
+ "rows": 1,
"cost": "COST_REPLACED",
"filtered": 100,
+ "attached_condition": "v4.min_c < 100",
"materialized": {
"query_block": {
- "select_id": 4,
+ "select_id": 2,
"cost": "COST_REPLACED",
- "having_condition": "max_c < 707",
+ "having_condition": "min_c < 100",
"filesort": {
- "sort_key": "t1.a, t1.b",
+ "sort_key": "v1.a, v1.b",
"temporary_table": {
"nested_loop": [
{
"table": {
- "table_name": "t1",
+ "table_name": "",
"access_type": "ALL",
"loops": 1,
"rows": 20,
"cost": "COST_REPLACED",
"filtered": 100,
- "attached_condition": "t1.a > 5"
+ "attached_condition": "v1.b = v1.a and v1.a < 15",
+ "materialized": {
+ "query_block": {
+ "select_id": 3,
+ "cost": "COST_REPLACED",
+ "having_condition": "max_c < 707",
+ "filesort": {
+ "sort_key": "t1.a, t1.b",
+ "temporary_table": {
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "loops": 1,
+ "rows": 20,
+ "cost": "COST_REPLACED",
+ "filtered": 100,
+ "attached_condition": "t1.b = t1.a and t1.a < 15"
+ }
+ }
+ ]
+ }
+ }
+ }
+ }
}
}
]
@@ -8296,8 +8297,8 @@ a b min_c a b max_c avg_c
explain select * from v4,v2 where
(v4.a=v2.b) and (v4.a=v4.b) and (v2.b<30);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY ALL NULL NULL NULL NULL 20 Using where
-1 PRIMARY ref key0 key0 5 v4.a 2
+1 PRIMARY ALL NULL NULL NULL NULL 20 Using where
+1 PRIMARY ref key0 key0 10 v2.b,v2.b 1
4 DERIVED t1 ALL NULL NULL NULL NULL 20 Using where; Using temporary; Using filesort
2 DERIVED ALL NULL NULL NULL NULL 20 Using where; Using temporary; Using filesort
3 DERIVED t1 ALL NULL NULL NULL NULL 20 Using where; Using temporary; Using filesort
@@ -8311,55 +8312,31 @@ EXPLAIN
"nested_loop": [
{
"table": {
- "table_name": "",
+ "table_name": "",
"access_type": "ALL",
"loops": 1,
"rows": 20,
"cost": "COST_REPLACED",
"filtered": 100,
- "attached_condition": "v4.b = v4.a and v4.a < 30 and v4.a is not null",
+ "attached_condition": "v2.b < 30 and v2.b is not null and v2.b is not null",
"materialized": {
"query_block": {
- "select_id": 2,
+ "select_id": 4,
"cost": "COST_REPLACED",
+ "having_condition": "max_c < 707",
"filesort": {
- "sort_key": "v1.a, v1.b",
+ "sort_key": "t1.a, t1.b",
"temporary_table": {
"nested_loop": [
{
"table": {
- "table_name": "",
+ "table_name": "t1",
"access_type": "ALL",
"loops": 1,
"rows": 20,
"cost": "COST_REPLACED",
"filtered": 100,
- "attached_condition": "v1.b = v1.a and v1.a < 15 and v1.a < 30",
- "materialized": {
- "query_block": {
- "select_id": 3,
- "cost": "COST_REPLACED",
- "having_condition": "max_c < 707",
- "filesort": {
- "sort_key": "t1.a, t1.b",
- "temporary_table": {
- "nested_loop": [
- {
- "table": {
- "table_name": "t1",
- "access_type": "ALL",
- "loops": 1,
- "rows": 20,
- "cost": "COST_REPLACED",
- "filtered": 100,
- "attached_condition": "t1.b = t1.a and t1.a < 15 and t1.a < 30"
- }
- }
- ]
- }
- }
- }
- }
+ "attached_condition": "t1.a > 5 and t1.b < 30"
}
}
]
@@ -8371,35 +8348,59 @@ EXPLAIN
},
{
"table": {
- "table_name": "",
+ "table_name": "",
"access_type": "ref",
"possible_keys": ["key0"],
"key": "key0",
- "key_length": "5",
- "used_key_parts": ["b"],
- "ref": ["v4.a"],
+ "key_length": "10",
+ "used_key_parts": ["a", "b"],
+ "ref": ["v2.b", "v2.b"],
"loops": 20,
- "rows": 2,
+ "rows": 1,
"cost": "COST_REPLACED",
"filtered": 100,
"materialized": {
"query_block": {
- "select_id": 4,
+ "select_id": 2,
"cost": "COST_REPLACED",
- "having_condition": "max_c < 707",
"filesort": {
- "sort_key": "t1.a, t1.b",
+ "sort_key": "v1.a, v1.b",
"temporary_table": {
"nested_loop": [
{
"table": {
- "table_name": "t1",
+ "table_name": "",
"access_type": "ALL",
"loops": 1,
"rows": 20,
"cost": "COST_REPLACED",
"filtered": 100,
- "attached_condition": "t1.a > 5 and t1.b < 30"
+ "attached_condition": "v1.b = v1.a and v1.a < 15 and v1.a < 30",
+ "materialized": {
+ "query_block": {
+ "select_id": 3,
+ "cost": "COST_REPLACED",
+ "having_condition": "max_c < 707",
+ "filesort": {
+ "sort_key": "t1.a, t1.b",
+ "temporary_table": {
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "loops": 1,
+ "rows": 20,
+ "cost": "COST_REPLACED",
+ "filtered": 100,
+ "attached_condition": "t1.b = t1.a and t1.a < 15 and t1.a < 30"
+ }
+ }
+ ]
+ }
+ }
+ }
+ }
}
}
]
@@ -8426,8 +8427,8 @@ a b min_c a b max_c avg_c
explain select * from v4,v2 where
(v4.a=v2.b) and (v4.a=v4.b) and ((v2.b<30) or (v4.a>2));
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY ALL NULL NULL NULL NULL 20 Using where
-1 PRIMARY ref key0 key0 5 v4.a 2
+1 PRIMARY ALL NULL NULL NULL NULL 20 Using where
+1 PRIMARY ref key0 key0 10 v2.b,v2.b 1
4 DERIVED t1 ALL NULL NULL NULL NULL 20 Using where; Using temporary; Using filesort
2 DERIVED ALL NULL NULL NULL NULL 20 Using where; Using temporary; Using filesort
3 DERIVED t1 ALL NULL NULL NULL NULL 20 Using where; Using temporary; Using filesort
@@ -8441,55 +8442,31 @@ EXPLAIN
"nested_loop": [
{
"table": {
- "table_name": "",
+ "table_name": "",
"access_type": "ALL",
"loops": 1,
"rows": 20,
"cost": "COST_REPLACED",
"filtered": 100,
- "attached_condition": "v4.b = v4.a and (v4.a < 30 or v4.a > 2) and v4.a is not null",
+ "attached_condition": "(v2.b < 30 or v2.b > 2) and v2.b is not null and v2.b is not null",
"materialized": {
"query_block": {
- "select_id": 2,
+ "select_id": 4,
"cost": "COST_REPLACED",
+ "having_condition": "max_c < 707",
"filesort": {
- "sort_key": "v1.a, v1.b",
+ "sort_key": "t1.a, t1.b",
"temporary_table": {
"nested_loop": [
{
"table": {
- "table_name": "",
+ "table_name": "t1",
"access_type": "ALL",
"loops": 1,
"rows": 20,
"cost": "COST_REPLACED",
"filtered": 100,
- "attached_condition": "v1.b = v1.a and v1.a < 15 and (v1.a < 30 or v1.a > 2)",
- "materialized": {
- "query_block": {
- "select_id": 3,
- "cost": "COST_REPLACED",
- "having_condition": "max_c < 707",
- "filesort": {
- "sort_key": "t1.a, t1.b",
- "temporary_table": {
- "nested_loop": [
- {
- "table": {
- "table_name": "t1",
- "access_type": "ALL",
- "loops": 1,
- "rows": 20,
- "cost": "COST_REPLACED",
- "filtered": 100,
- "attached_condition": "t1.b = t1.a and t1.a < 15 and (t1.a < 30 or t1.a > 2)"
- }
- }
- ]
- }
- }
- }
- }
+ "attached_condition": "t1.a > 5 and (t1.b < 30 or t1.b > 2)"
}
}
]
@@ -8501,35 +8478,59 @@ EXPLAIN
},
{
"table": {
- "table_name": "",
+ "table_name": "",
"access_type": "ref",
"possible_keys": ["key0"],
"key": "key0",
- "key_length": "5",
- "used_key_parts": ["b"],
- "ref": ["v4.a"],
+ "key_length": "10",
+ "used_key_parts": ["a", "b"],
+ "ref": ["v2.b", "v2.b"],
"loops": 20,
- "rows": 2,
+ "rows": 1,
"cost": "COST_REPLACED",
"filtered": 100,
"materialized": {
"query_block": {
- "select_id": 4,
+ "select_id": 2,
"cost": "COST_REPLACED",
- "having_condition": "max_c < 707",
"filesort": {
- "sort_key": "t1.a, t1.b",
+ "sort_key": "v1.a, v1.b",
"temporary_table": {
"nested_loop": [
{
"table": {
- "table_name": "t1",
+ "table_name": "",
"access_type": "ALL",
"loops": 1,
"rows": 20,
"cost": "COST_REPLACED",
"filtered": 100,
- "attached_condition": "t1.a > 5 and (t1.b < 30 or t1.b > 2)"
+ "attached_condition": "v1.b = v1.a and v1.a < 15 and (v1.a < 30 or v1.a > 2)",
+ "materialized": {
+ "query_block": {
+ "select_id": 3,
+ "cost": "COST_REPLACED",
+ "having_condition": "max_c < 707",
+ "filesort": {
+ "sort_key": "t1.a, t1.b",
+ "temporary_table": {
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "loops": 1,
+ "rows": 20,
+ "cost": "COST_REPLACED",
+ "filtered": 100,
+ "attached_condition": "t1.b = t1.a and t1.a < 15 and (t1.a < 30 or t1.a > 2)"
+ }
+ }
+ ]
+ }
+ }
+ }
+ }
}
}
]
@@ -20148,7 +20149,7 @@ where t2.b < 40 and t2.a=t3.a and t3.c=t.c;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 90 60.00 Using where
1 PRIMARY t3 ref idx_a idx_a 5 test.t2.a 1 100.00 Using where
-1 PRIMARY ref key0 key0 128 test.t3.c 5 100.00
+1 PRIMARY ref key0 key0 128 test.t3.c 1 100.00
2 DERIVED t4 ALL idx_c NULL NULL NULL 160 100.00 Using temporary; Using filesort
Warnings:
Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c`,`t`.`c` AS `t_c`,`t`.`max` AS `max`,`t`.`min` AS `min` from `test`.`t2` join `test`.`t3` join (/* select#2 */ select `test`.`t4`.`c` AS `c`,max(`test`.`t4`.`b`) AS `max`,min(`test`.`t4`.`b`) AS `min` from `test`.`t4` group by `test`.`t4`.`c`) `t` where `test`.`t3`.`a` = `test`.`t2`.`a` and `t`.`c` = `test`.`t3`.`c` and `test`.`t2`.`b` < 40
@@ -20198,7 +20199,7 @@ EXPLAIN
"used_key_parts": ["c"],
"ref": ["test.t3.c"],
"loops": 80.99999987,
- "rows": 5,
+ "rows": 1,
"cost": "COST_REPLACED",
"filtered": 100,
"materialized": {
@@ -21318,7 +21319,7 @@ id a
explain extended select id, a from t1 where id in (select id from v1);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL PRIMARY NULL NULL NULL 20 100.00
-1 PRIMARY ref key0 key0 4 test.t1.id 2 50.00 FirstMatch(t1)
+1 PRIMARY ref key0 key0 4 test.t1.id 1 100.00 FirstMatch(t1)
3 DERIVED t1 ALL PRIMARY NULL NULL NULL 20 100.00 Using temporary; Using filesort
3 DERIVED t2 ref ro_id ro_id 4 test.t1.id 1 100.00 Using where
Warnings:
@@ -21356,7 +21357,7 @@ on (t1.id = t2.ro_id AND t2.flag = 1)
group by t1.id) dt);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL PRIMARY NULL NULL NULL 20 100.00
-1 PRIMARY ref key1,distinct_key key1 4 test.t1.id 2 50.00 FirstMatch(t1)
+1 PRIMARY ref key1,distinct_key key1 4 test.t1.id 1 100.00 FirstMatch(t1)
3 DERIVED t1 ALL PRIMARY NULL NULL NULL 20 100.00 Using temporary; Using filesort
3 DERIVED t2 ref ro_id ro_id 4 test.t1.id 1 100.00 Using where
Warnings:
@@ -22025,7 +22026,7 @@ WHERE t1.id BETWEEN 200 AND 100000;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t3 range t1_id t1_id 5 NULL 47 Using where; Using index
1 PRIMARY t1 eq_ref PRIMARY PRIMARY 4 test.t3.t1_id 1 Using index
-1 PRIMARY ref key0 key0 5 test.t3.t1_id 10
+1 PRIMARY ref key0 key0 5 test.t3.t1_id 1
2 DERIVED t2 ALL t1_id NULL NULL NULL 2408 Using where; Using temporary; Using filesort
set optimizer_switch='split_materialized=default';
DROP TABLE t1,t2,t3;
@@ -22302,7 +22303,7 @@ from_agg_items.ledger_id = charges.from_ledger_id
WHERE charges.to_ledger_id = 2;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY charges ref PRIMARY,fk_charge_from_ledger,fk_charge_to_ledger fk_charge_to_ledger 8 const 8
-1 PRIMARY ref key0 key0 17 test.charges.from_ledger_id,test.charges.id 4
+1 PRIMARY ref key0 key0 17 test.charges.from_ledger_id,test.charges.id 1
2 DERIVED transaction_items ALL fk_items_transaction NULL NULL NULL 40 Using temporary; Using filesort
2 DERIVED transactions eq_ref PRIMARY PRIMARY 8 test.transaction_items.transaction_id 1
INSERT INTO charges (id, from_ledger_id, to_ledger_id, amount) VALUES
@@ -22507,7 +22508,7 @@ from_agg_items.ledger_id = charges.from_ledger_id
WHERE charges.to_ledger_id = 2;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY charges ref fk_charge_to_ledger fk_charge_to_ledger 8 const 10
-1 PRIMARY ref key0 key0 18 test.charges.from_ledger_id,test.charges.id 4
+1 PRIMARY ref key0 key0 18 test.charges.from_ledger_id,test.charges.id 1
2 DERIVED transaction_items ALL fk_items_transaction NULL NULL NULL 40 Using temporary; Using filesort
2 DERIVED transactions eq_ref PRIMARY PRIMARY 8 test.transaction_items.transaction_id 1
set optimizer_switch='split_materialized=default';
@@ -22845,6 +22846,8 @@ INSERT INTO t1 VALUES
(95,3290880,487,'2021-02-15 18:59:35'),(96,3290798,0,'2021-02-15 18:59:52'),
(97,3290777,983,'2021-02-15 19:00:10'),(98,3290811,488,'2021-02-15 19:00:10'),
(99,3290917,1283,'2021-02-15 19:00:36'),(100,3290858,482,'2021-02-15 19:00:42');
+insert into t1 select seq, 3300000+seq, 100+seq, '2021-02-09 18:31:35'
+from seq_101_to_1000;
CREATE TABLE t2 (a int) ENGINE=MYISAM;
INSERT INTO t2 VALUES
(3289475),(3289496),(3289562),(3289593),(3289594),(3289595),(3289626),
@@ -22853,7 +22856,7 @@ INSERT INTO t2 VALUES
ANALYZE TABLE t1,t2;
Table Op Msg_type Msg_text
test.t1 analyze status Engine-independent statistics collected
-test.t1 analyze status Table is already up to date
+test.t1 analyze status OK
test.t2 analyze status Engine-independent statistics collected
test.t2 analyze status OK
EXPLAIN SELECT t1.valdouble, t1.valint1
@@ -22865,9 +22868,9 @@ t1.valdate = dt.maxdate AND
t1.valint1 IN (SELECT * FROM t2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 21 Using where; Start temporary
-1 PRIMARY t1 ref valint1,valint1_2 valint1 5 test.t2.a 2 Using index condition; Using where; End temporary
+1 PRIMARY t1 ref valint1,valint1_2 valint1 5 test.t2.a 1 Using index condition; Using where; End temporary
1 PRIMARY ref key0 key0 11 test.t1.valdate,test.t1.valint1 1
-2 LATERAL DERIVED t ref valint1,valint1_2 valint1 5 test.t2.a 2 Using index condition
+2 LATERAL DERIVED t ref valint1,valint1_2 valint1 5 test.t2.a 1 Using index condition
SELECT t1.valdouble, t1.valint1
FROM t1,
(SELECT max(t.valdate) AS maxdate, t.valint1 FROM t1 t GROUP BY t.valint1)
@@ -23629,6 +23632,113 @@ a
drop table t;
# End of 10.5 tests
#
+# MDEV-38487: Prevent aggregate functions cloning when pushing HAVING into WHERE
+#
+CREATE TABLE t (a INT, b INT);
+INSERT INTO t VALUES (1, 10), (1, 20), (2, 50), (3, 100);
+explain format=JSON SELECT * FROM (SELECT a, MAX(b) as max_b FROM t GROUP BY a) as dt WHERE dt.max_b > 25;
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "cost": 0.010178738,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "",
+ "access_type": "ALL",
+ "loops": 1,
+ "rows": 4,
+ "cost": 0.010178738,
+ "filtered": 100,
+ "attached_condition": "dt.max_b > 25",
+ "materialized": {
+ "query_block": {
+ "select_id": 2,
+ "cost": 0.013196268,
+ "having_condition": "max_b > 25",
+ "filesort": {
+ "sort_key": "t.a",
+ "temporary_table": {
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "t",
+ "access_type": "ALL",
+ "loops": 1,
+ "rows": 4,
+ "cost": 0.01066122,
+ "filtered": 100
+ }
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ ]
+ }
+}
+SELECT * FROM (SELECT a, MAX(b) as max_b FROM t GROUP BY a) as dt WHERE dt.max_b > 25;
+a max_b
+2 50
+3 100
+CREATE VIEW v AS SELECT a, MAX(b) as max_b FROM t GROUP BY a;
+explain format=JSON SELECT * FROM v where max_b > 25;
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "cost": 0.010178738,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "",
+ "access_type": "ALL",
+ "loops": 1,
+ "rows": 4,
+ "cost": 0.010178738,
+ "filtered": 100,
+ "attached_condition": "v.max_b > 25",
+ "materialized": {
+ "query_block": {
+ "select_id": 2,
+ "cost": 0.013196268,
+ "having_condition": "max_b > 25",
+ "filesort": {
+ "sort_key": "t.a",
+ "temporary_table": {
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "t",
+ "access_type": "ALL",
+ "loops": 1,
+ "rows": 4,
+ "cost": 0.01066122,
+ "filtered": 100
+ }
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ ]
+ }
+}
+SELECT * FROM v where max_b > 25;
+a max_b
+2 50
+3 100
+DROP VIEW v;
+DROP TABLE t;
+# End of 10.6 tests
+#
# MDEV-28958: condition pushable into view after simplification
# contains constant TRUE/FALSE as subformula
#
@@ -23645,3 +23755,14 @@ a b
drop view v1,v2;
drop table t1,t2;
# End of 10.7 tests
+#
+# MDEV-36686: Crash with DEFAULT() in WHERE clause with nested views
+#
+create table t1 (a varchar(128));
+create view v1 as select a, count(*) from t1 group by a;
+create view v2 as select * from v1;
+select * from v2 where greatest(a, default(a));
+a count(*)
+drop view v2, v1;
+drop table t1;
+# End of 10.11 tests
diff --git a/mysql-test/main/derived_cond_pushdown.test b/mysql-test/main/derived_cond_pushdown.test
index 45840e710a313..0714dab783361 100644
--- a/mysql-test/main/derived_cond_pushdown.test
+++ b/mysql-test/main/derived_cond_pushdown.test
@@ -4280,6 +4280,9 @@ INSERT INTO t1 VALUES
(97,3290777,983,'2021-02-15 19:00:10'),(98,3290811,488,'2021-02-15 19:00:10'),
(99,3290917,1283,'2021-02-15 19:00:36'),(100,3290858,482,'2021-02-15 19:00:42');
+insert into t1 select seq, 3300000+seq, 100+seq, '2021-02-09 18:31:35'
+from seq_101_to_1000;
+
CREATE TABLE t2 (a int) ENGINE=MYISAM;
INSERT INTO t2 VALUES
(3289475),(3289496),(3289562),(3289593),(3289594),(3289595),(3289626),
@@ -4495,6 +4498,28 @@ drop table t;
--echo # End of 10.5 tests
+--echo #
+--echo # MDEV-38487: Prevent aggregate functions cloning when pushing HAVING into WHERE
+--echo #
+
+CREATE TABLE t (a INT, b INT);
+INSERT INTO t VALUES (1, 10), (1, 20), (2, 50), (3, 100);
+
+# outer where to inner having pushdown
+let $q= SELECT * FROM (SELECT a, MAX(b) as max_b FROM t GROUP BY a) as dt WHERE dt.max_b > 25;
+eval explain format=JSON $q;
+eval $q;
+
+CREATE VIEW v AS SELECT a, MAX(b) as max_b FROM t GROUP BY a;
+let $q= SELECT * FROM v where max_b > 25;
+eval explain format=JSON $q;
+eval $q;
+
+DROP VIEW v;
+DROP TABLE t;
+
+--echo # End of 10.6 tests
+
--echo #
--echo # MDEV-28958: condition pushable into view after simplification
--echo # contains constant TRUE/FALSE as subformula
@@ -4515,3 +4540,18 @@ drop view v1,v2;
drop table t1,t2;
--echo # End of 10.7 tests
+
+--echo #
+--echo # MDEV-36686: Crash with DEFAULT() in WHERE clause with nested views
+--echo #
+
+create table t1 (a varchar(128));
+create view v1 as select a, count(*) from t1 group by a;
+create view v2 as select * from v1;
+
+select * from v2 where greatest(a, default(a));
+
+drop view v2, v1;
+drop table t1;
+
+--echo # End of 10.11 tests
diff --git a/mysql-test/main/derived_opt.result b/mysql-test/main/derived_opt.result
index 446de335131de..984c8070870d0 100644
--- a/mysql-test/main/derived_opt.result
+++ b/mysql-test/main/derived_opt.result
@@ -566,4 +566,501 @@ DROP TABLE t1, t2;
#
# End of 10.3 tests
#
+#
+# MDEV-36321 keys generated on derived tables produce wrong out_rows estimates
+#
+create table t1 (
+grp_id int,
+value int,
+index (grp_id)
+);
+insert into t1 select
+A.seq, B.seq
+from
+seq_1_to_100 A,
+seq_1_to_100 B;
+create table t2 (a int);
+insert into t2 select seq from seq_1_to_5;
+create table t3 (b int);
+insert into t3 select seq from seq_1_to_5;
+analyze table t1,t2;
+Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
+test.t1 analyze status Table is already up to date
+test.t2 analyze status Engine-independent statistics collected
+test.t2 analyze status OK
+SET optimizer_trace='enabled=on';
+SET optimizer_trace_max_mem_size=10485760;
+select * from
+t2,
+(select max(value), grp_id from t1 group by grp_id) DT
+where
+t2.a= DT.grp_id;
+a max(value) grp_id
+1 100 1
+2 100 2
+3 100 3
+4 100 4
+5 100 5
+select
+json_detailed(json_extract(trace, '$**.infer_derived_key_statistics')) as t
+from information_schema.optimizer_trace;
+t
+[
+ {
+ "table_alias": "DT",
+ "key_name": "key0",
+ "key_parts": 1,
+ "select":
+ ["group_list_in_key"],
+ "rec_per_key_estimate": 1
+ }
+]
+# Same as above, but try a UNION:
+select * from
+t2,
+(select max(value), grp_id from t1 group by grp_id
+union all
+select max(value), grp_id from t1 group by grp_id) DT
+where
+t2.a= DT.grp_id;
+a max(value) grp_id
+1 100 1
+1 100 1
+2 100 2
+2 100 2
+3 100 3
+3 100 3
+4 100 4
+4 100 4
+5 100 5
+5 100 5
+select
+json_detailed(json_extract(trace, '$**.infer_derived_key_statistics')) as t
+from information_schema.optimizer_trace;
+t
+[
+ {
+ "table_alias": "DT",
+ "key_name": "key0",
+ "key_parts": 1,
+ "select":
+ [
+ "group_list_in_key",
+ "group_list_in_key"
+ ],
+ "rec_per_key_estimate": 2
+ }
+]
+# Same as the previous query but unhandled group by expression
+explain
+select * from
+t2,
+(select max(value), grp_id from t1 group by grp_id
+union all
+select max(value), grp_id from t1 group by MOD(grp_id,2)) DT
+where
+t2.a= DT.grp_id;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t2 ALL NULL NULL NULL NULL 5 Using where
+1 PRIMARY ref key0 key0 5 test.t2.a 101
+2 DERIVED t1 ALL NULL NULL NULL NULL 10000 Using temporary; Using filesort
+3 UNION t1 ALL NULL NULL NULL NULL 10000 Using temporary; Using filesort
+select
+json_detailed(json_extract(trace, '$**.infer_derived_key_statistics')) as t
+from information_schema.optimizer_trace;
+t
+[
+ {
+ "table_alias": "DT",
+ "key_name": "key0",
+ "key_parts": 1,
+ "select":
+ [
+ "group_list_in_key",
+ "unhandled query"
+ ]
+ }
+]
+# view/cte/derived merged inside our derived table
+create view v1 as select * from t1;
+explain
+select * from
+t2,
+(select grp_id, max(value) as maxval from v1 group by grp_id) DT
+where
+t2.a= DT.grp_id;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t2 ALL NULL NULL NULL NULL 5 Using where
+1 PRIMARY ref key0 key0 5 test.t2.a 1
+2 DERIVED t1 ALL grp_id NULL NULL NULL 10000 Using temporary; Using filesort
+drop view v1;
+explain
+with cte1 as (select * from t1)
+select * from
+t2,
+(select grp_id, max(value) as maxval from cte1 group by grp_id) DT
+where
+t2.a= DT.grp_id;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t2 ALL NULL NULL NULL NULL 5 Using where
+1 PRIMARY ref key0 key0 5 test.t2.a 1
+3 DERIVED t1 ALL grp_id NULL NULL NULL 10000 Using temporary; Using filesort
+explain
+select * from
+t2,
+(
+select grp_id, max(value) as maxval from
+(
+select * from t1, t3
+where t1.grp_id = t3.b
+) dt1
+group by grp_id
+) DT
+where
+t2.a= DT.grp_id;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t2 ALL NULL NULL NULL NULL 5 Using where
+1 PRIMARY ref key0 key0 5 test.t2.a 1
+2 DERIVED t3 ALL NULL NULL NULL NULL 5 Using where; Using temporary; Using filesort
+2 DERIVED t1 ref grp_id grp_id 5 test.t3.b 100
+# Example with equalities on GROUP BY columns and other columns
+# Must produce {table=, ref=test.t2.col2,test.t2.a, rows=1}
+alter table t2 add col2 int;
+explain
+select * from
+t2,
+(select max(value) as maxval, grp_id from t1 group by grp_id) DT
+where
+t2.col2=maxval and
+t2.a= DT.grp_id;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t2 ALL NULL NULL NULL NULL 5 Using where
+1 PRIMARY ref key0 key0 10 test.t2.col2,test.t2.a 1
+2 DERIVED t1 ALL grp_id NULL NULL NULL 10000 Using temporary; Using filesort
+select
+json_detailed(json_extract(trace, '$**.infer_derived_key_statistics')) as t
+from information_schema.optimizer_trace;
+t
+[
+ {
+ "table_alias": "DT",
+ "key_name": "key0",
+ "key_parts": 2,
+ "select":
+ ["group_list_in_key"],
+ "rec_per_key_estimate": 1
+ }
+]
+explain
+select * from
+t2,
+(select grp_id, max(value) as maxval from t1 group by grp_id) DT
+where
+t2.col2=maxval and
+t2.a= DT.grp_id;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t2 ALL NULL NULL NULL NULL 5 Using where
+1 PRIMARY ref key0 key0 10 test.t2.a,test.t2.col2 1
+2 DERIVED t1 ALL grp_id NULL NULL NULL 10000 Using temporary; Using filesort
+delete from t1;
+insert into t1 select 1, a.seq from seq_1_to_10 a;
+analyze table t1;
+Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
+test.t1 analyze status Table is already up to date
+explain
+select * from
+t2,
+(select distinct grp_id from t1
+union all
+select distinct value from t1) DT
+where
+t2.a= DT.grp_id;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t2 ALL NULL NULL NULL NULL 5 Using where
+1 PRIMARY ref key0 key0 5 test.t2.a 2
+2 DERIVED t1 range NULL grp_id 5 NULL 2 Using index for group-by
+3 UNION t1 ALL NULL NULL NULL NULL 10 Using temporary
+select
+json_detailed(json_extract(trace, '$**.infer_derived_key_statistics')) as t
+from information_schema.optimizer_trace;
+t
+[
+ {
+ "table_alias": "DT",
+ "key_name": "key0",
+ "key_parts": 1,
+ "select":
+ [
+ "distinct_in_query_block",
+ "distinct_in_query_block"
+ ],
+ "rec_per_key_estimate": 2
+ }
+]
+drop table t1, t2;
+create table t1
+(
+a int not null,
+b int,
+c int,
+d int,
+amount decimal,
+key t1_ix1 (a,b)
+);
+# More complex examples
+insert into t1 values (0, NULL, 0, NULL, 10.0000), (1, 1, 1, 1, 10.0000),
+(2, 2, 2, 2, 20.0000), (3, 3, 3, 3, 30.0000), (4, 4, 4, 4, 40.0000),
+(5, 5, 5, 5, NULL), (6, 6, 6, 6, NULL), (7, 7, 7, 7, 70.0000),
+(8, 8, 8, 8, 80.0000);
+create table t2
+(
+a int NOT NULL,
+b int,
+name varchar(50),
+key t2_ix1 (a,b)
+) engine = innodb;
+insert into t2 values (0, NULL, 'a'), (1, NULL, 'A'), (2, 2, 'B'), (3,3, 'C'),
+(4,4, 'D'), (5,5, NULL), (6,6, NULL), (7,7, 'E'), (8,8, 'F'), (9,9, 'G'),
+(10,10,'H'), (11,11, NULL), (12,12, NULL);
+drop table t3;
+create table t3
+(
+a int not null,
+b int,
+description varchar(50),
+key t3_ix1 (a,b)
+) engine = innodb;
+insert into t3 values (1, 1, 'bar'),(2,2,'buz'), (3,3, 'silver');
+insert into t3 select seq, seq, 'junk' from seq_3_to_13;
+create table t4
+(
+c int not null,
+d int,
+descr varchar(50),
+key t4_ix1 (c,d)
+) engine = innodb;
+insert into t4 values (1, 1, 'iron'), (2,2,'aluminium'), (3,3, 'silver');
+insert into t4 select seq, seq, 'junk' from seq_3_to_13;
+# split materialized
+explain
+select * from t1
+join t2 on t1.a = t2.a and t1.b = t2.b
+join
+(
+select a, b, description from t3 group by a, b
+) dt on dt.a = t1.a and dt.b = t1.b and dt.b = t2.b
+where dt.a < 1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 range t1_ix1 t1_ix1 4 NULL 1 Using index condition
+1 PRIMARY t2 ref t2_ix1 t2_ix1 9 test.t1.a,test.t1.b 1
+1 PRIMARY ref key0 key0 9 test.t1.a,test.t1.b 1
+2 LATERAL DERIVED t3 ref t3_ix1 t3_ix1 9 test.t1.a,test.t1.b 1 Using index condition
+select
+json_detailed(json_extract(trace, '$**.infer_derived_key_statistics')) as t
+from information_schema.optimizer_trace;
+t
+[
+ {
+ "table_alias": "dt",
+ "key_name": "key0",
+ "key_parts": 2,
+ "select":
+ ["group_list_in_key"],
+ "rec_per_key_estimate": 1
+ },
+ {
+ "table_alias": "dt",
+ "key_name": "key1",
+ "key_parts": 2,
+ "select":
+ ["group_list_in_key"],
+ "rec_per_key_estimate": 1
+ }
+]
+# union with distinct rows
+explain
+select * from t1
+join t2 on t1.a = t2.a and t1.b = t2.b
+join
+(
+select a, b, description from t3 group by a, b
+union
+select c, d, descr from t4 group by c, d
+) dt on dt.a = t1.a and dt.b = t1.b and dt.b = t2.b
+where dt.a < 1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 range t1_ix1 t1_ix1 4 NULL 1 Using index condition
+1 PRIMARY t2 ref t2_ix1 t2_ix1 9 test.t1.a,test.t1.b 1
+1 PRIMARY ref key1,distinct_key key1 9 test.t1.a,test.t1.b 2
+2 DERIVED t3 range t3_ix1 t3_ix1 4 NULL 1 Using index condition
+3 UNION t4 range t4_ix1 t4_ix1 4 NULL 1 Using index condition
+NULL UNION RESULT ALL NULL NULL NULL NULL NULL
+select
+json_detailed(json_extract(trace, '$**.infer_derived_key_statistics')) as t
+from information_schema.optimizer_trace;
+t
+[
+ {
+ "table_alias": "dt",
+ "key_name": "key1",
+ "key_parts": 2,
+ "select":
+ [
+ "group_list_in_key",
+ "group_list_in_key"
+ ],
+ "rec_per_key_estimate": 2
+ },
+ {
+ "table_alias": "dt",
+ "key_name": "key2",
+ "key_parts": 2,
+ "select":
+ [
+ "group_list_in_key",
+ "group_list_in_key"
+ ],
+ "rec_per_key_estimate": 2
+ }
+]
+# union without distinct rows
+explain
+select * from t1
+join t2 on t1.a = t2.a and t1.b = t2.b
+join
+(
+select a, b, description from t3 group by a, b
+union all
+select c, d, descr from t4 group by c, d
+) dt on dt.a = t1.a and dt.b = t1.b and dt.b = t2.b
+where dt.a < 1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 range t1_ix1 t1_ix1 4 NULL 1 Using index condition
+1 PRIMARY t2 ref t2_ix1 t2_ix1 9 test.t1.a,test.t1.b 1
+1 PRIMARY ref key0 key0 9 test.t1.a,test.t1.b 2
+2 DERIVED t3 range t3_ix1 t3_ix1 4 NULL 1 Using index condition
+3 UNION t4 range t4_ix1 t4_ix1 4 NULL 1 Using index condition
+select
+json_detailed(json_extract(trace, '$**.infer_derived_key_statistics')) as t
+from information_schema.optimizer_trace;
+t
+[
+ {
+ "table_alias": "dt",
+ "key_name": "key0",
+ "key_parts": 2,
+ "select":
+ [
+ "group_list_in_key",
+ "group_list_in_key"
+ ],
+ "rec_per_key_estimate": 2
+ },
+ {
+ "table_alias": "dt",
+ "key_name": "key1",
+ "key_parts": 2,
+ "select":
+ [
+ "group_list_in_key",
+ "group_list_in_key"
+ ],
+ "rec_per_key_estimate": 2
+ }
+]
+# union without distinct rows with simple non grouping 2nd select
+explain
+select * from t1
+join t2 on t1.a = t2.a and t1.b = t2.b
+join
+(
+select a, b, description from t3 group by a, b
+union all
+select c, d, descr from t4
+) dt on dt.a = t1.a and dt.b = t1.b and dt.b = t2.b
+where dt.a < 1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 range t1_ix1 t1_ix1 4 NULL 1 Using index condition
+1 PRIMARY t2 ref t2_ix1 t2_ix1 9 test.t1.a,test.t1.b 1
+1 PRIMARY ref key0 key0 9 test.t1.a,test.t1.b 1
+2 DERIVED t3 range t3_ix1 t3_ix1 4 NULL 1 Using index condition
+3 UNION t4 range t4_ix1 t4_ix1 4 NULL 1 Using index condition
+select
+json_detailed(json_extract(trace, '$**.infer_derived_key_statistics')) as t
+from information_schema.optimizer_trace;
+t
+[
+ {
+ "table_alias": "dt",
+ "key_name": "key0",
+ "key_parts": 2,
+ "select":
+ [
+ "group_list_in_key",
+ "unhandled query"
+ ]
+ },
+ {
+ "table_alias": "dt",
+ "key_name": "key1",
+ "key_parts": 2,
+ "select":
+ [
+ "group_list_in_key",
+ "unhandled query"
+ ]
+ }
+]
+# intersect
+explain
+select * from t1
+join t2 on t1.a = t2.a and t1.b = t2.b
+join
+(
+select a, b, description from t3 group by a, b
+intersect
+select c, d, descr from t4 group by c, d
+) dt on dt.a = t1.a and dt.b = t1.b and dt.b = t2.b
+where dt.a > 2 and dt.a < 4;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 range t1_ix1 t1_ix1 4 NULL 1 Using index condition
+1 PRIMARY t2 ref t2_ix1 t2_ix1 9 test.t1.a,test.t1.b 1
+1 PRIMARY ref key1,distinct_key key1 9 test.t1.a,test.t1.b 2
+2 DERIVED t3 range t3_ix1 t3_ix1 4 NULL 2 Using index condition
+3 INTERSECT t4 range t4_ix1 t4_ix1 4 NULL 2 Using index condition
+NULL INTERSECT RESULT ALL NULL NULL NULL NULL NULL
+select
+json_detailed(json_extract(trace, '$**.infer_derived_key_statistics')) as t
+from information_schema.optimizer_trace;
+t
+[
+ {
+ "table_alias": "dt",
+ "key_name": "key1",
+ "key_parts": 2,
+ "select":
+ [
+ "group_list_in_key",
+ "group_list_in_key"
+ ],
+ "rec_per_key_estimate": 2
+ },
+ {
+ "table_alias": "dt",
+ "key_name": "key2",
+ "key_parts": 2,
+ "select":
+ [
+ "group_list_in_key",
+ "group_list_in_key"
+ ],
+ "rec_per_key_estimate": 2
+ }
+]
+drop table t1, t2, t3, t4;
+#
+# End of 11.4 tests
+#
set optimizer_switch=@exit_optimizer_switch;
diff --git a/mysql-test/main/derived_opt.test b/mysql-test/main/derived_opt.test
index 778a4f0dbe82b..99c18a840d17e 100644
--- a/mysql-test/main/derived_opt.test
+++ b/mysql-test/main/derived_opt.test
@@ -1,4 +1,6 @@
# Initialize
+--source include/not_embedded.inc
+--source include/have_innodb.inc
--disable_warnings
drop table if exists t0,t1,t2,t3;
drop database if exists test1;
@@ -439,5 +441,277 @@ DROP TABLE t1, t2;
--echo # End of 10.3 tests
--echo #
+--echo #
+--echo # MDEV-36321 keys generated on derived tables produce wrong out_rows estimates
+--echo #
+--source include/have_sequence.inc
+
+create table t1 (
+ grp_id int,
+ value int,
+ index (grp_id)
+);
+
+insert into t1 select
+ A.seq, B.seq
+from
+ seq_1_to_100 A,
+ seq_1_to_100 B;
+
+create table t2 (a int);
+insert into t2 select seq from seq_1_to_5;
+
+create table t3 (b int);
+insert into t3 select seq from seq_1_to_5;
+
+analyze table t1,t2;
+
+SET optimizer_trace='enabled=on';
+SET optimizer_trace_max_mem_size=10485760;
+
+select * from
+ t2,
+ (select max(value), grp_id from t1 group by grp_id) DT
+where
+ t2.a= DT.grp_id;
+
+select
+ json_detailed(json_extract(trace, '$**.infer_derived_key_statistics')) as t
+from information_schema.optimizer_trace;
+
+
+--echo # Same as above, but try a UNION:
+select * from
+ t2,
+ (select max(value), grp_id from t1 group by grp_id
+ union all
+ select max(value), grp_id from t1 group by grp_id) DT
+where
+ t2.a= DT.grp_id;
+select
+ json_detailed(json_extract(trace, '$**.infer_derived_key_statistics')) as t
+from information_schema.optimizer_trace;
+
+--echo # Same as the previous query but unhandled group by expression
+explain
+select * from
+ t2,
+ (select max(value), grp_id from t1 group by grp_id
+ union all
+ select max(value), grp_id from t1 group by MOD(grp_id,2)) DT
+where
+ t2.a= DT.grp_id;
+select
+ json_detailed(json_extract(trace, '$**.infer_derived_key_statistics')) as t
+from information_schema.optimizer_trace;
+
+--echo # view/cte/derived merged inside our derived table
+
+create view v1 as select * from t1;
+
+explain
+select * from
+ t2,
+ (select grp_id, max(value) as maxval from v1 group by grp_id) DT
+where
+ t2.a= DT.grp_id;
+
+drop view v1;
+
+explain
+with cte1 as (select * from t1)
+select * from
+ t2,
+ (select grp_id, max(value) as maxval from cte1 group by grp_id) DT
+where
+ t2.a= DT.grp_id;
+
+explain
+select * from
+ t2,
+ (
+ select grp_id, max(value) as maxval from
+ (
+ select * from t1, t3
+ where t1.grp_id = t3.b
+ ) dt1
+ group by grp_id
+ ) DT
+where
+ t2.a= DT.grp_id;
+
+--echo # Example with equalities on GROUP BY columns and other columns
+--echo # Must produce {table=, ref=test.t2.col2,test.t2.a, rows=1}
+alter table t2 add col2 int;
+explain
+select * from
+ t2,
+ (select max(value) as maxval, grp_id from t1 group by grp_id) DT
+where
+ t2.col2=maxval and
+ t2.a= DT.grp_id;
+select
+ json_detailed(json_extract(trace, '$**.infer_derived_key_statistics')) as t
+from information_schema.optimizer_trace;
+
+# Same as above but swap the column order.
+# Now we'll get {table=, ref=test.t2.a,test.t2.col2, rows=1}
+explain
+select * from
+ t2,
+ (select grp_id, max(value) as maxval from t1 group by grp_id) DT
+where
+ t2.col2=maxval and
+ t2.a= DT.grp_id;
+
+
+delete from t1;
+insert into t1 select 1, a.seq from seq_1_to_10 a;
+
+analyze table t1;
+
+explain
+select * from
+ t2,
+ (select distinct grp_id from t1
+ union all
+ select distinct value from t1) DT
+where
+ t2.a= DT.grp_id;
+select
+ json_detailed(json_extract(trace, '$**.infer_derived_key_statistics')) as t
+from information_schema.optimizer_trace;
+
+drop table t1, t2;
+
+create table t1
+(
+ a int not null,
+ b int,
+ c int,
+ d int,
+ amount decimal,
+ key t1_ix1 (a,b)
+);
+
+--echo # More complex examples
+insert into t1 values (0, NULL, 0, NULL, 10.0000), (1, 1, 1, 1, 10.0000),
+(2, 2, 2, 2, 20.0000), (3, 3, 3, 3, 30.0000), (4, 4, 4, 4, 40.0000),
+(5, 5, 5, 5, NULL), (6, 6, 6, 6, NULL), (7, 7, 7, 7, 70.0000),
+(8, 8, 8, 8, 80.0000);
+
+create table t2
+(
+ a int NOT NULL,
+ b int,
+ name varchar(50),
+ key t2_ix1 (a,b)
+) engine = innodb;
+
+insert into t2 values (0, NULL, 'a'), (1, NULL, 'A'), (2, 2, 'B'), (3,3, 'C'),
+(4,4, 'D'), (5,5, NULL), (6,6, NULL), (7,7, 'E'), (8,8, 'F'), (9,9, 'G'),
+(10,10,'H'), (11,11, NULL), (12,12, NULL);
+
+drop table t3;
+
+create table t3
+(
+ a int not null,
+ b int,
+ description varchar(50),
+ key t3_ix1 (a,b)
+) engine = innodb;
+insert into t3 values (1, 1, 'bar'),(2,2,'buz'), (3,3, 'silver');
+insert into t3 select seq, seq, 'junk' from seq_3_to_13;
+
+create table t4
+(
+ c int not null,
+ d int,
+ descr varchar(50),
+ key t4_ix1 (c,d)
+) engine = innodb;
+insert into t4 values (1, 1, 'iron'), (2,2,'aluminium'), (3,3, 'silver');
+insert into t4 select seq, seq, 'junk' from seq_3_to_13;
+
+--echo # split materialized
+explain
+select * from t1
+join t2 on t1.a = t2.a and t1.b = t2.b
+join
+(
+ select a, b, description from t3 group by a, b
+) dt on dt.a = t1.a and dt.b = t1.b and dt.b = t2.b
+where dt.a < 1;
+select
+ json_detailed(json_extract(trace, '$**.infer_derived_key_statistics')) as t
+from information_schema.optimizer_trace;
+
+--echo # union with distinct rows
+explain
+select * from t1
+join t2 on t1.a = t2.a and t1.b = t2.b
+join
+(
+ select a, b, description from t3 group by a, b
+ union
+ select c, d, descr from t4 group by c, d
+) dt on dt.a = t1.a and dt.b = t1.b and dt.b = t2.b
+where dt.a < 1;
+select
+ json_detailed(json_extract(trace, '$**.infer_derived_key_statistics')) as t
+from information_schema.optimizer_trace;
+
+--echo # union without distinct rows
+explain
+select * from t1
+join t2 on t1.a = t2.a and t1.b = t2.b
+join
+(
+ select a, b, description from t3 group by a, b
+ union all
+ select c, d, descr from t4 group by c, d
+) dt on dt.a = t1.a and dt.b = t1.b and dt.b = t2.b
+where dt.a < 1;
+select
+ json_detailed(json_extract(trace, '$**.infer_derived_key_statistics')) as t
+from information_schema.optimizer_trace;
+
+--echo # union without distinct rows with simple non grouping 2nd select
+explain
+select * from t1
+join t2 on t1.a = t2.a and t1.b = t2.b
+join
+(
+ select a, b, description from t3 group by a, b
+ union all
+ select c, d, descr from t4
+) dt on dt.a = t1.a and dt.b = t1.b and dt.b = t2.b
+where dt.a < 1;
+select
+ json_detailed(json_extract(trace, '$**.infer_derived_key_statistics')) as t
+from information_schema.optimizer_trace;
+
+--echo # intersect
+explain
+select * from t1
+join t2 on t1.a = t2.a and t1.b = t2.b
+join
+(
+ select a, b, description from t3 group by a, b
+ intersect
+ select c, d, descr from t4 group by c, d
+) dt on dt.a = t1.a and dt.b = t1.b and dt.b = t2.b
+where dt.a > 2 and dt.a < 4;
+select
+ json_detailed(json_extract(trace, '$**.infer_derived_key_statistics')) as t
+from information_schema.optimizer_trace;
+
+drop table t1, t2, t3, t4;
+
+--echo #
+--echo # End of 11.4 tests
+--echo #
+
# The following command must be the last one the file
set optimizer_switch=@exit_optimizer_switch;
diff --git a/mysql-test/main/derived_split_innodb.result b/mysql-test/main/derived_split_innodb.result
index 809b15859bbae..6951da7371816 100644
--- a/mysql-test/main/derived_split_innodb.result
+++ b/mysql-test/main/derived_split_innodb.result
@@ -283,7 +283,7 @@ on t3.a=t.a and t3.c=t.c
where t3.b > 15;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t3 range idx_b idx_b 5 NULL 2 Using index condition; Using where
-1 PRIMARY ref key0 key0 133 test.t3.a,test.t3.c 2
+1 PRIMARY ref key0 key0 133 test.t3.a,test.t3.c 1
2 DERIVED t4 ALL NULL NULL NULL NULL 40 Using filesort
drop table t3, t4;
# End of 10.3 tests
@@ -348,7 +348,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 5
1 PRIMARY t2 ref a a 5 test.t1.b 2 Using where
1 PRIMARY t3 ref a a 5 test.t1.b 3 Using where
-1 PRIMARY ref key0 key0 5 test.t1.b 10 Using where
+1 PRIMARY ref key0 key0 5 test.t1.b 1 Using where
2 LATERAL DERIVED t10 ref grp_id grp_id 5 test.t1.b 100
2 LATERAL DERIVED t11 ALL NULL NULL NULL NULL 10 Using where; Using join buffer (flat, BNL join)
# The important part in the below output is:
@@ -449,7 +449,7 @@ ANALYZE
"ref": ["test.t1.b"],
"loops": 30,
"r_loops": 30,
- "rows": 10,
+ "rows": 1,
"r_rows": 1,
"cost": "REPLACED",
"r_table_time_ms": "REPLACED",
@@ -546,7 +546,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 5
1 PRIMARY t2 ref a a 5 test.t1.b 2 Using where
1 PRIMARY t3 ref a a 5 test.t1.b 3 Using where
-1 PRIMARY ref key0 key0 5 test.t1.b 10 Using where
+1 PRIMARY ref key0 key0 5 test.t1.b 1 Using where
2 LATERAL DERIVED t10 ref grp_id grp_id 5 test.t1.b 100
2 LATERAL DERIVED t11 ALL NULL NULL NULL NULL 10 Using where; Using join buffer (flat, BNL join)
explain
@@ -568,7 +568,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 5
1 PRIMARY t2 ref a a 5 test.t1.b 2 Using where
1 PRIMARY t3 ref a a 5 test.t1.b 3 Using where
-1 PRIMARY ref key0 key0 5 test.t1.b 10 Using where
+1 PRIMARY ref key0 key0 5 test.t1.b 1 Using where
2 LATERAL DERIVED t22 const PRIMARY PRIMARY 4 const 1 Using index
2 LATERAL DERIVED t10 ref grp_id grp_id 5 test.t1.b 100
2 LATERAL DERIVED t11 ALL NULL NULL NULL NULL 10 Using where; Using join buffer (flat, BNL join)
@@ -596,7 +596,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t5 eq_ref PRIMARY PRIMARY 4 test.t1.b 1 Using index
1 PRIMARY t2 ref a a 5 test.t1.b 2
1 PRIMARY t3 ref a a 5 test.t1.b 3
-1 PRIMARY ref key0 key0 5 test.t1.b 10 Using where
+1 PRIMARY ref key0 key0 5 test.t1.b 1 Using where
2 LATERAL DERIVED t22 const PRIMARY PRIMARY 4 const 1 Using index
2 LATERAL DERIVED t10 ref grp_id grp_id 5 test.t5.pk 100 Using index condition
2 LATERAL DERIVED t11 ALL NULL NULL NULL NULL 10 Using where; Using join buffer (flat, BNL join)
@@ -660,7 +660,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 5
1 PRIMARY t2 ref a a 5 test.t1.b 2 Using where
1 PRIMARY t3 ref a a 5 test.t1.b 3 Using where
-1 PRIMARY ref key0 key0 5 test.t1.b 10 Using where
+1 PRIMARY ref key0 key0 5 test.t1.b 1 Using where
2 LATERAL DERIVED t10 ref grp_id grp_id 5 test.t1.b 100
2 LATERAL DERIVED t11 ALL NULL NULL NULL NULL 10 Using where; Using join buffer (flat, BNL join)
select *
@@ -737,7 +737,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 5
1 PRIMARY t2 ref a a 5 test.t1.b 2 Using where
1 PRIMARY t3 ref a a 5 test.t1.b 3 Using where
-1 PRIMARY ref key0 key0 5 test.t1.b 10 Using where
+1 PRIMARY ref key0 key0 5 test.t1.b 1 Using where
2 LATERAL DERIVED t10 ref grp_id grp_id 5 test.t1.b 100
2 LATERAL DERIVED t11 hash_ALL NULL #hash#$hj 5 test.t10.col1 100 Using where; Using join buffer (flat, BNLH join)
select *
@@ -815,7 +815,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 5
1 PRIMARY t2 ALL NULL NULL NULL NULL 50 Using where; Using join buffer (flat, BNL join)
1 PRIMARY t3 ALL NULL NULL NULL NULL 15 Using where; Using join buffer (incremental, BNL join)
-1 PRIMARY ref key0 key0 5 test.t1.b 10 Using where
+1 PRIMARY ref key0 key0 5 test.t1.b 1 Using where
2 DERIVED t10 ALL grp_id NULL NULL NULL 10000 Using temporary; Using filesort
2 DERIVED t11 ALL NULL NULL NULL NULL 10 Using where; Using join buffer (flat, BNL join)
select *
@@ -997,10 +997,110 @@ T.grp_id=v1.COL10;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2
1 PRIMARY t2 ref a a 5 test.t1.a 1 Using where; Using index
-1 PRIMARY ref key0 key0 5 func 10 Using where
+1 PRIMARY ref key0 key0 5 func 1 Using where
2 DERIVED t10 index grp_id grp_id 5 NULL 10000 Using index; Using temporary; Using filesort
drop table t1,t2, t10;
drop view v1;
+#
+# MDEV-37407 Wrong result with LATERAL DERIVED
+#
+CREATE TABLE t1 (
+a int NOT NULL,
+b int default null,
+amount decimal DEFAULT NULL,
+KEY t1_IDX (a,b) USING BTREE
+) ENGINE=INNODB;
+CREATE TABLE t2 (
+a int NOT NULL,
+b int default null,
+name varchar(50) DEFAULT NULL,
+KEY t2_IDX (a,b) USING BTREE
+) ENGINE=INNODB;
+INSERT INTO t1 VALUES
+(1, NULL, 10.0000), (2, 2, 20.0000), (3, 3, 30.0000), (4, 4, 40.0000),
+(5, 5, NULL), (6, 6, NULL), (7, 7, 70.0000), (8, 8, 80.0000);
+INSERT INTO t2 VALUES
+(1, NULL, 'A'), (2,2, 'B'), (3,3, 'C'), (4,4, 'D'), (5,5, NULL), (6,6, NULL),
+(7,7, 'E'), (8,8, 'F'), (9,9, 'G'), (10,10,'H'), (11,11, NULL), (12,12, NULL);
+# Must use Split-Materialized:
+explain $query;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t2 range t2_IDX t2_IDX 4 NULL 1 Using index condition
+1 PRIMARY ref key0 key0 10 test.t2.a,test.t2.b 1 Using where
+2 LATERAL DERIVED t1 ref t1_IDX t1_IDX 9 test.t2.a,test.t2.b 1 Using index condition
+$query;
+a b name total_amt
+1 NULL A 10
+# Compare with correct result:
+set statement optimizer_switch='split_materialized=off' for $query;
+a b name total_amt
+1 NULL A 10
+DROP TABLE t1,t2;
+#
+# MDEV-37407 Wrong result with ORDER BY LIMIT
+# Both, with and without split_materialized should
+# produce the same results
+#
+SET @save_optimizer_switch= @@optimizer_switch;
+CREATE TABLE t1
+(a varchar(35), b varchar(4), KEY (a))
+ENGINE=InnoDB;
+INSERT INTO t1 VALUES
+('Albania','AXA'), ('Australia','AUS'), ('Myanmar','MMR'),
+('Bahamas','BS'), ('Brazil','BRA'), ('Barbados','BRB');
+CREATE TABLE t2
+(a varchar(4), b varchar(50), PRIMARY KEY (b,a), KEY (a))
+ENGINE=InnoDB;
+INSERT INTO t2 VALUES
+('AUS','Anglican'), ('MMR','Baptist'), ('BS','Anglican'),
+('BS','Baptist'), ('BS','Methodist'), ('BRB','Methodist'),
+('BRA','Baptist'), ('USA','Baptist');
+ANALYZE TABLE t1 PERSISTENT FOR ALL;
+Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
+test.t1 analyze status OK
+ANALYZE TABLE t2 PERSISTENT FOR ALL;
+Table Op Msg_type Msg_text
+test.t2 analyze status Engine-independent statistics collected
+test.t2 analyze status OK
+set optimizer_switch='split_materialized=off';
+SELECT t1.a
+FROM (SELECT a FROM t2 GROUP BY a ORDER BY a, COUNT(DISTINCT b) LIMIT 1) dt
+JOIN t1 ON
+dt.a=t1.b
+WHERE t1.a LIKE 'B%';
+a
+set optimizer_switch='split_materialized=on';
+SELECT t1.a
+FROM (SELECT a FROM t2 GROUP BY a ORDER BY a, COUNT(DISTINCT b) LIMIT 1) dt
+JOIN t1 ON
+dt.a=t1.b
+WHERE t1.a LIKE 'B%';
+a
+DROP TABLE t1,t2;
+SET optimizer_switch= @save_optimizer_switch;
+#
+# MDEV-29638 Crash when considering Split-Materialized plan
+#
+set @save_optimizer_switch= @@optimizer_switch;
+set optimizer_switch='condition_pushdown_for_derived=off,split_materialized=on';
+CREATE TABLE t1 (id int PRIMARY KEY)engine=innodb;
+CREATE TABLE t2 (id int PRIMARY KEY, c int) engine=innodb;
+CREATE TABLE t3 (id int PRIMARY KEY, a int , b int, KEY (a))engine=innodb;
+SELECT * FROM
+(
+SELECT DISTINCT t1.id
+FROM t1 JOIN
+(
+SELECT t2.id FROM t2 JOIN t3
+ON t3.id = t2.c
+WHERE (t3.a > 2 AND t3.b = 2)
+GROUP BY t2.id
+) m2 ON m2.id = t1.id
+) dt;
+id
+drop table t1, t2, t3;
+SET optimizer_switch= @save_optimizer_switch;
# End of 10.11 tests
#
# MDEV-37057 Wrong result with LATERAL DERIVED
diff --git a/mysql-test/main/derived_split_innodb.test b/mysql-test/main/derived_split_innodb.test
index ead2796165cd6..207d5e084d4a2 100644
--- a/mysql-test/main/derived_split_innodb.test
+++ b/mysql-test/main/derived_split_innodb.test
@@ -590,6 +590,119 @@ where
drop table t1,t2, t10;
drop view v1;
+--echo #
+--echo # MDEV-37407 Wrong result with LATERAL DERIVED
+--echo #
+
+CREATE TABLE t1 (
+ a int NOT NULL,
+ b int default null,
+ amount decimal DEFAULT NULL,
+ KEY t1_IDX (a,b) USING BTREE
+) ENGINE=INNODB;
+
+CREATE TABLE t2 (
+ a int NOT NULL,
+ b int default null,
+ name varchar(50) DEFAULT NULL,
+ KEY t2_IDX (a,b) USING BTREE
+) ENGINE=INNODB;
+
+INSERT INTO t1 VALUES
+(1, NULL, 10.0000), (2, 2, 20.0000), (3, 3, 30.0000), (4, 4, 40.0000),
+(5, 5, NULL), (6, 6, NULL), (7, 7, 70.0000), (8, 8, 80.0000);
+
+INSERT INTO t2 VALUES
+(1, NULL, 'A'), (2,2, 'B'), (3,3, 'C'), (4,4, 'D'), (5,5, NULL), (6,6, NULL),
+(7,7, 'E'), (8,8, 'F'), (9,9, 'G'), (10,10,'H'), (11,11, NULL), (12,12, NULL);
+
+let $query=
+SELECT t2.a,t2.b,t2.name,t.total_amt FROM t2
+LEFT JOIN
+(
+ SELECT a, b, sum(amount) total_amt FROM t1 GROUP BY a, b
+) AS t ON t2.a=t.a and t2.b<=>t.b
+WHERE t2.a < 2;
+
+--echo # Must use Split-Materialized:
+evalp explain $query;
+evalp $query;
+--echo # Compare with correct result:
+evalp set statement optimizer_switch='split_materialized=off' for $query;
+
+DROP TABLE t1,t2;
+
+--echo #
+--echo # MDEV-37407 Wrong result with ORDER BY LIMIT
+--echo # Both, with and without split_materialized should
+--echo # produce the same results
+--echo #
+
+SET @save_optimizer_switch= @@optimizer_switch;
+
+CREATE TABLE t1
+ (a varchar(35), b varchar(4), KEY (a))
+ENGINE=InnoDB;
+
+INSERT INTO t1 VALUES
+('Albania','AXA'), ('Australia','AUS'), ('Myanmar','MMR'),
+('Bahamas','BS'), ('Brazil','BRA'), ('Barbados','BRB');
+
+CREATE TABLE t2
+ (a varchar(4), b varchar(50), PRIMARY KEY (b,a), KEY (a))
+ENGINE=InnoDB;
+
+INSERT INTO t2 VALUES
+('AUS','Anglican'), ('MMR','Baptist'), ('BS','Anglican'),
+('BS','Baptist'), ('BS','Methodist'), ('BRB','Methodist'),
+('BRA','Baptist'), ('USA','Baptist');
+
+ANALYZE TABLE t1 PERSISTENT FOR ALL;
+ANALYZE TABLE t2 PERSISTENT FOR ALL;
+
+let $q=
+SELECT t1.a
+FROM (SELECT a FROM t2 GROUP BY a ORDER BY a, COUNT(DISTINCT b) LIMIT 1) dt
+ JOIN t1 ON
+ dt.a=t1.b
+WHERE t1.a LIKE 'B%';
+
+set optimizer_switch='split_materialized=off';
+eval $q;
+
+set optimizer_switch='split_materialized=on';
+eval $q;
+
+DROP TABLE t1,t2;
+
+SET optimizer_switch= @save_optimizer_switch;
+
+--echo #
+--echo # MDEV-29638 Crash when considering Split-Materialized plan
+--echo #
+
+set @save_optimizer_switch= @@optimizer_switch;
+set optimizer_switch='condition_pushdown_for_derived=off,split_materialized=on';
+
+CREATE TABLE t1 (id int PRIMARY KEY)engine=innodb;
+CREATE TABLE t2 (id int PRIMARY KEY, c int) engine=innodb;
+CREATE TABLE t3 (id int PRIMARY KEY, a int , b int, KEY (a))engine=innodb;
+
+SELECT * FROM
+(
+ SELECT DISTINCT t1.id
+ FROM t1 JOIN
+ (
+ SELECT t2.id FROM t2 JOIN t3
+ ON t3.id = t2.c
+ WHERE (t3.a > 2 AND t3.b = 2)
+ GROUP BY t2.id
+ ) m2 ON m2.id = t1.id
+) dt;
+
+drop table t1, t2, t3;
+SET optimizer_switch= @save_optimizer_switch;
+
--echo # End of 10.11 tests
--echo #
diff --git a/mysql-test/main/derived_view.result b/mysql-test/main/derived_view.result
index c819460c07976..c2aa35e3ca6f9 100644
--- a/mysql-test/main/derived_view.result
+++ b/mysql-test/main/derived_view.result
@@ -1242,7 +1242,7 @@ SELECT * FROM t1, t2, v1 WHERE t2.a=t1.a AND t2.a=v1.a AND t2.a=v1.b;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 system NULL NULL NULL NULL 1
1 PRIMARY t2 ref a a 4 const 1 Using index
-1 PRIMARY ref key0 key0 8 const,const 1
+1 PRIMARY ref key1 key1 8 func,func 1
2 DERIVED t3 ALL NULL NULL NULL NULL 12 Using temporary; Using filesort
SELECT * FROM t1, t2, v1 WHERE t2.a=t1.a AND t2.a=v1.a AND t2.a=v1.b;
a a a b
@@ -2431,7 +2431,7 @@ GROUP BY TABLE_SCHEMA) AS UNIQUES
ON ( COLUMNS.TABLE_SCHEMA = UNIQUES.TABLE_SCHEMA);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY COLUMNS ALL NULL NULL NULL NULL NULL Open_frm_only; Scanned all databases
-1 PRIMARY ref key0 key0 194 information_schema.COLUMNS.TABLE_SCHEMA 10
+1 PRIMARY ref key0 key0 194 information_schema.COLUMNS.TABLE_SCHEMA 1
2 DERIVED STATISTICS ALL NULL NULL NULL NULL NULL Open_frm_only; Scanned all databases; Using filesort
SELECT COUNT(*) > 0
FROM INFORMATION_SCHEMA.COLUMNS
@@ -4488,3 +4488,17 @@ deallocate prepare stmt;
drop view v1,v2;
drop table t1,t2;
# End of 10.6 tests
+#
+# MDEV-37266: Assertion in create_ref_for_key() with
+# derived_merge OFF
+#
+SET @save_optimizer_switch=@@optimizer_switch;
+SET optimizer_switch='derived_with_keys=on';
+CREATE TABLE t1 AS SELECT 1 AS a FROM seq_1_to_2;
+SELECT md5(a) IN (SELECT * FROM (SELECT '' FROM t1) as x) FROM t1;
+md5(a) IN (SELECT * FROM (SELECT '' FROM t1) as x)
+0
+0
+DROP table t1;
+SET optimizer_switch=@save_optimizer_switch;
+# End of 11.4 tests
diff --git a/mysql-test/main/derived_view.test b/mysql-test/main/derived_view.test
index 5338bcd34c6dd..97b9e1932db8d 100644
--- a/mysql-test/main/derived_view.test
+++ b/mysql-test/main/derived_view.test
@@ -2946,3 +2946,19 @@ drop view v1,v2;
drop table t1,t2;
--echo # End of 10.6 tests
+
+--echo #
+--echo # MDEV-37266: Assertion in create_ref_for_key() with
+--echo # derived_merge OFF
+--echo #
+
+SET @save_optimizer_switch=@@optimizer_switch;
+SET optimizer_switch='derived_with_keys=on';
+
+CREATE TABLE t1 AS SELECT 1 AS a FROM seq_1_to_2;
+SELECT md5(a) IN (SELECT * FROM (SELECT '' FROM t1) as x) FROM t1;
+
+DROP table t1;
+SET optimizer_switch=@save_optimizer_switch;
+
+--echo # End of 11.4 tests
diff --git a/mysql-test/main/dirty_close.result b/mysql-test/main/dirty_close.result
index d13fdb09192da..988f73750f41d 100644
--- a/mysql-test/main/dirty_close.result
+++ b/mysql-test/main/dirty_close.result
@@ -3,7 +3,6 @@ connect con2,localhost,root,,;
connection con1;
disconnect con1;
connection con2;
-DROP TABLE IF EXISTS t1;
CREATE TABLE t1 (n INT);
INSERT INTO t1 VALUES (1),(2),(3);
SELECT * FROM t1;
diff --git a/mysql-test/main/dirty_close.test b/mysql-test/main/dirty_close.test
index e49618170ab96..eb120ff7132d2 100644
--- a/mysql-test/main/dirty_close.test
+++ b/mysql-test/main/dirty_close.test
@@ -1,18 +1,11 @@
--source include/not_embedded.inc
-# Save the initial number of concurrent sessions
---source include/count_sessions.inc
-
connect (con1,localhost,root,,);
connect (con2,localhost,root,,);
connection con1;
dirty_close con1;
connection con2;
---disable_warnings
-DROP TABLE IF EXISTS t1;
---enable_warnings
-
CREATE TABLE t1 (n INT);
INSERT INTO t1 VALUES (1),(2),(3);
SELECT * FROM t1;
@@ -54,7 +47,3 @@ connection con1;
--reap
connection default;
disconnect con1;
-
-# Wait till all disconnects are completed
---source include/wait_until_count_sessions.inc
-
diff --git a/mysql-test/main/distinct.result b/mysql-test/main/distinct.result
index c3f4fae80e682..38371c34a35aa 100644
--- a/mysql-test/main/distinct.result
+++ b/mysql-test/main/distinct.result
@@ -212,7 +212,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index NULL PRIMARY 4 NULL 1 Using index
explain SELECT distinct a from t3 order by a desc limit 2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t3 index NULL a 5 NULL 40 Using index
+1 SIMPLE t3 range a a 5 NULL 10 Using index for group-by; Using temporary; Using filesort
explain SELECT distinct a,b from t3 order by a+1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t3 ALL NULL NULL NULL NULL 204 Using temporary; Using filesort
diff --git a/mysql-test/main/drop.result b/mysql-test/main/drop.result
index f4415117dc9ae..7344a085c7065 100644
--- a/mysql-test/main/drop.result
+++ b/mysql-test/main/drop.result
@@ -97,7 +97,6 @@ unlock tables;
connection addconroot1;
connection addconroot2;
disconnect addconroot2;
-connection addconroot1;
disconnect addconroot1;
connection default;
drop table if exists t1,t2;
diff --git a/mysql-test/main/drop.test b/mysql-test/main/drop.test
index 6b926d3f0c1c1..3f2e6770eb309 100644
--- a/mysql-test/main/drop.test
+++ b/mysql-test/main/drop.test
@@ -123,10 +123,7 @@ connection addconroot1;
connection addconroot2;
--reap
disconnect addconroot2;
---source include/wait_until_disconnected.inc
-connection addconroot1;
disconnect addconroot1;
---source include/wait_until_disconnected.inc
connection default;
--enable_service_connection
diff --git a/mysql-test/main/dyncol.result b/mysql-test/main/dyncol.result
index 9e1d3aabbb7c3..740e7c445d120 100644
--- a/mysql-test/main/dyncol.result
+++ b/mysql-test/main/dyncol.result
@@ -1427,9 +1427,9 @@ SELECT
column_get(column_create(1, -999999999999999 AS int), 1 AS TIME) AS t1,
column_get(column_create(1, -9223372036854775808 AS int), 1 AS TIME) AS t2;
t1 t2
--838:59:59 -838:59:59
+NULL -838:59:59
Warnings:
-Warning 1292 Truncated incorrect time value: '-999999999999999'
+Warning 1292 Incorrect time value: '-999999999999999'
Warning 1292 Truncated incorrect time value: '-9223372036854775808'
#
# end of 5.3 tests
diff --git a/mysql-test/main/error_simulation.result b/mysql-test/main/error_simulation.result
index ba4c8bcf47751..009f5323b37d8 100644
--- a/mysql-test/main/error_simulation.result
+++ b/mysql-test/main/error_simulation.result
@@ -125,13 +125,4 @@ SELECT f1(1);
Got one of the listed errors
DROP FUNCTION f1;
SET debug_dbug= @saved_dbug;
-#
-# MDEV-27978 wrong option name in error when exceeding max_session_mem_used
-#
-SET SESSION max_session_mem_used = 8192;
-SELECT * FROM information_schema.processlist;
-ERROR HY000: The MariaDB server is running with the --max-session-mem-used=8192 option so it cannot execute this statement
-SET SESSION max_session_mem_used = DEFAULT;
-#
# End of 10.2 tests
-#
diff --git a/mysql-test/main/error_simulation.test b/mysql-test/main/error_simulation.test
index fc5d9c537c73c..3beeefce39fde 100644
--- a/mysql-test/main/error_simulation.test
+++ b/mysql-test/main/error_simulation.test
@@ -144,8 +144,6 @@ SELECT a FROM t1 ORDER BY rand(1);
--echo #cleanup
DROP TABLE t1, pid_table;
-
-
--echo #
--echo # MDEV-12416 OOM in create_virtual_tmp_table() makes the server crash
--echo #
@@ -158,15 +156,4 @@ SELECT f1(1);
DROP FUNCTION f1;
SET debug_dbug= @saved_dbug;
---echo #
---echo # MDEV-27978 wrong option name in error when exceeding max_session_mem_used
---echo #
-SET SESSION max_session_mem_used = 8192;
---error ER_OPTION_PREVENTS_STATEMENT
-SELECT * FROM information_schema.processlist;
-SET SESSION max_session_mem_used = DEFAULT;
-
-
---echo #
--echo # End of 10.2 tests
---echo #
diff --git a/mysql-test/main/errors.result b/mysql-test/main/errors.result
index e056867695234..e4ccc8a73196e 100644
--- a/mysql-test/main/errors.result
+++ b/mysql-test/main/errors.result
@@ -1,4 +1,3 @@
-drop table if exists t1;
insert into t1 values(1);
ERROR 42S02: Table 'test.t1' doesn't exist
delete from t1;
@@ -170,12 +169,6 @@ UPDATE t1 SET a = 'new'
WHERE COLUMN_CREATE( 1, 'v', 1, 'w' ) IS NULL;
ERROR 22007: Illegal value used as argument of dynamic column function
drop table t1;
-set @max_session_mem_used_save= @@max_session_mem_used;
-set max_session_mem_used = 50000;
-select * from seq_1_to_1000;
-set max_session_mem_used = 8192;
-select * from seq_1_to_1000;
-set max_session_mem_used = @max_session_mem_used_save;
#
# MDEV-20604: Duplicate key value is silently truncated to 64
# characters in print_keydup_error
@@ -231,16 +224,3 @@ Error 1327 Undeclared variable: foo
Error 1305 PROCEDURE P1 does not exist
drop procedure P1;
# End of 10.4 tests
-#
-# MDEV-35828: Assertion fails in alloc_root() when memory causes it to call itself
-#
-CREATE TEMPORARY TABLE t1 (a INT,b INT);
-INSERT INTO t1 VALUES (1,1),(2,2);
-SET
-@tmp=@@max_session_mem_used,
-max_session_mem_used=8192;
-SELECT * FROM (t1 AS t2 LEFT JOIN t1 AS t3 USING (a)),t1;
-ERROR HY000: The MariaDB server is running with the --max-session-mem-used=8192 option so it cannot execute this statement
-DROP TABLE t1;
-SET max_session_mem_used=@tmp;
-# End of 10.6 tests
diff --git a/mysql-test/main/errors.test b/mysql-test/main/errors.test
index 87d6d2fdec9fd..e748b3bef2d40 100644
--- a/mysql-test/main/errors.test
+++ b/mysql-test/main/errors.test
@@ -3,31 +3,28 @@
#
--source include/have_sequence.inc
---disable_warnings
-drop table if exists t1;
---enable_warnings
---error 1146
+--error ER_NO_SUCH_TABLE
insert into t1 values(1);
---error 1146
+--error ER_NO_SUCH_TABLE
delete from t1;
---error 1146
+--error ER_NO_SUCH_TABLE
update t1 set a=1;
create table t1 (a int);
---error 1054
+--error ER_BAD_FIELD_ERROR
select count(test.t1.b) from t1;
---error 1054
+--error ER_BAD_FIELD_ERROR
select count(not_existing_database.t1) from t1;
---error 1054
+--error ER_BAD_FIELD_ERROR
select count(not_existing_database.t1.a) from t1;
---error 1044,1146
+--error ER_DBACCESS_DENIED_ERROR,ER_NO_SUCH_TABLE
select count(not_existing_database.t1.a) from not_existing_database.t1;
---error 1054
+--error ER_BAD_FIELD_ERROR
select 1 from t1 order by 2;
---error 1054
+--error ER_BAD_FIELD_ERROR
select 1 from t1 group by 2;
---error 1054
+--error ER_BAD_FIELD_ERROR
select 1 from t1 order by t1.b;
---error 1054
+--error ER_BAD_FIELD_ERROR
select count(*),b from t1;
drop table t1;
@@ -36,10 +33,10 @@ drop table t1;
#
# Bug #6080: Error message for a field with a display width that is too long
#
---error 1439
+--error ER_TOO_BIG_DISPLAYWIDTH
create table t1 (a int(256));
set sql_mode='traditional';
---error 1074
+--error ER_TOO_BIG_FIELDLENGTH
create table t1 (a varchar(66000));
set sql_mode=default;
@@ -95,7 +92,7 @@ delimiter ;|
flush status;
--disable_ps2_protocol
---error 1062
+--error ER_DUP_ENTRY
select f1(), f2();
--enable_ps2_protocol
show status like 'Com_insert';
@@ -202,24 +199,6 @@ UPDATE t1 SET a = 'new'
WHERE COLUMN_CREATE( 1, 'v', 1, 'w' ) IS NULL;
drop table t1;
-#
-# errors caused by max_session_mem_used
-#
-set @max_session_mem_used_save= @@max_session_mem_used;
-
---disable_result_log
-set max_session_mem_used = 50000;
---error 0,ER_OPTION_PREVENTS_STATEMENT
-select * from seq_1_to_1000;
-set max_session_mem_used = 8192;
---error 0,ER_OPTION_PREVENTS_STATEMENT
-select * from seq_1_to_1000;
---enable_result_log
-# We may not be able to execute any more queries with this connection
-# because of too little memory#
-
-set max_session_mem_used = @max_session_mem_used_save;
-
--echo #
--echo # MDEV-20604: Duplicate key value is silently truncated to 64
--echo # characters in print_keydup_error
@@ -283,24 +262,4 @@ show warnings;
drop procedure P1;
--- echo # End of 10.4 tests
-
-
---echo #
---echo # MDEV-35828: Assertion fails in alloc_root() when memory causes it to call itself
---echo #
-CREATE TEMPORARY TABLE t1 (a INT,b INT);
-INSERT INTO t1 VALUES (1,1),(2,2);
-
-SET
- @tmp=@@max_session_mem_used,
- max_session_mem_used=8192;
-
---error ER_OPTION_PREVENTS_STATEMENT
-SELECT * FROM (t1 AS t2 LEFT JOIN t1 AS t3 USING (a)),t1;
-
-DROP TABLE t1;
-SET max_session_mem_used=@tmp;
-
-
---echo # End of 10.6 tests
+--echo # End of 10.4 tests
diff --git a/mysql-test/main/explain_json_format_partitions.result b/mysql-test/main/explain_json_format_partitions.result
index 2ad33b3783b7d..16f624254847b 100644
--- a/mysql-test/main/explain_json_format_partitions.result
+++ b/mysql-test/main/explain_json_format_partitions.result
@@ -81,7 +81,8 @@ ANALYZE
"rows": 10,
"r_rows": 10,
"r_total_filtered": 30,
- "r_total_time_ms": "REPLACED",
+ "r_table_time_ms": "REPLACED",
+ "r_other_time_ms": "REPLACED",
"r_engine_stats": REPLACED,
"attached_condition": "t1.a in (2,3,4)",
"r_filtered": 30
@@ -106,7 +107,8 @@ ANALYZE
"rows": 10,
"r_rows": 10,
"r_total_filtered": 0,
- "r_total_time_ms": "REPLACED",
+ "r_table_time_ms": "REPLACED",
+ "r_other_time_ms": "REPLACED",
"r_engine_stats": REPLACED,
"attached_condition": "t1.a in (20,30,40)",
"r_filtered": 0
diff --git a/mysql-test/main/explain_non_select.result b/mysql-test/main/explain_non_select.result
index ca8aa246c98aa..aa3c4787dc7f0 100644
--- a/mysql-test/main/explain_non_select.result
+++ b/mysql-test/main/explain_non_select.result
@@ -72,7 +72,7 @@ id select_type table type possible_keys key key_len ref rows Extra
# This should use an index, possible_keys=NULL because there is no WHERE
explain update t1 set a=a+1 order by a limit 2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ALL NULL NULL NULL NULL 512 Using filesort
+1 SIMPLE t1 index NULL a 5 NULL 2 Using buffer
# This should use range, possible_keys={a,b}
explain update t1 set filler='fooo' where a<20 and b < 10;
id select_type table type possible_keys key key_len ref rows Extra
diff --git a/mysql-test/main/failed_auth_3909.result b/mysql-test/main/failed_auth_3909.result
index 5586997430185..8d16b0310a402 100644
--- a/mysql-test/main/failed_auth_3909.result
+++ b/mysql-test/main/failed_auth_3909.result
@@ -6,12 +6,15 @@ connect fail,localhost,u1;
ERROR 28000: Access denied for user 'u1'@'localhost' (using password: NO)
connect(localhost,uu2,,test,MASTER_PORT,MASTER_SOCKET);
connect fail,localhost,uu2;
-ERROR HY000: Server is running in --secure-auth mode, but 'uu2'@'localhost' has a password in the old format; please change the password to the new format
+ERROR HY000: User 'uu2'@'localhost' has a password in the old format; please change the password to the new format
connect(localhost,uu2,password,test,MASTER_PORT,MASTER_SOCKET);
connect fail,localhost,uu2,password;
-ERROR HY000: Server is running in --secure-auth mode, but 'uu2'@'localhost' has a password in the old format; please change the password to the new format
+ERROR HY000: User 'uu2'@'localhost' has a password in the old format; please change the password to the new format
+change_user u1,,;
ERROR 28000: Access denied for user 'u1'@'localhost' (using password: NO)
-ERROR HY000: Server is running in --secure-auth mode, but 'uu2'@'localhost' has a password in the old format; please change the password to the new format
-ERROR HY000: Server is running in --secure-auth mode, but 'uu2'@'localhost' has a password in the old format; please change the password to the new format
+change_user uu2,,;
+ERROR HY000: User 'uu2'@'localhost' has a password in the old format; please change the password to the new format
+change_user uu2,password,;
+ERROR HY000: User 'uu2'@'localhost' has a password in the old format; please change the password to the new format
delete from mysql.user where plugin = 'mysql_old_password';
flush privileges;
diff --git a/mysql-test/main/failed_auth_unixsocket.result b/mysql-test/main/failed_auth_unixsocket.result
index 084eb2fab64c5..94a3a70f46d30 100644
--- a/mysql-test/main/failed_auth_unixsocket.result
+++ b/mysql-test/main/failed_auth_unixsocket.result
@@ -4,6 +4,7 @@ delete from mysql.global_priv where user != 'root';
flush privileges;
connect(localhost,USER,,test,MASTER_PORT,MASTER_SOCKET);
ERROR 28000: Access denied for user 'USER'@'localhost'
+change_user USER,,;
ERROR 28000: Access denied for user 'USER'@'localhost'
replace mysql.global_priv select * from global_priv_backup;
flush privileges;
diff --git a/mysql-test/main/failed_auth_unixsocket.test b/mysql-test/main/failed_auth_unixsocket.test
index 5a77e1cdbda16..58c57be97b332 100644
--- a/mysql-test/main/failed_auth_unixsocket.test
+++ b/mysql-test/main/failed_auth_unixsocket.test
@@ -20,7 +20,7 @@ let $replace=Access denied for user '$USER';
connect (fail,localhost,$USER);
--enable_query_log
---replace_result $replace "Access denied for user 'USER'"
+--replace_result $USER USER
--error ER_ACCESS_DENIED_NO_PASSWORD_ERROR
change_user $USER;
diff --git a/mysql-test/main/features.result b/mysql-test/main/features.result
index cae4a37ca64e2..2f0c41936986e 100644
--- a/mysql-test/main/features.result
+++ b/mysql-test/main/features.result
@@ -20,6 +20,7 @@ Feature_subquery 0
Feature_system_versioning 0
Feature_timezone 0
Feature_trigger 0
+Feature_vector_index 0
Feature_window_functions 0
Feature_xml 0
#
@@ -209,3 +210,19 @@ show status like "feature_into_%";
Variable_name Value
Feature_into_outfile 4
Feature_into_variable 2
+#
+# Feature vector index
+#
+create table t1 (id int auto_increment primary key,
+u vector(5) not null, vector index (u));
+select * from t1;
+id u
+select * from t1;
+id u
+select * from t1;
+id u
+show status like "Feature_vector_index";
+Variable_name Value
+Feature_vector_index 2
+drop table t1;
+# End of 11.8 tests
diff --git a/mysql-test/main/features.test b/mysql-test/main/features.test
index 6ef617159e6ca..15cc5630c5525 100644
--- a/mysql-test/main/features.test
+++ b/mysql-test/main/features.test
@@ -166,3 +166,19 @@ drop table t1;
--remove_file $MYSQLTEST_VARDIR/tmp/features_outfile.1
--remove_file $MYSQLTEST_VARDIR/tmp/features_outfile.2
show status like "feature_into_%";
+
+--echo #
+--echo # Feature vector index
+--echo #
+
+--disable_service_connection
+create table t1 (id int auto_increment primary key,
+ u vector(5) not null, vector index (u));
+select * from t1;
+select * from t1;
+select * from t1;
+show status like "Feature_vector_index";
+drop table t1;
+--enable_service_connection
+
+--echo # End of 11.8 tests
diff --git a/mysql-test/main/fetch_first.result b/mysql-test/main/fetch_first.result
index 775595783b9fd..861273030e8ae 100644
--- a/mysql-test/main/fetch_first.result
+++ b/mysql-test/main/fetch_first.result
@@ -846,7 +846,7 @@ group by first_name, last_name
order by first_name
fetch first 2 rows with ties;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range t1_name t1_name 206 NULL 3 Using where; Using index for group-by
+1 SIMPLE t1 range t1_name t1_name 206 NULL 3 Using where; Using index for group-by; Using temporary; Using filesort
select first_name, last_name
from t1
where first_name != 'John'
@@ -871,7 +871,7 @@ select * from temp_table
order by first_name, last_name;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY ALL NULL NULL NULL NULL 2 Using filesort
-2 DERIVED t1 range t1_name t1_name 206 NULL 3 Using where; Using index for group-by
+2 DERIVED t1 range t1_name t1_name 206 NULL 3 Using where; Using index for group-by; Using temporary; Using filesort
with temp_table as (
select first_name, last_name
from t1
@@ -1462,3 +1462,88 @@ a b
3 bar
3 zzz
DROP TABLE t1;
+#
+# MDEV-37901: Wrong result with Loose Scan on QUICK_GROUP_MIN_MAX_SELECT WITH TIES
+#
+create table t1 (
+country varchar(100),
+city varchar(100),
+user_score int,
+index (country, city, user_score)
+);
+insert into t1
+select 'China', 'Shenzhen', seq from seq_10_to_100;
+insert into t1
+select 'India', 'New Delhi', seq from seq_10_to_100;
+insert into t1
+select 'Sri Lanka', 'Colombo', seq from seq_10_to_100;
+analyze table t1 persistent for all;
+Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
+test.t1 analyze status OK
+insert into t1
+select 'Finland', 'Espoo', seq from seq_10_to_200;
+insert into t1
+select 'Greece', 'Chania', seq from seq_10_to_20;
+insert into t1
+select 'Estonia', 'Narva', seq from seq_10_to_20;
+insert into t1
+select 'Russia', 'St Petersburg', seq from seq_10_to_20;
+# Must use "Using index for group-by":
+explain
+select country, city, min(user_score)
+from t1
+where user_score between 9 and 199
+group by country, city
+order by country
+fetch first 5 rows with ties;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range NULL country 811 NULL 4 Using where; Using index for group-by; Using temporary; Using filesort
+# Must not use "Using index for group-by":
+explain
+select country, city, sum(user_score)
+from t1
+where user_score between 9 and 199
+group by country, concat(city,'AA')
+order by country
+fetch first 5 rows with ties;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index NULL country 811 NULL 273 Using where; Using index; Using temporary; Using filesort
+select country, city, sum(user_score)
+from t1
+where user_score between 9 and 199
+group by country, concat(city,'AA')
+order by country
+fetch first 5 rows with ties;
+country city sum(user_score)
+China Shenzhen 5005
+Estonia Narva 165
+Finland Espoo 19855
+Greece Chania 165
+India New Delhi 5005
+# both using index and index with group by should produce same result
+select country, city, min(user_score)
+from t1
+where user_score between 9 and 199
+group by country, city
+order by country
+fetch first 5 rows with ties;
+country city min(user_score)
+China Shenzhen 10
+Estonia Narva 10
+Finland Espoo 10
+Greece Chania 10
+India New Delhi 10
+select country, city, min(user_score)
+from t1 use index()
+where user_score between 9 and 199
+group by country, city
+order by country
+fetch first 5 rows with ties;
+country city min(user_score)
+China Shenzhen 10
+Estonia Narva 10
+Finland Espoo 10
+Greece Chania 10
+India New Delhi 10
+drop table t1;
diff --git a/mysql-test/main/fetch_first.test b/mysql-test/main/fetch_first.test
index 71e45f5c28880..d4cb8edaa0d4f 100644
--- a/mysql-test/main/fetch_first.test
+++ b/mysql-test/main/fetch_first.test
@@ -1095,3 +1095,77 @@ SELECT DISTINCT a, b FROM t1 ORDER BY a FETCH FIRST 3 ROWS WITH TIES;
# Cleanup
DROP TABLE t1;
+
+
+--echo #
+--echo # MDEV-37901: Wrong result with Loose Scan on QUICK_GROUP_MIN_MAX_SELECT WITH TIES
+--echo #
+
+--source include/have_sequence.inc
+
+create table t1 (
+ country varchar(100),
+ city varchar(100),
+ user_score int,
+ index (country, city, user_score)
+);
+
+insert into t1
+select 'China', 'Shenzhen', seq from seq_10_to_100;
+insert into t1
+select 'India', 'New Delhi', seq from seq_10_to_100;
+insert into t1
+select 'Sri Lanka', 'Colombo', seq from seq_10_to_100;
+analyze table t1 persistent for all;
+
+insert into t1
+select 'Finland', 'Espoo', seq from seq_10_to_200;
+insert into t1
+select 'Greece', 'Chania', seq from seq_10_to_20;
+insert into t1
+select 'Estonia', 'Narva', seq from seq_10_to_20;
+insert into t1
+select 'Russia', 'St Petersburg', seq from seq_10_to_20;
+
+--echo # Must use "Using index for group-by":
+explain
+select country, city, min(user_score)
+from t1
+where user_score between 9 and 199
+group by country, city
+order by country
+fetch first 5 rows with ties;
+
+--echo # Must not use "Using index for group-by":
+explain
+select country, city, sum(user_score)
+from t1
+where user_score between 9 and 199
+group by country, concat(city,'AA')
+order by country
+fetch first 5 rows with ties;
+
+select country, city, sum(user_score)
+from t1
+where user_score between 9 and 199
+group by country, concat(city,'AA')
+order by country
+fetch first 5 rows with ties;
+
+--echo # both using index and index with group by should produce same result
+
+select country, city, min(user_score)
+from t1
+where user_score between 9 and 199
+group by country, city
+order by country
+fetch first 5 rows with ties;
+
+select country, city, min(user_score)
+from t1 use index()
+where user_score between 9 and 199
+group by country, city
+order by country
+fetch first 5 rows with ties;
+
+drop table t1;
diff --git a/mysql-test/main/file_contents.result b/mysql-test/main/file_contents.result
deleted file mode 100644
index 2b5e6e6229b6c..0000000000000
--- a/mysql-test/main/file_contents.result
+++ /dev/null
@@ -1,6 +0,0 @@
-
-Checking 'INFO_SRC' and 'INFO_BIN'
-INFO_SRC: Found MariaDB version number / Found GIT revision id
-INFO_BIN: Found 'Compiler ... used' line / Found 'Feature flags' line
-
-End of tests
diff --git a/mysql-test/main/file_contents.test b/mysql-test/main/file_contents.test
deleted file mode 100644
index 4734a0294f03b..0000000000000
--- a/mysql-test/main/file_contents.test
+++ /dev/null
@@ -1,70 +0,0 @@
-#
-# Testing files that were built to be packaged, both for existence and for contents
-#
-
-#
-# Bug #42969: Create MANIFEST files
-#
-# Use a Perl script to verify that files "docs/INFO_BIN" and "docs/INFO_SRC" do exist
-# and have the expected contents.
-
---perl
-print "\nChecking 'INFO_SRC' and 'INFO_BIN'\n";
-$dir_bin = $ENV{'MYSQL_BINDIR'};
-if ($dir_bin eq '/usr/') {
- # RPM package
- $dir_docs = $dir_bin;
- $dir_docs =~ s|/lib|/share/doc|;
- if(-d "$dir_docs/packages") {
- # SuSE: "packages/" in the documentation path
- $dir_docs = glob "$dir_docs/packages/MariaDB-server*";
- } else {
- # RedHat: version number in directory name
- $dir_docs = glob "$dir_docs/MariaDB-server*";
- }
-} elsif ($dir_bin eq '/usr') {
- # RPM build during development
- $dir_docs = "$dir_bin/share/doc";
- if(-d "$dir_docs/packages") {
- # SuSE: "packages/" in the documentation path
- $dir_docs = glob "$dir_docs/packages/MariaDB-server*";
- } else {
- # RedHat/Debian: version number in directory name
- $dir_docs = glob "$dir_docs/mariadb-server-*";
- $dir_docs = glob "$dir_docs/MariaDB-server*" unless -d $dir_docs;
- }
- # Slackware
- $dir_docs = glob "$dir_bin/doc/mariadb-[0-9]*" unless -d $dir_docs;
-} else {
- # tar.gz package, Windows, or developer work (in git)
- $dir_docs = $dir_bin;
- if(-d "$dir_docs/docs") {
- $dir_docs = "$dir_docs/docs"; # package
- } else {
- $dir_docs = "$dir_docs/Docs"; # development tree
- }
-}
-$found_version = "No line 'MariaDB source #.#.#' in $dir_docs/INFO_SRC";
-$found_revision = "No line 'revision-id: .....' in $dir_docs/INFO_SRC";
-open(I_SRC,"<","$dir_docs/INFO_SRC") or print "Cannot open 'INFO_SRC' in '$dir_docs' (starting from bindir '$dir_bin')\n";
-while(defined ($line = )) {
- if ($line =~ m|^MariaDB source \d+\.\d\.\d+|) {$found_version = "Found MariaDB version number";}
- if ($line =~ m|^commit: \w{40}$|) {$found_revision = "Found GIT revision id";}
-}
-close I_SRC;
-print "INFO_SRC: $found_version / $found_revision\n";
-$found_compiler = "No line about compiler information";
-$found_features = "No line 'Feature flags'";
-open(I_BIN,"<","$dir_docs/INFO_BIN") or print "Cannot open 'INFO_BIN' in '$dir_docs' (starting from bindir '$dir_bin')\n";
-while(defined ($line = )) {
- # "generator" on Windows, "flags" on Unix:
- if (($line =~ m| Compiler / generator used: |) ||
- ($line =~ m| Compiler flags used |)) {$found_compiler = "Found 'Compiler ... used' line";}
- if ($line =~ m| Feature flags used:|) {$found_features = "Found 'Feature flags' line";}
-}
-close I_BIN;
-print "INFO_BIN: $found_compiler / $found_features\n";
-EOF
-
---echo
---echo End of tests
diff --git a/mysql-test/main/filesort_debug.test b/mysql-test/main/filesort_debug.test
index 8f0fba099bcc4..d78087d27bbb9 100644
--- a/mysql-test/main/filesort_debug.test
+++ b/mysql-test/main/filesort_debug.test
@@ -1,6 +1,5 @@
--source include/have_debug.inc
--source include/have_debug_sync.inc
---source include/count_sessions.inc
call mtr.add_suppression("Sort aborted.*");
@@ -53,7 +52,6 @@ SET DEBUG_SYNC='now SIGNAL filesort_killed';
connection default;
disconnect con1;
disconnect con2;
---source include/wait_until_count_sessions.inc
SET DEBUG_SYNC= "RESET";
DROP TABLE t1;
diff --git a/mysql-test/main/fix_priv_tables.result b/mysql-test/main/fix_priv_tables.result
index c39ebfb922722..db1edd79c05f4 100644
--- a/mysql-test/main/fix_priv_tables.result
+++ b/mysql-test/main/fix_priv_tables.result
@@ -1,4 +1,3 @@
-drop table if exists t1,t1aa,t2aa;
set sql_mode="";
DROP DATABASE IF EXISTS testdb;
CREATE DATABASE testdb;
@@ -19,7 +18,7 @@ Grants for select_only_c1@localhost
GRANT USAGE ON *.* TO `select_only_c1`@`localhost`
GRANT SELECT (`c1`) ON `testdb`.`v1` TO `select_only_c1`@`localhost`
-"after fix privs"
+# after fix privs
SHOW GRANTS FOR 'show_view_tbl'@'localhost';
Grants for show_view_tbl@localhost
GRANT USAGE ON *.* TO `show_view_tbl`@`localhost`
@@ -35,3 +34,4 @@ DROP USER 'select_only_c1'@'localhost';
DROP VIEW testdb.v1;
DROP TABLE testdb.t1;
DROP DATABASE testdb;
+# End of 4.1 tests
diff --git a/mysql-test/main/fix_priv_tables.test b/mysql-test/main/fix_priv_tables.test
index 382417a6b1010..7ac99f3357cda 100644
--- a/mysql-test/main/fix_priv_tables.test
+++ b/mysql-test/main/fix_priv_tables.test
@@ -19,10 +19,6 @@ if (!$MYSQL_FIX_PRIVILEGE_TABLES)
# mysql_fix_system_tables which should be ignored.
# Instead, concentrate on the errors in r/system_mysql_db.reject
---disable_warnings
-drop table if exists t1,t1aa,t2aa;
---enable_warnings
-
set sql_mode="";
#
@@ -50,22 +46,16 @@ GRANT SELECT(c1) on testdb.v1 to 'select_only_c1'@localhost;
SHOW GRANTS FOR 'select_only_c1'@'localhost';
echo;
--- disable_result_log
--- disable_query_log
+--disable_result_log
+--disable_query_log
-# Run the mysql_fix_privilege_tables.sql using "mysql --force"
-# Determine the number of open sessions
---source include/count_sessions.inc
--exec $MYSQL --force mysql < $MYSQL_FIX_PRIVILEGE_TABLES > $MYSQLTEST_VARDIR/tmp/fix_priv_tables.log 2>&1
--remove_file $MYSQLTEST_VARDIR/tmp/fix_priv_tables.log
-# Wait till the number of open sessions is <= the number before the run with $MYSQL
-# = The session caused by mysql has finished its disconnect
---source include/wait_until_count_sessions.inc
--- enable_query_log
--- enable_result_log
+--enable_query_log
+--enable_result_log
-echo "after fix privs";
+echo # after fix privs;
SHOW GRANTS FOR 'show_view_tbl'@'localhost';
echo;
@@ -79,4 +69,4 @@ DROP VIEW testdb.v1;
DROP TABLE testdb.t1;
DROP DATABASE testdb;
-# End of 4.1 tests
+--echo # End of 4.1 tests
diff --git a/mysql-test/main/flush-innodb-notembedded.test b/mysql-test/main/flush-innodb-notembedded.test
index 1f73ba50fc44b..0677fa62a48f3 100644
--- a/mysql-test/main/flush-innodb-notembedded.test
+++ b/mysql-test/main/flush-innodb-notembedded.test
@@ -18,7 +18,6 @@ GRANT RELOAD, LOCK TABLES ON *.* TO user5@localhost;
FLUSH TABLE db1.t1 FOR EXPORT;
UNLOCK TABLES;
--disconnect con1
---source include/wait_until_disconnected.inc
--connection default
@@ -26,7 +25,6 @@ UNLOCK TABLES;
--error ER_SPECIFIC_ACCESS_DENIED_ERROR
FLUSH TABLE db1.t1 FOR EXPORT;
--disconnect con1
---source include/wait_until_disconnected.inc
--connection default
@@ -34,7 +32,6 @@ FLUSH TABLE db1.t1 FOR EXPORT;
--error ER_DBACCESS_DENIED_ERROR
FLUSH TABLE db1.t1 FOR EXPORT;
--disconnect con1
---source include/wait_until_disconnected.inc
--connection default
@@ -42,7 +39,6 @@ FLUSH TABLE db1.t1 FOR EXPORT;
--error ER_SPECIFIC_ACCESS_DENIED_ERROR
FLUSH TABLE db1.t1 FOR EXPORT;
--disconnect con1
---source include/wait_until_disconnected.inc
--connection default
@@ -50,7 +46,6 @@ FLUSH TABLE db1.t1 FOR EXPORT;
--error ER_TABLEACCESS_DENIED_ERROR
FLUSH TABLE db1.t1 FOR EXPORT;
--disconnect con1
---source include/wait_until_disconnected.inc
--connection default
DROP USER user1@localhost, user2@localhost, user3@localhost,
diff --git a/mysql-test/main/flush-innodb.result b/mysql-test/main/flush-innodb.result
index 5df79e4cc0c05..351ca0a34d254 100644
--- a/mysql-test/main/flush-innodb.result
+++ b/mysql-test/main/flush-innodb.result
@@ -157,7 +157,6 @@ CREATE TABLE t1(a INT) engine= MEMORY;
FLUSH TABLE t1 FOR EXPORT;
ERROR HY000: Storage engine MEMORY of the table `test`.`t1` doesn't have this option
DROP TABLE t1;
-connection con1;
disconnect con1;
connection default;
# Test 7: Check privileges required.
@@ -198,7 +197,6 @@ LOCK TABLE t1 READ;
UNLOCK TABLES;
connection default;
UNLOCK TABLES;
-connection con1;
disconnect con1;
connection default;
DROP TABLE t1, t2;
@@ -294,7 +292,6 @@ ERROR HY000: Can't execute the given command because you have active locked tabl
LOCK TABLES test.t1 WRITE;
UNLOCK TABLES;
DROP TABLE t1;
-connection con1;
disconnect con1;
connection default;
# End of 5.6 tests
diff --git a/mysql-test/main/flush-innodb.test b/mysql-test/main/flush-innodb.test
index fcb0608373e32..cf62ba6aec67e 100644
--- a/mysql-test/main/flush-innodb.test
+++ b/mysql-test/main/flush-innodb.test
@@ -222,8 +222,6 @@ UNLOCK TABLES;
--echo # Reaping DROP TABLE t1
--reap
--disconnect con2
---source include/wait_until_disconnected.inc
-
--connection default
DROP TABLE t2;
@@ -250,10 +248,7 @@ CREATE TABLE t1(a INT) engine= MEMORY;
FLUSH TABLE t1 FOR EXPORT;
DROP TABLE t1;
---connection con1
--disconnect con1
---source include/wait_until_disconnected.inc
-
--connection default
--echo # Test 7: Check privileges required.
@@ -313,10 +308,7 @@ UNLOCK TABLES;
--connection default
UNLOCK TABLES;
---connection con1
--disconnect con1
---source include/wait_until_disconnected.inc
-
--connection default
DROP TABLE t1, t2;
@@ -423,9 +415,7 @@ LOCK TABLES test.t1 WRITE;
UNLOCK TABLES;
DROP TABLE t1;
---connection con1
--disconnect con1
---source include/wait_until_disconnected.inc
--connection default
--echo # End of 5.6 tests
diff --git a/mysql-test/main/flush.result b/mysql-test/main/flush.result
index 584e79e72db6a..ccc7dc8b771a6 100644
--- a/mysql-test/main/flush.result
+++ b/mysql-test/main/flush.result
@@ -281,7 +281,6 @@ lock table t1 read, t2 read;
unlock tables;
connection default;
unlock tables;
-connection con1;
disconnect con1;
connection default;
drop table t1, t2, t3;
@@ -399,9 +398,7 @@ connection con2;
connection default;
commit;
# Cleanup
-connection con1;
disconnect con1;
-connection con2;
disconnect con2;
connection default;
drop table t1;
@@ -480,9 +477,7 @@ connection default;
# Reap INSERT.
handler t1 close;
# Cleanup.
-connection con1;
disconnect con1;
-connection con2;
disconnect con2;
connection default;
drop tables t1, t2;
diff --git a/mysql-test/main/flush.test b/mysql-test/main/flush.test
index 1085b469a0393..cb81f6e0fbcb1 100644
--- a/mysql-test/main/flush.test
+++ b/mysql-test/main/flush.test
@@ -177,7 +177,6 @@ set session low_priority_updates=default;
connect (con1,localhost,root,,);
send select benchmark(200, (select sin(1))) > 1000;
disconnect con1;
---source include/wait_until_disconnected.inc
connection default;
--echo End of 5.0 tests
@@ -361,9 +360,7 @@ unlock tables;
connection default;
unlock tables;
-connection con1;
disconnect con1;
---source include/wait_until_disconnected.inc
connection default;
drop table t1, t2, t3;
@@ -490,12 +487,8 @@ commit;
--echo # Cleanup
-connection con1;
disconnect con1;
---source include/wait_until_disconnected.inc
-connection con2;
disconnect con2;
---source include/wait_until_disconnected.inc
connection default;
drop table t1;
--enable_view_protocol
@@ -571,12 +564,8 @@ connection default;
handler t1 close;
--echo # Cleanup.
-connection con1;
disconnect con1;
---source include/wait_until_disconnected.inc
-connection con2;
disconnect con2;
---source include/wait_until_disconnected.inc
connection default;
drop tables t1, t2;
--enable_view_protocol
@@ -629,7 +618,6 @@ connect(con1, localhost, root);
FLUSH TABLES WITH READ LOCK;
UNLOCK TABLES;
disconnect con1;
---source include/wait_until_disconnected.inc
connection default;
COMMIT;
diff --git a/mysql-test/main/flush_block_commit.result b/mysql-test/main/flush_block_commit.result
index 73ea8859f1d07..1f577004ebd60 100644
--- a/mysql-test/main/flush_block_commit.result
+++ b/mysql-test/main/flush_block_commit.result
@@ -1,9 +1,7 @@
-# Save the initial number of concurrent sessions
connect con1,localhost,root,,;
connect con2,localhost,root,,;
connect con3,localhost,root,,;
connection con1;
-DROP TABLE IF EXISTS t1;
CREATE TABLE t1 (a INT) ENGINE=innodb;
BEGIN;
INSERT INTO t1 VALUES(1);
@@ -65,4 +63,3 @@ disconnect con3;
# drop the table.
DROP TABLE t1;
# End of 4.1 tests
-# Wait till all disconnects are completed
diff --git a/mysql-test/main/flush_block_commit.test b/mysql-test/main/flush_block_commit.test
index 0280aedf2ca73..a54cb67d53a2a 100644
--- a/mysql-test/main/flush_block_commit.test
+++ b/mysql-test/main/flush_block_commit.test
@@ -4,19 +4,14 @@
# This is intended to mimick how mysqldump and innobackup work.
# And it requires InnoDB
+--source include/no_view_protocol.inc
--source include/have_innodb.inc
---echo # Save the initial number of concurrent sessions
---source include/count_sessions.inc
-
connect (con1,localhost,root,,);
connect (con2,localhost,root,,);
connect (con3,localhost,root,,);
connection con1;
---disable_warnings
-DROP TABLE IF EXISTS t1;
---enable_warnings
CREATE TABLE t1 (a INT) ENGINE=innodb;
# blocks COMMIT ?
@@ -92,7 +87,3 @@ disconnect con3;
--echo # drop the table.
DROP TABLE t1;
--echo # End of 4.1 tests
-
---echo # Wait till all disconnects are completed
---source include/wait_until_count_sessions.inc
-
diff --git a/mysql-test/main/flush_block_commit_notembedded.result b/mysql-test/main/flush_block_commit_notembedded.result
index 7dd6410ac709e..d96eae85ceabe 100644
--- a/mysql-test/main/flush_block_commit_notembedded.result
+++ b/mysql-test/main/flush_block_commit_notembedded.result
@@ -1,4 +1,3 @@
-# Save the initial number of concurrent sessions
connect con1,localhost,root,,;
connect con2,localhost,root,,;
connection con1;
@@ -33,4 +32,3 @@ drop table t1;
connection default;
disconnect con1;
disconnect con2;
-# Wait till all disconnects are completed
diff --git a/mysql-test/main/flush_block_commit_notembedded.test b/mysql-test/main/flush_block_commit_notembedded.test
index 024640893d9c0..13899a24558e5 100644
--- a/mysql-test/main/flush_block_commit_notembedded.test
+++ b/mysql-test/main/flush_block_commit_notembedded.test
@@ -9,9 +9,6 @@
--source include/have_log_bin.inc
--source include/have_innodb.inc
---echo # Save the initial number of concurrent sessions
---source include/count_sessions.inc
-
--disable_query_log
# This may be triggered on a slow system or one that lacks native AIO.
call mtr.add_suppression("InnoDB: Trying to delete tablespace.*pending operations");
@@ -62,7 +59,3 @@ drop table t1;
connection default;
disconnect con1;
disconnect con2;
-
---echo # Wait till all disconnects are completed
---source include/wait_until_count_sessions.inc
-
diff --git a/mysql-test/main/flush_read_lock.result b/mysql-test/main/flush_read_lock.result
index a8f8431e1253b..8f5d39274809d 100644
--- a/mysql-test/main/flush_read_lock.result
+++ b/mysql-test/main/flush_read_lock.result
@@ -50,19 +50,6 @@ set local sql_mode="";
# check that DDL statements on temporary tables
# are compatible with FTRWL.
call mtr.add_suppression("BINLOG_BASE64_EVENT: Error executing row event.*error code: 1223");
-drop tables if exists t1_base, t2_base, t3_trans;
-drop tables if exists tm_base, tm_base_temp;
-drop database if exists mysqltest1;
-# We're going to test ALTER DATABASE UPGRADE
-drop database if exists `#mysql50#mysqltest-2`;
-drop procedure if exists p1;
-drop function if exists f1;
-drop view if exists v1;
-drop procedure if exists p2;
-drop function if exists f2_base;
-drop function if exists f2_temp;
-drop event if exists e1;
-drop event if exists e2;
create table t1_base(i int) engine=myisam;
create table t2_base(j int) engine=myisam;
create table t3_trans(i int) engine=innodb;
diff --git a/mysql-test/main/flush_read_lock.test b/mysql-test/main/flush_read_lock.test
index 358f020d4bc0d..619780df0dcf9 100644
--- a/mysql-test/main/flush_read_lock.test
+++ b/mysql-test/main/flush_read_lock.test
@@ -9,9 +9,8 @@
--source include/have_debug_sync.inc
# Parts of this test use DDL on events, BINLOG statement and
# other statements which are not supported in embedded server.
--- source include/not_embedded.inc
-# Save the initial number of concurrent sessions.
---source include/count_sessions.inc
+--source include/not_embedded.inc
+--source include/no_view_protocol.inc
set global sql_mode="";
set local sql_mode="";
@@ -68,21 +67,6 @@ set local sql_mode="";
call mtr.add_suppression("BINLOG_BASE64_EVENT: Error executing row event.*error code: 1223");
---disable_warnings
-drop tables if exists t1_base, t2_base, t3_trans;
-drop tables if exists tm_base, tm_base_temp;
-drop database if exists mysqltest1;
---echo # We're going to test ALTER DATABASE UPGRADE
-drop database if exists `#mysql50#mysqltest-2`;
-drop procedure if exists p1;
-drop function if exists f1;
-drop view if exists v1;
-drop procedure if exists p2;
-drop function if exists f2_base;
-drop function if exists f2_temp;
-drop event if exists e1;
-drop event if exists e2;
---enable_warnings
create table t1_base(i int) engine=myisam;
create table t2_base(j int) engine=myisam;
create table t3_trans(i int) engine=innodb;
@@ -2144,10 +2128,6 @@ disconnect con2;
disconnect con3;
set global sql_mode=default;
-# Check that all connections opened by test cases in this file are really
-# gone so execution of other tests won't be affected by their presence.
---source include/wait_until_count_sessions.inc
-
--echo #
--echo # Deadlock between FTWRL under open handler and DDL/LOCK TABLES
diff --git a/mysql-test/main/flush_read_lock_kill.test b/mysql-test/main/flush_read_lock_kill.test
index 8b76c0652272b..8807ea70ca791 100644
--- a/mysql-test/main/flush_read_lock_kill.test
+++ b/mysql-test/main/flush_read_lock_kill.test
@@ -13,9 +13,6 @@
# won't block FLUSH TABLES WITH GLOBAL READ LOCK.
--source include/have_innodb.inc
-# Save the initial number of concurrent sessions
---source include/count_sessions.inc
-
connect (con1,localhost,root,,);
connect (con2,localhost,root,,);
connection con1;
@@ -75,7 +72,3 @@ connection default;
disconnect con2;
DROP TABLE t1;
SET DEBUG_SYNC= 'RESET';
-
-# Wait till all disconnects are completed
---source include/wait_until_count_sessions.inc
-
diff --git a/mysql-test/main/foreign_key.result b/mysql-test/main/foreign_key.result
index 82bef2b23dee7..04067cb824c38 100644
--- a/mysql-test/main/foreign_key.result
+++ b/mysql-test/main/foreign_key.result
@@ -18,7 +18,7 @@ create table t2 (id int PRIMARY KEY, FOREIGN KEY (id) REFERENCES t1(id)) engine=
insert into t1 values (1), (2), (3), (4), (5), (6);
insert into t2 values (3), (5);
delete from t1;
-ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`id`) REFERENCES `t1` (`id`))
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `1` FOREIGN KEY (`id`) REFERENCES `t1` (`id`))
select * from t1;
id
1
@@ -29,8 +29,8 @@ id
6
delete ignore from t1;
Warnings:
-Warning 1451 Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`id`) REFERENCES `t1` (`id`))
-Warning 1451 Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`id`) REFERENCES `t1` (`id`))
+Warning 1451 Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `1` FOREIGN KEY (`id`) REFERENCES `t1` (`id`))
+Warning 1451 Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `1` FOREIGN KEY (`id`) REFERENCES `t1` (`id`))
select row_count();
row_count()
-1
diff --git a/mysql-test/main/foreign_key_lowercase0.result b/mysql-test/main/foreign_key_lowercase0.result
new file mode 100644
index 0000000000000..d3322459ae285
--- /dev/null
+++ b/mysql-test/main/foreign_key_lowercase0.result
@@ -0,0 +1,21 @@
+CREATE TABLE `FAMILY_PARENT` (
+`PARENT_ID` char(36) NOT NULL,
+`PARENT_NAME` varchar(200) NOT NULL,
+PRIMARY KEY (`PARENT_ID`)
+) ENGINE=InnoDB CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
+CREATE TABLE `FAMILY_CHILD` (
+`PARENT_ID` char(36) NOT NULL,
+`CHILD_NAME` varchar(200) NOT NULL,
+PRIMARY KEY (`PARENT_ID`,`CHILD_NAME`),
+CONSTRAINT `CHILD_FK` FOREIGN KEY (`PARENT_ID`) REFERENCES `FAMILY_PARENT` (`PARENT_ID`) ON DELETE CASCADE
+) ENGINE=InnoDB CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
+SHOW CREATE TABLE FAMILY_CHILD;
+Table Create Table
+FAMILY_CHILD CREATE TABLE `FAMILY_CHILD` (
+ `PARENT_ID` char(36) NOT NULL,
+ `CHILD_NAME` varchar(200) NOT NULL,
+ PRIMARY KEY (`PARENT_ID`,`CHILD_NAME`),
+ CONSTRAINT `CHILD_FK` FOREIGN KEY (`PARENT_ID`) REFERENCES `FAMILY_PARENT` (`PARENT_ID`) ON DELETE CASCADE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin
+DROP TABLE FAMILY_CHILD;
+DROP TABLE FAMILY_PARENT;
diff --git a/mysql-test/main/foreign_key_lowercase0.test b/mysql-test/main/foreign_key_lowercase0.test
new file mode 100644
index 0000000000000..eafd3755166d2
--- /dev/null
+++ b/mysql-test/main/foreign_key_lowercase0.test
@@ -0,0 +1,22 @@
+# echo MDEV-34953 tablename of CONSTRAINT FOREIGN KEY REFERENCES
+--source include/have_lowercase0.inc
+--source include/have_innodb.inc
+CREATE TABLE `FAMILY_PARENT` (
+ `PARENT_ID` char(36) NOT NULL,
+ `PARENT_NAME` varchar(200) NOT NULL,
+ PRIMARY KEY (`PARENT_ID`)
+) ENGINE=InnoDB CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
+
+CREATE TABLE `FAMILY_CHILD` (
+ `PARENT_ID` char(36) NOT NULL,
+ `CHILD_NAME` varchar(200) NOT NULL,
+ PRIMARY KEY (`PARENT_ID`,`CHILD_NAME`),
+ CONSTRAINT `CHILD_FK` FOREIGN KEY (`PARENT_ID`) REFERENCES `FAMILY_PARENT` (`PARENT_ID`) ON DELETE CASCADE
+) ENGINE=InnoDB CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
+
+# check that foreign key constraint name
+SHOW CREATE TABLE FAMILY_CHILD;
+
+DROP TABLE FAMILY_CHILD;
+DROP TABLE FAMILY_PARENT;
+
diff --git a/mysql-test/main/func_compress.test b/mysql-test/main/func_compress.test
index d1822a099a357..a8170eed2db79 100644
--- a/mysql-test/main/func_compress.test
+++ b/mysql-test/main/func_compress.test
@@ -59,7 +59,6 @@ set @@global.max_allowed_packet=1048576*100;
--connect (newconn, localhost, root,,)
eval select compress(repeat('aaaaaaaaaa', IF('$LOW_MEMORY', 10, 10000000))) is null;
disconnect newconn;
---source include/wait_until_disconnected.inc
connection default;
set @@global.max_allowed_packet=@save_max_allowed_packet;
diff --git a/mysql-test/main/func_crypt.result b/mysql-test/main/func_crypt.result
index 87c55dd21c38e..f97262238cd13 100644
--- a/mysql-test/main/func_crypt.result
+++ b/mysql-test/main/func_crypt.result
@@ -45,6 +45,8 @@ select password(NULL);
password(NULL)
set global old_passwords=on;
+Warnings:
+Warning 4200 The setting 'old_passwords' is ignored. It only exists for compatibility with old installations and will be removed in a future release
select password('');
password('')
@@ -58,20 +60,26 @@ select old_password('idkfa');
old_password('idkfa')
5c078dc54ca0fcca
set old_passwords=on;
+Warnings:
+Warning 4200 The setting 'old_passwords' is ignored. It only exists for compatibility with old installations and will be removed in a future release
select password('idkfa');
password('idkfa')
-5c078dc54ca0fcca
+*B669C9DAC3AA6F2254B03CDEF8DFDD6B2D1054BA
select old_password('idkfa');
old_password('idkfa')
5c078dc54ca0fcca
set global old_passwords=off;
+Warnings:
+Warning 4200 The setting 'old_passwords' is ignored. It only exists for compatibility with old installations and will be removed in a future release
select password('idkfa');
password('idkfa')
-5c078dc54ca0fcca
+*B669C9DAC3AA6F2254B03CDEF8DFDD6B2D1054BA
select old_password('idkfa');
old_password('idkfa')
5c078dc54ca0fcca
set old_passwords=off;
+Warnings:
+Warning 4200 The setting 'old_passwords' is ignored. It only exists for compatibility with old installations and will be removed in a future release
select password('idkfa ');
password('idkfa ')
*2DC31D90647B4C1ABC9231563D2236E96C9A2DB2
diff --git a/mysql-test/main/func_des_encrypt.result b/mysql-test/main/func_des_encrypt.result
deleted file mode 100644
index e24f6b32b566b..0000000000000
--- a/mysql-test/main/func_des_encrypt.result
+++ /dev/null
@@ -1,101 +0,0 @@
-select des_encrypt('hello');
-des_encrypt('hello')
-2nV}
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-#
-# Bug #11643: des_encrypt() causes server to die
-#
-CREATE TABLE t1 (des VARBINARY(200) NOT NULL DEFAULT '') ENGINE=MyISAM;
-INSERT INTO t1 VALUES ('1234'), ('12345'), ('123456'), ('1234567');
-UPDATE t1 SET des=DES_ENCRYPT('1234');
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-SELECT LENGTH(des) FROM t1;
-LENGTH(des)
-9
-9
-9
-9
-SELECT DES_DECRYPT(des) FROM t1;
-DES_DECRYPT(des)
-1234
-1234
-1234
-1234
-Warnings:
-Warning 1287 'des_decrypt' is deprecated and will be removed in a future release
-SELECT
-LENGTH(DES_ENCRYPT('1234')),
-LENGTH(DES_ENCRYPT('12345')),
-LENGTH(DES_ENCRYPT('123456')),
-LENGTH(DES_ENCRYPT('1234567'));
-LENGTH(DES_ENCRYPT('1234')) LENGTH(DES_ENCRYPT('12345')) LENGTH(DES_ENCRYPT('123456')) LENGTH(DES_ENCRYPT('1234567'))
-9 9 9 9
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-SELECT
-DES_DECRYPT(DES_ENCRYPT('1234')),
-DES_DECRYPT(DES_ENCRYPT('12345')),
-DES_DECRYPT(DES_ENCRYPT('123456')),
-DES_DECRYPT(DES_ENCRYPT('1234567'));
-DES_DECRYPT(DES_ENCRYPT('1234')) DES_DECRYPT(DES_ENCRYPT('12345')) DES_DECRYPT(DES_ENCRYPT('123456')) DES_DECRYPT(DES_ENCRYPT('1234567'))
-1234 12345 123456 1234567
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-Warning 1287 'des_decrypt' is deprecated and will be removed in a future release
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-Warning 1287 'des_decrypt' is deprecated and will be removed in a future release
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-Warning 1287 'des_decrypt' is deprecated and will be removed in a future release
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-Warning 1287 'des_decrypt' is deprecated and will be removed in a future release
-DROP TABLE t1;
-End of 5.0 tests
-#
-# MDEV-23330 Server crash or ASAN negative-size-param in
-# my_strnncollsp_binary / SORT_FIELD_ATTR::compare_packed_varstrings
-#
-CREATE TABLE t1 (a CHAR(240), b BIT(48));
-INSERT INTO t1 VALUES ('a',b'0001'),('b',b'0010'),('c',b'0011'),('d',b'0100'),('e',b'0001'),('f',b'0101'),('g',b'0110'),('h',b'0111'),('i',b'1000'),('j',b'1001');
-SELECT DES_DECRYPT(a, 'x'), HEX(BINARY b) FROM t1 GROUP BY 1, 2 WITH ROLLUP;
-DES_DECRYPT(a, 'x') HEX(BINARY b)
-a 000000000001
-a NULL
-b 000000000002
-b NULL
-c 000000000003
-c NULL
-d 000000000004
-d NULL
-e 000000000001
-e NULL
-f 000000000005
-f NULL
-g 000000000006
-g NULL
-h 000000000007
-h NULL
-i 000000000008
-i NULL
-j 000000000009
-j NULL
-NULL NULL
-Warnings:
-Warning 1287 'des_decrypt' is deprecated and will be removed in a future release
-DROP TABLE t1;
-CREATE TABLE t1 (a INT);
-INSERT t1 VALUES (1),(2);
-SELECT CHAR_LENGTH(a), DES_DECRYPT(a) FROM (SELECT _utf8 0xC2A2 AS a FROM t1) AS t2;
-CHAR_LENGTH(a) DES_DECRYPT(a)
-1
-1
-Warnings:
-Warning 1287 'des_decrypt' is deprecated and will be removed in a future release
-DROP TABLE t1;
-#
-# End of 10.5 tests
-#
diff --git a/mysql-test/main/func_des_encrypt.test b/mysql-test/main/func_des_encrypt.test
deleted file mode 100644
index 20f4c46fbf55c..0000000000000
--- a/mysql-test/main/func_des_encrypt.test
+++ /dev/null
@@ -1,70 +0,0 @@
--- source include/have_des.inc
-#double warning for view protocol
---source include/no_view_protocol.inc
-
-# This test can't be in func_encrypt.test, because it requires
-# --des-key-file to not be set.
-
-#
-# Bug #11643: des_encrypt() causes server to die
-#
-select des_encrypt('hello');
-
-# End of 4.1 tests
-
---echo #
---echo # Bug #11643: des_encrypt() causes server to die
---echo #
-
-CREATE TABLE t1 (des VARBINARY(200) NOT NULL DEFAULT '') ENGINE=MyISAM;
-
-INSERT INTO t1 VALUES ('1234'), ('12345'), ('123456'), ('1234567');
-
-UPDATE t1 SET des=DES_ENCRYPT('1234');
-
-SELECT LENGTH(des) FROM t1;
-SELECT DES_DECRYPT(des) FROM t1;
-
-SELECT
- LENGTH(DES_ENCRYPT('1234')),
- LENGTH(DES_ENCRYPT('12345')),
- LENGTH(DES_ENCRYPT('123456')),
- LENGTH(DES_ENCRYPT('1234567'));
-SELECT
- DES_DECRYPT(DES_ENCRYPT('1234')),
- DES_DECRYPT(DES_ENCRYPT('12345')),
- DES_DECRYPT(DES_ENCRYPT('123456')),
- DES_DECRYPT(DES_ENCRYPT('1234567'));
-
-DROP TABLE t1;
-
---Echo End of 5.0 tests
-
---echo #
---echo # MDEV-23330 Server crash or ASAN negative-size-param in
---echo # my_strnncollsp_binary / SORT_FIELD_ATTR::compare_packed_varstrings
---echo #
-
-CREATE TABLE t1 (a CHAR(240), b BIT(48));
-INSERT INTO t1 VALUES ('a',b'0001'),('b',b'0010'),('c',b'0011'),('d',b'0100'),('e',b'0001'),('f',b'0101'),('g',b'0110'),('h',b'0111'),('i',b'1000'),('j',b'1001');
-SELECT DES_DECRYPT(a, 'x'), HEX(BINARY b) FROM t1 GROUP BY 1, 2 WITH ROLLUP;
-DROP TABLE t1;
-
-#
-# don't change the charset of a literal Item_string
-#
-
-CREATE TABLE t1 (a INT);
-INSERT t1 VALUES (1),(2);
-# There is a problem with cursor-protocol and DES_DECRYPT(),
-# but DES_DECRYPT has been deprecated from MariaDB 10.10.0,
-# and will be removed in a future release. That's why this
-# case is excluded without bug
---disable_cursor_protocol
-SELECT CHAR_LENGTH(a), DES_DECRYPT(a) FROM (SELECT _utf8 0xC2A2 AS a FROM t1) AS t2;
---enable_cursor_protocol
-DROP TABLE t1;
-
---echo #
---echo # End of 10.5 tests
---echo #
diff --git a/mysql-test/main/func_encrypt.result b/mysql-test/main/func_encrypt.result
deleted file mode 100644
index d58f1ef5ef4be..0000000000000
--- a/mysql-test/main/func_encrypt.result
+++ /dev/null
@@ -1,373 +0,0 @@
-drop table if exists t1;
-create table t1 (x blob);
-insert into t1 values (des_encrypt('The quick red fox jumped over the lazy brown dog','The quick red fox jumped over the lazy brown dog'));
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-insert into t1 values (des_encrypt('a','The quick red fox jumped over the lazy brown dog'));
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-insert into t1 values (des_encrypt('The quick red fox jumped over the lazy brown dog','a'));
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-insert into t1 values (des_encrypt('ab','The quick red fox jumped over the lazy brown dog'));
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-insert into t1 values (des_encrypt('The quick red fox jumped over the lazy brown dog','ab'));
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-insert into t1 values (des_encrypt('abc','The quick red fox jumped over the lazy brown dog'));
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-insert into t1 values (des_encrypt('The quick red fox jumped over the lazy brown dog','abc'));
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-insert into t1 values (des_encrypt('abcd','The quick red fox jumped over the lazy brown dog'));
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-insert into t1 values (des_encrypt('The quick red fox jumped over the lazy brown dog','abcd'));
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-insert into t1 values (des_encrypt('abcde','The quick red fox jumped over the lazy brown dog'));
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-insert into t1 values (des_encrypt('The quick red fox jumped over the lazy brown dog','abcde'));
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-insert into t1 values (des_encrypt('abcdef','The quick red fox jumped over the lazy brown dog'));
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-insert into t1 values (des_encrypt('The quick red fox jumped over the lazy brown dog','abcdef'));
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-insert into t1 values (des_encrypt('abcdefg','The quick red fox jumped over the lazy brown dog'));
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-insert into t1 values (des_encrypt('The quick red fox jumped over the lazy brown dog','abcdefg'));
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-insert into t1 values (des_encrypt('abcdefgh','The quick red fox jumped over the lazy brown dog'));
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-insert into t1 values (des_encrypt('The quick red fox jumped over the lazy brown dog','abcdefgh'));
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-insert into t1 values (des_encrypt('abcdefghi','The quick red fox jumped over the lazy brown dog'));
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-insert into t1 values (des_encrypt('The quick red fox jumped over the lazy brown dog','abcdefghi'));
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-insert into t1 values (des_encrypt('abcdefghij','The quick red fox jumped over the lazy brown dog'));
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-insert into t1 values (des_encrypt('The quick red fox jumped over the lazy brown dog','abcdefghij'));
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-insert into t1 values (des_encrypt('abcdefghijk','The quick red fox jumped over the lazy brown dog'));
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-insert into t1 values (des_encrypt('The quick red fox jumped over the lazy brown dog','abcdefghijk'));
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-insert into t1 values (des_encrypt('The quick red fox jumped over the lazy brown dog','sabakala'));
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-insert into t1 values (des_encrypt('quick red fox jumped over the lazy brown dog','sabakala'));
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-insert into t1 values (des_encrypt('red fox jumped over the lazy brown dog','sabakala'));
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-insert into t1 values (des_encrypt('fox jumped over the lazy brown dog','sabakala'));
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-insert into t1 values (des_encrypt('jumped over the lazy brown dog','sabakala'));
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-insert into t1 values (des_encrypt('over the lazy brown dog','sabakala'));
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-insert into t1 values (des_encrypt('the lazy brown dog','sabakala'));
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-insert into t1 values (des_encrypt('lazy brown dog','sabakala'));
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-insert into t1 values (des_encrypt('brown dog','sabakala'));
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-insert into t1 values (des_encrypt('dog','sabakala'));
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-insert into t1 values (des_encrypt('dog!','sabakala'));
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-insert into t1 values (des_encrypt('dog!!','sabakala'));
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-insert into t1 values (des_encrypt('dog!!!','sabakala'));
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-insert into t1 values (des_encrypt('dog!!!!','sabakala'));
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-insert into t1 values (des_encrypt('dog!!!!!','sabakala'));
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-insert into t1 values (des_encrypt('jumped over the lazy brown dog','sabakala'));
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-insert into t1 values (des_encrypt('jumped over the lazy brown dog','sabakala'));
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-select hex(x), hex(des_decrypt(x,'sabakala')) from t1;
-hex(x) hex(des_decrypt(x,'sabakala'))
-FFA185A4656D113445E31D7A5B31BB57671A4CA9E21E63FE5D9C801E0CC7AA6190C13E269C2AE8D8060D3FB3FEA94FEC7FB006B9DCAC3E3E41 NULL
-FFC620C3B84E926A54 NULL
-FFA4F77D4220A16C980AF7CB576F8DC0A864F357825C16F329F24F66EBA775765B7C1538B90970740F853B556AEBD35AC31B962EA9B12B5AD4 NULL
-FFACFF5921BB876A90 NULL
-FFA6F18760E7CC5A4C325244B8486F692AAA11D229AF9ED4E4C9D56D7C0278C0DDA58F73E15E2B5F6C1DDD19B22B8071C454C930585449AAEB NULL
-FF3736DFEDC4B765F4 NULL
-FF598681EA5F03CD6D6AEA2B118DF4885DD78BECDFB012BBB05386E436DC403D3CB9DE3BE8D5D3BB7FD90A1F9F9A3E055BB3B4FD3F6A869473 NULL
-FF15B8B5952D630CAE NULL
-FF11EE3A400685226B76D5EC567681FA90247CE3C9DBE43341311C22F74562B1199957D80E300737791F6345BBC61AE03F28F52E5A6DCC78B2 NULL
-FF0A832AE10DC85483 NULL
-FF6F5C0BF4C5F899B4E7C091D9B1F1E92A7623B651B150CA3E7F420B4DD316D2C1BF76FCF9F9A046C000A9E21C106591E8C1930201B1750269 NULL
-FFA08D5FB849A9FC90 NULL
-FFF7331312FE153A39B1EC0D65BC1D3A0B6FCD49DA8C95D6161F53B11D297BAE142BCA6B9492DAE9A02AF455F16CA2C1CF4E1AD17297E947E2 NULL
-FFDEE60A938478E059 NULL
-FF95A729E73D5D87416A53055029E8CAA95B4F7B49F3D2D821A95D1FCE70F4B7A3226077176723F3DCC0A44D3B2EE9EFBC4D31AA87C948916C NULL
-FF1C78557F542A1FDC91943761B2EED14F NULL
-FF1E35B0775EEE512544A75BDAF58EA1655F5C899D3C5191A47263E2D11C3E688F662AB79F66D3B1DF9C75BD869EB8E04FDAE85719CB573A43 NULL
-FF1C78557F542A1FDCDC4182B5314185E5 NULL
-FF783123DCB36F98A51C39A560C92E129F1DDEEAB170825406A61260FBFBBFB0F2E48DB3282588A975C9C71E0EACA71A2B642A8C9C2E921A9F NULL
-FF1C78557F542A1FDCAC4B1B6B47206306 NULL
-FF6D9B450837017D06CA1F1C9A0E700D03DEF06A4F954527A961CA805F70320E9F3F0007636B80768A253A5F7ADABC18B78F1A2FA560CC0B21 NULL
-FF1C78557F542A1FDCE9038BD99DD43F2E NULL
-FF23FD03BA7548DD0957EBA7A8FBF7A18589762F3913E9A935BDA72F6F28202DC64572E0D633A54EA55BFD2C749E408C8632CCE36A7AE00619 NULL
-FFD8DD3C4ABCB02FCDFE1383ECC0F61E7D02CD3BA72BBAEA26384D14835796501B3DC9A2F7EC2FC1633BDA6D56464536FE12010049C53A1991 54686520717569636B2072656420666F78206A756D706564206F76657220746865206C617A792062726F776E20646F67
-FFACC5C5479575CBCA518B05778139B1BFC10F07299C98D04F580BC2F816828722D65A89C1831BD29DA626D319813BD374 717569636B2072656420666F78206A756D706564206F76657220746865206C617A792062726F776E20646F67
-FF128D5517241DEEC631ABD2A47FA66E57930001417F18204328B0B2CB13F7AD2F50B8336EFAE7DE21 72656420666F78206A756D706564206F76657220746865206C617A792062726F776E20646F67
-FF7CF971283B4DC2D050B3DB22684737B74B5B1CF12CF2FAC5A5995A298505F56D82BBFB9FC3E70059 666F78206A756D706564206F76657220746865206C617A792062726F776E20646F67
-FF8333F3DD21E4488F967E03DD12394813A49F72848BB49473D3CB1C8A1AACF220 6A756D706564206F76657220746865206C617A792062726F776E20646F67
-FFE8CB7FD80E6262C5FEB042A2DCC73B699CEEDCA6DC4458A0 6F76657220746865206C617A792062726F776E20646F67
-FFA29334D7CDB1B403DF3EB992067DD524C7D568E8D98EBFE5 746865206C617A792062726F776E20646F67
-FF4F0C5858FE2358D400E38831D5577C85 6C617A792062726F776E20646F67
-FFB370CD6BAFD1CB95974D21DCCA2DD9D7 62726F776E20646F67
-FF8F7777B28C7A459A 646F67
-FF75213A4D7D01D715 646F6721
-FF2DCAF574B173FB4D 646F672121
-FFFA775787BE776B15 646F67212121
-FF3FC2E42D7C840905 646F6721212121
-FF9723312D26D9E6DA01D01A784A64DB9D 646F672121212121
-FF8333F3DD21E4488F967E03DD12394813A49F72848BB49473D3CB1C8A1AACF220 6A756D706564206F76657220746865206C617A792062726F776E20646F67
-FF8333F3DD21E4488F967E03DD12394813A49F72848BB49473D3CB1C8A1AACF220 6A756D706564206F76657220746865206C617A792062726F776E20646F67
-Warnings:
-Warning 1287 'des_decrypt' is deprecated and will be removed in a future release
-select des_decrypt(x,'sabakala') as s from t1 having s like '%dog%';
-s
-The quick red fox jumped over the lazy brown dog
-quick red fox jumped over the lazy brown dog
-red fox jumped over the lazy brown dog
-fox jumped over the lazy brown dog
-jumped over the lazy brown dog
-over the lazy brown dog
-the lazy brown dog
-lazy brown dog
-brown dog
-dog
-dog!
-dog!!
-dog!!!
-dog!!!!
-dog!!!!!
-jumped over the lazy brown dog
-jumped over the lazy brown dog
-Warnings:
-Warning 1287 'des_decrypt' is deprecated and will be removed in a future release
-drop table t1;
-select hex(des_encrypt("hello")),des_decrypt(des_encrypt("hello"));
-hex(des_encrypt("hello")) des_decrypt(des_encrypt("hello"))
-85D6DC8859F9759BBB hello
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-Warning 1287 'des_decrypt' is deprecated and will be removed in a future release
-select des_decrypt(des_encrypt("hello",4));
-des_decrypt(des_encrypt("hello",4))
-hello
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-Warning 1287 'des_decrypt' is deprecated and will be removed in a future release
-select des_decrypt(des_encrypt("hello",'test'),'test');
-des_decrypt(des_encrypt("hello",'test'),'test')
-hello
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-Warning 1287 'des_decrypt' is deprecated and will be removed in a future release
-select hex(des_encrypt("hello")),hex(des_encrypt("hello",5)),hex(des_encrypt("hello",'default_password'));
-hex(des_encrypt("hello")) hex(des_encrypt("hello",5)) hex(des_encrypt("hello",'default_password'))
-85D6DC8859F9759BBB 85D6DC8859F9759BBB FFD6DC8859F9759BBB
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-select des_decrypt(des_encrypt("hello"),'default_password');
-des_decrypt(des_encrypt("hello"),'default_password')
-hello
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-Warning 1287 'des_decrypt' is deprecated and will be removed in a future release
-select des_decrypt(des_encrypt("hello",4),'password4');
-des_decrypt(des_encrypt("hello",4),'password4')
-hello
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-Warning 1287 'des_decrypt' is deprecated and will be removed in a future release
-select des_encrypt("hello",10);
-des_encrypt("hello",10)
-NULL
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-Warning 1108 Incorrect parameters to procedure 'des_encrypt'
-select des_encrypt(NULL);
-des_encrypt(NULL)
-NULL
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-select des_encrypt(NULL, 10);
-des_encrypt(NULL, 10)
-NULL
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-select des_encrypt(NULL, NULL);
-des_encrypt(NULL, NULL)
-NULL
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-select des_encrypt(10, NULL);
-des_encrypt(10, NULL)
-NULL
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-Warning 1108 Incorrect parameters to procedure 'des_encrypt'
-select des_encrypt("hello", NULL);
-des_encrypt("hello", NULL)
-NULL
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-Warning 1108 Incorrect parameters to procedure 'des_encrypt'
-select des_decrypt("hello",10);
-des_decrypt("hello",10)
-hello
-Warnings:
-Warning 1287 'des_decrypt' is deprecated and will be removed in a future release
-select des_decrypt(NULL);
-des_decrypt(NULL)
-NULL
-Warnings:
-Warning 1287 'des_decrypt' is deprecated and will be removed in a future release
-select des_decrypt(NULL, 10);
-des_decrypt(NULL, 10)
-NULL
-Warnings:
-Warning 1287 'des_decrypt' is deprecated and will be removed in a future release
-select des_decrypt(NULL, NULL);
-des_decrypt(NULL, NULL)
-NULL
-Warnings:
-Warning 1287 'des_decrypt' is deprecated and will be removed in a future release
-select des_decrypt(10, NULL);
-des_decrypt(10, NULL)
-10
-Warnings:
-Warning 1287 'des_decrypt' is deprecated and will be removed in a future release
-select des_decrypt("hello", NULL);
-des_decrypt("hello", NULL)
-hello
-Warnings:
-Warning 1287 'des_decrypt' is deprecated and will be removed in a future release
-SET @a=des_decrypt(des_encrypt("hello"));
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-Warning 1287 'des_decrypt' is deprecated and will be removed in a future release
-flush des_key_file;
-select @a = des_decrypt(des_encrypt("hello"));
-@a = des_decrypt(des_encrypt("hello"))
-1
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-Warning 1287 'des_decrypt' is deprecated and will be removed in a future release
-select hex("hello");
-hex("hello")
-68656C6C6F
-select hex(des_decrypt(des_encrypt("hello",4),'password2'));
-hex(des_decrypt(des_encrypt("hello",4),'password2'))
-NULL
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-Warning 1287 'des_decrypt' is deprecated and will be removed in a future release
-select hex(des_decrypt(des_encrypt("hello","hidden")));
-hex(des_decrypt(des_encrypt("hello","hidden")))
-NULL
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-Warning 1287 'des_decrypt' is deprecated and will be removed in a future release
-Warning 1108 Incorrect parameters to procedure 'des_decrypt'
-explain extended select des_decrypt(des_encrypt("hello",4),'password2'), des_decrypt(des_encrypt("hello","hidden"));
-id select_type table type possible_keys key key_len ref rows filtered Extra
-1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-Warning 1287 'des_decrypt' is deprecated and will be removed in a future release
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-Warning 1287 'des_decrypt' is deprecated and will be removed in a future release
-Note 1003 select des_decrypt(des_encrypt('hello',4),'password2') AS `des_decrypt(des_encrypt("hello",4),'password2')`,des_decrypt(des_encrypt('hello','hidden')) AS `des_decrypt(des_encrypt("hello","hidden"))`
-#
-# Start of 10.1 tests
-#
-#
-# MDEV-8369 Unexpected impossible WHERE for a condition on a ZEROFILL field
-#
-CREATE TABLE t1 (a INT(6) ZEROFILL);
-INSERT INTO t1 VALUES (1),(2);
-EXPLAIN EXTENDED
-SELECT * FROM t1 WHERE a=1 AND DES_ENCRYPT('test',a)=_latin1 'abc' COLLATE latin1_bin;
-id select_type table type possible_keys key key_len ref rows filtered Extra
-1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = 1 and des_encrypt('test',`test`.`t1`.`a`) = 'abc'
-DROP TABLE t1;
-#
-# End of 10.1 tests
-#
-#
-# Start of 10.2 tests
-#
-#
-# MDEV-10134 Add full support for DEFAULT
-#
-CREATE TABLE t1 (
-a VARCHAR(30),
-b BLOB DEFAULT DES_ENCRYPT(a, 'passwd'),
-c TEXT DEFAULT DES_DECRYPT(b, 'passwd')
-);
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-Warning 1287 'des_decrypt' is deprecated and will be removed in a future release
-SHOW CREATE TABLE t1;
-Table Create Table
-t1 CREATE TABLE `t1` (
- `a` varchar(30) DEFAULT NULL,
- `b` blob DEFAULT des_encrypt(`a`,'passwd'),
- `c` text DEFAULT des_decrypt(`b`,'passwd')
-) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci
-INSERT INTO t1 (a) VALUES ('test');
-SELECT c FROM t1;
-c
-test
-DROP TABLE t1;
-#
-# End of 10.2 tests
-#
diff --git a/mysql-test/main/func_encrypt.test b/mysql-test/main/func_encrypt.test
deleted file mode 100644
index 306939ef2ac85..0000000000000
--- a/mysql-test/main/func_encrypt.test
+++ /dev/null
@@ -1,134 +0,0 @@
--- source include/have_des.inc
-#double warning for view protocol
---source include/no_view_protocol.inc
-
---disable_warnings
-drop table if exists t1;
---enable_warnings
-
-create table t1 (x blob);
-insert into t1 values (des_encrypt('The quick red fox jumped over the lazy brown dog','The quick red fox jumped over the lazy brown dog'));
-insert into t1 values (des_encrypt('a','The quick red fox jumped over the lazy brown dog'));
-insert into t1 values (des_encrypt('The quick red fox jumped over the lazy brown dog','a'));
-insert into t1 values (des_encrypt('ab','The quick red fox jumped over the lazy brown dog'));
-insert into t1 values (des_encrypt('The quick red fox jumped over the lazy brown dog','ab'));
-insert into t1 values (des_encrypt('abc','The quick red fox jumped over the lazy brown dog'));
-insert into t1 values (des_encrypt('The quick red fox jumped over the lazy brown dog','abc'));
-insert into t1 values (des_encrypt('abcd','The quick red fox jumped over the lazy brown dog'));
-insert into t1 values (des_encrypt('The quick red fox jumped over the lazy brown dog','abcd'));
-insert into t1 values (des_encrypt('abcde','The quick red fox jumped over the lazy brown dog'));
-insert into t1 values (des_encrypt('The quick red fox jumped over the lazy brown dog','abcde'));
-insert into t1 values (des_encrypt('abcdef','The quick red fox jumped over the lazy brown dog'));
-insert into t1 values (des_encrypt('The quick red fox jumped over the lazy brown dog','abcdef'));
-insert into t1 values (des_encrypt('abcdefg','The quick red fox jumped over the lazy brown dog'));
-insert into t1 values (des_encrypt('The quick red fox jumped over the lazy brown dog','abcdefg'));
-insert into t1 values (des_encrypt('abcdefgh','The quick red fox jumped over the lazy brown dog'));
-insert into t1 values (des_encrypt('The quick red fox jumped over the lazy brown dog','abcdefgh'));
-insert into t1 values (des_encrypt('abcdefghi','The quick red fox jumped over the lazy brown dog'));
-insert into t1 values (des_encrypt('The quick red fox jumped over the lazy brown dog','abcdefghi'));
-insert into t1 values (des_encrypt('abcdefghij','The quick red fox jumped over the lazy brown dog'));
-insert into t1 values (des_encrypt('The quick red fox jumped over the lazy brown dog','abcdefghij'));
-insert into t1 values (des_encrypt('abcdefghijk','The quick red fox jumped over the lazy brown dog'));
-insert into t1 values (des_encrypt('The quick red fox jumped over the lazy brown dog','abcdefghijk'));
-insert into t1 values (des_encrypt('The quick red fox jumped over the lazy brown dog','sabakala'));
-insert into t1 values (des_encrypt('quick red fox jumped over the lazy brown dog','sabakala'));
-insert into t1 values (des_encrypt('red fox jumped over the lazy brown dog','sabakala'));
-insert into t1 values (des_encrypt('fox jumped over the lazy brown dog','sabakala'));
-insert into t1 values (des_encrypt('jumped over the lazy brown dog','sabakala'));
-insert into t1 values (des_encrypt('over the lazy brown dog','sabakala'));
-insert into t1 values (des_encrypt('the lazy brown dog','sabakala'));
-insert into t1 values (des_encrypt('lazy brown dog','sabakala'));
-insert into t1 values (des_encrypt('brown dog','sabakala'));
-insert into t1 values (des_encrypt('dog','sabakala'));
-insert into t1 values (des_encrypt('dog!','sabakala'));
-insert into t1 values (des_encrypt('dog!!','sabakala'));
-insert into t1 values (des_encrypt('dog!!!','sabakala'));
-insert into t1 values (des_encrypt('dog!!!!','sabakala'));
-insert into t1 values (des_encrypt('dog!!!!!','sabakala'));
-insert into t1 values (des_encrypt('jumped over the lazy brown dog','sabakala'));
-insert into t1 values (des_encrypt('jumped over the lazy brown dog','sabakala'));
-select hex(x), hex(des_decrypt(x,'sabakala')) from t1;
-select des_decrypt(x,'sabakala') as s from t1 having s like '%dog%';
-drop table t1;
-
-#
-# Test default keys
-#
-select hex(des_encrypt("hello")),des_decrypt(des_encrypt("hello"));
-select des_decrypt(des_encrypt("hello",4));
-select des_decrypt(des_encrypt("hello",'test'),'test');
-select hex(des_encrypt("hello")),hex(des_encrypt("hello",5)),hex(des_encrypt("hello",'default_password'));
-select des_decrypt(des_encrypt("hello"),'default_password');
-select des_decrypt(des_encrypt("hello",4),'password4');
-
-# Test use of invalid parameters
-select des_encrypt("hello",10);
-select des_encrypt(NULL);
-select des_encrypt(NULL, 10);
-select des_encrypt(NULL, NULL);
-select des_encrypt(10, NULL);
-select des_encrypt("hello", NULL);
-
-select des_decrypt("hello",10);
-select des_decrypt(NULL);
-select des_decrypt(NULL, 10);
-select des_decrypt(NULL, NULL);
-select des_decrypt(10, NULL);
-select des_decrypt("hello", NULL);
-
-
-# Test flush
-SET @a=des_decrypt(des_encrypt("hello"));
-flush des_key_file;
-select @a = des_decrypt(des_encrypt("hello"));
-
-# Test usage of wrong password
-select hex("hello");
-select hex(des_decrypt(des_encrypt("hello",4),'password2'));
-select hex(des_decrypt(des_encrypt("hello","hidden")));
-
-explain extended select des_decrypt(des_encrypt("hello",4),'password2'), des_decrypt(des_encrypt("hello","hidden"));
-
-# End of 4.1 tests
-
---echo #
---echo # Start of 10.1 tests
---echo #
-
---echo #
---echo # MDEV-8369 Unexpected impossible WHERE for a condition on a ZEROFILL field
---echo #
-CREATE TABLE t1 (a INT(6) ZEROFILL);
-INSERT INTO t1 VALUES (1),(2);
-# This should not propagate a=1 into DES_ENCRYPT
-EXPLAIN EXTENDED
-SELECT * FROM t1 WHERE a=1 AND DES_ENCRYPT('test',a)=_latin1 'abc' COLLATE latin1_bin;
-DROP TABLE t1;
-
---echo #
---echo # End of 10.1 tests
---echo #
-
---echo #
---echo # Start of 10.2 tests
---echo #
-
---echo #
---echo # MDEV-10134 Add full support for DEFAULT
---echo #
-
-CREATE TABLE t1 (
- a VARCHAR(30),
- b BLOB DEFAULT DES_ENCRYPT(a, 'passwd'),
- c TEXT DEFAULT DES_DECRYPT(b, 'passwd')
-);
---disable_warnings
-SHOW CREATE TABLE t1;
---enable_warnings
-INSERT INTO t1 (a) VALUES ('test');
-SELECT c FROM t1;
-DROP TABLE t1;
-
---echo #
---echo # End of 10.2 tests
---echo #
diff --git a/mysql-test/main/func_encrypt_nossl.result b/mysql-test/main/func_encrypt_nossl.result
deleted file mode 100644
index 274db05fd8cea..0000000000000
--- a/mysql-test/main/func_encrypt_nossl.result
+++ /dev/null
@@ -1,131 +0,0 @@
-select des_encrypt("test", 'akeystr');
-des_encrypt("test", 'akeystr')
-NULL
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-Warning 1289 The 'des_encrypt' feature is disabled; you need MariaDB built with 'openssl des cipher (HAVE_des)' to have it working
-select des_encrypt("test", 1);
-des_encrypt("test", 1)
-NULL
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-Warning 1289 The 'des_encrypt' feature is disabled; you need MariaDB built with 'openssl des cipher (HAVE_des)' to have it working
-select des_encrypt("test", 9);
-des_encrypt("test", 9)
-NULL
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-Warning 1289 The 'des_encrypt' feature is disabled; you need MariaDB built with 'openssl des cipher (HAVE_des)' to have it working
-select des_encrypt("test", 100);
-des_encrypt("test", 100)
-NULL
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-Warning 1289 The 'des_encrypt' feature is disabled; you need MariaDB built with 'openssl des cipher (HAVE_des)' to have it working
-select des_encrypt("test", NULL);
-des_encrypt("test", NULL)
-NULL
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-Warning 1289 The 'des_encrypt' feature is disabled; you need MariaDB built with 'openssl des cipher (HAVE_des)' to have it working
-select des_encrypt(NULL, NULL);
-des_encrypt(NULL, NULL)
-NULL
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-Warning 1289 The 'des_encrypt' feature is disabled; you need MariaDB built with 'openssl des cipher (HAVE_des)' to have it working
-select des_decrypt("test", 'anotherkeystr');
-des_decrypt("test", 'anotherkeystr')
-NULL
-Warnings:
-Warning 1287 'des_decrypt' is deprecated and will be removed in a future release
-Warning 1289 The 'des_decrypt' feature is disabled; you need MariaDB built with 'openssl des cipher (HAVE_des)' to have it working
-select des_decrypt(1, 1);
-des_decrypt(1, 1)
-NULL
-Warnings:
-Warning 1287 'des_decrypt' is deprecated and will be removed in a future release
-Warning 1289 The 'des_decrypt' feature is disabled; you need MariaDB built with 'openssl des cipher (HAVE_des)' to have it working
-select des_decrypt(des_encrypt("test", 'thekey'));
-des_decrypt(des_encrypt("test", 'thekey'))
-NULL
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-Warning 1287 'des_decrypt' is deprecated and will be removed in a future release
-Warning 1289 The 'des_decrypt' feature is disabled; you need MariaDB built with 'openssl des cipher (HAVE_des)' to have it working
-select hex(des_encrypt("hello")),des_decrypt(des_encrypt("hello"));
-hex(des_encrypt("hello")) des_decrypt(des_encrypt("hello"))
-NULL NULL
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-Warning 1287 'des_decrypt' is deprecated and will be removed in a future release
-Warning 1289 The 'des_encrypt' feature is disabled; you need MariaDB built with 'openssl des cipher (HAVE_des)' to have it working
-Warning 1289 The 'des_decrypt' feature is disabled; you need MariaDB built with 'openssl des cipher (HAVE_des)' to have it working
-select des_decrypt(des_encrypt("hello",4));
-des_decrypt(des_encrypt("hello",4))
-NULL
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-Warning 1287 'des_decrypt' is deprecated and will be removed in a future release
-Warning 1289 The 'des_decrypt' feature is disabled; you need MariaDB built with 'openssl des cipher (HAVE_des)' to have it working
-select des_decrypt(des_encrypt("hello",'test'),'test');
-des_decrypt(des_encrypt("hello",'test'),'test')
-NULL
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-Warning 1287 'des_decrypt' is deprecated and will be removed in a future release
-Warning 1289 The 'des_decrypt' feature is disabled; you need MariaDB built with 'openssl des cipher (HAVE_des)' to have it working
-select hex(des_encrypt("hello")),hex(des_encrypt("hello",5)),hex(des_encrypt("hello",'default_password'));
-hex(des_encrypt("hello")) hex(des_encrypt("hello",5)) hex(des_encrypt("hello",'default_password'))
-NULL NULL NULL
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-Warning 1289 The 'des_encrypt' feature is disabled; you need MariaDB built with 'openssl des cipher (HAVE_des)' to have it working
-Warning 1289 The 'des_encrypt' feature is disabled; you need MariaDB built with 'openssl des cipher (HAVE_des)' to have it working
-Warning 1289 The 'des_encrypt' feature is disabled; you need MariaDB built with 'openssl des cipher (HAVE_des)' to have it working
-select des_decrypt(des_encrypt("hello"),'default_password');
-des_decrypt(des_encrypt("hello"),'default_password')
-NULL
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-Warning 1287 'des_decrypt' is deprecated and will be removed in a future release
-Warning 1289 The 'des_decrypt' feature is disabled; you need MariaDB built with 'openssl des cipher (HAVE_des)' to have it working
-select des_decrypt(des_encrypt("hello",4),'password4');
-des_decrypt(des_encrypt("hello",4),'password4')
-NULL
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-Warning 1287 'des_decrypt' is deprecated and will be removed in a future release
-Warning 1289 The 'des_decrypt' feature is disabled; you need MariaDB built with 'openssl des cipher (HAVE_des)' to have it working
-SET @a=des_decrypt(des_encrypt("hello"));
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-Warning 1287 'des_decrypt' is deprecated and will be removed in a future release
-Warning 1289 The 'des_decrypt' feature is disabled; you need MariaDB built with 'openssl des cipher (HAVE_des)' to have it working
-flush des_key_file;
-select @a = des_decrypt(des_encrypt("hello"));
-@a = des_decrypt(des_encrypt("hello"))
-NULL
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-Warning 1287 'des_decrypt' is deprecated and will be removed in a future release
-select hex("hello");
-hex("hello")
-68656C6C6F
-select hex(des_decrypt(des_encrypt("hello",4),'password2'));
-hex(des_decrypt(des_encrypt("hello",4),'password2'))
-NULL
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-Warning 1287 'des_decrypt' is deprecated and will be removed in a future release
-Warning 1289 The 'des_decrypt' feature is disabled; you need MariaDB built with 'openssl des cipher (HAVE_des)' to have it working
-select hex(des_decrypt(des_encrypt("hello","hidden")));
-hex(des_decrypt(des_encrypt("hello","hidden")))
-NULL
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-Warning 1287 'des_decrypt' is deprecated and will be removed in a future release
-Warning 1289 The 'des_decrypt' feature is disabled; you need MariaDB built with 'openssl des cipher (HAVE_des)' to have it working
diff --git a/mysql-test/main/func_encrypt_nossl.test b/mysql-test/main/func_encrypt_nossl.test
deleted file mode 100644
index a9718a1644ad4..0000000000000
--- a/mysql-test/main/func_encrypt_nossl.test
+++ /dev/null
@@ -1,38 +0,0 @@
--- source include/is_embedded.inc
-
-#
-# Test output from des_encrypt and des_decrypt when server is
-# compiled without openssl support
-#
-select des_encrypt("test", 'akeystr');
-select des_encrypt("test", 1);
-select des_encrypt("test", 9);
-select des_encrypt("test", 100);
-select des_encrypt("test", NULL);
-select des_encrypt(NULL, NULL);
-select des_decrypt("test", 'anotherkeystr');
-select des_decrypt(1, 1);
-select des_decrypt(des_encrypt("test", 'thekey'));
-
-
-#
-# Test default keys
-#
-select hex(des_encrypt("hello")),des_decrypt(des_encrypt("hello"));
-select des_decrypt(des_encrypt("hello",4));
-select des_decrypt(des_encrypt("hello",'test'),'test');
-select hex(des_encrypt("hello")),hex(des_encrypt("hello",5)),hex(des_encrypt("hello",'default_password'));
-select des_decrypt(des_encrypt("hello"),'default_password');
-select des_decrypt(des_encrypt("hello",4),'password4');
-
-# Test flush
-SET @a=des_decrypt(des_encrypt("hello"));
-flush des_key_file;
-select @a = des_decrypt(des_encrypt("hello"));
-
-# Test usage of wrong password
-select hex("hello");
-select hex(des_decrypt(des_encrypt("hello",4),'password2'));
-select hex(des_decrypt(des_encrypt("hello","hidden")));
-
-# End of 4.1 tests
diff --git a/mysql-test/main/func_encrypt_ucs2.result b/mysql-test/main/func_encrypt_ucs2.result
deleted file mode 100644
index 0aed95c3eabb5..0000000000000
--- a/mysql-test/main/func_encrypt_ucs2.result
+++ /dev/null
@@ -1,25 +0,0 @@
-#
-# Bug#59648 my_strtoll10_mb2: Assertion `(*endptr - s) % 2 == 0' failed.
-#
-SELECT CHAR_LENGTH(DES_ENCRYPT(0, CHAR('1' USING ucs2)));
-CHAR_LENGTH(DES_ENCRYPT(0, CHAR('1' USING ucs2)))
-9
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-SELECT CONVERT(DES_ENCRYPT(0, CHAR('1' USING ucs2)),UNSIGNED);
-CONVERT(DES_ENCRYPT(0, CHAR('1' USING ucs2)),UNSIGNED)
-0
-Warnings:
-Warning 1287 'des_encrypt' is deprecated and will be removed in a future release
-Warning 1292 Truncated incorrect INTEGER value: '\xFFT\xDCiK\x92j\xE6\xFC'
-SELECT CHAR_LENGTH(DES_DECRYPT(0xFF0DC9FC9537CA75F4, CHAR('1' USING ucs2))) as a;
-a
-4
-Warnings:
-Warning 1287 'des_decrypt' is deprecated and will be removed in a future release
-SELECT CONVERT(DES_DECRYPT(0xFF0DC9FC9537CA75F4, CHAR('1' using ucs2)), UNSIGNED) as a;
-a
-0
-Warnings:
-Warning 1287 'des_decrypt' is deprecated and will be removed in a future release
-Warning 1292 Truncated incorrect INTEGER value: 'test'
diff --git a/mysql-test/main/func_encrypt_ucs2.test b/mysql-test/main/func_encrypt_ucs2.test
deleted file mode 100644
index aaf233fa0315e..0000000000000
--- a/mysql-test/main/func_encrypt_ucs2.test
+++ /dev/null
@@ -1,16 +0,0 @@
--- source include/have_des.inc
--- source include/have_ucs2.inc
-#double warning for view protocol
---source include/no_view_protocol.inc
-
---echo #
---echo # Bug#59648 my_strtoll10_mb2: Assertion `(*endptr - s) % 2 == 0' failed.
---echo #
-
-SELECT CHAR_LENGTH(DES_ENCRYPT(0, CHAR('1' USING ucs2)));
-SELECT CONVERT(DES_ENCRYPT(0, CHAR('1' USING ucs2)),UNSIGNED);
-
---disable_view_protocol
-SELECT CHAR_LENGTH(DES_DECRYPT(0xFF0DC9FC9537CA75F4, CHAR('1' USING ucs2))) as a;
-SELECT CONVERT(DES_DECRYPT(0xFF0DC9FC9537CA75F4, CHAR('1' using ucs2)), UNSIGNED) as a;
---enable_view_protocol
diff --git a/mysql-test/main/func_extract.result b/mysql-test/main/func_extract.result
index b8dcb86ae24af..05946fd2ec9f8 100644
--- a/mysql-test/main/func_extract.result
+++ b/mysql-test/main/func_extract.result
@@ -74,16 +74,22 @@ INSERT INTO t1 VALUES
# Expect empty sets
SELECT a, b, EXTRACT(DAY_HOUR FROM a), EXTRACT(DAY_HOUR FROM b) FROM t1 WHERE NOT (EXTRACT(DAY_HOUR FROM a)<=>EXTRACT(DAY_HOUR FROM b));
a b EXTRACT(DAY_HOUR FROM a) EXTRACT(DAY_HOUR FROM b)
+0.999999 0.999999000 0 NULL
SELECT a, b, EXTRACT(DAY FROM a), EXTRACT(DAY FROM b) FROM t1 WHERE NOT (EXTRACT(DAY FROM a)<=>EXTRACT(DAY FROM b));
a b EXTRACT(DAY FROM a) EXTRACT(DAY FROM b)
+0.999999 0.999999000 0 NULL
SELECT a, b, EXTRACT(HOUR FROM a), EXTRACT(HOUR FROM b) FROM t1 WHERE NOT (EXTRACT(HOUR FROM a)<=>EXTRACT(HOUR FROM b));
a b EXTRACT(HOUR FROM a) EXTRACT(HOUR FROM b)
+0.999999 0.999999000 0 NULL
SELECT a, b, EXTRACT(MINUTE FROM a), EXTRACT(MINUTE FROM b) FROM t1 WHERE NOT (EXTRACT(MINUTE FROM a)<=>EXTRACT(MINUTE FROM b));
a b EXTRACT(MINUTE FROM a) EXTRACT(MINUTE FROM b)
+0.999999 0.999999000 0 NULL
SELECT a, b, EXTRACT(SECOND FROM a), EXTRACT(SECOND FROM b) FROM t1 WHERE NOT (EXTRACT(SECOND FROM a)<=>EXTRACT(SECOND FROM b));
a b EXTRACT(SECOND FROM a) EXTRACT(SECOND FROM b)
+0.999999 0.999999000 0 NULL
SELECT a, b, EXTRACT(MICROSECOND FROM a), EXTRACT(MICROSECOND FROM b) FROM t1 WHERE NOT (EXTRACT(MICROSECOND FROM a)<=>EXTRACT(MICROSECOND FROM b));
a b EXTRACT(MICROSECOND FROM a) EXTRACT(MICROSECOND FROM b)
+0.999999 0.999999000 999999 NULL
# Detailed results
SELECT
a,
@@ -118,32 +124,32 @@ Warnings:
Warning 1292 Incorrect INTERVAL DAY TO SECOND value: '9999-12-31 23:59:59.123456'
Warning 1292 Incorrect INTERVAL DAY TO SECOND value: '2001-01-01 10:20:30.123456'
Warning 1292 Incorrect INTERVAL DAY TO SECOND value: '4294967296:59:59.123456'
-Warning 1292 Incorrect interval value: '4294967296:59:59.123456'
-Warning 1292 Incorrect interval value: '4294967296:59:59.123456'
-Warning 1292 Incorrect interval value: '4294967296:59:59.123456'
-Warning 1292 Incorrect interval value: '4294967296:59:59.123456'
-Warning 1292 Incorrect interval value: '4294967296:59:59.123456'
-Warning 1292 Incorrect interval value: '4294967296:59:59.123456'
-Warning 1292 Incorrect interval value: '4294967296:59:59.123456'
-Warning 1292 Incorrect interval value: '4294967296:59:59.123456'
+Warning 1292 Incorrect interval value: '4294967296:59:59.123456' for column `test`.`t1`.`a` at row 3
+Warning 1292 Incorrect interval value: '4294967296:59:59.123456' for column `test`.`t1`.`a` at row 3
+Warning 1292 Incorrect interval value: '4294967296:59:59.123456' for column `test`.`t1`.`a` at row 3
+Warning 1292 Incorrect interval value: '4294967296:59:59.123456' for column `test`.`t1`.`a` at row 3
+Warning 1292 Incorrect interval value: '4294967296:59:59.123456' for column `test`.`t1`.`a` at row 3
+Warning 1292 Incorrect interval value: '4294967296:59:59.123456' for column `test`.`t1`.`a` at row 3
+Warning 1292 Incorrect interval value: '4294967296:59:59.123456' for column `test`.`t1`.`a` at row 3
+Warning 1292 Incorrect interval value: '4294967296:59:59.123456' for column `test`.`t1`.`a` at row 3
Warning 1292 Incorrect INTERVAL DAY TO SECOND value: '4294967295:59:59.123456'
-Warning 1292 Incorrect interval value: '4294967295:59:59.123456'
-Warning 1292 Incorrect interval value: '4294967295:59:59.123456'
-Warning 1292 Incorrect interval value: '4294967295:59:59.123456'
-Warning 1292 Incorrect interval value: '4294967295:59:59.123456'
-Warning 1292 Incorrect interval value: '4294967295:59:59.123456'
-Warning 1292 Incorrect interval value: '4294967295:59:59.123456'
-Warning 1292 Incorrect interval value: '4294967295:59:59.123456'
-Warning 1292 Incorrect interval value: '4294967295:59:59.123456'
+Warning 1292 Incorrect interval value: '4294967295:59:59.123456' for column `test`.`t1`.`a` at row 4
+Warning 1292 Incorrect interval value: '4294967295:59:59.123456' for column `test`.`t1`.`a` at row 4
+Warning 1292 Incorrect interval value: '4294967295:59:59.123456' for column `test`.`t1`.`a` at row 4
+Warning 1292 Incorrect interval value: '4294967295:59:59.123456' for column `test`.`t1`.`a` at row 4
+Warning 1292 Incorrect interval value: '4294967295:59:59.123456' for column `test`.`t1`.`a` at row 4
+Warning 1292 Incorrect interval value: '4294967295:59:59.123456' for column `test`.`t1`.`a` at row 4
+Warning 1292 Incorrect interval value: '4294967295:59:59.123456' for column `test`.`t1`.`a` at row 4
+Warning 1292 Incorrect interval value: '4294967295:59:59.123456' for column `test`.`t1`.`a` at row 4
Warning 1292 Incorrect INTERVAL DAY TO SECOND value: '87649416:59:59.123456'
-Warning 1292 Incorrect interval value: '87649416:59:59.123456'
-Warning 1292 Incorrect interval value: '87649416:59:59.123456'
-Warning 1292 Incorrect interval value: '87649416:59:59.123456'
-Warning 1292 Incorrect interval value: '87649416:59:59.123456'
-Warning 1292 Incorrect interval value: '87649416:59:59.123456'
-Warning 1292 Incorrect interval value: '87649416:59:59.123456'
-Warning 1292 Incorrect interval value: '87649416:59:59.123456'
-Warning 1292 Incorrect interval value: '87649416:59:59.123456'
+Warning 1292 Incorrect interval value: '87649416:59:59.123456' for column `test`.`t1`.`a` at row 5
+Warning 1292 Incorrect interval value: '87649416:59:59.123456' for column `test`.`t1`.`a` at row 5
+Warning 1292 Incorrect interval value: '87649416:59:59.123456' for column `test`.`t1`.`a` at row 5
+Warning 1292 Incorrect interval value: '87649416:59:59.123456' for column `test`.`t1`.`a` at row 5
+Warning 1292 Incorrect interval value: '87649416:59:59.123456' for column `test`.`t1`.`a` at row 5
+Warning 1292 Incorrect interval value: '87649416:59:59.123456' for column `test`.`t1`.`a` at row 5
+Warning 1292 Incorrect interval value: '87649416:59:59.123456' for column `test`.`t1`.`a` at row 5
+Warning 1292 Incorrect interval value: '87649416:59:59.123456' for column `test`.`t1`.`a` at row 5
SELECT
b,
CAST(b AS INTERVAL DAY_SECOND(6)) AS cidm,
@@ -166,7 +172,7 @@ b cidm dh EXTRACT(DAY_HOUR FROM b) EXTRACT(DAY FROM b) EXTRACT(HOUR FROM b) EXTR
99995959.123456000 416 15:59:59.123456 9999 41615 416 15 59 59 123456
99990101.123456000 416 15:01:01.123456 9999 41615 416 15 1 1 123456
99990101.000000000 416 15:01:01.000000 9999 41615 416 15 1 1 0
-0.999999000 00:00:00.999999 0 0 0 0 0 0 999999
+0.999999000 00:00:00.999999 NULL NULL NULL NULL NULL NULL NULL
0.999990000 00:00:00.999990 0 0 0 0 0 0 999990
0.999900000 00:00:00.999900 0 0 0 0 0 0 999900
0.999000000 00:00:00.999000 0 0 0 0 0 0 999000
@@ -209,6 +215,14 @@ Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '99995959.123456000'
Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '99990101.123456000'
Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '99990101.000000000'
Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '0.999999000'
+Warning 1292 Incorrect interval value: '0.999999000' for column `test`.`t1`.`b` at row 11
+Warning 1292 Incorrect interval value: '0.999999000' for column `test`.`t1`.`b` at row 11
+Warning 1292 Incorrect interval value: '0.999999000' for column `test`.`t1`.`b` at row 11
+Warning 1292 Incorrect interval value: '0.999999000' for column `test`.`t1`.`b` at row 11
+Warning 1292 Incorrect interval value: '0.999999000' for column `test`.`t1`.`b` at row 11
+Warning 1292 Incorrect interval value: '0.999999000' for column `test`.`t1`.`b` at row 11
+Warning 1292 Incorrect interval value: '0.999999000' for column `test`.`t1`.`b` at row 11
+Warning 1292 Incorrect interval value: '0.999999000' for column `test`.`t1`.`b` at row 11
Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '0.999990000'
Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '0.999900000'
Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '0.999000000'
@@ -252,15 +266,15 @@ a cidm EXTRACT(DAY_HOUR FROM a) EXTRACT(DAY_MINUTE FROM a) EXTRACT(DAY_SECOND FR
NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
Warnings:
Warning 1292 Incorrect INTERVAL DAY TO SECOND value: ''
-Warning 1292 Incorrect interval value: ''
-Warning 1292 Incorrect interval value: ''
-Warning 1292 Incorrect interval value: ''
-Warning 1292 Incorrect interval value: ''
-Warning 1292 Incorrect interval value: ''
-Warning 1292 Incorrect interval value: ''
-Warning 1292 Incorrect interval value: ''
-Warning 1292 Incorrect interval value: ''
-Warning 1292 Incorrect interval value: ''
+Warning 1292 Incorrect interval value: '' for column `test`.`t1`.`a` at row 1
+Warning 1292 Incorrect interval value: '' for column `test`.`t1`.`a` at row 1
+Warning 1292 Incorrect interval value: '' for column `test`.`t1`.`a` at row 1
+Warning 1292 Incorrect interval value: '' for column `test`.`t1`.`a` at row 1
+Warning 1292 Incorrect interval value: '' for column `test`.`t1`.`a` at row 1
+Warning 1292 Incorrect interval value: '' for column `test`.`t1`.`a` at row 1
+Warning 1292 Incorrect interval value: '' for column `test`.`t1`.`a` at row 1
+Warning 1292 Incorrect interval value: '' for column `test`.`t1`.`a` at row 1
+Warning 1292 Incorrect interval value: '' for column `test`.`t1`.`a` at row 1
DROP TABLE t1;
# Backward compatibility
# This still parses as DATETIME
@@ -600,26 +614,26 @@ EXTRACT(DAY FROM a) EXTRACT(DAY_SECOND FROM a) a cidm
0 10203 01:02:03/ 01:02:03.000000
20 20102030 20 10:20:30 20 10:20:30.000000
Warnings:
-Warning 1292 Truncated incorrect time value: '2024:01:03 garbage /////'
-Warning 1292 Truncated incorrect time value: '2024:01:03 garbage /////'
+Warning 1292 Incorrect time value: '2024:01:03 garbage /////' for column `test`.`t1`.`a` at row 1
+Warning 1292 Incorrect time value: '2024:01:03 garbage /////' for column `test`.`t1`.`a` at row 1
Warning 1292 Incorrect INTERVAL DAY TO SECOND value: '2024:01:03 garbage /////'
-Warning 1292 Truncated incorrect time value: '24:01:03 garbage /////'
-Warning 1292 Truncated incorrect time value: '24:01:03 garbage /////'
+Warning 1292 Incorrect time value: '24:01:03 garbage /////' for column `test`.`t1`.`a` at row 2
+Warning 1292 Incorrect time value: '24:01:03 garbage /////' for column `test`.`t1`.`a` at row 2
Warning 1292 Incorrect INTERVAL DAY TO SECOND value: '24:01:03 garbage /////'
-Warning 1292 Truncated incorrect time value: '01:01:03 garbage /////'
-Warning 1292 Truncated incorrect time value: '01:01:03 garbage /////'
+Warning 1292 Incorrect time value: '01:01:03 garbage /////' for column `test`.`t1`.`a` at row 3
+Warning 1292 Incorrect time value: '01:01:03 garbage /////' for column `test`.`t1`.`a` at row 3
Warning 1292 Incorrect INTERVAL DAY TO SECOND value: '01:01:03 garbage /////'
-Warning 1292 Truncated incorrect time value: '01:02:03:'
-Warning 1292 Truncated incorrect time value: '01:02:03:'
+Warning 1292 Incorrect time value: '01:02:03:' for column `test`.`t1`.`a` at row 8
+Warning 1292 Incorrect time value: '01:02:03:' for column `test`.`t1`.`a` at row 8
Warning 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '01:02:03:'
-Warning 1292 Truncated incorrect time value: '01:02:03-'
-Warning 1292 Truncated incorrect time value: '01:02:03-'
+Warning 1292 Incorrect time value: '01:02:03-' for column `test`.`t1`.`a` at row 9
+Warning 1292 Incorrect time value: '01:02:03-' for column `test`.`t1`.`a` at row 9
Warning 1292 Incorrect INTERVAL DAY TO SECOND value: '01:02:03-'
-Warning 1292 Truncated incorrect time value: '01:02:03;'
-Warning 1292 Truncated incorrect time value: '01:02:03;'
+Warning 1292 Incorrect time value: '01:02:03;' for column `test`.`t1`.`a` at row 10
+Warning 1292 Incorrect time value: '01:02:03;' for column `test`.`t1`.`a` at row 10
Warning 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '01:02:03;'
-Warning 1292 Truncated incorrect time value: '01:02:03/'
-Warning 1292 Truncated incorrect time value: '01:02:03/'
+Warning 1292 Incorrect time value: '01:02:03/' for column `test`.`t1`.`a` at row 11
+Warning 1292 Incorrect time value: '01:02:03/' for column `test`.`t1`.`a` at row 11
Warning 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '01:02:03/'
DROP TABLE t1;
#
diff --git a/mysql-test/main/func_group.result b/mysql-test/main/func_group.result
index b669f44b4e33d..c5a9a56fc52a0 100644
--- a/mysql-test/main/func_group.result
+++ b/mysql-test/main/func_group.result
@@ -1530,6 +1530,9 @@ DROP TABLE t1;
#
# Bug#43668: Wrong comparison and MIN/MAX for YEAR(2)
#
+set old_mode=2_DIGIT_YEAR;
+Warnings:
+Warning 1287 '2_DIGIT_YEAR' is deprecated and will be removed in a future release
create table t1 (f1 year(2), f2 year(4), f3 date, f4 datetime);
Warnings:
Warning 1287 'YEAR(2)' is deprecated and will be removed in a future release. Please use 'YEAR(4)' instead
@@ -1775,6 +1778,7 @@ f1 f2 f3 f4 f1 = f2
NULL NULL NULL NULL NULL
71 1971 1971-01-01 1971-11-11 22:22:22 1
drop table t1;
+set old_mode=DEFAULT;
#
# Bug #54465: assert: field_types == 0 || field_types[field_pos] ==
# MYSQL_TYPE_LONGLONG
@@ -2569,6 +2573,23 @@ concat(a,":",group_concat(b))
1:2,7
4:5
drop table t1;
-#
# End of 10.3 tests
#
+# MDEV-37888 unexpected type changing after changing AVG to MAX
+#
+SELECT 1, MAX(1), AVG(1);
+Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
+def 1 3 1 1 N 32897 0 63
+def MAX(1) 8 1 1 Y 32896 0 63
+def AVG(1) 246 7 6 Y 32896 4 63
+1 MAX(1) AVG(1)
+1 1 1.0000
+SELECT 1, MAX(1), AVG(1) UNION ALL SELECT 'one', 'max', 'avg';
+Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
+def 1 253 3 3 N 1 39 8
+def MAX(1) 253 3 3 Y 0 39 8
+def AVG(1) 253 7 7 Y 0 39 8
+1 MAX(1) AVG(1)
+1 1 1.00000
+one max avg
+# End of 10.11 tests
diff --git a/mysql-test/main/func_group.test b/mysql-test/main/func_group.test
index 4cfeb46f36808..4255dcac8bd7e 100644
--- a/mysql-test/main/func_group.test
+++ b/mysql-test/main/func_group.test
@@ -1069,6 +1069,7 @@ DROP TABLE t1;
--echo #
--echo # Bug#43668: Wrong comparison and MIN/MAX for YEAR(2)
--echo #
+set old_mode=2_DIGIT_YEAR;
--enable_prepare_warnings
create table t1 (f1 year(2), f2 year(4), f3 date, f4 datetime);
--disable_prepare_warnings
@@ -1098,6 +1099,7 @@ select a.f1 as a, b.f4 as b, a.f1 > b.f4 as gt,
from t1 a, t1 b;
select *, f1 = f2 from t1;
drop table t1;
+set old_mode=DEFAULT;
--echo #
--echo # Bug #54465: assert: field_types == 0 || field_types[field_pos] ==
@@ -1802,6 +1804,16 @@ insert t1 values (1,2,3),(4,5,6),(1,7,8);
select concat(a,":",group_concat(b)) from t1 group by a;
drop table t1;
---echo #
--echo # End of 10.3 tests
+
--echo #
+--echo # MDEV-37888 unexpected type changing after changing AVG to MAX
+--echo #
+enable_metadata;
+disable_view_protocol;
+SELECT 1, MAX(1), AVG(1);
+SELECT 1, MAX(1), AVG(1) UNION ALL SELECT 'one', 'max', 'avg';
+enable_view_protocol;
+disable_metadata;
+
+--echo # End of 10.11 tests
diff --git a/mysql-test/main/func_hybrid_type.result b/mysql-test/main/func_hybrid_type.result
index 9885a9a1c2489..40b288e9e69a3 100644
--- a/mysql-test/main/func_hybrid_type.result
+++ b/mysql-test/main/func_hybrid_type.result
@@ -3456,8 +3456,8 @@ SELECT DISTINCT - GREATEST( b, CAST( NULL AS DATETIME ) ) AS f FROM t1;
f
NULL
Warnings:
-Warning 1292 Truncated incorrect datetime value: 'foo'
-Warning 1292 Truncated incorrect datetime value: 'bar'
+Warning 1292 Incorrect datetime value: 'foo' for column `test`.`t1`.`b` at row 1
+Warning 1292 Incorrect datetime value: 'bar' for column `test`.`t1`.`b` at row 2
DROP TABLE t1;
CREATE TABLE t1 (b LONGBLOB);
INSERT IGNORE INTO t1 VALUES ('foo'),('bar');
@@ -3465,8 +3465,8 @@ SELECT DISTINCT - GREATEST( b, CAST( NULL AS TIME) ) AS f FROM t1;
f
NULL
Warnings:
-Warning 1292 Incorrect time value: 'foo'
-Warning 1292 Incorrect time value: 'bar'
+Warning 1292 Incorrect time value: 'foo' for column `test`.`t1`.`b` at row 1
+Warning 1292 Incorrect time value: 'bar' for column `test`.`t1`.`b` at row 2
DROP TABLE t1;
CREATE TABLE t1 (b LONGBLOB);
INSERT IGNORE INTO t1 VALUES ('foo'),('bar');
@@ -3474,8 +3474,8 @@ SELECT DISTINCT - GREATEST( b, CAST( NULL AS DATE) ) AS f FROM t1;
f
NULL
Warnings:
-Warning 1292 Truncated incorrect datetime value: 'foo'
-Warning 1292 Truncated incorrect datetime value: 'bar'
+Warning 1292 Incorrect datetime value: 'foo' for column `test`.`t1`.`b` at row 1
+Warning 1292 Incorrect datetime value: 'bar' for column `test`.`t1`.`b` at row 2
DROP TABLE t1;
#
# End of 10.1 tests
diff --git a/mysql-test/main/func_json.result b/mysql-test/main/func_json.result
index e4e26cd2cceba..a549cb73291e0 100644
--- a/mysql-test/main/func_json.result
+++ b/mysql-test/main/func_json.result
@@ -640,24 +640,20 @@ ex
set @save_max_allowed_packet=@@max_allowed_packet;
set @save_net_buffer_length=@@net_buffer_length;
set @@global.net_buffer_length=1024;
-set @@global.max_allowed_packet=2048;
+set @@global.max_allowed_packet=4096;
connect newconn, localhost, root,,;
show variables like 'net_buffer_length';
Variable_name Value
net_buffer_length 1024
show variables like 'max_allowed_packet';
Variable_name Value
-max_allowed_packet 2048
+max_allowed_packet 4096
select json_array(repeat('a',1024),repeat('a',1024)) as ex;
ex
-NULL
-Warnings:
-Warning 1301 Result of json_array() was larger than max_allowed_packet (2048) - truncated
+["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"]
select json_object("a", repeat('a',1024),"b", repeat('a',1024)) as ex;
ex
-NULL
-Warnings:
-Warning 1301 Result of json_object() was larger than max_allowed_packet (2048) - truncated
+{"a": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "b": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}
connection default;
set @@global.max_allowed_packet = @save_max_allowed_packet;
set @@global.net_buffer_length = @save_net_buffer_length;
@@ -679,7 +675,7 @@ JSON_SEARCH('{"foo":"bar"}', 'all' , @str, '%', @path)
"$.foo"
SELECT JSON_VALUE('[{"foo": 1},"bar"]', '$[*][0]');
JSON_VALUE('[{"foo": 1},"bar"]', '$[*][0]')
-bar
+NULL
CREATE TABLE t1 (f INT NOT NULL);
INSERT INTO t1 VALUES (0);
SELECT JSON_KEYS(f) FROM t1 ORDER BY 1;
@@ -1062,9 +1058,6 @@ SELECT JSON_EXTRACT('{"a":null, "b":10, "c":"null"}', '$.a');
JSON_EXTRACT('{"a":null, "b":10, "c":"null"}', '$.a')
null
#
-# Start of 10.4 tests
-#
-#
# MDEV-16351 JSON_OBJECT() treats hybrid functions with boolean arguments as numbers
#
SELECT
@@ -1476,7 +1469,7 @@ SET @old_collation_connection= @@COLLATION_CONNECTION;
SET COLLATION_CONNECTION= ucs2_unicode_ci;
SELECT JSON_VALUE('["foo"]', '$**[0]') AS f;
f
-foo
+NULL
SET @@COLLATION_CONNECTION= @old_collation_connection;
#
# MDEV-32587 JSON_VALID fail to validate integer zero in scientific notation
@@ -2404,7 +2397,7 @@ SET @json= '[
]';
SELECT JSON_VALUE(@json, '$[0][1 to 2].key1');
JSON_VALUE(@json, '$[0][1 to 2].key1')
-value1
+NULL
SET @json='{
"A": [0,
[1, 2, 3],
@@ -2421,7 +2414,7 @@ SET @json='{
}';
SELECT JSON_QUERY(@json, '$.A[-2][-3 to -1]');
JSON_QUERY(@json, '$.A[-2][-3 to -1]')
-[13, 14]
+NULL
SET @json= '[
[1, {"key1": "value1"}, 3],
[false, 5, 6],
@@ -2569,7 +2562,7 @@ SET @json1= '[
]';
SELECT JSON_VALUE(@json1, '$[2][1 to 2].key1');
JSON_VALUE(@json1, '$[2][1 to 2].key1')
-value7
+NULL
SET @json= '[
[1.1, {"key1": "value1"}, 3],
[false, 5, 6],
@@ -2579,10 +2572,10 @@ SET @json= '[
]';
SELECT JSON_VALUE(@json, '$[*][0]');
JSON_VALUE(@json, '$[*][0]')
-1.1
+NULL
SELECT JSON_VALUE(@json, '$[2 to 3][0]');
JSON_VALUE(@json, '$[2 to 3][0]')
-7
+NULL
#
# MDEV-28072: JSON_EXTRACT has inconsistent behavior with '0' value in
# json path (when range is used)
@@ -2691,6 +2684,108 @@ NULL
SET @@collation_connection= @save_collation_connection;
# End of 10.9 Test
#
+# MDEV-30691 Assertion `strlen(Ptr) == str_length' failed in void Binary_string::chop()
+#
+set @@collation_connection=utf32_czech_ci;
+select json_detailed('[[123],456]');
+json_detailed('[[123],456]')
+[
+ [123],
+ 456
+]
+set @@collation_connection=@save_collation_connection;
+select json_detailed('[[123],456]');
+json_detailed('[[123],456]')
+[
+ [123],
+ 456
+]
+#
+# MDEV-37428 JSON_VALUE returns NULL for a key with an empty string value rather than an empty string
+#
+SELECT JSON_VALUE(JSON_OBJECT("a", ""), '$.a') = "" AS not_null;
+not_null
+1
+#
+# MDEV-36319: Wrong result json_table
+#
+SET @JSON='
+{
+ "SZ": [
+ {
+ "NAME": "S0",
+ "OFFERS": [
+ {
+ "NAME": "S0A0"
+ }
+ ]
+ },
+ {
+ "NAME": "S1",
+ "OFFERS": [
+ {
+ "NAME": "S1A0"
+ },
+ {
+ "NAME": "S1A1"
+ }
+ ]
+ },
+ {
+ "NAME": "S2",
+ "OFFERS": [
+ {
+ "NAME": "S2A0"
+ }
+ ]
+ },
+ {
+ "NAME": "S3",
+ "OFFERS": [
+ {
+ "NAME": "S3A0"
+ }
+ ]
+ },
+ {
+ "NAME": "S4",
+ "OFFERS": [
+ {
+ "NAME": "S4A0"
+ }
+ ]
+ },
+ {
+ "NAME": "S5",
+ "OFFERS": [
+ {
+ "NAME": "S5A0"
+ }
+ ]
+ }
+ ]
+}
+
+'
+;
+# Should return EMPTY result
+SELECT * FROM json_table(@JSON, '$.SZ[0].OFFERS[1]'
+COLUMNS(NAME VARCHAR(30) PATH '$.NAME')) AS t_sz;
+NAME
+# Should return S1A1
+SELECT * FROM json_table(@JSON, '$.SZ[1].OFFERS[1]'
+COLUMNS(NAME VARCHAR(30) PATH '$.NAME')) AS t_sz;
+NAME
+S1A1
+#
+# MDEV-25148: Unexpected success and result set upon erroneous
+# JSON_VALUE call
+#
+SELECT JSON_VALUE('{"a":[1,2]}', '$.a[*]');
+JSON_VALUE('{"a":[1,2]}', '$.a[*]')
+NULL
+# End of 10.11 Test
+#
# MDEV-32007: JSON_VALUE and JSON_EXTRACT doesn't handle dash (-)
# as first character in key
#
@@ -4842,16 +4937,16 @@ JSON_SCHEMA_VALID(@schema_array, '[')
0
Warnings:
Warning 4037 Unexpected end of JSON text in argument 2 to function 'json_schema_valid'
-SELECT JSON_SCHEMA_VALID(repeat('[', 100000), json_object());
-JSON_SCHEMA_VALID(repeat('[', 100000), json_object())
+SELECT JSON_SCHEMA_VALID(repeat('[', 100), json_object());
+JSON_SCHEMA_VALID(repeat('[', 100), json_object())
NULL
Warnings:
-Warning 4040 Limit of 32 on JSON nested structures depth is reached in argument 1 to function 'json_schema_valid' at position 32
-SELECT JSON_SCHEMA_VALID(json_object(), repeat('[', 10000000));
-JSON_SCHEMA_VALID(json_object(), repeat('[', 10000000))
+Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_schema_valid'
+SELECT JSON_SCHEMA_VALID(json_object(), repeat('[', 100));
+JSON_SCHEMA_VALID(json_object(), repeat('[', 100))
0
Warnings:
-Warning 4040 Limit of 32 on JSON nested structures depth is reached in argument 2 to function 'json_schema_valid' at position 32
+Warning 4037 Unexpected end of JSON text in argument 2 to function 'json_schema_valid'
#
# MDEV-30677: Incorrect result for "SELECT JSON_SCHEMA_VALID('{}', NULL)"
#
@@ -4895,6 +4990,8 @@ NULL
SELECT JSON_KEY_VALUE('', '$.a');
JSON_KEY_VALUE('', '$.a')
NULL
+Warnings:
+Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_key_value'
SELECT JSON_KEY_VALUE('[1,2,3]', '');
JSON_KEY_VALUE('[1,2,3]', '')
NULL
@@ -5069,6 +5166,7 @@ FROM JSON_TABLE(
JSON_KEY_VALUE('{"key1":{"a":1, "b": [1,2,3, {"some_key":"some_val", "c":3}]}, "key2":"val2"}', '$.key1.b[0]'), '$[*]'
COLUMNS (k VARCHAR(20) PATH '$.key', v VARCHAR(20) PATH '$.value', id FOR ORDINALITY)) AS jt;
k v id
+# End of 11.2 test
#
# MDEV-26182: Implement json_array_intersect()
#
@@ -5265,4 +5363,405 @@ SET @obj1='{ "a": 1,"b": 2,"c": 3}';
SELECT JSON_OBJECT_FILTER_KEYS (@obj1,@arr1);
JSON_OBJECT_FILTER_KEYS (@obj1,@arr1)
NULL
-# End of 11.2 Test
+SET character_set_database=default;
+SET CHARACTER SET default;
+#
+# MDEV-33149: JSON_ARRAY_INTERSECT function crashes the server when
+# called with empty json arrays, UBSAN runtime error: member access
+# within null pointer of type 'struct String' in
+# Item_func_json_array_intersect::prepare_json_and_create_hash
+#
+SELECT json_array_intersect(@a,@b);
+json_array_intersect(@a,@b)
+NULL
+#
+# MDEV-36809: json_array_intersect crashs when unused table ref provided
+#
+select json_array_intersect('[["1", "7"], ["2", "6"], ["4", "5"], ["3", "8"]]', '[["2","6"],["3","8"],["4","5"],["1","7"]]') as result from (values (1),(2),(3),(4),(5)) x;
+result
+[["2", "6"], ["3", "8"], ["4", "5"], ["1", "7"]]
+[["2", "6"], ["3", "8"], ["4", "5"], ["1", "7"]]
+[["2", "6"], ["3", "8"], ["4", "5"], ["1", "7"]]
+[["2", "6"], ["3", "8"], ["4", "5"], ["1", "7"]]
+[["2", "6"], ["3", "8"], ["4", "5"], ["1", "7"]]
+SELECT ( WITH x AS ( WITH x ( x ) AS ( SELECT ( 1.000000 ) ) SELECT x FROM x ) SELECT * FROM x WHERE ( SELECT AVG ( x ) OVER ( ORDER BY JSON_ARRAY_INTERSECT ( '[["1", "7"], ["2", "6"], ["3", "8"]]' , '[["2","6"],["3","8"],["4","5"],["1","7"]]' ) ) FROM x ) ) as result;
+result
+1.000000
+#
+# MDEV-37864: mysql-test/mtr --cursor main.func_json fails
+#
+select json_array_intersect('[["1", "7"], ["2", "6"], ["4", "5"], ["3", "8"]]', '[["2","6"],["3","8"],["4","5"],["1","7"]]') as result from (values (1),(2),(3),(4),(5)) x;
+result
+[["2", "6"], ["3", "8"], ["4", "5"], ["1", "7"]]
+[["2", "6"], ["3", "8"], ["4", "5"], ["1", "7"]]
+[["2", "6"], ["3", "8"], ["4", "5"], ["1", "7"]]
+[["2", "6"], ["3", "8"], ["4", "5"], ["1", "7"]]
+[["2", "6"], ["3", "8"], ["4", "5"], ["1", "7"]]
+#
+# MDEV-33640: Server crashes at my_hash_free
+#
+SELECT JSON_SCHEMA_VALID('{"properties": "a_string": {"pattern": "^[5-9]$"}}}', '{"a_string": "8"}');
+ERROR HY000: Invalid value for keyword properties
+#
+# MDEV-38356 JSON_SCHEMA_VALID() crashes with a long enum
+#
+select json_schema_valid('{"enum":[0]}', sformat('"{:#>200}"','0'));
+json_schema_valid('{"enum":[0]}', sformat('"{:#>200}"','0'))
+0
+# End of 11.4 Test
+# Beginning of 12.3 Test
+#
+# MDEV-37072: Implement IS JSON predicate
+#
+set names utf8mb4;
+SELECT '[1, 2]' IS JSON;
+'[1, 2]' IS JSON
+1
+SELECT '{"key1":1, "key2":[2,3]}' IS JSON;
+'{"key1":1, "key2":[2,3]}' IS JSON
+1
+SELECT '123' IS JSON;
+'123' IS JSON
+1
+SELECT 'null' IS JSON;
+'null' IS JSON
+1
+SELECT 'invalid' IS JSON;
+'invalid' IS JSON
+0
+SELECT '{"key1":1, "key2":[2,3]' IS JSON;
+'{"key1":1, "key2":[2,3]' IS JSON
+0
+SELECT '[1, 2' IS JSON;
+'[1, 2' IS JSON
+0
+SELECT 'NULL' IS JSON;
+'NULL' IS JSON
+0
+SELECT 'invalid' IS NOT JSON;
+'invalid' IS NOT JSON
+1
+SELECT '{"key1":1, "key2":[2,3]' IS NOT JSON;
+'{"key1":1, "key2":[2,3]' IS NOT JSON
+1
+SELECT '[1, 2]' IS NOT JSON;
+'[1, 2]' IS NOT JSON
+0
+SELECT '{"key1":1, "key2":[2,3]}' IS NOT JSON;
+'{"key1":1, "key2":[2,3]}' IS NOT JSON
+0
+# Type constraints
+SELECT js,
+js IS JSON "json?",
+js IS JSON VALUE "value?",
+js IS JSON SCALAR "scalar?",
+js IS JSON OBJECT "object?",
+js IS JSON ARRAY "array?"
+FROM (VALUES
+('123'), ('"string"'), ('{"key":1}'), ('[1,2,3]'), ('[]'), ('{}'),
+('true'), ('false'), ('null')) foo(js);
+js json? value? scalar? object? array?
+123 1 1 1 0 0
+"string" 1 1 1 0 0
+{"key":1} 1 1 0 1 0
+[1,2,3] 1 1 0 0 1
+[] 1 1 0 0 1
+{} 1 1 0 1 0
+true 1 1 1 0 0
+false 1 1 1 0 0
+null 1 1 1 0 0
+# UNIQUE KEYS constraint
+SELECT '"a",1,1,2]' IS JSON WITH UNIQUE KEYS;
+'"a",1,1,2]' IS JSON WITH UNIQUE KEYS
+0
+SELECT '{"a": 42,"b": [{"c":1, "c":2}]}' IS JSON WITH UNIQUE KEYS;
+'{"a": 42,"b": [{"c":1, "c":2}]}' IS JSON WITH UNIQUE KEYS
+0
+SELECT '{"a": 42,"b": [{"a": {"a": [{"a" : "a", "a" : "a" }]} }]}' IS JSON WITH UNIQUE KEYS;
+'{"a": 42,"b": [{"a": {"a": [{"a" : "a", "a" : "a" }]} }]}' IS JSON WITH UNIQUE KEYS
+0
+SELECT '{"a": 42,"b": [{"a": {"a": [{"a" : "a"}]} }]}' IS JSON WITH UNIQUE KEYS;
+'{"a": 42,"b": [{"a": {"a": [{"a" : "a"}]} }]}' IS JSON WITH UNIQUE KEYS
+1
+SELECT '[{"a":1}, {"a":1}]' IS JSON WITH UNIQUE KEYS;
+'[{"a":1}, {"a":1}]' IS JSON WITH UNIQUE KEYS
+1
+SELECT '[{"a":1, "a":2}, {"b":1}]' IS JSON WITH UNIQUE KEYS;
+'[{"a":1, "a":2}, {"b":1}]' IS JSON WITH UNIQUE KEYS
+0
+SELECT '{"a": {"b":1, "b":2}}' IS JSON WITH UNIQUE KEYS;
+'{"a": {"b":1, "b":2}}' IS JSON WITH UNIQUE KEYS
+0
+SELECT '[{"a":1}, [{"b":1, "b":2}]]' IS JSON WITH UNIQUE KEYS;
+'[{"a":1}, [{"b":1, "b":2}]]' IS JSON WITH UNIQUE KEYS
+0
+SELECT '{"a": [{"b": {"c":1, "c":2}}]}' IS JSON WITH UNIQUE KEYS;
+'{"a": [{"b": {"c":1, "c":2}}]}' IS JSON WITH UNIQUE KEYS
+0
+SELECT '[{}]' IS JSON WITH UNIQUE KEYS;
+'[{}]' IS JSON WITH UNIQUE KEYS
+1
+SELECT '[1, {"a":1}, 2, {"b":2}]' IS JSON WITH UNIQUE KEYS;
+'[1, {"a":1}, 2, {"b":2}]' IS JSON WITH UNIQUE KEYS
+1
+SELECT '[{"a":1}, 1, {"a":1, "a":2}, 2]' IS JSON WITH UNIQUE KEYS;
+'[{"a":1}, 1, {"a":1, "a":2}, 2]' IS JSON WITH UNIQUE KEYS
+0
+SELECT '[{"a":1}, [{"b":1}], {"c":1}]' IS JSON WITH UNIQUE KEYS;
+'[{"a":1}, [{"b":1}], {"c":1}]' IS JSON WITH UNIQUE KEYS
+1
+SELECT '[{"a":1}, [{"b":1, "b":2}], {"c":1}]' IS JSON WITH UNIQUE KEYS;
+'[{"a":1}, [{"b":1, "b":2}], {"c":1}]' IS JSON WITH UNIQUE KEYS
+0
+SELECT '[[[[{"a":1, "a":2}]]]]' IS JSON WITH UNIQUE KEYS;
+'[[[[{"a":1, "a":2}]]]]' IS JSON WITH UNIQUE KEYS
+0
+SELECT '[[[{"a":1}]], [[{"b":1}]]]' IS JSON WITH UNIQUE KEYS;
+'[[[{"a":1}]], [[{"b":1}]]]' IS JSON WITH UNIQUE KEYS
+1
+SELECT '[[[{"a":1, "a":2}]], [[{"b":1}]]]' IS JSON WITH UNIQUE KEYS;
+'[[[{"a":1, "a":2}]], [[{"b":1}]]]' IS JSON WITH UNIQUE KEYS
+0
+SELECT '[{"a":[{"b":1, "b":2}]}, {"c":[{"d":1}]}]' IS JSON WITH UNIQUE KEYS;
+'[{"a":[{"b":1, "b":2}]}, {"c":[{"d":1}]}]' IS JSON WITH UNIQUE KEYS
+0
+SELECT '{"a":{"b":1, "c":2}, "d":{"b":1, "c":2}}' IS JSON WITH UNIQUE KEYS;
+'{"a":{"b":1, "c":2}, "d":{"b":1, "c":2}}' IS JSON WITH UNIQUE KEYS
+1
+SELECT '[{"a":[{"b":[{"c":1}]}]}, {"d":[{"e":[{"f":1, "f":2}]}]}]' IS JSON WITH UNIQUE KEYS;
+'[{"a":[{"b":[{"c":1}]}]}, {"d":[{"e":[{"f":1, "f":2}]}]}]' IS JSON WITH UNIQUE KEYS
+0
+SELECT '[{}, {"a":{}}, [{}]]' IS JSON WITH UNIQUE KEYS;
+'[{}, {"a":{}}, [{}]]' IS JSON WITH UNIQUE KEYS
+1
+SELECT '{"a":{"b":{"b":1}}, "d":{"e":{"f":1}}}' IS JSON WITH UNIQUE KEYS;
+'{"a":{"b":{"b":1}}, "d":{"e":{"f":1}}}' IS JSON WITH UNIQUE KEYS
+1
+SELECT js,
+js IS JSON OBJECT WITH UNIQUE KEYS "object_with_unique",
+js IS JSON OBJECT WITHOUT UNIQUE KEYS "object_without_unique",
+js IS JSON ARRAY WITH UNIQUE KEYS "array_with_unique",
+js IS JSON ARRAY WITHOUT UNIQUE KEYS "array_without_unique"
+FROM (VALUES
+('{"a":1, "b":2, "c":3}'),
+('{"a":1, "a":2, "a":3}'),
+('[{"a":"1"},{"c":"2","c":"3"}]'),
+('[{"a":"1"},{"b":"2","c":"3"}]'),
+('[1,2,3]'), ('[1,1,1]'), ('[]'), ('123'),
+('"string"'), ('true'), ('null')) foo(js);
+js object_with_unique object_without_unique array_with_unique array_without_unique
+{"a":1, "b":2, "c":3} 1 1 0 0
+{"a":1, "a":2, "a":3} 0 1 0 0
+[{"a":"1"},{"c":"2","c":"3"}] 0 0 0 1
+[{"a":"1"},{"b":"2","c":"3"}] 0 0 1 1
+[1,2,3] 0 0 1 1
+[1,1,1] 0 0 1 1
+[] 0 0 1 1
+123 0 0 0 0
+"string" 0 0 0 0
+true 0 0 0 0
+null 0 0 0 0
+# Test with table data
+CREATE TABLE test_json (
+json_col JSON,
+text_col TEXT
+);
+INSERT INTO test_json VALUES
+('{"name":"Alice", "age":25}', '{"name":"Alice", "age":25}'),
+('[1,2,3]', '[1,2,3]'),
+('42', '42'),
+('"hello"', '"hello"'),
+('true', 'true'),
+('null', 'null'),
+('"invalid"', 'invalid'),
+('{"key1":1, "key2":2}', '{"key1":1, "key2":2}'),
+('{"key1":1, "key1":2}', '{"key1":1, "key1":2}');
+SELECT
+json_col,
+json_col IS JSON as is_json,
+json_col IS JSON VALUE as is_value,
+json_col IS JSON SCALAR as is_scalar,
+json_col IS JSON OBJECT as is_object,
+json_col IS JSON ARRAY as is_array,
+json_col IS JSON OBJECT WITH UNIQUE KEYS as object_with_unique,
+json_col IS JSON OBJECT WITHOUT UNIQUE KEYS as object_without_unique
+FROM test_json;
+json_col is_json is_value is_scalar is_object is_array object_with_unique object_without_unique
+{"name":"Alice", "age":25} 1 1 0 1 0 1 1
+[1,2,3] 1 1 0 0 1 0 0
+42 1 1 1 0 0 0 0
+"hello" 1 1 1 0 0 0 0
+true 1 1 1 0 0 0 0
+null 1 1 1 0 0 0 0
+"invalid" 1 1 1 0 0 0 0
+{"key1":1, "key2":2} 1 1 0 1 0 1 1
+{"key1":1, "key1":2} 1 1 0 1 0 0 1
+SELECT
+text_col,
+text_col IS JSON as is_json,
+text_col IS JSON VALUE as is_value,
+text_col IS JSON SCALAR as is_scalar,
+text_col IS JSON OBJECT as is_object,
+text_col IS JSON ARRAY as is_array
+FROM test_json;
+text_col is_json is_value is_scalar is_object is_array
+{"name":"Alice", "age":25} 1 1 0 1 0
+[1,2,3] 1 1 0 0 1
+42 1 1 1 0 0
+"hello" 1 1 1 0 0
+true 1 1 1 0 0
+null 1 1 1 0 0
+invalid 0 0 0 0 0
+{"key1":1, "key2":2} 1 1 0 1 0
+{"key1":1, "key1":2} 1 1 0 1 0
+SELECT
+COUNT(*) as total_rows,
+SUM(json_col IS JSON) as valid_json_count,
+SUM(json_col IS JSON OBJECT) as object_count,
+SUM(json_col IS JSON ARRAY) as array_count,
+SUM(json_col IS JSON SCALAR) as scalar_count
+FROM test_json;
+total_rows valid_json_count object_count array_count scalar_count
+9 9 3 1 5
+# Edge cases
+SELECT js,
+js IS JSON "json?",
+js IS JSON VALUE "value?",
+js IS JSON SCALAR "scalar?",
+js IS JSON OBJECT "object?",
+js IS JSON ARRAY "array?"
+FROM (VALUES
+(NULL), (''), (' '), ('\n'), ('\t'),
+('{"key":1,}'), ('{"key":1, "key2":}'), ('{key:1}'),
+('{"emoji":"😊"}'), ('{"unicode":"\\u0041"}'),
+(x'48656C6C6F'), ('2'), (CONCAT('{"a":', 1, '}')),
+(JSON_OBJECT('a', 1, 'b', 2)), (JSON_ARRAY(1, 2, 3)), (JSON_QUOTE('hello'))) foo(js);
+js json? value? scalar? object? array?
+NULL NULL NULL NULL NULL NULL
+ 0 0 0 0 0
+ 0 0 0 0 0
+
+ 0 0 0 0 0
+ 0 0 0 0 0
+{"key":1,} 0 0 0 0 0
+{"key":1, "key2":} 0 0 0 0 0
+{key:1} 0 0 0 0 0
+{"emoji":"😊"} 1 1 0 1 0
+{"unicode":"\u0041"} 1 1 0 1 0
+Hello 0 0 0 0 0
+2 1 1 1 0 0
+{"a":1} 1 1 0 1 0
+{"a": 1, "b": 2} 1 1 0 1 0
+[1, 2, 3] 1 1 0 0 1
+"hello" 1 1 1 0 0
+# Large json object with unique keys
+CREATE PROCEDURE build_large_json()
+BEGIN
+SET @json='{"key1":1';
+SET @i=2;
+WHILE @i <= 1000 DO
+SET @json = CONCAT(@json, ',"key', @i, '":', @i);
+SET @i = @i + 1;
+END WHILE;
+SET @json = CONCAT(@json, '}');
+END|
+CALL build_large_json()|
+SELECT @json IS JSON OBJECT WITH UNIQUE KEYS AS unique_keys|
+unique_keys
+1
+DROP PROCEDURE build_large_json|
+DROP TABLE test_json;
+# Generated columns
+CREATE TABLE test_generated_json (
+j TEXT,
+is_json BOOL GENERATED ALWAYS AS (j IS JSON) VIRTUAL,
+is_not_json BOOL GENERATED ALWAYS AS (j IS NOT JSON) VIRTUAL,
+is_array BOOL GENERATED ALWAYS AS (j IS JSON ARRAY) VIRTUAL,
+is_object BOOL GENERATED ALWAYS AS (j IS JSON OBJECT) VIRTUAL,
+is_scalar BOOL GENERATED ALWAYS AS (j IS JSON SCALAR) VIRTUAL,
+with_unique_keys BOOL GENERATED ALWAYS AS (j IS JSON OBJECT WITH UNIQUE KEYS) VIRTUAL,
+without_unique_keys BOOL GENERATED ALWAYS AS (j IS JSON OBJECT WITHOUT UNIQUE KEYS) VIRTUAL
+);
+INSERT INTO test_generated_json (j) VALUES
+('[1, 2, 3]'),
+('{"key": "value"}'),
+('3'),
+(NULL),
+('{}'),
+('invalid'),
+('{"key": "value", "key2": "value2"}'),
+('{"key": "value", "key": "value2"}');
+SELECT
+j,
+is_json,
+is_not_json,
+is_array,
+is_object,
+is_scalar,
+with_unique_keys,
+without_unique_keys
+FROM test_generated_json;
+j is_json is_not_json is_array is_object is_scalar with_unique_keys without_unique_keys
+[1, 2, 3] 1 0 1 0 0 0 0
+{"key": "value"} 1 0 0 1 0 1 1
+3 1 0 0 0 1 0 0
+NULL NULL NULL NULL NULL NULL NULL NULL
+{} 1 0 0 1 0 1 1
+invalid 0 1 0 0 0 0 0
+{"key": "value", "key2": "value2"} 1 0 0 1 0 1 1
+{"key": "value", "key": "value2"} 1 0 0 1 0 0 1
+DROP TABLE test_generated_json;
+# CHECK constraints
+CREATE TABLE test_check_json (
+j TEXT CHECK (j IS JSON),
+j_array JSON CHECK (j_array IS JSON ARRAY),
+j_object JSON CHECK (j_object IS JSON OBJECT),
+j_object_with_unique_keys JSON CHECK (j_object_with_unique_keys IS JSON OBJECT WITH UNIQUE KEYS)
+);
+INSERT INTO test_check_json VALUES
+('[1, 2, 3]', '[1, 2]', '{"key": "value"}', '{"key": "value"}'),
+('{"key": "value"}', '[1, 2]', '{"key": "value"}', '{"key": "value", "key2": "value2"}');
+INSERT INTO test_check_json VALUES ('[1, 2, 3]', '{1, 2}', '{"key": "value"}', 'invalid');
+ERROR 23000: CONSTRAINT `test_check_json.j_array` failed for `test`.`test_check_json`
+INSERT INTO test_check_json VALUES ('[1, 2, 3]', '[1, 2]', '{"key": "value"}', '{"key": "value", "key": "value2"}');
+ERROR 23000: CONSTRAINT `test_check_json.j_object_with_unique_keys` failed for `test`.`test_check_json`
+DROP TABLE test_check_json;
+# DEFAULT clauses
+CREATE TABLE test_default_json (
+j TEXT,
+is_json BOOL DEFAULT (j IS JSON),
+is_not_json BOOL DEFAULT (j IS NOT JSON),
+is_array BOOL DEFAULT (j IS JSON ARRAY),
+is_object BOOL DEFAULT (j IS JSON OBJECT),
+is_scalar BOOL DEFAULT (j IS JSON SCALAR),
+with_unique_keys BOOL DEFAULT (j IS JSON OBJECT WITH UNIQUE KEYS),
+without_unique_keys BOOL DEFAULT (j IS JSON OBJECT WITHOUT UNIQUE KEYS)
+);
+INSERT INTO test_default_json (j) VALUES
+('[1, 2, 3]'),
+('{"key": "value"}'),
+('3'),
+(NULL),
+('{}'),
+('{"key": "value", "key2": "value2"}'),
+('{"key": "value", "key": "value2"}');
+SELECT
+j,
+is_json,
+is_not_json,
+is_array,
+is_object,
+is_scalar,
+with_unique_keys,
+without_unique_keys
+FROM test_default_json;
+j is_json is_not_json is_array is_object is_scalar with_unique_keys without_unique_keys
+[1, 2, 3] 1 0 1 0 0 0 0
+{"key": "value"} 1 0 0 1 0 1 1
+3 1 0 0 0 1 0 0
+NULL NULL NULL NULL NULL NULL NULL NULL
+{} 1 0 0 1 0 1 1
+{"key": "value", "key2": "value2"} 1 0 0 1 0 1 1
+{"key": "value", "key": "value2"} 1 0 0 1 0 0 1
+DROP TABLE test_default_json;
+# End of 12.3
diff --git a/mysql-test/main/func_json.test b/mysql-test/main/func_json.test
index 453ede9e26b25..13be0f591e5ce 100644
--- a/mysql-test/main/func_json.test
+++ b/mysql-test/main/func_json.test
@@ -78,7 +78,7 @@ select json_contains_path('{"key1":1, "key2":[2,3]}', "aLl", "$.key1", "$.key2")
select json_contains_path('{ "a": true }', NULL, '$.a' ) as exp;
select json_contains_path('{ "a": true }', 'all', NULL ) as exp;
select json_contains_path('{"a":{"b":"c"}}', 'one', '$.a.*') as exp;
-
+
select json_extract('{"key1":"asd", "key2":[2,3]}', "$.key1") as exp;
select json_extract('{"key1":"asd", "key2":[2,3]}', "$.keyX", "$.keyY") as exp;
select json_extract('{"key1":"asd", "key2":[2,3]}', "$.key1", "$.key2") as exp;
@@ -208,7 +208,6 @@ drop table t2;
--enable_cursor_protocol
drop table t1;
-
select json_object("a", json_object("b", "abcd"));
#enable after fix MDEV-31554
--disable_cursor_protocol
@@ -310,7 +309,7 @@ set @save_max_allowed_packet=@@max_allowed_packet;
set @save_net_buffer_length=@@net_buffer_length;
set @@global.net_buffer_length=1024;
-set @@global.max_allowed_packet=2048;
+set @@global.max_allowed_packet=4096;
--connect (newconn, localhost, root,,)
show variables like 'net_buffer_length';
@@ -323,7 +322,6 @@ set @@global.max_allowed_packet = @save_max_allowed_packet;
set @@global.net_buffer_length = @save_net_buffer_length;
--disconnect newconn
-
#
# MDEV-12262 Assertion `!null_value' failed in virtual bool Item::send on JSON_REMOVE.
#
@@ -597,7 +595,6 @@ SELECT
CAST(JSON_EXTRACT('{"x":false}', '$.x') AS DOUBLE) AS cf,
CAST(JSON_EXTRACT('{"x":false}', '$.x') AS DECIMAL) AS cd;
-
--echo #
--echo # MDEV-24585 Assertion `je->s.cs == nice_js->charset()' failed in json_nice.
--echo #
@@ -689,14 +686,9 @@ SELECT JSON_VALUE('{"nulltest": null}', '$.nulltest');
SELECT 1 + NULL;
SELECT 1 + JSON_VALUE('{"nulltest": null}', '$.nulltest');
-
SELECT NULL;
SELECT JSON_EXTRACT('{"a":null, "b":10, "c":"null"}', '$.a');
---echo #
---echo # Start of 10.4 tests
---echo #
-
--echo #
--echo # MDEV-16351 JSON_OBJECT() treats hybrid functions with boolean arguments as numbers
--echo #
@@ -739,7 +731,6 @@ SELECT * FROM t1 WHERE CASE WHEN JSON_OBJECT('x', (SELECT MAX(a=3) FROM t1))='{"
SELECT * FROM t1 WHERE CASE WHEN JSON_OBJECT('x', (SELECT MAX(a=2) FROM t1))='{"x": true}' THEN a END;
SELECT * FROM t1 WHERE CASE WHEN JSON_OBJECT('x', (SELECT MAX(a=2) FROM t1))='{"x": false}' THEN a END;
-
DROP TABLE t1;
-- echo #
@@ -941,7 +932,6 @@ insert into t200 values
]
}');
-
select JSON_DETAILED(JSON_EXTRACT(a, '$**.analyzing_range_alternatives')) as exp from t200;
select JSON_PRETTY(JSON_EXTRACT(a, '$**.analyzing_range_alternatives')) as exp from t200;
select JSON_LOOSE(JSON_EXTRACT(a, '$**.analyzing_range_alternatives')) as exp from t200;
@@ -957,7 +947,6 @@ SELECT JSON_LENGTH();
--echo # MDEV-23187: Assorted assertion failures in json_find_path with certain collations
-
SET @old_collation_connection= @@COLLATION_CONNECTION;
SET COLLATION_CONNECTION= ucs2_unicode_ci;
@@ -1107,10 +1096,10 @@ DROP TABLE t1;
CREATE TABLE t1(id int primary key, name varchar(50));
CREATE TABLE t2(id int, owner_id int);
-
+
INSERT INTO t1 VALUES (1, "name1"), (2, "name2"), (3, "name3");
INSERT INTO t2 VALUES (1, 1), (2, 1), (3, 2), (4, 3);
-
+
SELECT t1.id, JSON_ARRAYAGG(JSON_OBJECT('id',t2.id) ORDER BY t2.id) as materials
from t1 LEFT JOIN t2 on t1.id = t2.owner_id
GROUP BY t1.id ORDER BY id;
@@ -1133,7 +1122,7 @@ CREATE TABLE arrNestTest (
id VARCHAR(80) AS (JSON_COMPACT(JSON_EXTRACT(doc, "$._id"))) UNIQUE KEY,
doc JSON,
CONSTRAINT id_not_null CHECK(id IS NOT NULL));
-
+
INSERT INTO test.arrNestTest (doc) VALUES ('{ "_id" : { "$oid" : "611c0a463b150154132f6636" }, "a" : [ { "a" : [ { "a" : [ { "a" : [ { "a" : [ { "a" : [ { "a" : [ { "a" : [ { "a" : [ { "a" : [ { "a" : [ { "a" : [ { "a" : [ { "a" : [ { "a" : [ { "a" : 1.0 } ] } ] } ] } ] } ] } ] } ] } ] } ] } ] } ] } ] } ] } ] } ] }');
SELECT * FROM arrNestTest;
DROP TABLE arrNestTest;
@@ -1156,14 +1145,12 @@ set names latin1;
select json_arrayagg('ä'), json_objectagg(1, 'ä');
--enable_service_connection
-
--echo #
--echo # MDEV-32287: JSON_EXTRACT not returning multiple values for same path
--echo #
select JSON_EXTRACT("[1, 2, [30, 40]]", '$[2][1]', '$[2][1]');
-
--echo #
--echo # MDEV-31402: SIGSEGV in json_get_path_next | Item_func_json_extract::read_json
--echo #
@@ -1180,7 +1167,6 @@ DROP TABLE t;
SELECT JSON_TYPE(json_value(JSON_OBJECT("id", 1, "name", 'Monty', "date", Cast('2019-01-01' as Date) ), '$.date')) as x;
-
--echo #
--echo # MDEV-22141: JSON_REMOVE returns NULL on valid arguments
--echo #
@@ -1188,7 +1174,6 @@ SELECT JSON_TYPE(json_value(JSON_OBJECT("id", 1, "name", 'Monty', "date", Cast('
SELECT JSON_REMOVE('{"A": { "B": 1 }}', '$.A.B.C.D');
-
--echo #
--echo # MDEV-34143: Server crashes when executing JSON_EXTRACT after setting non-default collation_connection
--echo #
@@ -1202,7 +1187,6 @@ SELECT JSON_EXTRACT('{"a": 1,"b": 2}','$.a');
SET @@collation_connection= @save_collation_connection;
-
--echo # End of 10.5 tests
--echo #
@@ -1226,19 +1210,16 @@ SELECT JSON_ARRAY_APPEND(JSON_ARRAY(l1, l2, l3, l4), '$[0]', 'k3'), JSON_ARRAY_I
SELECT JSON_INSERT(JSON_OBJECT(l1, l2, l3, l4), '$.k3', 'v3'),JSON_SET(JSON_OBJECT(l1, l2, l3, l4), '$.k2', 'new v2'),JSON_REPLACE(JSON_OBJECT(l1, l2, l3, l4), '$.k2', 'new v2') from t;
DROP TABLE t;
-
--echo #
--echo # MDEV-27412: JSON_TABLE doesn't properly unquote strings
--echo #
-
SET @data = '[{"Data": "